diff --git a/backend/__pycache__/db_utils.cpython-313.pyc b/backend/__pycache__/db_utils.cpython-313.pyc index feab553..dfc8c39 100644 Binary files a/backend/__pycache__/db_utils.cpython-313.pyc and b/backend/__pycache__/db_utils.cpython-313.pyc differ diff --git a/backend/__pycache__/main.cpython-313.pyc b/backend/__pycache__/main.cpython-313.pyc index 5140ab0..4a21043 100644 Binary files a/backend/__pycache__/main.cpython-313.pyc and b/backend/__pycache__/main.cpython-313.pyc differ diff --git a/backend/db_utils.py b/backend/db_utils.py index 03f3c2b..c5ba8ba 100644 --- a/backend/db_utils.py +++ b/backend/db_utils.py @@ -55,7 +55,7 @@ def list_recipes_db() -> List[Dict[str, Any]]: cur.execute( """ SELECT id, name, meal_type, time_minutes, - tags, ingredients, steps, image + tags, ingredients, steps, image, made_by FROM recipes ORDER BY id """ @@ -68,7 +68,7 @@ def list_recipes_db() -> List[Dict[str, Any]]: def update_recipe_db(recipe_id: int, recipe_data: Dict[str, Any]) -> Optional[Dict[str, Any]]: """ עדכון מתכון קיים לפי id. - recipe_data: name, meal_type, time_minutes, tags, ingredients, steps, image + recipe_data: name, meal_type, time_minutes, tags, ingredients, steps, image, made_by """ conn = get_conn() try: @@ -82,9 +82,10 @@ def update_recipe_db(recipe_id: int, recipe_data: Dict[str, Any]) -> Optional[Di tags = %s, ingredients = %s, steps = %s, - image = %s + image = %s, + made_by = %s WHERE id = %s - RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps, image + RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps, image, made_by """, ( recipe_data["name"], @@ -94,6 +95,7 @@ def update_recipe_db(recipe_id: int, recipe_data: Dict[str, Any]) -> Optional[Di json.dumps(recipe_data.get("ingredients", [])), json.dumps(recipe_data.get("steps", [])), recipe_data.get("image"), + recipe_data.get("made_by"), recipe_id, ), ) @@ -131,9 +133,9 @@ def create_recipe_db(recipe_data: Dict[str, Any]) -> Dict[str, Any]: with conn.cursor() as cur: cur.execute( """ - INSERT INTO recipes (name, meal_type, time_minutes, tags, ingredients, steps, image) - VALUES (%s, %s, %s, %s, %s, %s, %s) - RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps, image + INSERT INTO recipes (name, meal_type, time_minutes, tags, ingredients, steps, image, made_by) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s) + RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps, image, made_by """, ( recipe_data["name"], @@ -143,6 +145,7 @@ def create_recipe_db(recipe_data: Dict[str, Any]) -> Dict[str, Any]: json.dumps(recipe_data.get("ingredients", [])), json.dumps(recipe_data.get("steps", [])), recipe_data.get("image"), + recipe_data.get("made_by"), ), ) row = cur.fetchone() @@ -160,7 +163,7 @@ def get_recipes_by_filters_db( try: query = """ SELECT id, name, meal_type, time_minutes, - tags, ingredients, steps + tags, ingredients, steps, image, made_by FROM recipes WHERE 1=1 """ diff --git a/backend/main.py b/backend/main.py index 6328b3c..74ac977 100644 --- a/backend/main.py +++ b/backend/main.py @@ -21,6 +21,7 @@ class RecipeBase(BaseModel): name: str meal_type: str # breakfast / lunch / dinner / snack time_minutes: int + made_by: Optional[str] = None # Person who created this recipe version tags: List[str] = [] ingredients: List[str] = [] steps: List[str] = [] @@ -63,6 +64,7 @@ def list_recipes(): name=r["name"], meal_type=r["meal_type"], time_minutes=r["time_minutes"], + made_by=r.get("made_by"), tags=r["tags"] or [], ingredients=r["ingredients"] or [], steps=r["steps"] or [], @@ -85,6 +87,7 @@ def create_recipe(recipe_in: RecipeCreate): name=row["name"], meal_type=row["meal_type"], time_minutes=row["time_minutes"], + made_by=row.get("made_by"), tags=row["tags"] or [], ingredients=row["ingredients"] or [], steps=row["steps"] or [], @@ -105,6 +108,7 @@ def update_recipe(recipe_id: int, recipe_in: RecipeUpdate): name=row["name"], meal_type=row["meal_type"], time_minutes=row["time_minutes"], + made_by=row.get("made_by"), tags=row["tags"] or [], ingredients=row["ingredients"] or [], steps=row["steps"] or [], @@ -137,6 +141,7 @@ def random_recipe( name=r["name"], meal_type=r["meal_type"], time_minutes=r["time_minutes"], + made_by=r.get("made_by"), tags=r["tags"] or [], ingredients=r["ingredients"] or [], steps=r["steps"] or [], diff --git a/backend/schema.sql b/backend/schema.sql index 905d5c4..aa7547c 100644 --- a/backend/schema.sql +++ b/backend/schema.sql @@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS recipes ( name TEXT NOT NULL, meal_type TEXT NOT NULL, -- breakfast / lunch / dinner / snack time_minutes INTEGER NOT NULL, - + made_by TEXT, -- Person who created this recipe version tags JSONB NOT NULL DEFAULT '[]', -- ["מהיר", "בריא"] ingredients JSONB NOT NULL DEFAULT '[]', -- ["ביצה", "עגבניה", "מלח"] steps JSONB NOT NULL DEFAULT '[]', -- ["לחתוך", "לבשל", ...] @@ -18,8 +18,12 @@ CREATE INDEX IF NOT EXISTS idx_recipes_meal_type CREATE INDEX IF NOT EXISTS idx_recipes_time_minutes ON recipes (time_minutes); +CREATE INDEX IF NOT EXISTS idx_recipes_made_by + ON recipes (made_by); + CREATE INDEX IF NOT EXISTS idx_recipes_tags_jsonb ON recipes USING GIN (tags); CREATE INDEX IF NOT EXISTS idx_recipes_ingredients_jsonb ON recipes USING GIN (ingredients); + diff --git a/frontend/src/App.css b/frontend/src/App.css index 6af280a..8f706a8 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -314,6 +314,13 @@ select { color: var(--text-muted); } +.recipe-made-by { + margin: 0.3rem 0 0; + font-size: 0.8rem; + color: var(--accent); + font-weight: 500; +} + .pill-row { display: flex; flex-wrap: wrap; diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 10e6a3b..5d61159 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -19,6 +19,7 @@ function App() { const [filterMealType, setFilterMealType] = useState(""); const [filterMaxTime, setFilterMaxTime] = useState(""); const [filterTags, setFilterTags] = useState([]); + const [filterMadeBy, setFilterMadeBy] = useState(""); // Random recipe filters const [mealTypeFilter, setMealTypeFilter] = useState(""); @@ -95,6 +96,11 @@ function App() { } } + // Filter by made_by + if (filterMadeBy && (!recipe.made_by || recipe.made_by !== filterMadeBy)) { + return false; + } + return true; }); }; @@ -222,6 +228,8 @@ function App() { onMaxTimeChange={setFilterMaxTime} filterTags={filterTags} onTagsChange={setFilterTags} + filterMadeBy={filterMadeBy} + onMadeByChange={setFilterMadeBy} /> diff --git a/frontend/src/components/RecipeDetails.jsx b/frontend/src/components/RecipeDetails.jsx index 5c0d00e..402a58d 100644 --- a/frontend/src/components/RecipeDetails.jsx +++ b/frontend/src/components/RecipeDetails.jsx @@ -26,6 +26,9 @@ function RecipeDetails({ recipe, onEditClick, onDeleteClick, onShowDeleteModal }
{translateMealType(recipe.meal_type)} · {recipe.time_minutes} דקות הכנה
+ {recipe.made_by && ( +