Add small pic to recipes and update the scehma.sql
This commit is contained in:
parent
984e10682b
commit
02e4a5d7fa
Binary file not shown.
Binary file not shown.
@ -55,7 +55,7 @@ def list_recipes_db() -> List[Dict[str, Any]]:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, name, meal_type, time_minutes,
|
||||
tags, ingredients, steps
|
||||
tags, ingredients, steps, image
|
||||
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
|
||||
recipe_data: name, meal_type, time_minutes, tags, ingredients, steps, image
|
||||
"""
|
||||
conn = get_conn()
|
||||
try:
|
||||
@ -81,9 +81,10 @@ def update_recipe_db(recipe_id: int, recipe_data: Dict[str, Any]) -> Optional[Di
|
||||
time_minutes = %s,
|
||||
tags = %s,
|
||||
ingredients = %s,
|
||||
steps = %s
|
||||
steps = %s,
|
||||
image = %s
|
||||
WHERE id = %s
|
||||
RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps
|
||||
RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps, image
|
||||
""",
|
||||
(
|
||||
recipe_data["name"],
|
||||
@ -92,6 +93,7 @@ def update_recipe_db(recipe_id: int, recipe_data: Dict[str, Any]) -> Optional[Di
|
||||
json.dumps(recipe_data.get("tags", [])),
|
||||
json.dumps(recipe_data.get("ingredients", [])),
|
||||
json.dumps(recipe_data.get("steps", [])),
|
||||
recipe_data.get("image"),
|
||||
recipe_id,
|
||||
),
|
||||
)
|
||||
@ -129,9 +131,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)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
RETURNING id, name, meal_type, time_minutes, tags, ingredients, steps
|
||||
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
|
||||
""",
|
||||
(
|
||||
recipe_data["name"],
|
||||
@ -140,6 +142,7 @@ def create_recipe_db(recipe_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
json.dumps(recipe_data.get("tags", [])),
|
||||
json.dumps(recipe_data.get("ingredients", [])),
|
||||
json.dumps(recipe_data.get("steps", [])),
|
||||
recipe_data.get("image"),
|
||||
),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
|
||||
@ -24,6 +24,7 @@ class RecipeBase(BaseModel):
|
||||
tags: List[str] = []
|
||||
ingredients: List[str] = []
|
||||
steps: List[str] = []
|
||||
image: Optional[str] = None # Base64-encoded image or image URL
|
||||
|
||||
|
||||
class RecipeCreate(RecipeBase):
|
||||
@ -65,6 +66,7 @@ def list_recipes():
|
||||
tags=r["tags"] or [],
|
||||
ingredients=r["ingredients"] or [],
|
||||
steps=r["steps"] or [],
|
||||
image=r.get("image"),
|
||||
)
|
||||
for r in rows
|
||||
]
|
||||
@ -86,6 +88,7 @@ def create_recipe(recipe_in: RecipeCreate):
|
||||
tags=row["tags"] or [],
|
||||
ingredients=row["ingredients"] or [],
|
||||
steps=row["steps"] or [],
|
||||
image=row.get("image"),
|
||||
)
|
||||
|
||||
@app.put("/recipes/{recipe_id}", response_model=Recipe)
|
||||
@ -105,6 +108,7 @@ def update_recipe(recipe_id: int, recipe_in: RecipeUpdate):
|
||||
tags=row["tags"] or [],
|
||||
ingredients=row["ingredients"] or [],
|
||||
steps=row["steps"] or [],
|
||||
image=row.get("image"),
|
||||
)
|
||||
|
||||
|
||||
@ -136,6 +140,7 @@ def random_recipe(
|
||||
tags=r["tags"] or [],
|
||||
ingredients=r["ingredients"] or [],
|
||||
steps=r["steps"] or [],
|
||||
image=r.get("image"),
|
||||
)
|
||||
for r in rows
|
||||
]
|
||||
|
||||
@ -7,7 +7,8 @@ CREATE TABLE IF NOT EXISTS recipes (
|
||||
|
||||
tags JSONB NOT NULL DEFAULT '[]', -- ["מהיר", "בריא"]
|
||||
ingredients JSONB NOT NULL DEFAULT '[]', -- ["ביצה", "עגבניה", "מלח"]
|
||||
steps JSONB NOT NULL DEFAULT '[]' -- ["לחתוך", "לבשל", ...]
|
||||
steps JSONB NOT NULL DEFAULT '[]', -- ["לחתוך", "לבשל", ...]
|
||||
image TEXT -- Base64-encoded image or image URL
|
||||
);
|
||||
|
||||
-- Optional: index for filters
|
||||
|
||||
25
frontend/src/assets/placeholder.svg
Normal file
25
frontend/src/assets/placeholder.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Background -->
|
||||
<rect width="200" height="200" fill="#e0e0e0"/>
|
||||
|
||||
<!-- Food plate icon -->
|
||||
<circle cx="100" cy="100" r="70" fill="#c0c0c0" stroke="#999" stroke-width="2"/>
|
||||
|
||||
<!-- Fork -->
|
||||
<g transform="translate(60, 80)">
|
||||
<line x1="0" y1="0" x2="0" y2="35" stroke="#666" stroke-width="2" stroke-linecap="round"/>
|
||||
<line x1="-8" y1="5" x2="-8" y2="35" stroke="#666" stroke-width="2" stroke-linecap="round"/>
|
||||
<line x1="8" y1="5" x2="8" y2="35" stroke="#666" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="0" cy="0" r="3" fill="#666"/>
|
||||
</g>
|
||||
|
||||
<!-- Knife -->
|
||||
<g transform="translate(130, 80)">
|
||||
<line x1="0" y1="0" x2="0" y2="35" stroke="#666" stroke-width="2" stroke-linecap="round"/>
|
||||
<polygon points="0,0 -6,8 6,8" fill="#666"/>
|
||||
<circle cx="0" cy="2" r="3" fill="#999"/>
|
||||
</g>
|
||||
|
||||
<!-- "No Image" text -->
|
||||
<text x="100" y="155" font-family="Arial, sans-serif" font-size="14" fill="#666" text-anchor="middle" font-weight="bold">No Image</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@ -1,3 +1,5 @@
|
||||
import placeholderImage from "../assets/placeholder.svg";
|
||||
|
||||
function RecipeDetails({ recipe, onEditClick, onDeleteClick, onShowDeleteModal }) {
|
||||
if (!recipe) {
|
||||
return (
|
||||
@ -14,11 +16,9 @@ function RecipeDetails({ recipe, onEditClick, onDeleteClick, onShowDeleteModal }
|
||||
return (
|
||||
<section className="panel recipe-card">
|
||||
{/* Recipe Image */}
|
||||
{recipe.image && (
|
||||
<div className="recipe-image-container">
|
||||
<img src={recipe.image} alt={recipe.name} className="recipe-image" />
|
||||
<img src={recipe.image || placeholderImage} alt={recipe.name} className="recipe-image" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<header className="recipe-header">
|
||||
<div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import placeholderImage from "../assets/placeholder.svg";
|
||||
|
||||
function RecipeSearchList({
|
||||
allRecipes,
|
||||
@ -181,11 +182,9 @@ function RecipeSearchList({
|
||||
}
|
||||
onClick={() => onSelect(r)}
|
||||
>
|
||||
{r.image && (
|
||||
<div className="recipe-list-image">
|
||||
<img src={r.image} alt={r.name} />
|
||||
<img src={r.image || placeholderImage} alt={r.name} />
|
||||
</div>
|
||||
)}
|
||||
<div className="recipe-list-main">
|
||||
<div className="recipe-list-name">{r.name}</div>
|
||||
<div className="recipe-list-meta">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user