diff --git a/backend/__pycache__/db_utils.cpython-313.pyc b/backend/__pycache__/db_utils.cpython-313.pyc index 5cdd7f3..e224238 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 be7bf31..ad86ee8 100644 Binary files a/backend/__pycache__/main.cpython-313.pyc and b/backend/__pycache__/main.cpython-313.pyc differ diff --git a/backend/__pycache__/user_db_utils.cpython-313.pyc b/backend/__pycache__/user_db_utils.cpython-313.pyc index c500bba..89b66ff 100644 Binary files a/backend/__pycache__/user_db_utils.cpython-313.pyc and b/backend/__pycache__/user_db_utils.cpython-313.pyc differ diff --git a/backend/db_utils.py b/backend/db_utils.py index a8f6141..f2c1881 100644 --- a/backend/db_utils.py +++ b/backend/db_utils.py @@ -54,10 +54,12 @@ def list_recipes_db() -> List[Dict[str, Any]]: with conn.cursor() as cur: cur.execute( """ - SELECT id, name, meal_type, time_minutes, - tags, ingredients, steps, image, made_by, user_id - FROM recipes - ORDER BY id + SELECT r.id, r.name, r.meal_type, r.time_minutes, + r.tags, r.ingredients, r.steps, r.image, r.made_by, r.user_id, + u.display_name as owner_display_name + FROM recipes r + LEFT JOIN users u ON r.user_id = u.id + ORDER BY r.id """ ) rows = cur.fetchall() @@ -163,19 +165,21 @@ def get_recipes_by_filters_db( conn = get_conn() try: query = """ - SELECT id, name, meal_type, time_minutes, - tags, ingredients, steps, image, made_by, user_id - FROM recipes + SELECT r.id, r.name, r.meal_type, r.time_minutes, + r.tags, r.ingredients, r.steps, r.image, r.made_by, r.user_id, + u.display_name as owner_display_name + FROM recipes r + LEFT JOIN users u ON r.user_id = u.id WHERE 1=1 """ params: List = [] if meal_type: - query += " AND meal_type = %s" + query += " AND r.meal_type = %s" params.append(meal_type.lower()) if max_time: - query += " AND time_minutes <= %s" + query += " AND r.time_minutes <= %s" params.append(max_time) with conn.cursor() as cur: diff --git a/backend/main.py b/backend/main.py index a52d7db..ae87be5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -51,6 +51,7 @@ class RecipeCreate(RecipeBase): class Recipe(RecipeBase): id: int user_id: Optional[int] = None # Recipe owner ID + owner_display_name: Optional[str] = None # Owner's display name for filtering class RecipeUpdate(RecipeBase): @@ -132,6 +133,7 @@ def list_recipes(): steps=r["steps"] or [], image=r.get("image"), user_id=r.get("user_id"), + owner_display_name=r.get("owner_display_name"), ) for r in rows ] @@ -157,6 +159,7 @@ def create_recipe(recipe_in: RecipeCreate, current_user: dict = Depends(get_curr steps=row["steps"] or [], image=row.get("image"), user_id=row.get("user_id"), + owner_display_name=current_user.get("display_name"), ) @app.put("/recipes/{recipe_id}", response_model=Recipe) @@ -192,6 +195,7 @@ def update_recipe(recipe_id: int, recipe_in: RecipeUpdate, current_user: dict = steps=row["steps"] or [], image=row.get("image"), user_id=row.get("user_id"), + owner_display_name=current_user.get("display_name"), ) @@ -239,6 +243,7 @@ def random_recipe( steps=r["steps"] or [], image=r.get("image"), user_id=r.get("user_id"), + owner_display_name=r.get("owner_display_name"), ) for r in rows ] @@ -288,6 +293,17 @@ def register(user: UserRegister): detail="האימייל כבר רשום במערכת" ) + # Check if display_name already exists + print(f"[REGISTER] Checking if display_name exists...") + from user_db_utils import get_user_by_display_name + existing_display_name = get_user_by_display_name(user.display_name) + if existing_display_name: + print(f"[REGISTER] Display name already exists") + raise HTTPException( + status_code=400, + detail="שם התצוגה כבר קיים במערכת" + ) + # Hash password and create user print(f"[REGISTER] Hashing password...") password_hash = hash_password(user.password) diff --git a/backend/schema.sql b/backend/schema.sql index 88bfd34..78b2138 100644 --- a/backend/schema.sql +++ b/backend/schema.sql @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS users ( password_hash TEXT NOT NULL, first_name TEXT, last_name TEXT, - display_name TEXT NOT NULL, + display_name TEXT UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); diff --git a/backend/user_db_utils.py b/backend/user_db_utils.py index 264da28..0b4be44 100644 --- a/backend/user_db_utils.py +++ b/backend/user_db_utils.py @@ -84,3 +84,19 @@ def get_user_by_id(user_id: int): finally: cur.close() conn.close() + + +def get_user_by_display_name(display_name: str): + """Get user by display name""" + conn = get_db_connection() + cur = conn.cursor(cursor_factory=RealDictCursor) + try: + cur.execute( + "SELECT id, username, email, display_name, created_at FROM users WHERE display_name = %s", + (display_name,) + ) + user = cur.fetchone() + return dict(user) if user else None + finally: + cur.close() + conn.close() diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 467216d..0b573d7 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -27,7 +27,7 @@ function App() { const [filterMealType, setFilterMealType] = useState(""); const [filterMaxTime, setFilterMaxTime] = useState(""); const [filterTags, setFilterTags] = useState([]); - const [filterMadeBy, setFilterMadeBy] = useState(""); + const [filterOwner, setFilterOwner] = useState(""); // Random recipe filters const [mealTypeFilter, setMealTypeFilter] = useState(""); @@ -126,8 +126,8 @@ function App() { } } - // Filter by made_by - if (filterMadeBy && (!recipe.made_by || recipe.made_by !== filterMadeBy)) { + // Filter by made_by (username) + if (filterOwner && (!recipe.made_by || recipe.made_by !== filterOwner)) { return false; } @@ -343,8 +343,8 @@ function App() { onMaxTimeChange={setFilterMaxTime} filterTags={filterTags} onTagsChange={setFilterTags} - filterMadeBy={filterMadeBy} - onMadeByChange={setFilterMadeBy} + filterOwner={filterOwner} + onOwnerChange={setFilterOwner} /> diff --git a/frontend/src/components/RecipeDetails.jsx b/frontend/src/components/RecipeDetails.jsx index 4df5323..c23dced 100644 --- a/frontend/src/components/RecipeDetails.jsx +++ b/frontend/src/components/RecipeDetails.jsx @@ -35,8 +35,8 @@ function RecipeDetails({ recipe, onEditClick, onDeleteClick, onShowDeleteModal,
{translateMealType(recipe.meal_type)} · {recipe.time_minutes} דקות הכנה
- {recipe.made_by && ( -