101 lines
3.3 KiB
TypeScript
101 lines
3.3 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
||
import { BrowserRouter as Router, Routes, Route, Link, Navigate } from "react-router-dom";
|
||
import { getSeed, getTrips, getTripItems, toggleTripItem } from "./api";
|
||
import ItemsPage from "./pages/ItemsPage";
|
||
|
||
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();
|
||
}, []);
|
||
|
||
return (
|
||
<Router>
|
||
<div className="p-4 max-w-2xl mx-auto">
|
||
<h1 className="text-2xl font-bold mb-4">Packlist</h1>
|
||
|
||
<div className="flex gap-2 mb-4">
|
||
<Link to="/trips">
|
||
<button className="bg-blue-500 text-white px-4 py-2 rounded">
|
||
Alle Trips
|
||
</button>
|
||
</Link>
|
||
<Link to="/items">
|
||
<button className="bg-green-500 text-white px-4 py-2 rounded">
|
||
Alle Items
|
||
</button>
|
||
</Link>
|
||
<button
|
||
className="bg-gray-300 text-gray-800 px-4 py-2 rounded"
|
||
onClick={async () => {
|
||
await getSeed();
|
||
await loadTrips();
|
||
}}
|
||
>
|
||
Seed-Daten erzeugen
|
||
</button>
|
||
</div>
|
||
|
||
<Routes>
|
||
<Route
|
||
path="/trips"
|
||
element={
|
||
<>
|
||
{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>
|
||
))}
|
||
</>
|
||
}
|
||
/>
|
||
<Route path="/items" element={<ItemsPage />} />
|
||
{/* Optional: Redirect / to /trips */}
|
||
<Route path="/" element={<Navigate to="/trips" />} />
|
||
</Routes>
|
||
</div>
|
||
</Router>
|
||
);
|
||
}
|