From d385e4017125b1b20bd1b6e43916b160bbd1d360 Mon Sep 17 00:00:00 2001 From: Felix Zett Date: Sun, 31 Aug 2025 19:21:38 +0200 Subject: [PATCH] feat: enhance TripChecklist to load and display items with associated tags and group items by marked tags --- backend/routes/trip_items.py | 6 +- backend/schemas.py | 2 +- frontend/src/pages/TripChecklist.tsx | 103 ++++++++++++++++++++++++++- 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/backend/routes/trip_items.py b/backend/routes/trip_items.py index 66a7a76..e884bfc 100644 --- a/backend/routes/trip_items.py +++ b/backend/routes/trip_items.py @@ -15,7 +15,10 @@ def list_trip_items(trip_id: UUID, db: Session = Depends(get_db)): raise HTTPException(status_code=404, detail="Trip not found") items = ( db.query(models.TripItem) - .options(joinedload(models.TripItem.tag)) + .options( + joinedload(models.TripItem.tag), + joinedload(models.TripItem.item).joinedload(models.Item.tags), # <--- Item mit Tags laden + ) .filter(models.TripItem.trip_id == trip_id) .order_by( func.regexp_replace( @@ -34,6 +37,7 @@ def list_trip_items(trip_id: UUID, db: Session = Depends(get_db)): name_calculated=ti.name_calculated, checked=ti.checked, tag=ti.tag, + item=ti.item, ) for ti in items ] diff --git a/backend/schemas.py b/backend/schemas.py index 0ff39c1..16f5130 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -1,4 +1,3 @@ - from typing import List, Optional from uuid import UUID from datetime import date @@ -60,6 +59,7 @@ class TripItemOut(BaseModel): name_calculated: str checked: bool tag: Optional[TagOut] = None + item: Optional[ItemOut] = None class Config: orm_mode = True diff --git a/frontend/src/pages/TripChecklist.tsx b/frontend/src/pages/TripChecklist.tsx index 1fa29b7..694a3ec 100644 --- a/frontend/src/pages/TripChecklist.tsx +++ b/frontend/src/pages/TripChecklist.tsx @@ -41,6 +41,11 @@ export default function TripChecklist({ trips }: { trips: any[] }) { marked_tag_ids: newMarked.map((t) => t.id), }); setMarkedTags(newMarked); + // Items neu laden + if (id) { + const updated = await getTripItems(id); + setItems(updated); + } } async function handleRemoveTag(tagId: string) { @@ -55,6 +60,11 @@ export default function TripChecklist({ trips }: { trips: any[] }) { }); setSelectedTags(newSelected); setMarkedTags(newMarked); + // Items neu laden + if (id) { + const updated = await getTripItems(id); + setItems(updated); + } } async function handleAddTag(tagId: string) { @@ -70,10 +80,34 @@ export default function TripChecklist({ trips }: { trips: any[] }) { }); setSelectedTags(newSelected); setTagInput(""); + // Items neu laden + if (id) { + const updated = await getTripItems(id); + setItems(updated); + } } if (!trip) return
Trip not found
; + // Gruppiere Items nach Kategorie (item.tag) + const itemsWithoutTag = items.filter((item) => !item.tag); + // Map: tagId -> { tag, items: [...] } + const itemsByTag: Record = {}; + items + .filter((item) => item.tag) + .forEach((item) => { + const tagId = item.tag.id; + if (!itemsByTag[tagId]) { + itemsByTag[tagId] = { tag: item.tag, items: [] }; + } + itemsByTag[tagId].items.push(item); + }); + + // Sortiere Kategorien alphabetisch nach Tag-Name + const sortedTagGroups = Object.values(itemsByTag).sort((a, b) => + a.tag.name.localeCompare(b.tag.name) + ); + return (
{/* Tag-Liste */} @@ -155,7 +189,8 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
{/* ...Rest der Checklist... */} );