pmtool / src /components /leaves /LeaveStatusUpdate.tsx
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
5.41 kB
import React from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { format } from "date-fns";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Leave, LeaveStatus, LeaveStatusUpdateRequest } from "@/types";
import { toast } from "sonner";
const statusUpdateSchema = z.object({
comments: z.string().min(3, {
message: "Comments must be at least 3 characters",
}).optional(),
});
type StatusUpdateFormValues = z.infer<typeof statusUpdateSchema>;
interface LeaveStatusUpdateProps {
leave: Leave | null;
action: "approve" | "reject";
isOpen: boolean;
onOpenChange: (open: boolean) => void;
onSubmit: (data: LeaveStatusUpdateRequest) => Promise<void>;
approverId: number;
isSubmitting: boolean;
}
const LeaveStatusUpdate: React.FC<LeaveStatusUpdateProps> = ({
leave,
action,
isOpen,
onOpenChange,
onSubmit,
approverId,
isSubmitting,
}) => {
const form = useForm<StatusUpdateFormValues>({
resolver: zodResolver(statusUpdateSchema),
defaultValues: {
comments: "",
},
});
if (!leave) return null;
const handleSubmit = async (values: StatusUpdateFormValues) => {
try {
const updateData: LeaveStatusUpdateRequest = {
id: leave.id,
status: action === "approve" ? "Approved" : "Rejected",
approvedById: approverId,
actionDate: format(new Date(), "yyyy-MM-dd'T'HH:mm:ss"),
comments: values.comments,
};
await onSubmit(updateData);
form.reset();
toast.success(`Leave request ${action === "approve" ? "approved" : "rejected"} successfully`);
onOpenChange(false);
} catch (error) {
console.error(`Error ${action} leave request:`, error);
toast.error(`Failed to ${action} leave request`);
}
};
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>
{action === "approve" ? "Approve" : "Reject"} Leave Request
</DialogTitle>
<DialogDescription>
{action === "approve"
? "Approve the leave request and provide any optional comments."
: "Reject the leave request and provide a reason for rejection."}
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<div className="font-medium">Employee:</div>
<div className="col-span-3">ID: {leave.employeeId}</div>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<div className="font-medium">Date:</div>
<div className="col-span-3">
{format(new Date(leave.startDate), "PPP")} to{" "}
{format(new Date(leave.endDate), "PPP")}
</div>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<div className="font-medium">Type:</div>
<div className="col-span-3">{leave.type}</div>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<div className="font-medium">Reason:</div>
<div className="col-span-3">{leave.reason}</div>
</div>
<FormField
control={form.control}
name="comments"
render={({ field }) => (
<FormItem>
<FormLabel>Comments</FormLabel>
<FormControl>
<Textarea
placeholder={
action === "approve"
? "Optional comments for approval"
: "Please provide a reason for rejection"
}
className="resize-none"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<DialogFooter>
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
Cancel
</Button>
<Button type="submit" disabled={isSubmitting} variant={action === "reject" ? "destructive" : "default"}>
{isSubmitting
? "Processing..."
: action === "approve"
? "Approve"
: "Reject"}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
);
};
export default LeaveStatusUpdate;