feat: implement tailwind v4 and shadcn

This commit is contained in:
2025-12-02 12:00:16 +01:00
parent 274ac8afa5
commit a1a5fb502d
27 changed files with 3051 additions and 1601 deletions

View File

@@ -3,6 +3,19 @@
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
import {
Loader2,
LogOut,
Sun,
Moon,
Sunrise,
ClipboardList,
Users,
Settings,
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
interface User {
id: number
@@ -30,7 +43,6 @@ export default function CaregiverDashboardPage() {
useEffect(() => {
const fetchData = async () => {
try {
// Check auth
const userRes = await fetch('/api/users/me', { credentials: 'include' })
if (!userRes.ok) {
router.push('/caregiver/login')
@@ -43,7 +55,6 @@ export default function CaregiverDashboardPage() {
}
setUser(userData.user)
// Fetch today's orders stats
const today = new Date().toISOString().split('T')[0]
const ordersRes = await fetch(`/api/meal-orders?where[date][equals]=${today}&limit=1000`, {
credentials: 'include',
@@ -77,8 +88,8 @@ export default function CaregiverDashboardPage() {
if (loading) {
return (
<div className="login-page">
<div className="spinner" />
<div className="min-h-screen flex items-center justify-center bg-muted/50">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
)
}
@@ -89,78 +100,127 @@ export default function CaregiverDashboardPage() {
: 'Care Home'
return (
<>
<header className="header">
<div className="header__content">
<h1 className="header__title">{tenantName}</h1>
<div className="header__user">
<span className="header__user-name">{user?.name || user?.email}</span>
<button onClick={handleLogout} className="btn btn--secondary">
<div className="min-h-screen bg-muted/50">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between">
<h1 className="text-xl font-semibold">{tenantName}</h1>
<div className="flex items-center gap-4">
<span className="text-sm text-muted-foreground">{user?.name || user?.email}</span>
<Button variant="outline" size="sm" onClick={handleLogout}>
<LogOut className="mr-2 h-4 w-4" />
Logout
</button>
</Button>
</div>
</div>
</header>
<main className="container">
<div className="page-title">
<h1>Dashboard</h1>
<p>Today&apos;s overview</p>
<main className="container py-6">
<div className="mb-6">
<h2 className="text-2xl font-bold tracking-tight">Dashboard</h2>
<p className="text-muted-foreground">Today&apos;s overview</p>
</div>
<div className="stats-grid">
<div className="stat-card">
<div className="stat-card__value">{stats.total}</div>
<div className="stat-card__label">Total Orders Today</div>
</div>
<div className="stat-card">
<div className="stat-card__value">{stats.pending}</div>
<div className="stat-card__label">Pending</div>
</div>
<div className="stat-card">
<div className="stat-card__value">{stats.preparing}</div>
<div className="stat-card__label">Preparing</div>
</div>
<div className="stat-card">
<div className="stat-card__value">{stats.prepared}</div>
<div className="stat-card__label">Prepared</div>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 mb-8">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Orders</CardTitle>
<ClipboardList className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.total}</div>
<p className="text-xs text-muted-foreground">Today</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Pending</CardTitle>
<div className="h-2 w-2 rounded-full bg-yellow-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.pending}</div>
<p className="text-xs text-muted-foreground">Awaiting preparation</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Preparing</CardTitle>
<div className="h-2 w-2 rounded-full bg-blue-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.preparing}</div>
<p className="text-xs text-muted-foreground">In progress</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Prepared</CardTitle>
<div className="h-2 w-2 rounded-full bg-green-500" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.prepared}</div>
<p className="text-xs text-muted-foreground">Ready to serve</p>
</CardContent>
</Card>
</div>
<div className="card">
<div className="card__header">
<h2>Quick Actions</h2>
</div>
<div className="card__body">
<div className="quick-actions">
<Link href="/caregiver/orders/new?mealType=breakfast" className="quick-action">
<div className="quick-action__icon">🌅</div>
<div className="quick-action__label">New Breakfast</div>
<Card>
<CardHeader>
<CardTitle>Quick Actions</CardTitle>
</CardHeader>
<CardContent>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<Link href="/caregiver/orders/new?mealType=breakfast">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<Sunrise className="h-8 w-8 mb-2 text-orange-500" />
<span className="font-medium">New Breakfast</span>
</CardContent>
</Card>
</Link>
<Link href="/caregiver/orders/new?mealType=lunch" className="quick-action">
<div className="quick-action__icon"></div>
<div className="quick-action__label">New Lunch</div>
<Link href="/caregiver/orders/new?mealType=lunch">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<Sun className="h-8 w-8 mb-2 text-yellow-500" />
<span className="font-medium">New Lunch</span>
</CardContent>
</Card>
</Link>
<Link href="/caregiver/orders/new?mealType=dinner" className="quick-action">
<div className="quick-action__icon">🌙</div>
<div className="quick-action__label">New Dinner</div>
<Link href="/caregiver/orders/new?mealType=dinner">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<Moon className="h-8 w-8 mb-2 text-indigo-500" />
<span className="font-medium">New Dinner</span>
</CardContent>
</Card>
</Link>
<Link href="/caregiver/orders" className="quick-action">
<div className="quick-action__icon">📋</div>
<div className="quick-action__label">View Orders</div>
<Link href="/caregiver/orders">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<ClipboardList className="h-8 w-8 mb-2 text-muted-foreground" />
<span className="font-medium">View Orders</span>
</CardContent>
</Card>
</Link>
<Link href="/caregiver/residents" className="quick-action">
<div className="quick-action__icon">👥</div>
<div className="quick-action__label">Residents</div>
<Link href="/caregiver/residents">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<Users className="h-8 w-8 mb-2 text-muted-foreground" />
<span className="font-medium">Residents</span>
</CardContent>
</Card>
</Link>
<Link href="/admin" className="quick-action">
<div className="quick-action__icon"></div>
<div className="quick-action__label">Admin Panel</div>
<Link href="/admin">
<Card className="cursor-pointer transition-colors hover:bg-accent">
<CardContent className="flex flex-col items-center justify-center p-6">
<Settings className="h-8 w-8 mb-2 text-muted-foreground" />
<span className="font-medium">Admin Panel</span>
</CardContent>
</Card>
</Link>
</div>
</div>
</div>
</CardContent>
</Card>
</main>
</>
</div>
)
}

View File

@@ -2,6 +2,13 @@
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import { Loader2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Alert, AlertDescription } from '@/components/ui/alert'
export default function CaregiverLoginPage() {
const router = useRouter()
@@ -11,7 +18,6 @@ export default function CaregiverLoginPage() {
const [loading, setLoading] = useState(false)
const [checking, setChecking] = useState(true)
// Check if already logged in
useEffect(() => {
const checkAuth = async () => {
try {
@@ -50,7 +56,6 @@ export default function CaregiverLoginPage() {
throw new Error(data.errors?.[0]?.message || 'Login failed')
}
// Check if user has caregiver or admin role
const user = data.user
const hasCaregiverRole =
user?.roles?.includes('super-admin') ||
@@ -60,7 +65,6 @@ export default function CaregiverLoginPage() {
)
if (!hasCaregiverRole) {
// Logout if not a caregiver
await fetch('/api/users/logout', {
method: 'POST',
credentials: 'include',
@@ -78,31 +82,38 @@ export default function CaregiverLoginPage() {
if (checking) {
return (
<div className="login-page">
<div className="spinner" />
<div className="min-h-screen flex items-center justify-center bg-muted/50">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
)
}
return (
<div className="login-page">
<div className="login-page__card">
<div className="login-page__logo">
<h1>Meal Planner</h1>
<p>Caregiver Portal</p>
<div className="min-h-screen flex items-center justify-center bg-muted/50 p-4">
<div className="w-full max-w-md">
<div className="text-center mb-8">
<h1 className="text-2xl font-bold tracking-tight">Meal Planner</h1>
<p className="text-muted-foreground">Caregiver Portal</p>
</div>
<div className="card">
<div className="card__body">
{error && <div className="message message--error">{error}</div>}
<Card>
<CardHeader>
<CardTitle>Login</CardTitle>
<CardDescription>Enter your credentials to access the caregiver portal</CardDescription>
</CardHeader>
<CardContent>
{error && (
<Alert variant="destructive" className="mb-4">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
type="email"
id="email"
className="input"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
@@ -111,12 +122,11 @@ export default function CaregiverLoginPage() {
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input
type="password"
id="password"
className="input"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter your password"
@@ -125,16 +135,19 @@ export default function CaregiverLoginPage() {
/>
</div>
<button
type="submit"
className="btn btn--primary btn--block btn--large"
disabled={loading}
>
{loading ? 'Logging in...' : 'Login'}
</button>
<Button type="submit" className="w-full" size="lg" disabled={loading}>
{loading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Logging in...
</>
) : (
'Login'
)}
</Button>
</form>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
)

View File

@@ -3,6 +3,27 @@
import React, { useState, useEffect, Suspense } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import Link from 'next/link'
import {
ArrowLeft,
Loader2,
Search,
Sunrise,
Sun,
Moon,
AlertTriangle,
Check,
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Checkbox } from '@/components/ui/checkbox'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Separator } from '@/components/ui/separator'
import { Badge } from '@/components/ui/badge'
import { cn } from '@/lib/utils'
interface Resident {
id: number
@@ -119,6 +140,33 @@ const defaultDinner: DinnerOptions = {
additions: { sugar: false, sweetener: false },
}
function CheckboxOption({
id,
label,
checked,
onCheckedChange,
}: {
id: string
label: string
checked: boolean
onCheckedChange: (checked: boolean) => void
}) {
return (
<div
className={cn(
'flex items-center space-x-3 rounded-lg border p-3 cursor-pointer transition-colors',
checked ? 'border-primary bg-primary/5' : 'border-border hover:bg-muted/50'
)}
onClick={() => onCheckedChange(!checked)}
>
<Checkbox id={id} checked={checked} onCheckedChange={onCheckedChange} />
<Label htmlFor={id} className="cursor-pointer flex-1">
{label}
</Label>
</div>
)
}
function NewOrderContent() {
const router = useRouter()
const searchParams = useSearchParams()
@@ -217,289 +265,254 @@ function NewOrderContent() {
}
}
const renderCheckbox = (
label: string,
checked: boolean,
onChange: (checked: boolean) => void,
) => (
<label className={`checkbox-item ${checked ? 'checkbox-item--checked' : ''}`}>
<input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
<span>{label}</span>
</label>
)
if (loading) {
return (
<div className="login-page">
<div className="spinner" />
<div className="min-h-screen flex items-center justify-center bg-muted/50">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
)
}
return (
<>
<header className="header">
<div className="header__content">
<Link href="/caregiver/dashboard" className="btn btn--secondary">
&larr; Back
</Link>
<h1 className="header__title">New Meal Order</h1>
<div className="min-h-screen bg-muted/50">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center">
<Button variant="ghost" size="sm" asChild>
<Link href="/caregiver/dashboard">
<ArrowLeft className="mr-2 h-4 w-4" />
Back
</Link>
</Button>
<h1 className="ml-4 text-xl font-semibold">New Meal Order</h1>
</div>
</header>
<main className="container">
<main className="container py-6">
{/* Progress Steps */}
<div className="steps">
<div className={`steps__step ${step >= 1 ? 'steps__step--active' : ''} ${step > 1 ? 'steps__step--completed' : ''}`} />
<div className={`steps__step ${step >= 2 ? 'steps__step--active' : ''} ${step > 2 ? 'steps__step--completed' : ''}`} />
<div className={`steps__step ${step >= 3 ? 'steps__step--active' : ''} ${step > 3 ? 'steps__step--completed' : ''}`} />
<div className={`steps__step ${step >= 4 ? 'steps__step--active' : ''}`} />
<div className="flex gap-2 mb-6">
{[1, 2, 3, 4].map((s) => (
<div
key={s}
className={cn(
'h-2 flex-1 rounded-full transition-colors',
step >= s ? (step > s ? 'bg-green-500' : 'bg-primary') : 'bg-muted'
)}
/>
))}
</div>
{error && <div className="message message--error">{error}</div>}
{error && (
<Alert variant="destructive" className="mb-6">
<AlertTriangle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
{/* Step 1: Select Meal Type */}
{step === 1 && (
<div className="card">
<div className="card__header">
<h2>Step 1: Select Meal Type</h2>
</div>
<div className="card__body">
<div className="form-group">
<label htmlFor="date">Date</label>
<input
<Card>
<CardHeader>
<CardTitle>Step 1: Select Meal Type</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-2">
<Label htmlFor="date">Date</Label>
<Input
type="date"
id="date"
className="input"
value={date}
onChange={(e) => setDate(e.target.value)}
/>
</div>
<div className="meal-type-grid">
<button
type="button"
className={`meal-type-btn ${mealType === 'breakfast' ? 'meal-type-btn--selected' : ''}`}
onClick={() => setMealType('breakfast')}
>
<div className="meal-type-btn__icon">🌅</div>
<div className="meal-type-btn__label">Breakfast</div>
<div className="meal-type-btn__sublabel">Frühstück</div>
</button>
<button
type="button"
className={`meal-type-btn ${mealType === 'lunch' ? 'meal-type-btn--selected' : ''}`}
onClick={() => setMealType('lunch')}
>
<div className="meal-type-btn__icon"></div>
<div className="meal-type-btn__label">Lunch</div>
<div className="meal-type-btn__sublabel">Mittagessen</div>
</button>
<button
type="button"
className={`meal-type-btn ${mealType === 'dinner' ? 'meal-type-btn--selected' : ''}`}
onClick={() => setMealType('dinner')}
>
<div className="meal-type-btn__icon">🌙</div>
<div className="meal-type-btn__label">Dinner</div>
<div className="meal-type-btn__sublabel">Abendessen</div>
</button>
<div className="grid gap-4 sm:grid-cols-3">
{[
{ type: 'breakfast' as MealType, icon: Sunrise, label: 'Breakfast', sublabel: 'Frühstück', color: 'text-orange-500' },
{ type: 'lunch' as MealType, icon: Sun, label: 'Lunch', sublabel: 'Mittagessen', color: 'text-yellow-500' },
{ type: 'dinner' as MealType, icon: Moon, label: 'Dinner', sublabel: 'Abendessen', color: 'text-indigo-500' },
].map(({ type, icon: Icon, label, sublabel, color }) => (
<Card
key={type}
className={cn(
'cursor-pointer transition-colors',
mealType === type ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'
)}
onClick={() => setMealType(type)}
>
<CardContent className="flex flex-col items-center justify-center p-6">
<Icon className={cn('h-10 w-10 mb-2', color)} />
<span className="font-semibold">{label}</span>
<span className="text-sm text-muted-foreground">{sublabel}</span>
</CardContent>
</Card>
))}
</div>
<div style={{ marginTop: '1.5rem' }}>
<button
className="btn btn--primary btn--block btn--large"
disabled={!mealType}
onClick={() => setStep(2)}
>
Continue
</button>
</div>
</div>
</div>
<Button
className="w-full"
size="lg"
disabled={!mealType}
onClick={() => setStep(2)}
>
Continue
</Button>
</CardContent>
</Card>
)}
{/* Step 2: Select Resident */}
{step === 2 && (
<div className="card">
<div className="card__header">
<h2>Step 2: Select Resident</h2>
</div>
<div className="card__body">
<div className="form-group">
<div className="search-box">
<input
type="text"
placeholder="Search by name or room..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<Card>
<CardHeader>
<CardTitle>Step 2: Select Resident</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
type="text"
placeholder="Search by name or room..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
</div>
<div className="resident-list">
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 max-h-96 overflow-y-auto">
{filteredResidents.map((resident) => (
<div
<Card
key={resident.id}
className={`resident-card ${selectedResident?.id === resident.id ? 'resident-card--selected' : ''}`}
className={cn(
'cursor-pointer transition-colors',
selectedResident?.id === resident.id ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'
)}
onClick={() => setSelectedResident(resident)}
>
<div className="resident-card__name">{resident.name}</div>
<div className="resident-card__details">
<span>Room {resident.room}</span>
{resident.table && <span>Table {resident.table}</span>}
{resident.station && <span>{resident.station}</span>}
</div>
{resident.highCaloric && (
<div className="resident-card__badge">High Caloric</div>
)}
</div>
<CardContent className="p-4">
<div className="font-semibold">{resident.name}</div>
<div className="flex gap-2 text-sm text-muted-foreground mt-1">
<span>Room {resident.room}</span>
{resident.table && <span>Table {resident.table}</span>}
</div>
{resident.highCaloric && (
<Badge variant="secondary" className="mt-2 bg-yellow-100 text-yellow-800">
High Caloric
</Badge>
)}
</CardContent>
</Card>
))}
</div>
<div style={{ marginTop: '1.5rem', display: 'flex', gap: '1rem' }}>
<button className="btn btn--secondary" onClick={() => setStep(1)}>
<div className="flex gap-4 pt-4">
<Button variant="outline" onClick={() => setStep(1)}>
Back
</button>
<button
className="btn btn--primary btn--block btn--large"
</Button>
<Button
className="flex-1"
size="lg"
disabled={!selectedResident}
onClick={() => setStep(3)}
>
Continue
</button>
</Button>
</div>
</div>
</div>
</CardContent>
</Card>
)}
{/* Step 3: Meal Options */}
{step === 3 && (
<div className="card">
<div className="card__header">
<h2>Step 3: {mealType && getMealTypeLabel(mealType)} Options</h2>
</div>
<div className="card__body">
{/* Show resident notes if any */}
<Card>
<CardHeader>
<CardTitle>Step 3: {mealType && getMealTypeLabel(mealType)} Options</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
{(selectedResident?.aversions || selectedResident?.notes) && (
<div className="message message--warning">
<strong>Notes for {selectedResident?.name}:</strong>
{selectedResident?.aversions && <div>Aversions: {selectedResident.aversions}</div>}
{selectedResident?.notes && <div>{selectedResident.notes}</div>}
</div>
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Notes for {selectedResident?.name}</AlertTitle>
<AlertDescription>
{selectedResident?.aversions && <div>Aversions: {selectedResident.aversions}</div>}
{selectedResident?.notes && <div>{selectedResident.notes}</div>}
</AlertDescription>
</Alert>
)}
{/* BREAKFAST OPTIONS */}
{mealType === 'breakfast' && (
<>
<div className="section">
<h3 className="section__title">General</h3>
<div className="checkbox-group">
{renderCheckbox('According to Plan (lt. Plan)', breakfast.accordingToPlan, (v) =>
setBreakfast({ ...breakfast, accordingToPlan: v }),
)}
<div className="space-y-3">
<h3 className="font-semibold">General</h3>
<CheckboxOption
id="accordingToPlan"
label="According to Plan (lt. Plan)"
checked={breakfast.accordingToPlan}
onCheckedChange={(v) => setBreakfast({ ...breakfast, accordingToPlan: v })}
/>
</div>
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Bread (Brot)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="breadRoll" label="Bread Roll (Brötchen)" checked={breakfast.bread.breadRoll} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, breadRoll: v } })} />
<CheckboxOption id="wholeGrainRoll" label="Whole Grain Roll (Vollkornbrötchen)" checked={breakfast.bread.wholeGrainRoll} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainRoll: v } })} />
<CheckboxOption id="greyBread" label="Grey Bread (Graubrot)" checked={breakfast.bread.greyBread} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, greyBread: v } })} />
<CheckboxOption id="wholeGrainBread" label="Whole Grain Bread (Vollkornbrot)" checked={breakfast.bread.wholeGrainBread} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainBread: v } })} />
<CheckboxOption id="whiteBread" label="White Bread (Weißbrot)" checked={breakfast.bread.whiteBread} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, whiteBread: v } })} />
<CheckboxOption id="crispbread" label="Crispbread (Knäckebrot)" checked={breakfast.bread.crispbread} onCheckedChange={(v) => setBreakfast({ ...breakfast, bread: { ...breakfast.bread, crispbread: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Bread (Brot)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Bread Roll (Brötchen)', breakfast.bread.breadRoll, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, breadRoll: v } }),
)}
{renderCheckbox('Whole Grain Roll (Vollkornbrötchen)', breakfast.bread.wholeGrainRoll, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainRoll: v } }),
)}
{renderCheckbox('Grey Bread (Graubrot)', breakfast.bread.greyBread, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, greyBread: v } }),
)}
{renderCheckbox('Whole Grain Bread (Vollkornbrot)', breakfast.bread.wholeGrainBread, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainBread: v } }),
)}
{renderCheckbox('White Bread (Weißbrot)', breakfast.bread.whiteBread, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, whiteBread: v } }),
)}
{renderCheckbox('Crispbread (Knäckebrot)', breakfast.bread.crispbread, (v) =>
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, crispbread: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Preparation</h3>
<div className="grid gap-2 sm:grid-cols-3">
<CheckboxOption id="porridge" label="Porridge (Brei)" checked={breakfast.porridge} onCheckedChange={(v) => setBreakfast({ ...breakfast, porridge: v })} />
<CheckboxOption id="sliced" label="Sliced (geschnitten)" checked={breakfast.preparation.sliced} onCheckedChange={(v) => setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, sliced: v } })} />
<CheckboxOption id="spread" label="Spread (geschmiert)" checked={breakfast.preparation.spread} onCheckedChange={(v) => setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, spread: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Preparation</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Porridge (Brei)', breakfast.porridge, (v) =>
setBreakfast({ ...breakfast, porridge: v }),
)}
{renderCheckbox('Sliced (geschnitten)', breakfast.preparation.sliced, (v) =>
setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, sliced: v } }),
)}
{renderCheckbox('Spread (geschmiert)', breakfast.preparation.spread, (v) =>
setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, spread: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Spreads (Aufstrich)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="butter" label="Butter" checked={breakfast.spreads.butter} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, butter: v } })} />
<CheckboxOption id="margarine" label="Margarine" checked={breakfast.spreads.margarine} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, margarine: v } })} />
<CheckboxOption id="jam" label="Jam (Konfitüre)" checked={breakfast.spreads.jam} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, jam: v } })} />
<CheckboxOption id="diabeticJam" label="Diabetic Jam (Diab. Konfitüre)" checked={breakfast.spreads.diabeticJam} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, diabeticJam: v } })} />
<CheckboxOption id="honey" label="Honey (Honig)" checked={breakfast.spreads.honey} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, honey: v } })} />
<CheckboxOption id="cheese" label="Cheese (Käse)" checked={breakfast.spreads.cheese} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, cheese: v } })} />
<CheckboxOption id="quark" label="Quark" checked={breakfast.spreads.quark} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, quark: v } })} />
<CheckboxOption id="sausage" label="Sausage (Wurst)" checked={breakfast.spreads.sausage} onCheckedChange={(v) => setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, sausage: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Spreads (Aufstrich)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Butter', breakfast.spreads.butter, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, butter: v } }),
)}
{renderCheckbox('Margarine', breakfast.spreads.margarine, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, margarine: v } }),
)}
{renderCheckbox('Jam (Konfitüre)', breakfast.spreads.jam, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, jam: v } }),
)}
{renderCheckbox('Diabetic Jam (Diab. Konfitüre)', breakfast.spreads.diabeticJam, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, diabeticJam: v } }),
)}
{renderCheckbox('Honey (Honig)', breakfast.spreads.honey, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, honey: v } }),
)}
{renderCheckbox('Cheese (Käse)', breakfast.spreads.cheese, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, cheese: v } }),
)}
{renderCheckbox('Quark', breakfast.spreads.quark, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, quark: v } }),
)}
{renderCheckbox('Sausage (Wurst)', breakfast.spreads.sausage, (v) =>
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, sausage: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Beverages (Getränke)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="coffee" label="Coffee (Kaffee)" checked={breakfast.beverages.coffee} onCheckedChange={(v) => setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coffee: v } })} />
<CheckboxOption id="tea" label="Tea (Tee)" checked={breakfast.beverages.tea} onCheckedChange={(v) => setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, tea: v } })} />
<CheckboxOption id="hotMilk" label="Hot Milk (Milch heiß)" checked={breakfast.beverages.hotMilk} onCheckedChange={(v) => setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, hotMilk: v } })} />
<CheckboxOption id="coldMilk" label="Cold Milk (Milch kalt)" checked={breakfast.beverages.coldMilk} onCheckedChange={(v) => setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coldMilk: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Beverages (Getränke)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Coffee (Kaffee)', breakfast.beverages.coffee, (v) =>
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coffee: v } }),
)}
{renderCheckbox('Tea (Tee)', breakfast.beverages.tea, (v) =>
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, tea: v } }),
)}
{renderCheckbox('Hot Milk (Milch heiß)', breakfast.beverages.hotMilk, (v) =>
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, hotMilk: v } }),
)}
{renderCheckbox('Cold Milk (Milch kalt)', breakfast.beverages.coldMilk, (v) =>
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coldMilk: v } }),
)}
</div>
</div>
<Separator />
<div className="section">
<h3 className="section__title">Additions (Zusätze)</h3>
<div className="checkbox-group checkbox-group--cols-3">
{renderCheckbox('Sugar (Zucker)', breakfast.additions.sugar, (v) =>
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sugar: v } }),
)}
{renderCheckbox('Sweetener (Süßstoff)', breakfast.additions.sweetener, (v) =>
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sweetener: v } }),
)}
{renderCheckbox('Coffee Creamer (Kaffeesahne)', breakfast.additions.coffeeCreamer, (v) =>
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, coffeeCreamer: v } }),
)}
<div className="space-y-3">
<h3 className="font-semibold">Additions (Zusätze)</h3>
<div className="grid gap-2 sm:grid-cols-3">
<CheckboxOption id="sugar" label="Sugar (Zucker)" checked={breakfast.additions.sugar} onCheckedChange={(v) => setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sugar: v } })} />
<CheckboxOption id="sweetener" label="Sweetener (Süßstoff)" checked={breakfast.additions.sweetener} onCheckedChange={(v) => setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sweetener: v } })} />
<CheckboxOption id="coffeeCreamer" label="Coffee Creamer (Kaffeesahne)" checked={breakfast.additions.coffeeCreamer} onCheckedChange={(v) => setBreakfast({ ...breakfast, additions: { ...breakfast.additions, coffeeCreamer: v } })} />
</div>
</div>
</>
@@ -508,83 +521,63 @@ function NewOrderContent() {
{/* LUNCH OPTIONS */}
{mealType === 'lunch' && (
<>
<div className="section">
<h3 className="section__title">Portion Size</h3>
<div className="checkbox-group checkbox-group--cols-3">
<label
className={`checkbox-item ${lunch.portionSize === 'small' ? 'checkbox-item--checked' : ''}`}
>
<input
type="radio"
name="portionSize"
checked={lunch.portionSize === 'small'}
onChange={() => setLunch({ ...lunch, portionSize: 'small' })}
/>
<span>Small (Kleine)</span>
</label>
<label
className={`checkbox-item ${lunch.portionSize === 'large' ? 'checkbox-item--checked' : ''}`}
>
<input
type="radio"
name="portionSize"
checked={lunch.portionSize === 'large'}
onChange={() => setLunch({ ...lunch, portionSize: 'large' })}
/>
<span>Large (Große)</span>
</label>
<label
className={`checkbox-item ${lunch.portionSize === 'vegetarian' ? 'checkbox-item--checked' : ''}`}
>
<input
type="radio"
name="portionSize"
checked={lunch.portionSize === 'vegetarian'}
onChange={() => setLunch({ ...lunch, portionSize: 'vegetarian' })}
/>
<span>Vegetarian</span>
</label>
<div className="space-y-3">
<h3 className="font-semibold">Portion Size</h3>
<RadioGroup
value={lunch.portionSize}
onValueChange={(v) => setLunch({ ...lunch, portionSize: v as 'small' | 'large' | 'vegetarian' })}
className="grid gap-2 sm:grid-cols-3"
>
{[
{ value: 'small', label: 'Small (Kleine)' },
{ value: 'large', label: 'Large (Große)' },
{ value: 'vegetarian', label: 'Vegetarian' },
].map(({ value, label }) => (
<div
key={value}
className={cn(
'flex items-center space-x-3 rounded-lg border p-3 cursor-pointer transition-colors',
lunch.portionSize === value ? 'border-primary bg-primary/5' : 'border-border hover:bg-muted/50'
)}
onClick={() => setLunch({ ...lunch, portionSize: value as 'small' | 'large' | 'vegetarian' })}
>
<RadioGroupItem value={value} id={value} />
<Label htmlFor={value} className="cursor-pointer">{label}</Label>
</div>
))}
</RadioGroup>
</div>
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Meal Options</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="soup" label="Soup (Suppe)" checked={lunch.soup} onCheckedChange={(v) => setLunch({ ...lunch, soup: v })} />
<CheckboxOption id="dessert" label="Dessert" checked={lunch.dessert} onCheckedChange={(v) => setLunch({ ...lunch, dessert: v })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Meal Options</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Soup (Suppe)', lunch.soup, (v) => setLunch({ ...lunch, soup: v }))}
{renderCheckbox('Dessert', lunch.dessert, (v) => setLunch({ ...lunch, dessert: v }))}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Special Preparations</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="pureedFood" label="Pureed Food (passierte Kost)" checked={lunch.specialPreparations.pureedFood} onCheckedChange={(v) => setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedFood: v } })} />
<CheckboxOption id="pureedMeat" label="Pureed Meat (passiertes Fleisch)" checked={lunch.specialPreparations.pureedMeat} onCheckedChange={(v) => setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedMeat: v } })} />
<CheckboxOption id="slicedMeat" label="Sliced Meat (geschnittenes Fleisch)" checked={lunch.specialPreparations.slicedMeat} onCheckedChange={(v) => setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, slicedMeat: v } })} />
<CheckboxOption id="mashedPotatoes" label="Mashed Potatoes (Kartoffelbrei)" checked={lunch.specialPreparations.mashedPotatoes} onCheckedChange={(v) => setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, mashedPotatoes: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Special Preparations</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Pureed Food (passierte Kost)', lunch.specialPreparations.pureedFood, (v) =>
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedFood: v } }),
)}
{renderCheckbox('Pureed Meat (passiertes Fleisch)', lunch.specialPreparations.pureedMeat, (v) =>
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedMeat: v } }),
)}
{renderCheckbox('Sliced Meat (geschnittenes Fleisch)', lunch.specialPreparations.slicedMeat, (v) =>
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, slicedMeat: v } }),
)}
{renderCheckbox('Mashed Potatoes (Kartoffelbrei)', lunch.specialPreparations.mashedPotatoes, (v) =>
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, mashedPotatoes: v } }),
)}
</div>
</div>
<Separator />
<div className="section">
<h3 className="section__title">Restrictions</h3>
<div className="checkbox-group checkbox-group--cols-3">
{renderCheckbox('No Fish (ohne Fisch)', lunch.restrictions.noFish, (v) =>
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, noFish: v } }),
)}
{renderCheckbox('Finger Food', lunch.restrictions.fingerFood, (v) =>
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, fingerFood: v } }),
)}
{renderCheckbox('Only Sweet (nur süß)', lunch.restrictions.onlySweet, (v) =>
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, onlySweet: v } }),
)}
<div className="space-y-3">
<h3 className="font-semibold">Restrictions</h3>
<div className="grid gap-2 sm:grid-cols-3">
<CheckboxOption id="noFish" label="No Fish (ohne Fisch)" checked={lunch.restrictions.noFish} onCheckedChange={(v) => setLunch({ ...lunch, restrictions: { ...lunch.restrictions, noFish: v } })} />
<CheckboxOption id="fingerFood" label="Finger Food" checked={lunch.restrictions.fingerFood} onCheckedChange={(v) => setLunch({ ...lunch, restrictions: { ...lunch.restrictions, fingerFood: v } })} />
<CheckboxOption id="onlySweet" label="Only Sweet (nur süß)" checked={lunch.restrictions.onlySweet} onCheckedChange={(v) => setLunch({ ...lunch, restrictions: { ...lunch.restrictions, onlySweet: v } })} />
</div>
</div>
</>
@@ -593,163 +586,161 @@ function NewOrderContent() {
{/* DINNER OPTIONS */}
{mealType === 'dinner' && (
<>
<div className="section">
<h3 className="section__title">General</h3>
<div className="checkbox-group">
{renderCheckbox('According to Plan (lt. Plan)', dinner.accordingToPlan, (v) =>
setDinner({ ...dinner, accordingToPlan: v }),
)}
<div className="space-y-3">
<h3 className="font-semibold">General</h3>
<CheckboxOption
id="dinnerAccordingToPlan"
label="According to Plan (lt. Plan)"
checked={dinner.accordingToPlan}
onCheckedChange={(v) => setDinner({ ...dinner, accordingToPlan: v })}
/>
</div>
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Bread (Brot)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="dinnerGreyBread" label="Grey Bread (Graubrot)" checked={dinner.bread.greyBread} onCheckedChange={(v) => setDinner({ ...dinner, bread: { ...dinner.bread, greyBread: v } })} />
<CheckboxOption id="dinnerWholeGrainBread" label="Whole Grain Bread (Vollkornbrot)" checked={dinner.bread.wholeGrainBread} onCheckedChange={(v) => setDinner({ ...dinner, bread: { ...dinner.bread, wholeGrainBread: v } })} />
<CheckboxOption id="dinnerWhiteBread" label="White Bread (Weißbrot)" checked={dinner.bread.whiteBread} onCheckedChange={(v) => setDinner({ ...dinner, bread: { ...dinner.bread, whiteBread: v } })} />
<CheckboxOption id="dinnerCrispbread" label="Crispbread (Knäckebrot)" checked={dinner.bread.crispbread} onCheckedChange={(v) => setDinner({ ...dinner, bread: { ...dinner.bread, crispbread: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Bread (Brot)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Grey Bread (Graubrot)', dinner.bread.greyBread, (v) =>
setDinner({ ...dinner, bread: { ...dinner.bread, greyBread: v } }),
)}
{renderCheckbox('Whole Grain Bread (Vollkornbrot)', dinner.bread.wholeGrainBread, (v) =>
setDinner({ ...dinner, bread: { ...dinner.bread, wholeGrainBread: v } }),
)}
{renderCheckbox('White Bread (Weißbrot)', dinner.bread.whiteBread, (v) =>
setDinner({ ...dinner, bread: { ...dinner.bread, whiteBread: v } }),
)}
{renderCheckbox('Crispbread (Knäckebrot)', dinner.bread.crispbread, (v) =>
setDinner({ ...dinner, bread: { ...dinner.bread, crispbread: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Preparation</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="dinnerSpread" label="Spread (geschmiert)" checked={dinner.preparation.spread} onCheckedChange={(v) => setDinner({ ...dinner, preparation: { ...dinner.preparation, spread: v } })} />
<CheckboxOption id="dinnerSliced" label="Sliced (geschnitten)" checked={dinner.preparation.sliced} onCheckedChange={(v) => setDinner({ ...dinner, preparation: { ...dinner.preparation, sliced: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Preparation</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Spread (geschmiert)', dinner.preparation.spread, (v) =>
setDinner({ ...dinner, preparation: { ...dinner.preparation, spread: v } }),
)}
{renderCheckbox('Sliced (geschnitten)', dinner.preparation.sliced, (v) =>
setDinner({ ...dinner, preparation: { ...dinner.preparation, sliced: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Spreads (Aufstrich)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="dinnerButter" label="Butter" checked={dinner.spreads.butter} onCheckedChange={(v) => setDinner({ ...dinner, spreads: { ...dinner.spreads, butter: v } })} />
<CheckboxOption id="dinnerMargarine" label="Margarine" checked={dinner.spreads.margarine} onCheckedChange={(v) => setDinner({ ...dinner, spreads: { ...dinner.spreads, margarine: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Spreads (Aufstrich)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Butter', dinner.spreads.butter, (v) =>
setDinner({ ...dinner, spreads: { ...dinner.spreads, butter: v } }),
)}
{renderCheckbox('Margarine', dinner.spreads.margarine, (v) =>
setDinner({ ...dinner, spreads: { ...dinner.spreads, margarine: v } }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Additional Items</h3>
<div className="grid gap-2 sm:grid-cols-3">
<CheckboxOption id="dinnerSoup" label="Soup (Suppe)" checked={dinner.soup} onCheckedChange={(v) => setDinner({ ...dinner, soup: v })} />
<CheckboxOption id="dinnerPorridge" label="Porridge (Brei)" checked={dinner.porridge} onCheckedChange={(v) => setDinner({ ...dinner, porridge: v })} />
<CheckboxOption id="dinnerNoFish" label="No Fish (ohne Fisch)" checked={dinner.noFish} onCheckedChange={(v) => setDinner({ ...dinner, noFish: v })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Additional Items</h3>
<div className="checkbox-group checkbox-group--cols-3">
{renderCheckbox('Soup (Suppe)', dinner.soup, (v) => setDinner({ ...dinner, soup: v }))}
{renderCheckbox('Porridge (Brei)', dinner.porridge, (v) =>
setDinner({ ...dinner, porridge: v }),
)}
{renderCheckbox('No Fish (ohne Fisch)', dinner.noFish, (v) =>
setDinner({ ...dinner, noFish: v }),
)}
<Separator />
<div className="space-y-3">
<h3 className="font-semibold">Beverages (Getränke)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="dinnerTea" label="Tea (Tee)" checked={dinner.beverages.tea} onCheckedChange={(v) => setDinner({ ...dinner, beverages: { ...dinner.beverages, tea: v } })} />
<CheckboxOption id="dinnerCocoa" label="Cocoa (Kakao)" checked={dinner.beverages.cocoa} onCheckedChange={(v) => setDinner({ ...dinner, beverages: { ...dinner.beverages, cocoa: v } })} />
<CheckboxOption id="dinnerHotMilk" label="Hot Milk (Milch heiß)" checked={dinner.beverages.hotMilk} onCheckedChange={(v) => setDinner({ ...dinner, beverages: { ...dinner.beverages, hotMilk: v } })} />
<CheckboxOption id="dinnerColdMilk" label="Cold Milk (Milch kalt)" checked={dinner.beverages.coldMilk} onCheckedChange={(v) => setDinner({ ...dinner, beverages: { ...dinner.beverages, coldMilk: v } })} />
</div>
</div>
<div className="section">
<h3 className="section__title">Beverages (Getränke)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Tea (Tee)', dinner.beverages.tea, (v) =>
setDinner({ ...dinner, beverages: { ...dinner.beverages, tea: v } }),
)}
{renderCheckbox('Cocoa (Kakao)', dinner.beverages.cocoa, (v) =>
setDinner({ ...dinner, beverages: { ...dinner.beverages, cocoa: v } }),
)}
{renderCheckbox('Hot Milk (Milch heiß)', dinner.beverages.hotMilk, (v) =>
setDinner({ ...dinner, beverages: { ...dinner.beverages, hotMilk: v } }),
)}
{renderCheckbox('Cold Milk (Milch kalt)', dinner.beverages.coldMilk, (v) =>
setDinner({ ...dinner, beverages: { ...dinner.beverages, coldMilk: v } }),
)}
</div>
</div>
<Separator />
<div className="section">
<h3 className="section__title">Additions (Zusätze)</h3>
<div className="checkbox-group checkbox-group--cols-2">
{renderCheckbox('Sugar (Zucker)', dinner.additions.sugar, (v) =>
setDinner({ ...dinner, additions: { ...dinner.additions, sugar: v } }),
)}
{renderCheckbox('Sweetener (Süßstoff)', dinner.additions.sweetener, (v) =>
setDinner({ ...dinner, additions: { ...dinner.additions, sweetener: v } }),
)}
<div className="space-y-3">
<h3 className="font-semibold">Additions (Zusätze)</h3>
<div className="grid gap-2 sm:grid-cols-2">
<CheckboxOption id="dinnerSugar" label="Sugar (Zucker)" checked={dinner.additions.sugar} onCheckedChange={(v) => setDinner({ ...dinner, additions: { ...dinner.additions, sugar: v } })} />
<CheckboxOption id="dinnerSweetener" label="Sweetener (Süßstoff)" checked={dinner.additions.sweetener} onCheckedChange={(v) => setDinner({ ...dinner, additions: { ...dinner.additions, sweetener: v } })} />
</div>
</div>
</>
)}
<div style={{ marginTop: '1.5rem', display: 'flex', gap: '1rem' }}>
<button className="btn btn--secondary" onClick={() => setStep(2)}>
<div className="flex gap-4 pt-4">
<Button variant="outline" onClick={() => setStep(2)}>
Back
</button>
<button className="btn btn--primary btn--block btn--large" onClick={() => setStep(4)}>
</Button>
<Button className="flex-1" size="lg" onClick={() => setStep(4)}>
Review Order
</button>
</Button>
</div>
</div>
</div>
</CardContent>
</Card>
)}
{/* Step 4: Review and Submit */}
{step === 4 && (
<div className="card">
<div className="card__header">
<h2>Step 4: Review & Submit</h2>
</div>
<div className="card__body">
<div className="order-summary">
<div className="order-summary__row">
<span className="order-summary__label">Resident</span>
<span className="order-summary__value">{selectedResident?.name}</span>
<Card>
<CardHeader>
<CardTitle>Step 4: Review & Submit</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="rounded-lg bg-muted p-4 space-y-3">
<div className="flex justify-between">
<span className="text-muted-foreground">Resident</span>
<span className="font-medium">{selectedResident?.name}</span>
</div>
<div className="order-summary__row">
<span className="order-summary__label">Room</span>
<span className="order-summary__value">{selectedResident?.room}</span>
<Separator />
<div className="flex justify-between">
<span className="text-muted-foreground">Room</span>
<span className="font-medium">{selectedResident?.room}</span>
</div>
<div className="order-summary__row">
<span className="order-summary__label">Date</span>
<span className="order-summary__value">{date}</span>
<Separator />
<div className="flex justify-between">
<span className="text-muted-foreground">Date</span>
<span className="font-medium">{date}</span>
</div>
<div className="order-summary__row">
<span className="order-summary__label">Meal Type</span>
<span className="order-summary__value">{mealType && getMealTypeLabel(mealType)}</span>
<Separator />
<div className="flex justify-between">
<span className="text-muted-foreground">Meal Type</span>
<span className="font-medium">{mealType && getMealTypeLabel(mealType)}</span>
</div>
</div>
{selectedResident?.highCaloric && (
<div className="message message--warning" style={{ marginTop: '1rem' }}>
<strong>Note:</strong> This resident requires high caloric meals.
</div>
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertDescription>
<strong>Note:</strong> This resident requires high caloric meals.
</AlertDescription>
</Alert>
)}
<div style={{ marginTop: '1.5rem', display: 'flex', gap: '1rem' }}>
<button className="btn btn--secondary" onClick={() => setStep(3)}>
<div className="flex gap-4">
<Button variant="outline" onClick={() => setStep(3)}>
Back
</button>
<button
className="btn btn--success btn--block btn--large"
</Button>
<Button
className="flex-1 bg-green-600 hover:bg-green-700"
size="lg"
onClick={handleSubmit}
disabled={submitting}
>
{submitting ? 'Creating...' : 'Create Order'}
</button>
{submitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating...
</>
) : (
<>
<Check className="mr-2 h-4 w-4" />
Create Order
</>
)}
</Button>
</div>
</div>
</div>
</CardContent>
</Card>
)}
</main>
</>
</div>
)
}
@@ -757,8 +748,8 @@ export default function NewOrderPage() {
return (
<Suspense
fallback={
<div className="login-page">
<div className="spinner" />
<div className="min-h-screen flex items-center justify-center bg-muted/50">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
}
>

View File

@@ -3,6 +3,28 @@
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
import { ArrowLeft, Plus, Loader2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Badge } from '@/components/ui/badge'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
interface Resident {
id: number
@@ -69,7 +91,16 @@ export default function OrdersListPage() {
}
const getStatusBadge = (status: string) => {
return <span className={`badge badge--${status}`}>{status.charAt(0).toUpperCase() + status.slice(1)}</span>
switch (status) {
case 'pending':
return <Badge variant="outline" className="bg-yellow-50 text-yellow-700 border-yellow-200">Pending</Badge>
case 'preparing':
return <Badge variant="outline" className="bg-blue-50 text-blue-700 border-blue-200">Preparing</Badge>
case 'prepared':
return <Badge variant="outline" className="bg-green-50 text-green-700 border-green-200">Prepared</Badge>
default:
return <Badge variant="outline">{status}</Badge>
}
}
const getResidentName = (resident: Resident | number) => {
@@ -80,89 +111,99 @@ export default function OrdersListPage() {
}
return (
<>
<header className="header">
<div className="header__content">
<Link href="/caregiver/dashboard" className="btn btn--secondary">
&larr; Back
</Link>
<h1 className="header__title">Meal Orders</h1>
<Link href="/caregiver/orders/new" className="btn btn--primary">
+ New Order
</Link>
<div className="min-h-screen bg-muted/50">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between">
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" asChild>
<Link href="/caregiver/dashboard">
<ArrowLeft className="mr-2 h-4 w-4" />
Back
</Link>
</Button>
<h1 className="text-xl font-semibold">Meal Orders</h1>
</div>
<Button asChild>
<Link href="/caregiver/orders/new">
<Plus className="mr-2 h-4 w-4" />
New Order
</Link>
</Button>
</div>
</header>
<main className="container">
<div className="card">
<div className="card__header">
<h2>Filter Orders</h2>
</div>
<div className="card__body">
<div className="grid grid--2">
<div className="form-group">
<label htmlFor="date">Date</label>
<input
<main className="container py-6">
<Card className="mb-6">
<CardHeader>
<CardTitle>Filter Orders</CardTitle>
</CardHeader>
<CardContent>
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="date">Date</Label>
<Input
type="date"
id="date"
className="input"
value={dateFilter}
onChange={(e) => setDateFilter(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="mealType">Meal Type</label>
<select
id="mealType"
className="select"
value={mealTypeFilter}
onChange={(e) => setMealTypeFilter(e.target.value)}
>
<option value="all">All Types</option>
<option value="breakfast">Breakfast</option>
<option value="lunch">Lunch</option>
<option value="dinner">Dinner</option>
</select>
<div className="space-y-2">
<Label htmlFor="mealType">Meal Type</Label>
<Select value={mealTypeFilter} onValueChange={setMealTypeFilter}>
<SelectTrigger>
<SelectValue placeholder="Select meal type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All Types</SelectItem>
<SelectItem value="breakfast">Breakfast</SelectItem>
<SelectItem value="lunch">Lunch</SelectItem>
<SelectItem value="dinner">Dinner</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
<div className="card" style={{ marginTop: '1rem' }}>
<div className="card__body" style={{ padding: 0, overflowX: 'auto' }}>
<Card>
<CardContent className="p-0">
{loading ? (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<div className="spinner" style={{ margin: '0 auto' }} />
<div className="flex items-center justify-center p-8">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : orders.length === 0 ? (
<div style={{ padding: '2rem', textAlign: 'center', color: 'var(--gray-500)' }}>
No orders found for the selected criteria.
<div className="flex flex-col items-center justify-center p-8 text-center">
<p className="text-muted-foreground">No orders found for the selected criteria.</p>
<Button asChild className="mt-4">
<Link href="/caregiver/orders/new">Create New Order</Link>
</Button>
</div>
) : (
<table className="table">
<thead>
<tr>
<th>Resident</th>
<th>Date</th>
<th>Meal</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<Table>
<TableHeader>
<TableRow>
<TableHead>Resident</TableHead>
<TableHead>Date</TableHead>
<TableHead>Meal</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{orders.map((order) => (
<tr key={order.id}>
<td>{getResidentName(order.resident)}</td>
<td>{order.date}</td>
<td>{getMealTypeLabel(order.mealType)}</td>
<td>{getStatusBadge(order.status)}</td>
</tr>
<TableRow key={order.id}>
<TableCell className="font-medium">{getResidentName(order.resident)}</TableCell>
<TableCell>{order.date}</TableCell>
<TableCell>{getMealTypeLabel(order.mealType)}</TableCell>
<TableCell>{getStatusBadge(order.status)}</TableCell>
</TableRow>
))}
</tbody>
</table>
</TableBody>
</Table>
)}
</div>
</div>
</CardContent>
</Card>
</main>
</>
</div>
)
}

View File

@@ -3,6 +3,12 @@
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
import { ArrowLeft, Search, Loader2, Plus } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Badge } from '@/components/ui/badge'
interface Resident {
id: number
@@ -51,83 +57,93 @@ export default function ResidentsListPage() {
)
return (
<>
<header className="header">
<div className="header__content">
<Link href="/caregiver/dashboard" className="btn btn--secondary">
&larr; Back
</Link>
<h1 className="header__title">Residents</h1>
<div className="min-h-screen bg-muted/50">
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center">
<Button variant="ghost" size="sm" asChild>
<Link href="/caregiver/dashboard">
<ArrowLeft className="mr-2 h-4 w-4" />
Back
</Link>
</Button>
<h1 className="ml-4 text-xl font-semibold">Residents</h1>
</div>
</header>
<main className="container">
<div className="page-title">
<h1>Residents</h1>
<p>View resident information and dietary requirements</p>
<main className="container py-6">
<div className="mb-6">
<h2 className="text-2xl font-bold tracking-tight">Residents</h2>
<p className="text-muted-foreground">View resident information and dietary requirements</p>
</div>
<div className="actions-bar">
<div className="search-box">
<input
<div className="mb-6">
<div className="relative max-w-md">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
type="text"
placeholder="Search by name, room, or station..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
</div>
</div>
{loading ? (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<div className="spinner" style={{ margin: '0 auto' }} />
<div className="flex items-center justify-center p-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : filteredResidents.length === 0 ? (
<div className="card">
<div className="card__body" style={{ textAlign: 'center', color: 'var(--gray-500)' }}>
No residents found.
</div>
</div>
<Card>
<CardContent className="flex flex-col items-center justify-center p-8 text-center">
<p className="text-muted-foreground">No residents found.</p>
</CardContent>
</Card>
) : (
<div className="resident-list">
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{filteredResidents.map((resident) => (
<div key={resident.id} className="resident-card">
<div className="resident-card__name">{resident.name}</div>
<div className="resident-card__details">
<span>Room {resident.room}</span>
{resident.table && <span>Table {resident.table}</span>}
{resident.station && <span>{resident.station}</span>}
</div>
{resident.highCaloric && (
<div className="resident-card__badge">High Caloric</div>
)}
{(resident.aversions || resident.notes) && (
<div style={{ marginTop: '0.75rem', fontSize: '0.875rem', color: 'var(--gray-600)' }}>
{resident.aversions && (
<div>
<strong>Aversions:</strong> {resident.aversions}
</div>
)}
{resident.notes && (
<div>
<strong>Notes:</strong> {resident.notes}
</div>
)}
<Card key={resident.id}>
<CardContent className="p-4">
<div className="font-semibold text-lg">{resident.name}</div>
<div className="flex flex-wrap gap-2 text-sm text-muted-foreground mt-1">
<span>Room {resident.room}</span>
{resident.table && <span>Table {resident.table}</span>}
{resident.station && <span>{resident.station}</span>}
</div>
)}
<div style={{ marginTop: '1rem' }}>
<Link
href={`/caregiver/orders/new?resident=${resident.id}`}
className="btn btn--primary btn--block"
>
Create Order
</Link>
</div>
</div>
{resident.highCaloric && (
<Badge variant="secondary" className="mt-3 bg-yellow-100 text-yellow-800">
High Caloric
</Badge>
)}
{(resident.aversions || resident.notes) && (
<div className="mt-3 text-sm text-muted-foreground space-y-1">
{resident.aversions && (
<div>
<span className="font-medium">Aversions:</span> {resident.aversions}
</div>
)}
{resident.notes && (
<div>
<span className="font-medium">Notes:</span> {resident.notes}
</div>
)}
</div>
)}
<Button asChild className="w-full mt-4">
<Link href={`/caregiver/orders/new?resident=${resident.id}`}>
<Plus className="mr-2 h-4 w-4" />
Create Order
</Link>
</Button>
</CardContent>
</Card>
))}
</div>
)}
</main>
</>
</div>
)
}