import { useState } from 'react' import { createFileRoute, Link, redirect, useRouter } from '@tanstack/react-router' import { getCurrentStaffUser } from '#/lib/auth' import { authClient } from '#/lib/auth-client' import { formatDateTimeLocal } from '#/lib/datetime' import { createReservation, deleteReservation, getReservations, getTables, updateReservation, } from '#/lib/reservations' export const Route = createFileRoute('/staff/')({ component: StaffDashboard, beforeLoad: async () => { const staffUser = await getCurrentStaffUser() if (!staffUser) { throw redirect({ to: '/staff/login' }) } return { staffUser } }, loader: async ({ context }) => { const [reservations, tables] = await Promise.all([getReservations(), getTables()]) return { staffUser: context.staffUser, reservations, tables } }, }) const dateTimeFormatter = new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium', timeStyle: 'short', }) function isSameDay(a: Date, b: Date) { return ( a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() ) } type ReservationRow = Awaited>[number] type FormState = { tableId: number | string customerName: string customerEmail: string partySize: number reservationTime: string } function emptyForm(defaultTableId: number | string): FormState { return { tableId: defaultTableId, customerName: '', customerEmail: '', partySize: 2, reservationTime: formatDateTimeLocal(new Date(Date.now() + 60 * 60 * 1000)), } } function StaffDashboard() { const router = useRouter() const { staffUser, reservations, tables } = Route.useLoaderData() const [editingId, setEditingId] = useState(null) const [form, setForm] = useState(() => emptyForm(tables[0]?.id ?? '')) const [error, setError] = useState(null) const [success, setSuccess] = useState(null) const [isSubmitting, setIsSubmitting] = useState(false) const [deletingId, setDeletingId] = useState(null) const now = new Date() const todaysReservations = reservations.filter((r) => isSameDay(new Date(r.reservationTime), now)) const guestsToday = todaysReservations.reduce((sum, r) => sum + r.partySize, 0) const upcoming = reservations.filter((r) => new Date(r.reservationTime).getTime() >= now.getTime()) function startEdit(reservation: ReservationRow) { setEditingId(reservation.id) setForm({ tableId: reservation.tableId, customerName: reservation.customerName, customerEmail: reservation.customerEmail, partySize: reservation.partySize, reservationTime: formatDateTimeLocal(new Date(reservation.reservationTime)), }) setError(null) setSuccess(null) } function cancelEdit() { setEditingId(null) setForm(emptyForm(tables[0]?.id ?? '')) setError(null) } async function handleSubmit(event: React.FormEvent) { event.preventDefault() setError(null) setSuccess(null) if (!form.tableId) { setError('Bitte wählen Sie einen Tisch aus') return } setIsSubmitting(true) try { const payload = { tableId: Number(form.tableId), customerName: form.customerName, customerEmail: form.customerEmail, partySize: Number(form.partySize), reservationTime: new Date(form.reservationTime).toISOString(), } if (editingId) { await updateReservation({ data: { id: editingId, ...payload } }) setSuccess('Reservierung wurde aktualisiert.') } else { await createReservation({ data: payload }) setSuccess('Reservierung wurde angelegt.') } setEditingId(null) setForm(emptyForm(tables[0]?.id ?? '')) await router.invalidate() } catch (err) { setError(err instanceof Error ? err.message : 'Etwas ist schiefgelaufen') } finally { setIsSubmitting(false) } } async function handleDelete(reservation: ReservationRow) { if (!window.confirm(`Reservierung von ${reservation.customerName} wirklich löschen?`)) { return } setDeletingId(reservation.id) setError(null) setSuccess(null) try { await deleteReservation({ data: { id: reservation.id } }) if (editingId === reservation.id) { cancelEdit() } setSuccess('Reservierung wurde gelöscht.') await router.invalidate() } catch (err) { setError(err instanceof Error ? err.message : 'Etwas ist schiefgelaufen') } finally { setDeletingId(null) } } async function handleLogout() { await authClient.signOut() await router.navigate({ to: '/staff/login' }) await router.invalidate() } return (
Steakhaus bei Mirko
{staffUser.role === 'admin' && ( Mitarbeiter )} Angemeldet als {staffUser.name}

Reservierungen

{reservations.length} Reservierungen gesamt
{todaysReservations.length} Heute
{guestsToday} Gäste heute
{upcoming.length} Anstehend

{editingId ? 'Reservierung bearbeiten' : 'Neue Reservierung'}

{editingId && ( )}
{error &&

{error}

} {success &&

{success}

}
{reservations.length === 0 ? (

Noch keine Reservierungen vorhanden.

) : (
{reservations.map((reservation) => ( ))}
Datum & Uhrzeit Tisch Kunde Personen
{dateTimeFormatter.format(new Date(reservation.reservationTime))} {reservation.tableName} {reservation.customerName}
{reservation.customerEmail}
{reservation.partySize}
)}
) }