pmtool / src /components /leaves /LeaveBalance.tsx
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
4.04 kB
import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { LeaveBalance as LeaveBalanceType } from "@/types";
import { cn } from "@/lib/utils";
import { Loader2 } from "lucide-react";
interface LeaveBalanceDisplayProps {
balances: LeaveBalanceType[];
year: number;
isLoading?: boolean;
}
const LeaveBalance: React.FC<LeaveBalanceDisplayProps> = ({
balances,
year,
isLoading = false,
}) => {
// Function to calculate percentage used
const calculatePercentage = (used: number, total: number) => {
if (total === 0) return 0;
return Math.min((used / total) * 100, 100); // Cap at 100%
};
// Map leave master IDs to types and colors
const leaveTypeMap: Record<number, { label: string, color: string }> = {
4: { label: "Annual Leave", color: "bg-blue-500" },
5: { label: "Sick Leave", color: "bg-red-500" },
6: { label: "Personal Leave", color: "bg-green-500" },
7: { label: "Unpaid Leave", color: "bg-gray-500" },
8: { label: "Maternity Leave", color: "bg-pink-500" },
9: { label: "Paternity Leave", color: "bg-purple-500" },
10: { label: "Compensatory Leave", color: "bg-orange-500" },
11: { label: "Bereavement Leave", color: "bg-slate-500" },
13: { label: "Half Day Leave", color: "bg-amber-500" },
};
if (isLoading) {
return (
<Card className="w-full">
<CardHeader>
<CardTitle className="text-lg">Leave Balance ({year})</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center justify-center py-6">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
</CardContent>
</Card>
);
}
if (!balances || balances.length === 0) {
return (
<Card className="w-full">
<CardHeader>
<CardTitle className="text-lg">Leave Balance ({year})</CardTitle>
</CardHeader>
<CardContent>
<p className="text-center text-muted-foreground py-6">
No leave balance information available
</p>
</CardContent>
</Card>
);
}
return (
<Card className="w-full">
<CardHeader>
<CardTitle className="text-lg">Leave Balance ({year})</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{balances.map((balance) => {
const typeInfo = leaveTypeMap[balance.leavesMasterId] ||
{ label: `Leave Type ${balance.leavesMasterId}`, color: "bg-gray-500" };
const percentage = calculatePercentage(balance.used, balance.allocated);
const remaining = balance.pending;
return (
<div key={balance.id} className="space-y-1">
<div className="flex justify-between text-sm">
<span>{typeInfo.label}</span>
{balance.allocated === 0 ? (
<span>Unlimited</span>
) : (
<span className="font-medium">
{remaining} of {balance.allocated} days left
</span>
)}
</div>
<div className="relative h-2 w-full overflow-hidden rounded-full bg-secondary">
<div
className={cn("h-full absolute left-0 top-0", typeInfo.color)}
style={{ width: `${percentage}%` }}
/>
</div>
{balance.carryForward > 0 && (
<div className="text-xs text-muted-foreground">
Includes {balance.carryForward} carried forward days
</div>
)}
</div>
);
})}
</div>
</CardContent>
</Card>
);
};
export default LeaveBalance;