85 lines
3.4 KiB
TypeScript
85 lines
3.4 KiB
TypeScript
import { Badge } from '@/components/ui/badge';
|
|
import {
|
|
Card,
|
|
CardDescription,
|
|
CardFooter,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from '@/components/ui/card';
|
|
import { cn } from '@/lib/utils';
|
|
import type { Payroll } from '@/types';
|
|
|
|
export interface PayrollCardProps {
|
|
payroll: Payroll;
|
|
onClick?: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function PayrollCard({ payroll, onClick, className }: PayrollCardProps) {
|
|
return (
|
|
<Card
|
|
className={cn(
|
|
'@container/card relative cursor-pointer bg-card/50 shadow-lg backdrop-blur-sm transition-transform hover:scale-[1.02]',
|
|
className,
|
|
)}
|
|
onClick={onClick}
|
|
>
|
|
<CardHeader className="gap-3">
|
|
<div className="flex w-full items-start justify-between gap-3">
|
|
<CardDescription className="min-w-0 flex-1 leading-tight font-bold break-words text-foreground">
|
|
{payroll.user?.name}
|
|
</CardDescription>
|
|
<Badge
|
|
variant={payroll.is_paid ? 'default' : 'outline'}
|
|
className={cn(
|
|
'flex shrink-0 items-center gap-1 px-1.5 py-0.5 text-[10px] font-bold sm:text-xs',
|
|
payroll.is_paid
|
|
? 'bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300'
|
|
: 'text-muted-foreground',
|
|
)}
|
|
>
|
|
{payroll.is_paid ? 'Lunas' : 'Pending'}
|
|
</Badge>
|
|
</div>
|
|
|
|
<CardTitle className="text-xl font-bold tracking-tight break-words tabular-nums sm:text-2xl">
|
|
{payroll.total_salary_formatted}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
|
|
<CardFooter className="flex-col items-start gap-1.5 text-xs">
|
|
<div className="w-full space-y-1">
|
|
<div className="flex justify-between text-muted-foreground">
|
|
<span>Gaji Pokok</span>
|
|
<span>{payroll.base_salary_formatted}</span>
|
|
</div>
|
|
{payroll.adjustments?.map((adj, idx) => (
|
|
<div
|
|
key={idx}
|
|
className="flex justify-between text-muted-foreground italic"
|
|
>
|
|
<span>{adj.description}</span>
|
|
<span
|
|
className={
|
|
adj.type === 'bonus'
|
|
? 'font-medium text-green-600'
|
|
: 'font-medium text-red-500'
|
|
}
|
|
>
|
|
{adj.type === 'bonus' ? '+' : '-'}
|
|
{adj.amount_formatted}
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="mt-1.5 flex w-full items-center justify-between border-t pt-1.5 text-muted-foreground">
|
|
<span>Periode</span>
|
|
<span className="font-semibold text-foreground">
|
|
{payroll.period_month_formatted}
|
|
</span>
|
|
</div>
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
}
|