Files
weeding/src/app/dashboard/reservations/new/reservation-form.tsx

292 lines
13 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 { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
import { createReservation } from "./actions"
import { useState } from "react"
import { toast } from "sonner"
import { Check, ChevronsUpDown } from "lucide-react"
import { cn } from "@/lib/utils"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
const formSchema = z.object({
hall_id: z.string().min(1, "Salon seçmelisiniz."),
customer_id: z.string().min(1, "Müşteri seçmelisiniz."),
package_id: z.string().optional(),
date: z.string().min(1, "Tarih seçmelisiniz."),
start_time: z.string().min(1, "Başlangıç saati seçmelisiniz."),
end_time: z.string().min(1, "Bitiş saati seçmelisiniz."),
notes: z.string().optional(),
})
interface ReservationFormProps {
halls: { id: string, name: string }[]
customers: { id: string, full_name: string, phone?: string | null }[]
packages: { id: string, name: string, price: number }[]
}
export function ReservationForm({ halls, customers, packages }: ReservationFormProps) {
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [openCustomer, setOpenCustomer] = useState(false)
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
hall_id: "",
customer_id: "",
package_id: "",
date: "",
start_time: "",
end_time: "",
notes: "",
},
})
async function onSubmit(values: z.infer<typeof formSchema>) {
setLoading(true)
setError(null)
// Combine date and time
const startDateTime = new Date(`${values.date}T${values.start_time}`)
const endDateTime = new Date(`${values.date}T${values.end_time}`)
if (endDateTime <= startDateTime) {
setError("Bitiş saati başlangıç saatinden sonra olmalıdır.")
setLoading(false)
return
}
try {
const result = await createReservation({
hall_id: values.hall_id,
customer_id: values.customer_id,
package_id: values.package_id === "none" ? undefined : values.package_id,
start_time: startDateTime.toISOString(),
end_time: endDateTime.toISOString(),
notes: values.notes,
})
if (result && result.error) {
setError(result.error)
}
} catch (e) {
setError("Beklenmedik bir hata oluştu.")
} finally {
setLoading(false)
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
{error && (
<div className="bg-destructive/15 text-destructive px-4 py-2 rounded-md text-sm font-medium">
{error}
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="hall_id"
render={({ field }) => (
<FormItem>
<FormLabel>Salon</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Salon Seçin" />
</SelectTrigger>
</FormControl>
<SelectContent>
{halls.map(hall => (
<SelectItem key={hall.id} value={hall.id}>{hall.name}</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="customer_id"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Müşteri</FormLabel>
<Popover open={openCustomer} onOpenChange={setOpenCustomer}>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
aria-expanded={openCustomer}
className={cn(
"w-full justify-between",
!field.value && "text-muted-foreground"
)}
>
{field.value
? customers.find((customer) => customer.id === field.value)?.full_name
: "Müşteri Seçin"}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[300px] p-0">
<Command>
<CommandInput placeholder="Müşteri ara (İsim veya Telefon)..." />
<CommandList>
<CommandEmpty>Müşteri bulunamadı.</CommandEmpty>
<CommandGroup>
{customers.map((customer) => (
<CommandItem
value={`${customer.full_name} ${customer.phone || ''}`}
key={customer.id}
onSelect={() => {
form.setValue("customer_id", customer.id)
setOpenCustomer(false)
}}
>
<Check
className={cn(
"mr-2 h-4 w-4",
customer.id === field.value
? "opacity-100"
: "opacity-0"
)}
/>
<div className="flex flex-col">
<span>{customer.full_name}</span>
{customer.phone && (
<span className="text-xs text-muted-foreground">{customer.phone}</span>
)}
</div>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<FormField
control={form.control}
name="date"
render={({ field }) => (
<FormItem>
<FormLabel>Tarih</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="start_time"
render={({ field }) => (
<FormItem>
<FormLabel>Başlangıç Saati</FormLabel>
<FormControl>
<Input type="time" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="end_time"
render={({ field }) => (
<FormItem>
<FormLabel>Bitiş Saati</FormLabel>
<FormControl>
<Input type="time" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="package_id"
render={({ field }) => (
<FormItem>
<FormLabel>Paket (Opsiyonel)</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Paket Seçin" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="none">Paket Yok</SelectItem>
{packages.map(p => (
<SelectItem key={p.id} value={p.id}>{p.name} - {p.price}</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="notes"
render={({ field }) => (
<FormItem>
<FormLabel>Notlar</FormLabel>
<FormControl>
<Textarea placeholder="Özel istekler..." {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" disabled={loading} className="w-full">
{loading ? "Oluşturuluyor..." : "Rezervasyonu Oluştur"}
</Button>
</form>
</Form>
)
}