diff --git a/frontend/src/components/RecipeCard.tsx b/frontend/src/components/RecipeCard.tsx
index 5a2b7d4..3fc44e0 100644
--- a/frontend/src/components/RecipeCard.tsx
+++ b/frontend/src/components/RecipeCard.tsx
@@ -7,6 +7,8 @@ interface RecipeCardProps {
tags?: Tag[];
}
+const foodEmojis = ['🥗', '🍲', '🍝', '🍜', '🍛', '🥘', '🍗', '🍤', '🍕', '🥪', '🍳', '🍱'];
+
function formatTime(minutes?: number): string {
if (!minutes) return '';
if (minutes < 60) return `${minutes}m`;
@@ -21,61 +23,83 @@ function formatDate(timestamp?: number): string {
return date.toLocaleDateString();
}
+function accentForRecipe(recipe: Recipe, tags: Tag[]) {
+ if (tags[0]?.color) return tags[0].color;
+ const palette = ['#f97316', '#ef4444', '#22c55e', '#06b6d4', '#3b82f6', '#a855f7'];
+ return palette[recipe.id % palette.length];
+}
+
+function emojiForRecipe(recipe: Recipe) {
+ return foodEmojis[recipe.id % foodEmojis.length];
+}
+
+function MetaChip({ label, value, emoji }: { label: string; value: string; emoji: string }) {
+ return (
+
+ {emoji}
+ {value}
+ {label}
+
+ );
+}
+
export function RecipeCard({ recipe, tags = [] }: RecipeCardProps) {
const totalTime = (recipe.prep_time_minutes || 0) + (recipe.cook_time_minutes || 0);
+ const accent = accentForRecipe(recipe, tags);
return (
-
- {/* Title */}
-
{recipe.title}
- {/* Description */}
- {recipe.description &&
{recipe.description}
}
+
+
+ {tags[0]?.name ?? 'Homemade'}
+
+
+ {emojiForRecipe(recipe)}
+
+
+
+
+
{recipe.title}
+
+ {recipe.description ? (
+
{recipe.description}
+ ) : (
+
No description yet
+ )}
+
+
+ {recipe.servings ? : null}
+ {totalTime > 0 ? : null}
+
+
- {/* Tags */}
{tags.length > 0 && (
-
- {tags.map(tag => (
+
+ {tags.slice(0, 4).map((tag) => (
{tag.name}
))}
+ {tags.length > 4 ? +{tags.length - 4} : null}
)}
- {/* Meta information */}
-
- {recipe.servings && (
-
- 🍽️
- {recipe.servings} servings
-
- )}
- {totalTime > 0 && (
-
- ⏱️
- {formatTime(totalTime)}
-
- )}
- {recipe.last_cooked_at && (
-
- 👨🍳
- Last cooked {formatDate(recipe.last_cooked_at)}
-
- )}
-
-
-
-
{recipe.ingredients.length} ingredients
-
View Recipe →
+
+ {recipe.last_cooked_at ? `Cooked ${formatDate(recipe.last_cooked_at)}` : 'Not cooked yet'}
+ View recipe →
diff --git a/frontend/src/pages/RecipeListPage.tsx b/frontend/src/pages/RecipeListPage.tsx
index 1d71e57..bfdee38 100644
--- a/frontend/src/pages/RecipeListPage.tsx
+++ b/frontend/src/pages/RecipeListPage.tsx
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';
+import heroImage from '../assets/hero.png';
import { useRecipes } from '../hooks/useRecipes';
import { useTags } from '../hooks/useTags';
import { RecipeCard } from '../components/RecipeCard';
@@ -43,37 +44,74 @@ export function RecipeListPage() {
};
const filteredRecipes = recipes;
- const hasActiveFilters = searchQuery || selectedTagId !== null;
+ const hasActiveFilters = Boolean(searchQuery) || selectedTagId !== null;
return (
-
+
-
-
+
+
+
+
Kitchen Companion
+
Cook smarter with your favorite recipes in one place
+
+ Build your personal cookbook, tag meals by mood or diet, and find what you need fast.
+
+
+
+
+

+
+
+
+
+
+
+
-
My Recipes
+
My Recipes
Browse and search your recipe collection
+ New Recipe
- {/* Search/Tag Filter Row */}
-