'use client' import { useEffect, useState } from 'react' import { trpc } from '@/lib/trpc/client' import { toast } from 'sonner' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Skeleton } from '@/components/ui/skeleton' import { ExternalLink, Hotel as HotelIcon, Loader2, Save } from 'lucide-react' interface Props { programId: string } export function HotelsTab({ programId }: Props) { const utils = trpc.useUtils() const { data: hotel, isLoading } = trpc.logistics.getHotel.useQuery({ programId }) const [name, setName] = useState('') const [address, setAddress] = useState('') const [link, setLink] = useState('') const [notes, setNotes] = useState('') // Sync form state from server data on first load / after save. useEffect(() => { if (hotel) { setName(hotel.name) setAddress(hotel.address ?? '') setLink(hotel.link ?? '') setNotes(hotel.notes ?? '') } }, [hotel]) const upsertMutation = trpc.logistics.upsertHotel.useMutation({ onSuccess: () => { toast.success('Hotel saved') utils.logistics.getHotel.invalidate({ programId }) }, onError: (err) => toast.error(err.message), }) const handleSave = () => { if (!name.trim()) { toast.error('Hotel name is required') return } upsertMutation.mutate({ programId, name: name.trim(), address: address.trim() || undefined, link: link.trim() || '', notes: notes.trim() || undefined, }) } if (isLoading) return const dirty = name !== (hotel?.name ?? '') || address !== (hotel?.address ?? '') || link !== (hotel?.link ?? '') || notes !== (hotel?.notes ?? '') return (
Hotel for this edition
One hotel per edition. Used in confirmation emails and finalist communications.
setName(e.target.value)} placeholder="Hôtel de Paris" required />