feat: add Navigation component and update layout for Items and Tags pages
This commit is contained in:
parent
797d1de350
commit
71af5b911c
4 changed files with 74 additions and 40 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { BrowserRouter as Router, Routes, Route, Link, Navigate, useNavigate } from "react-router-dom";
|
||||
import { BrowserRouter as Router, Routes, Route, Link, useLocation, Navigate, useNavigate } from "react-router-dom";
|
||||
import { getSeed, getTrips, getNextTripId } from "./api";
|
||||
import ItemsPage from "./pages/ItemsPage";
|
||||
import TripChecklist from "./pages/TripChecklist";
|
||||
|
|
@ -21,6 +21,74 @@ function NextTripRedirect({ trips }: { trips: any[] }) {
|
|||
return <Navigate to={`/trips/${nextTripId}`} replace />;
|
||||
}
|
||||
|
||||
function Navigation() {
|
||||
const location = useLocation();
|
||||
const navItems = [
|
||||
{ to: "/trips", label: "Trips" },
|
||||
{ to: "/items", label: "Items" },
|
||||
{ to: "/tags", label: "Tags" },
|
||||
];
|
||||
|
||||
// Navigation für den Titel-Link
|
||||
const navigate = useNavigate();
|
||||
async function goToCurrentTrip() {
|
||||
try {
|
||||
const id = await getNextTripId();
|
||||
navigate(`/trips/${id}`);
|
||||
} catch {
|
||||
alert("Kein anstehender Trip gefunden");
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe, ob ein einzelner Trip angezeigt wird
|
||||
const isTripDetail = /^\/trips\/[^/]+$/.test(location.pathname);
|
||||
|
||||
return (
|
||||
<nav className="mb-8 flex items-center gap-4 bg-white/80 backdrop-blur border-b border-gray-200 px-2 py-2 rounded-xl shadow-sm">
|
||||
<button
|
||||
className="text-2xl font-extrabold text-blue-700 tracking-tight mr-4 select-none hover:underline bg-transparent p-0"
|
||||
style={{ background: "none", border: "none" }}
|
||||
onClick={goToCurrentTrip}
|
||||
title="Zum aktuellen Trip"
|
||||
>
|
||||
Packliste
|
||||
</button>
|
||||
{navItems.map((item) => {
|
||||
// Trips ist NICHT aktiv, wenn ein einzelner Trip angezeigt wird
|
||||
const isActive =
|
||||
!isTripDetail && location.pathname.startsWith(item.to);
|
||||
return (
|
||||
<Link
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
className={
|
||||
"px-4 py-2 rounded font-medium transition " +
|
||||
(isActive
|
||||
? "bg-blue-600 text-white shadow"
|
||||
: "text-blue-700 hover:bg-blue-100 hover:text-blue-900")
|
||||
}
|
||||
style={{
|
||||
boxShadow: isActive ? "0 2px 8px 0 rgba(37,99,235,0.08)" : undefined,
|
||||
border: isActive ? "2px solid #2563eb" : undefined,
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
<button
|
||||
className="ml-auto bg-gray-100 text-gray-700 px-4 py-2 rounded hover:bg-gray-200 transition"
|
||||
onClick={async () => {
|
||||
await getSeed();
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
Seed-Daten erzeugen
|
||||
</button>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const [trips, setTrips] = useState<any[]>([]);
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -45,41 +113,7 @@ export default function App() {
|
|||
|
||||
return (
|
||||
<div className="p-4 max-w-5xl mx-auto">
|
||||
<h1 className="text-2xl font-bold mb-4">Packlist</h1>
|
||||
|
||||
<div className="flex gap-2 mb-4">
|
||||
<button
|
||||
className="bg-yellow-500 text-white px-4 py-2 rounded"
|
||||
onClick={goToCurrentTrip}
|
||||
>
|
||||
Zum aktuellen Trip
|
||||
</button>
|
||||
<Link to="/trips">
|
||||
<button className="bg-blue-500 text-white px-4 py-2 rounded">
|
||||
Trips
|
||||
</button>
|
||||
</Link>
|
||||
<Link to="/items">
|
||||
<button className="bg-green-500 text-white px-4 py-2 rounded">
|
||||
Items
|
||||
</button>
|
||||
</Link>
|
||||
<Link to="/tags">
|
||||
<button className="bg-purple-500 text-white px-4 py-2 rounded">
|
||||
Tags
|
||||
</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>
|
||||
|
||||
<Navigation />
|
||||
<Routes>
|
||||
<Route path="/trips" element={<TripsPage />} />
|
||||
<Route path="/trips/:id" element={<TripChecklist trips={trips} />} />
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export default function ItemsPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="p-4 max-w-3xl mx-auto">
|
||||
<div className="p-2">
|
||||
<h1 className="text-2xl font-bold mb-4">Items</h1>
|
||||
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export default function TagsPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="p-4 max-w-xl mx-auto">
|
||||
<div className="p-2">
|
||||
<h1 className="text-2xl font-bold mb-4">Alle Tags</h1>
|
||||
<form className="flex gap-2 mb-6" onSubmit={handleCreate}>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ export default function TripsPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Packlist</h1>
|
||||
<div className="p-2">
|
||||
<h1 className="text-2xl font-bold mb-4">Trips</h1>
|
||||
<button
|
||||
className="mb-4 bg-blue-500 text-white px-4 py-2 rounded"
|
||||
onClick={() => setShowForm((v) => !v)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue