siakad-itm/resources/js/components/form-dialog.tsx

94 lines
3.1 KiB
TypeScript

import { Form } from '@inertiajs/react';
import { Save, X } from 'lucide-react';
import type { ReactNode } from 'react';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { cn } from '@/lib/utils';
type FormDialogProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;
action: React.ComponentProps<typeof Form>['action'];
resetOnSuccess?: boolean;
onSuccess?: () => void;
submitDisabled?: boolean;
submitLabel?: ReactNode;
submittingLabel?: ReactNode;
contentClassName?: string;
children:
| ReactNode
| ((ctx: {
errors: Record<string, string>;
processing: boolean;
}) => ReactNode);
};
export function FormDialog({
open,
onOpenChange,
title,
action,
resetOnSuccess,
onSuccess,
submitDisabled = false,
submitLabel = 'Simpan',
submittingLabel = 'Menyimpan...',
contentClassName,
children,
}: FormDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
className={cn(
'flex max-h-[85vh] flex-col overflow-hidden',
contentClassName,
)}
>
<Form
action={action}
resetOnSuccess={resetOnSuccess}
onSuccess={onSuccess}
className="flex min-h-0 flex-1 flex-col"
>
{({ errors, processing }) => (
<>
<DialogHeader className="shrink-0">
<DialogTitle>{title}</DialogTitle>
</DialogHeader>
<div className="grid flex-1 gap-4 overflow-y-auto py-4">
{typeof children === 'function'
? children({ errors, processing })
: children}
</div>
<DialogFooter className="shrink-0">
<Button
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
>
<X className="h-4 w-4" />
Batal
</Button>
<Button
type="submit"
disabled={processing || submitDisabled}
>
<Save className="h-4 w-4" />
{processing ? submittingLabel : submitLabel}
</Button>
</DialogFooter>
</>
)}
</Form>
</DialogContent>
</Dialog>
);
}