Files
WearPartTracker/app/components/BikeDetail.tsx
Denis Urs Rudolph de193bc783 Initial commit: Fahrrad Verschleißteile Tracker
- Next.js SPA mit Bun Runtime
- Prisma mit SQLite Datenbank
- Vollständige CRUD-Operationen für Fahrräder, Verschleißteile und Wartungshistorie
- Warnsystem für bevorstehende Wartungen
- Statistik-Features (Gesamtkosten, durchschnittliche Lebensdauer)
- Zod-Validierung für alle API-Requests
- Umfassende Test-Suite (41 Tests)
2025-12-05 22:17:50 +01:00

90 lines
2.7 KiB
TypeScript

'use client'
import { BikeWithParts } from '@/types'
import { useState } from 'react'
import Link from 'next/link'
import WearPartList from './WearPartList'
import WearPartForm from './WearPartForm'
interface BikeDetailProps {
bike: BikeWithParts
onUpdate: () => void
}
export default function BikeDetail({ bike, onUpdate }: BikeDetailProps) {
const [showPartForm, setShowPartForm] = useState(false)
return (
<main className="min-h-screen p-8 bg-gray-50">
<div className="max-w-7xl mx-auto">
<Link
href="/"
className="inline-flex items-center text-blue-600 hover:text-blue-800 mb-6"
>
Zurück zur Übersicht
</Link>
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h1 className="text-3xl font-bold text-gray-900 mb-4">{bike.name}</h1>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
{bike.brand && (
<div>
<span className="text-gray-500">Marke:</span>
<p className="font-medium">{bike.brand}</p>
</div>
)}
{bike.model && (
<div>
<span className="text-gray-500">Modell:</span>
<p className="font-medium">{bike.model}</p>
</div>
)}
{bike.purchaseDate && (
<div>
<span className="text-gray-500">Kaufdatum:</span>
<p className="font-medium">
{new Date(bike.purchaseDate).toLocaleDateString('de-DE')}
</p>
</div>
)}
</div>
{bike.notes && (
<div className="mt-4">
<span className="text-gray-500">Notizen:</span>
<p className="mt-1">{bike.notes}</p>
</div>
)}
</div>
<div className="mb-6 flex justify-between items-center">
<h2 className="text-2xl font-semibold text-gray-900">
Verschleißteile
</h2>
<button
onClick={() => setShowPartForm(!showPartForm)}
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
{showPartForm ? 'Abbrechen' : '+ Neues Verschleißteil'}
</button>
</div>
{showPartForm && (
<div className="mb-6">
<WearPartForm
bikeId={bike.id}
onSuccess={() => {
setShowPartForm(false)
onUpdate()
}}
onCancel={() => setShowPartForm(false)}
/>
</div>
)}
<WearPartList bikeId={bike.id} parts={bike.wearParts} onUpdate={onUpdate} />
</div>
</main>
)
}