swag-shop/frontend/src/pages/sales/recent-sales/components/purchase-action-dialog.tsx

220 lines
5.2 KiB
TypeScript

"use client";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "@/hooks/useToast";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Purchase } from "../data/schema";
import { usePurchase } from "@/hooks/usePurchase";
const formSchema = z.object({
user_id: z.number({ invalid_type_error: "User ID must be a number." }),
used_coupon_id: z.number().nullable().optional(),
total: z
.number({ invalid_type_error: "Total must be a number." })
.min(0, { message: "Total must be at least 0." }),
date_purchased: z.coerce.date({
errorMap: () => ({ message: "Invalid date." })
}),
isEdit: z.boolean()
});
type PurchaseForm = z.infer<typeof formSchema>;
interface Props {
currentRow?: Purchase;
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function PurchasesActionDialog({
currentRow,
open,
onOpenChange
}: Props) {
const { createPurchase, updatePurchase } = usePurchase(currentRow?.id);
const isEdit = !!currentRow;
const form = useForm<PurchaseForm>({
resolver: zodResolver(formSchema),
defaultValues: isEdit
? {
...currentRow,
date_purchased: new Date(currentRow.date_purchased),
isEdit
}
: {
user_id: 0,
used_coupon_id: null,
total: 0,
date_purchased: new Date(),
isEdit
}
});
const onSubmit = (values: PurchaseForm) => {
try {
const payload = {
...values,
date_purchased: values.date_purchased.toISOString()
};
if (isEdit) {
updatePurchase.mutate({ ...currentRow, ...payload });
} else {
createPurchase.mutate({...payload, used_coupon_id: payload.used_coupon_id ?? null });
}
toast({
title: isEdit ? "Purchase updated" : "Purchase created",
description: `User #${values.user_id}${values.total.toFixed(2)}`
});
form.reset();
onOpenChange(false);
} catch (err) {
toast({
title: "An error occurred",
description: (err as Error).message,
variant: "destructive"
});
}
};
return (
<Dialog
open={open}
onOpenChange={(state) => {
form.reset();
onOpenChange(state);
}}>
<DialogContent className="sm:max-w-lg">
<DialogHeader className="text-left">
<DialogTitle>
{isEdit ? "Edit Purchase" : "Add New Purchase"}
</DialogTitle>
<DialogDescription>
{isEdit
? "Update the purchase details below."
: "Record a new purchase."}
</DialogDescription>
</DialogHeader>
<ScrollArea className="-mr-4 h-[26.25rem] w-full py-1 pr-4">
<Form {...form}>
<form
id="purchase-form"
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4 p-0.5">
<FormField
control={form.control}
name="user_id"
render={({ field }) => (
<FormItem>
<FormLabel>User ID</FormLabel>
<FormControl>
<Input
type="number"
placeholder="e.g., 12"
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="used_coupon_id"
render={({ field }) => (
<FormItem>
<FormLabel>Coupon ID (optional)</FormLabel>
<FormControl>
<Input
type="number"
placeholder="e.g., 5"
value={field.value ?? ""}
onChange={(e) => {
const value = e.target.value;
field.onChange(value === "" ? null : Number(value));
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="total"
render={({ field }) => (
<FormItem>
<FormLabel>Total ()</FormLabel>
<FormControl>
<Input
type="number"
step="0.01"
placeholder="e.g., 12.50"
{...field}
onChange={(e) => field.onChange(Number(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="date_purchased"
render={({ field }) => (
<FormItem>
<FormLabel>Purchase Date</FormLabel>
<FormControl>
<Input
type="datetime-local"
value={field.value.toISOString().slice(0, 16)}
onChange={(e) =>
field.onChange(new Date(e.target.value))
}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</ScrollArea>
<DialogFooter>
<Button type="submit" form="purchase-form">
Save changes
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}