MIF_E31221222/sigap-website/app/_components/form-wrapper.tsx

159 lines
7.5 KiB
TypeScript

"use client"
import { format } from "date-fns"
import { CalendarIcon, ChevronLeft, ChevronRight } from "lucide-react"
import { cn } from "@/lib/utils"
// UI Components
import { FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription } from "@/app/_components/ui/form"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/app/_components/ui/select"
import { Input } from "@/app/_components/ui/input"
import { Button } from "@/app/_components/ui/button"
import { Textarea } from "@/app/_components/ui/textarea"
import { Popover, PopoverContent, PopoverTrigger } from "@/app/_components/ui/popover"
import { Switch } from "@/app/_components/ui/switch"
import { Checkbox } from "@/app/_components/ui/checkbox"
import { DayPicker } from "react-day-picker"
import { DateTimePicker } from "@/app/_components/date-time-picker"
import { DateTimePicker2 } from "./ui/date-picker"
// Reusable form field component to reduce repetition
interface FormFieldProps {
name: string
label: string
type: string
control: any
placeholder?: string
options?: { value: string; label: string }[]
rows?: number
isDate?: boolean
isBoolean?: boolean
description?: string
booleanType?: "switch" | "checkbox" | "select"
fromYear?: number
toYear?: number
}
export function FormFieldWrapper({
name,
label,
type,
control,
placeholder,
options,
rows = 1,
isDate,
isBoolean,
description,
booleanType = "switch",
fromYear = 1900,
toYear = new Date().getFullYear(),
}: FormFieldProps) {
// Default boolean options for select
const booleanOptions = [
{ value: "false", label: "False" },
{ value: "true", label: "True" },
]
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<FormItem
className={
isBoolean && booleanType === "switch"
? "flex items-start justify-between rounded-lg border p-4"
: "flex justify-between items-start gap-4"
}
>
<div className={isBoolean && booleanType === "switch" ? "space-y-1" : "w-1/3"}>
<FormLabel className={isBoolean && booleanType === "switch" ? "text-base" : ""}>{label}</FormLabel>
<p className="text-xs text-muted-foreground">{type}</p>
{description && isBoolean && booleanType === "switch" && <FormDescription>{description}</FormDescription>}
</div>
<div className={isBoolean && booleanType === "switch" ? "" : "w-2/3"}>
<FormControl>
{isBoolean ? (
booleanType === "switch" ? (
<Switch checked={field.value} onCheckedChange={field.onChange} />
) : booleanType === "checkbox" ? (
<Checkbox checked={field.value} onCheckedChange={field.onChange} />
) : (
<Select
onValueChange={(value) => field.onChange(value === "true")}
defaultValue={String(field.value)}
>
<SelectTrigger>
<SelectValue placeholder={placeholder || `Select ${label.toLowerCase()}`} />
</SelectTrigger>
<SelectContent>
{booleanOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
)
) : type.includes("select") && options ? (
<Select onValueChange={field.onChange} defaultValue={field.value}>
<SelectTrigger>
<SelectValue placeholder={placeholder || `Select ${label.toLowerCase()}`} />
</SelectTrigger>
<SelectContent>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
) : isDate ? (
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
className={cn("w-full pl-3 text-left font-normal", !field.value && "text-muted-foreground")}
>
{field.value ? format(field.value, "MM/dd/yyyy hh:mm:ss a") : <span>Pick a date and time</span>}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<DateTimePicker
selected={field.value instanceof Date ? field.value : undefined}
onSelect={field.onChange}
disabled={(date) => date > new Date() || date < new Date(`${fromYear}-01-01`)}
fromYear={fromYear}
toYear={toYear}
showTimePicker
/>
</PopoverContent>
</Popover>
) : rows > 1 ? (
<Textarea
{...field}
className="resize-none"
rows={rows}
value={field.value ?? ""}
placeholder={placeholder}
/>
) : (
<Input
{...field}
type={type.includes("URL") ? "url" : type === "string" ? "text" : type}
placeholder={placeholder}
value={field.value ?? ""}
/>
)}
</FormControl>
{!(isBoolean && booleanType === "switch") && <FormMessage />}
</div>
</FormItem>
)}
/>
)
}