Files
myeasycms-v2/packages/features/booking-management/src/components/create-booking-form.tsx

254 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useRouter } from 'next/navigation';
import { zodResolver } from '@hookform/resolvers/zod';
import { useAction } from 'next-safe-action/hooks';
import { useForm } from 'react-hook-form';
import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@kit/ui/form';
import { Input } from '@kit/ui/input';
import { toast } from '@kit/ui/sonner';
import { CreateBookingSchema } from '../schema/booking.schema';
import { createBooking } from '../server/actions/booking-actions';
interface Props {
accountId: string;
account: string;
rooms: Array<{
id: string;
roomNumber: string;
name?: string;
pricePerNight: number;
}>;
}
export function CreateBookingForm({ accountId, account, rooms }: Props) {
const router = useRouter();
const form = useForm({
resolver: zodResolver(CreateBookingSchema),
defaultValues: {
accountId,
roomId: '',
checkIn: '',
checkOut: '',
adults: 1,
children: 0,
status: 'confirmed' as const,
totalPrice: 0,
notes: '',
},
});
const { execute, isPending } = useAction(createBooking, {
onSuccess: ({ data }) => {
if (data?.success) {
toast.success('Buchung erfolgreich erstellt');
router.push(`/home/${account}/bookings-cms`);
}
},
onError: ({ error }) => {
toast.error(error.serverError ?? 'Fehler beim Erstellen der Buchung');
},
});
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit((data) => execute(data))}
className="space-y-6"
>
<Card>
<CardHeader>
<CardTitle>Zimmer & Zeitraum</CardTitle>
</CardHeader>
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-3">
<FormField
control={form.control}
name="roomId"
render={({ field }) => (
<FormItem>
<FormLabel>Zimmer *</FormLabel>
<FormControl>
<select
{...field}
className="border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm"
>
<option value=""> Zimmer wählen </option>
{rooms.map((r) => (
<option key={r.id} value={r.id}>
{r.roomNumber}
{r.name ? ` ${r.name}` : ''} ({r.pricePerNight}{' '}
/Nacht)
</option>
))}
</select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="checkIn"
render={({ field }) => (
<FormItem>
<FormLabel>Check-in *</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="checkOut"
render={({ field }) => (
<FormItem>
<FormLabel>Check-out *</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Gäste</CardTitle>
</CardHeader>
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<FormField
control={form.control}
name="adults"
render={({ field }) => (
<FormItem>
<FormLabel>Erwachsene *</FormLabel>
<FormControl>
<Input
type="number"
min={1}
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="children"
render={({ field }) => (
<FormItem>
<FormLabel>Kinder</FormLabel>
<FormControl>
<Input
type="number"
min={0}
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Preis & Notizen</CardTitle>
</CardHeader>
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<FormField
control={form.control}
name="totalPrice"
render={({ field }) => (
<FormItem>
<FormLabel>Gesamtpreis ()</FormLabel>
<FormControl>
<Input
type="number"
min={0}
step="0.01"
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>Status</FormLabel>
<FormControl>
<select
{...field}
className="border-input bg-background flex h-10 w-full rounded-md border px-3 py-2 text-sm"
>
<option value="pending">Ausstehend</option>
<option value="confirmed">Bestätigt</option>
<option value="checked_in">Eingecheckt</option>
<option value="checked_out">Ausgecheckt</option>
<option value="cancelled">Storniert</option>
<option value="no_show">Nicht erschienen</option>
</select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="sm:col-span-2">
<FormField
control={form.control}
name="notes"
render={({ field }) => (
<FormItem>
<FormLabel>Notizen</FormLabel>
<FormControl>
<textarea
{...field}
className="border-input bg-background flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
<div className="flex justify-end gap-2">
<Button type="button" variant="outline" onClick={() => router.back()}>
Abbrechen
</Button>
<Button type="submit" disabled={isPending}>
{isPending ? 'Wird erstellt...' : 'Buchung erstellen'}
</Button>
</div>
</form>
</Form>
);
}