'use client'
import React, { useState, useEffect, Suspense } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import Link from 'next/link'
import { format } from 'date-fns'
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
name: string
room: string
table?: string
station?: string
highCaloric?: boolean
aversions?: string
notes?: string
}
type MealType = 'breakfast' | 'lunch' | 'dinner'
interface BreakfastOptions {
accordingToPlan: boolean
bread: {
breadRoll: boolean
wholeGrainRoll: boolean
greyBread: boolean
wholeGrainBread: boolean
whiteBread: boolean
crispbread: boolean
}
porridge: boolean
preparation: { sliced: boolean; spread: boolean }
spreads: {
butter: boolean
margarine: boolean
jam: boolean
diabeticJam: boolean
honey: boolean
cheese: boolean
quark: boolean
sausage: boolean
}
beverages: { coffee: boolean; tea: boolean; hotMilk: boolean; coldMilk: boolean }
additions: { sugar: boolean; sweetener: boolean; coffeeCreamer: boolean }
}
interface LunchOptions {
portionSize: 'small' | 'large' | 'vegetarian'
soup: boolean
dessert: boolean
specialPreparations: {
pureedFood: boolean
pureedMeat: boolean
slicedMeat: boolean
mashedPotatoes: boolean
}
restrictions: { noFish: boolean; fingerFood: boolean; onlySweet: boolean }
}
interface DinnerOptions {
accordingToPlan: boolean
bread: { greyBread: boolean; wholeGrainBread: boolean; whiteBread: boolean; crispbread: boolean }
preparation: { spread: boolean; sliced: boolean }
spreads: { butter: boolean; margarine: boolean }
soup: boolean
porridge: boolean
noFish: boolean
beverages: { tea: boolean; cocoa: boolean; hotMilk: boolean; coldMilk: boolean }
additions: { sugar: boolean; sweetener: boolean }
}
const defaultBreakfast: BreakfastOptions = {
accordingToPlan: false,
bread: {
breadRoll: false,
wholeGrainRoll: false,
greyBread: false,
wholeGrainBread: false,
whiteBread: false,
crispbread: false,
},
porridge: false,
preparation: { sliced: false, spread: false },
spreads: {
butter: false,
margarine: false,
jam: false,
diabeticJam: false,
honey: false,
cheese: false,
quark: false,
sausage: false,
},
beverages: { coffee: false, tea: false, hotMilk: false, coldMilk: false },
additions: { sugar: false, sweetener: false, coffeeCreamer: false },
}
const defaultLunch: LunchOptions = {
portionSize: 'large',
soup: false,
dessert: true,
specialPreparations: {
pureedFood: false,
pureedMeat: false,
slicedMeat: false,
mashedPotatoes: false,
},
restrictions: { noFish: false, fingerFood: false, onlySweet: false },
}
const defaultDinner: DinnerOptions = {
accordingToPlan: false,
bread: { greyBread: false, wholeGrainBread: false, whiteBread: false, crispbread: false },
preparation: { spread: false, sliced: false },
spreads: { butter: false, margarine: false },
soup: false,
porridge: false,
noFish: false,
beverages: { tea: false, cocoa: false, hotMilk: false, coldMilk: false },
additions: { sugar: false, sweetener: false },
}
function CheckboxOption({
id,
label,
checked,
onCheckedChange,
}: {
id: string
label: string
checked: boolean
onCheckedChange: (checked: boolean) => void
}) {
return (
onCheckedChange(!checked)}
>
)
}
function NewOrderContent() {
const router = useRouter()
const searchParams = useSearchParams()
const initialMealType = (searchParams.get('mealType') as MealType) || null
const [step, setStep] = useState(initialMealType ? 2 : 1)
const [residents, setResidents] = useState([])
const [selectedResident, setSelectedResident] = useState(null)
const [mealType, setMealType] = useState(initialMealType)
const [date, setDate] = useState(() => format(new Date(), 'yyyy-MM-dd'))
const [breakfast, setBreakfast] = useState(defaultBreakfast)
const [lunch, setLunch] = useState(defaultLunch)
const [dinner, setDinner] = useState(defaultDinner)
const [loading, setLoading] = useState(true)
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState(null)
const [searchQuery, setSearchQuery] = useState('')
useEffect(() => {
const fetchResidents = async () => {
try {
const res = await fetch('/api/residents?where[active][equals]=true&limit=100&sort=name', {
credentials: 'include',
})
if (res.ok) {
const data = await res.json()
setResidents(data.docs || [])
} else if (res.status === 401) {
router.push('/caregiver/login')
}
} catch (err) {
console.error('Error fetching residents:', err)
} finally {
setLoading(false)
}
}
fetchResidents()
}, [router])
const filteredResidents = residents.filter(
(r) =>
r.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
r.room.toLowerCase().includes(searchQuery.toLowerCase()),
)
const handleSubmit = async () => {
if (!selectedResident || !mealType || !date) return
setSubmitting(true)
setError(null)
try {
const orderData: Record = {
resident: selectedResident.id,
date,
mealType,
status: 'pending',
}
if (mealType === 'breakfast') {
orderData.breakfast = breakfast
} else if (mealType === 'lunch') {
orderData.lunch = lunch
} else if (mealType === 'dinner') {
orderData.dinner = dinner
}
const res = await fetch('/api/meal-orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData),
credentials: 'include',
})
if (!res.ok) {
const data = await res.json()
throw new Error(data.errors?.[0]?.message || 'Failed to create order')
}
router.push('/caregiver/dashboard')
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred')
} finally {
setSubmitting(false)
}
}
const getMealTypeLabel = (type: MealType) => {
switch (type) {
case 'breakfast':
return 'Breakfast (Frühstück)'
case 'lunch':
return 'Lunch (Mittagessen)'
case 'dinner':
return 'Dinner (Abendessen)'
}
}
if (loading) {
return (
)
}
return (
{/* Progress Steps */}
{[1, 2, 3, 4].map((s) => (
= s ? (step > s ? 'bg-green-500' : 'bg-primary') : 'bg-muted'
)}
/>
))}
{error && (
{error}
)}
{/* Step 1: Select Meal Type */}
{step === 1 && (
Step 1: Select Meal Type
setDate(e.target.value)}
/>
{[
{ 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 }) => (
setMealType(type)}
>
{label}
{sublabel}
))}
)}
{/* Step 2: Select Resident */}
{step === 2 && (
Step 2: Select Resident
setSearchQuery(e.target.value)}
className="pl-10"
/>
{filteredResidents.map((resident) => (
setSelectedResident(resident)}
>
{resident.name}
Room {resident.room}
{resident.table && Table {resident.table}}
{resident.highCaloric && (
High Caloric
)}
))}
)}
{/* Step 3: Meal Options */}
{step === 3 && (
Step 3: {mealType && getMealTypeLabel(mealType)} Options
{(selectedResident?.aversions || selectedResident?.notes) && (
Notes for {selectedResident?.name}
{selectedResident?.aversions && Aversions: {selectedResident.aversions}
}
{selectedResident?.notes && {selectedResident.notes}
}
)}
{/* BREAKFAST OPTIONS */}
{mealType === 'breakfast' && (
<>
General
setBreakfast({ ...breakfast, accordingToPlan: v })}
/>
Bread (Brot)
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, breadRoll: v } })} />
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainRoll: v } })} />
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, greyBread: v } })} />
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, wholeGrainBread: v } })} />
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, whiteBread: v } })} />
setBreakfast({ ...breakfast, bread: { ...breakfast.bread, crispbread: v } })} />
Preparation
setBreakfast({ ...breakfast, porridge: v })} />
setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, sliced: v } })} />
setBreakfast({ ...breakfast, preparation: { ...breakfast.preparation, spread: v } })} />
Spreads (Aufstrich)
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, butter: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, margarine: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, jam: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, diabeticJam: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, honey: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, cheese: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, quark: v } })} />
setBreakfast({ ...breakfast, spreads: { ...breakfast.spreads, sausage: v } })} />
Beverages (Getränke)
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coffee: v } })} />
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, tea: v } })} />
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, hotMilk: v } })} />
setBreakfast({ ...breakfast, beverages: { ...breakfast.beverages, coldMilk: v } })} />
Additions (Zusätze)
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sugar: v } })} />
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, sweetener: v } })} />
setBreakfast({ ...breakfast, additions: { ...breakfast.additions, coffeeCreamer: v } })} />
>
)}
{/* LUNCH OPTIONS */}
{mealType === 'lunch' && (
<>
Portion Size
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 }) => (
setLunch({ ...lunch, portionSize: value as 'small' | 'large' | 'vegetarian' })}
>
))}
Meal Options
setLunch({ ...lunch, soup: v })} />
setLunch({ ...lunch, dessert: v })} />
Special Preparations
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedFood: v } })} />
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, pureedMeat: v } })} />
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, slicedMeat: v } })} />
setLunch({ ...lunch, specialPreparations: { ...lunch.specialPreparations, mashedPotatoes: v } })} />
Restrictions
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, noFish: v } })} />
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, fingerFood: v } })} />
setLunch({ ...lunch, restrictions: { ...lunch.restrictions, onlySweet: v } })} />
>
)}
{/* DINNER OPTIONS */}
{mealType === 'dinner' && (
<>
General
setDinner({ ...dinner, accordingToPlan: v })}
/>
Bread (Brot)
setDinner({ ...dinner, bread: { ...dinner.bread, greyBread: v } })} />
setDinner({ ...dinner, bread: { ...dinner.bread, wholeGrainBread: v } })} />
setDinner({ ...dinner, bread: { ...dinner.bread, whiteBread: v } })} />
setDinner({ ...dinner, bread: { ...dinner.bread, crispbread: v } })} />
Preparation
setDinner({ ...dinner, preparation: { ...dinner.preparation, spread: v } })} />
setDinner({ ...dinner, preparation: { ...dinner.preparation, sliced: v } })} />
Spreads (Aufstrich)
setDinner({ ...dinner, spreads: { ...dinner.spreads, butter: v } })} />
setDinner({ ...dinner, spreads: { ...dinner.spreads, margarine: v } })} />
Additional Items
setDinner({ ...dinner, soup: v })} />
setDinner({ ...dinner, porridge: v })} />
setDinner({ ...dinner, noFish: v })} />
Beverages (Getränke)
setDinner({ ...dinner, beverages: { ...dinner.beverages, tea: v } })} />
setDinner({ ...dinner, beverages: { ...dinner.beverages, cocoa: v } })} />
setDinner({ ...dinner, beverages: { ...dinner.beverages, hotMilk: v } })} />
setDinner({ ...dinner, beverages: { ...dinner.beverages, coldMilk: v } })} />
Additions (Zusätze)
setDinner({ ...dinner, additions: { ...dinner.additions, sugar: v } })} />
setDinner({ ...dinner, additions: { ...dinner.additions, sweetener: v } })} />
>
)}
)}
{/* Step 4: Review and Submit */}
{step === 4 && (
Step 4: Review & Submit
Resident
{selectedResident?.name}
Room
{selectedResident?.room}
Date
{date}
Meal Type
{mealType && getMealTypeLabel(mealType)}
{selectedResident?.highCaloric && (
Note: This resident requires high caloric meals.
)}
)}
)
}
export default function NewOrderPage() {
return (
}
>
)
}