feat: implement TripChecklist component and update trips route for detailed view
This commit is contained in:
parent
e79d3a2b87
commit
3186a9d549
2 changed files with 59 additions and 44 deletions
|
|
@ -1,22 +1,17 @@
|
||||||
import React, { useState, useEffect } from "react";
|
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 { getSeed, getTrips, getTripItems, toggleTripItem } from "./api";
|
||||||
import ItemsPage from "./pages/ItemsPage";
|
import ItemsPage from "./pages/ItemsPage";
|
||||||
|
import TripChecklist from "./pages/TripChecklist";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [trips, setTrips] = useState<any[]>([]);
|
const [trips, setTrips] = useState<any[]>([]);
|
||||||
const [items, setItems] = useState<Record<string, any[]>>({});
|
|
||||||
|
|
||||||
async function loadTrips() {
|
async function loadTrips() {
|
||||||
const data = await getTrips();
|
const data = await getTrips();
|
||||||
setTrips(data);
|
setTrips(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadItems(tripId: string) {
|
|
||||||
const data = await getTripItems(tripId);
|
|
||||||
setItems((prev) => ({ ...prev, [tripId]: data }));
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadTrips();
|
loadTrips();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -52,47 +47,25 @@ export default function App() {
|
||||||
<Route
|
<Route
|
||||||
path="/trips"
|
path="/trips"
|
||||||
element={
|
element={
|
||||||
<>
|
<ul>
|
||||||
{trips.map((trip) => (
|
{trips.map((trip) => (
|
||||||
<div key={trip.id} className="border rounded p-2 mb-4">
|
<li key={trip.id} className="mb-2">
|
||||||
<div className="flex justify-between items-center">
|
<Link
|
||||||
<div>
|
to={`/trips/${trip.id}`}
|
||||||
<h2 className="font-bold">{trip.name}</h2>
|
className="text-blue-600 underline"
|
||||||
<p>
|
|
||||||
{trip.start_date} – {trip.end_date}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
className="text-sm text-blue-500 underline"
|
|
||||||
onClick={() => loadItems(trip.id)}
|
|
||||||
>
|
>
|
||||||
Packliste anzeigen
|
{trip.name} <span className="text-gray-500">({trip.start_date} – {trip.end_date})</span>
|
||||||
</button>
|
</Link>
|
||||||
</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>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/trips/:id"
|
||||||
|
element={<TripChecklist trips={trips} />}
|
||||||
|
/>
|
||||||
<Route path="/items" element={<ItemsPage />} />
|
<Route path="/items" element={<ItemsPage />} />
|
||||||
{/* Optional: Redirect / to /trips */}
|
|
||||||
<Route path="/" element={<Navigate to="/trips" />} />
|
<Route path="/" element={<Navigate to="/trips" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
42
frontend/src/pages/TripChecklist.tsx
Normal file
42
frontend/src/pages/TripChecklist.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue