Style recipe list

This commit is contained in:
Anika Raemer 2025-09-13 08:41:07 +02:00
parent 568606213d
commit a50497426b
3 changed files with 45 additions and 34 deletions

View file

@ -8,22 +8,6 @@
@apply p-4 flex; @apply p-4 flex;
} }
.sidebar {
@apply min-w-[16rem] bg-gray-50 p-4 w-1/3 border-r pr-4;
}
.sidebar-title {
@apply text-blue-900 font-bold mb-2;
}
.sidebar-link {
@apply block bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition w-full px-4 py-2 hover:bg-blue-100
}
.sidebar-item-text {
@apply font-semibold text-blue-400;
}
.content-title{ .content-title{
@apply text-3xl font-black mb-8 text-blue-400; @apply text-3xl font-black mb-8 text-blue-400;
} }

View file

@ -3,18 +3,38 @@ import { Link } from "react-router-dom"
type RecipeListItemProps = { type RecipeListItemProps = {
title: string title: string
targetPath: string targetPath: string
imageUrl?: string
} }
/** /**
* List item for the recipe list. Selecting an item navigates to the recipe * List item for the recipe list. Selecting an item navigates to the recipe
*/ */
export default function RecipeListItem({ title, targetPath: path}: RecipeListItemProps) {
export default function RecipeListItem({ title, targetPath, imageUrl }: RecipeListItemProps) {
return ( return (
<Link <Link
to={path} to={targetPath}
className="sidebar-link" className="h-60 w-60 block rounded-xl overflow-hidden shadow-md hover:shadow-lg transition-shadow bg-white dark:bg-gray-800"
> >
<h2 className="sidebar-item-text">{title}</h2> {/* Optional recipe image */}
{imageUrl ? (
<img
src={imageUrl}
alt={title}
className="w-full h-40 object-cover"
/>
)
: <div className="bg-gray-300 w-full h-40 flex justify-center items-center">
<label className="font-black text-gray-500" >no image</label>
</div>
}
{/* Card content */}
<div className="p-4">
<h2 className="text-lg font-semibold text-blue-400 dark:text-gray-100">
{title}
</h2>
</div>
</Link> </Link>
) )
} }

View file

@ -14,7 +14,7 @@ export default function RecipeListPage() {
useEffect(() => { useEffect(() => {
const loadRecipeList = async () => { const loadRecipeList = async () => {
try { try {
// Fetch recipe data when editing an existing one // Fetch recipe list
console.log("loading recipe list") console.log("loading recipe list")
const data = await fetchRecipeList() const data = await fetchRecipeList()
setRecipeList(data) setRecipeList(data)
@ -26,20 +26,27 @@ export default function RecipeListPage() {
}, []) }, [])
if(!recipeList) { return <div>Unable to load recipes1</div>} if(!recipeList) { return <div>Unable to load recipes1</div>}
// @todo find a better representation than an oldfashioned sidebar
return ( return (
<div className="sidebar"> /*Contaier spanning entire screen used to center content horizontally */
<h1 className="sidebar-title">Recipes</h1> <div className="w-screen min-h-screen flex justify-center">
{/* Container defining the maximum width of the content */}
<div className="flex flex-col gap-2"> <div className="bg-gray-100 w-full min-h-screen max-w-5xl shadow-xl p-8">
{recipeList.map((recipe) => ( {/* Header - remains in position when scrolling */}
<RecipeListItem <div className="sticky bg-gray-100 top-0 left-0 right-0 mb-4">
key={recipe.id} <h1 className="content-title text-blue-900">Recipes</h1>
title = {recipe.title} <label>{recipeList.length} Recipes</label>
targetPath={'recipe/'+recipe.id} </div>
/> {/*Content - List of recipe cards */}
))} <div className="grid gap-6 grid-cols-[repeat(auto-fit,minmax(220px,1fr))]">
{recipeList.map((recipe) => (
<RecipeListItem
key={recipe.id}
title = {recipe.title}
targetPath={'recipe/'+recipe.id}
/>
))}
</div>
</div> </div>
</div> </div>
) )
} }