feat: implement TripChecklist component and update trips route for detailed view

This commit is contained in:
Felix Zett 2025-08-30 20:56:48 +02:00
parent e79d3a2b87
commit 3186a9d549
2 changed files with 59 additions and 44 deletions

View file

@ -1,22 +1,17 @@
import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Routes, Route, Link, Navigate } from "react-router-dom";
import { BrowserRouter as Router, Routes, Route, Link, Navigate, useParams } from "react-router-dom";
import { getSeed, getTrips, getTripItems, toggleTripItem } from "./api";
import ItemsPage from "./pages/ItemsPage";
import TripChecklist from "./pages/TripChecklist";
export default function App() {
const [trips, setTrips] = useState<any[]>([]);
const [items, setItems] = useState<Record<string, any[]>>({});
async function loadTrips() {
const data = await getTrips();
setTrips(data);
}
async function loadItems(tripId: string) {
const data = await getTripItems(tripId);
setItems((prev) => ({ ...prev, [tripId]: data }));
}
useEffect(() => {
loadTrips();
}, []);
@ -52,47 +47,25 @@ export default function App() {
<Route
path="/trips"
element={
<>
<ul>
{trips.map((trip) => (
<div key={trip.id} className="border rounded p-2 mb-4">
<div className="flex justify-between items-center">
<div>
<h2 className="font-bold">{trip.name}</h2>
<p>
{trip.start_date} {trip.end_date}
</p>
</div>
<button
className="text-sm text-blue-500 underline"
onClick={() => loadItems(trip.id)}
>
Packliste anzeigen
</button>
</div>
{items[trip.id] && (
<ul className="mt-2">
{items[trip.id].map((item) => (
<li key={item.id} className="flex items-center gap-2">
<input
type="checkbox"
checked={item.checked}
onChange={async () => {
await toggleTripItem(item.id);
await loadItems(trip.id);
}}
/>
<span>{item.name_calculated}</span>
</li>
))}
</ul>
)}
</div>
<li key={trip.id} className="mb-2">
<Link
to={`/trips/${trip.id}`}
className="text-blue-600 underline"
>
{trip.name} <span className="text-gray-500">({trip.start_date} {trip.end_date})</span>
</Link>
</li>
))}
</>
</ul>
}
/>
<Route
path="/trips/:id"
element={<TripChecklist trips={trips} />}
/>
<Route path="/items" element={<ItemsPage />} />
{/* Optional: Redirect / to /trips */}
<Route path="/" element={<Navigate to="/trips" />} />
</Routes>
</div>

View file

@ -0,0 +1,42 @@
// filepath: frontend/src/pages/TripChecklist.tsx
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { getTripItems, toggleTripItem } from "../api";
export default function TripChecklist({ trips }: { trips: any[] }) {
const { id } = useParams();
const [items, setItems] = useState<any[]>([]);
useEffect(() => {
if (id) {
getTripItems(id).then(setItems);
}
}, [id]);
const trip = trips.find((t) => t.id === id);
if (!trip) return <div>Trip not found</div>;
return (
<div>
<h2 className="font-bold text-xl mb-2">{trip.name}</h2>
<p className="mb-4">{trip.start_date} {trip.end_date}</p>
<ul>
{items.map((item) => (
<li key={item.id} className="flex items-center gap-2">
<input
type="checkbox"
checked={item.checked}
onChange={async () => {
await toggleTripItem(item.id);
const updated = await getTripItems(id!);
setItems(updated);
}}
/>
<span>{item.name_calculated}</span>
</li>
))}
</ul>
</div>
);
}