dstpabuaran.com/resources/js/components/card/attendance-card.tsx

103 lines
4.5 KiB
TypeScript

import { Clock, LogIn, LogOut } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
type TodayAttendance = {
id: number;
attendance_date: string;
check_in_at: string | null;
check_out_at: string | null;
check_in_photo: string | null;
check_out_photo: string | null;
check_in_latitude: number;
check_in_longitude: number;
check_out_latitude: number | null;
check_out_longitude: number | null;
work_duration_minutes: number | null;
} | null;
type AttendanceCardProps = {
todayAttendance: TodayAttendance;
isOnLeave: boolean;
canCheckIn: boolean;
onCheckIn?: () => void;
onCheckOut?: () => void;
};
export function AttendanceCard({ todayAttendance, isOnLeave, canCheckIn, onCheckIn, onCheckOut }: AttendanceCardProps) {
const hasCheckedIn = !!todayAttendance?.check_in_at;
const hasCheckedOut = !!todayAttendance?.check_out_at;
function formatTime(dateStr: string | null): string {
if (!dateStr) {
return '-';
}
const d = new Date(dateStr);
return d.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', hour12: false });
}
return (
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<div className="flex size-8 items-center justify-center rounded-md bg-muted">
<Clock className="size-4 text-muted-foreground" />
</div>
<CardTitle>Presensi Hari Ini</CardTitle>
</div>
</CardHeader>
<CardContent>
{isOnLeave ? (
<div className="rounded-md bg-yellow-50 p-3 text-sm text-yellow-700 dark:bg-yellow-900/20 dark:text-yellow-400">
Anda sedang cuti hari ini.
</div>
) : !canCheckIn ? (
<div className="rounded-md bg-muted p-3 text-sm text-muted-foreground">
Anda tidak memiliki akses presensi.
</div>
) : (
<div className="space-y-3">
<div className="grid grid-cols-2 gap-3">
<div className="rounded-md bg-muted p-3">
<p className="text-xs text-muted-foreground">Masuk</p>
<p className="text-lg font-semibold">{formatTime(todayAttendance?.check_in_at ?? null)}</p>
</div>
<div className="rounded-md bg-muted p-3">
<p className="text-xs text-muted-foreground">Pulang</p>
<p className="text-lg font-semibold">{formatTime(todayAttendance?.check_out_at ?? null)}</p>
</div>
</div>
{todayAttendance?.work_duration_minutes != null && (
<div className="rounded-md bg-muted p-3">
<p className="text-xs text-muted-foreground">Durasi Kerja</p>
<p className="text-lg font-semibold">
{Math.floor(todayAttendance.work_duration_minutes / 60)}j {todayAttendance.work_duration_minutes % 60}m
</p>
</div>
)}
<div className="flex gap-2">
{!hasCheckedIn ? (
<Button onClick={onCheckIn} className="flex-1">
<LogIn className="mr-2 size-4" />
Presensi Masuk
</Button>
) : !hasCheckedOut ? (
<Button onClick={onCheckOut} className="flex-1" variant="destructive">
<LogOut className="mr-2 size-4" />
Presensi Pulang
</Button>
) : (
<div className="flex-1 rounded-md bg-green-50 p-3 text-center text-sm text-green-700 dark:bg-green-900/20 dark:text-green-400">
Presensi selesai untuk hari ini.
</div>
)}
</div>
</div>
)}
</CardContent>
</Card>
);
}