diff --git a/src/components/admin/logistics/lunch-event-config.tsx b/src/components/admin/logistics/lunch-event-config.tsx new file mode 100644 index 0000000..50019a9 --- /dev/null +++ b/src/components/admin/logistics/lunch-event-config.tsx @@ -0,0 +1,246 @@ +'use client' + +import { useState } from 'react' +import type { LunchEvent } from '@prisma/client' +import { trpc } from '@/lib/trpc/client' +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { Switch } from '@/components/ui/switch' +import { Textarea } from '@/components/ui/textarea' +import { Badge } from '@/components/ui/badge' +import { X } from 'lucide-react' +import { toast } from 'sonner' + +function toLocalDateTimeInputValue(d: Date | null | undefined): string { + if (!d) return '' + // datetime-local expects "YYYY-MM-DDTHH:mm" in local time. + const pad = (n: number) => String(n).padStart(2, '0') + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad( + d.getHours(), + )}:${pad(d.getMinutes())}` +} + +export function LunchEventConfig({ + programId, + event, +}: { + programId: string + event: LunchEvent +}) { + const utils = trpc.useUtils() + const update = trpc.lunch.updateEvent.useMutation({ + onSuccess: () => { + utils.lunch.getEvent.invalidate({ programId }) + utils.lunch.getEventForMember.invalidate({ programId }) + }, + onError: (e) => toast.error(e.message), + }) + const [extraInput, setExtraInput] = useState('') + + const eventAt = event.eventAt ? new Date(event.eventAt) : null + const endAt = event.endAt ? new Date(event.endAt) : null + + return ( + + + Event configuration + Per-edition lunch settings. + + + {/* enabled */} +
+
+ +

+ When off, attendees see no banner or picker; admins still see this tab. +

+
+ update.mutate({ programId, enabled: v })} + disabled={update.isPending} + /> +
+ + {/* eventAt */} +
+ + { + const v = e.target.value + update.mutate({ programId, eventAt: v ? new Date(v) : null }) + }} + disabled={update.isPending} + className="max-w-sm" + /> +
+ + {/* endAt */} +
+ + { + const v = e.target.value + update.mutate({ programId, endAt: v ? new Date(v) : null }) + }} + disabled={update.isPending} + className="max-w-sm" + /> +
+ + {/* venue */} +
+ + + update.mutate({ programId, venue: e.target.value || null }) + } + disabled={update.isPending} + /> +
+ + {/* notes */} +
+ +