132 lines
5.4 KiB
TypeScript
132 lines
5.4 KiB
TypeScript
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
|
import { Button } from '@/components/ui/button';
|
|
import { CalendarCheck, CheckCircle2, Clock, LogIn, LogOut } from 'lucide-react';
|
|
|
|
type TodayAttendance = {
|
|
id: number;
|
|
check_in_at: string | null;
|
|
check_out_at: string | null;
|
|
} | null;
|
|
|
|
type TodayAttendanceAlertProps = {
|
|
todayAttendance: TodayAttendance;
|
|
canCheckIn?: boolean;
|
|
isOnLeave?: boolean;
|
|
locationLoading?: boolean;
|
|
onCheckIn?: () => void;
|
|
onCheckOut?: () => void;
|
|
showButtons?: boolean;
|
|
};
|
|
|
|
function formatTime(dateStr: string | null): string {
|
|
if (!dateStr) {
|
|
return '-';
|
|
}
|
|
|
|
return new Date(dateStr).toLocaleTimeString('id-ID', {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
hour12: false,
|
|
});
|
|
}
|
|
|
|
export function TodayAttendanceAlert({
|
|
todayAttendance,
|
|
canCheckIn = true,
|
|
isOnLeave = false,
|
|
locationLoading = false,
|
|
onCheckIn,
|
|
onCheckOut,
|
|
showButtons = true,
|
|
}: TodayAttendanceAlertProps) {
|
|
const hasCheckedIn = !!todayAttendance?.check_in_at;
|
|
const hasCheckedOut = !!todayAttendance?.check_out_at;
|
|
|
|
return (
|
|
<Alert>
|
|
<CalendarCheck className="h-4 w-4" />
|
|
<AlertTitle>Presensi Hari Ini</AlertTitle>
|
|
<AlertDescription>
|
|
<div className="flex flex-col gap-4">
|
|
<div className="flex flex-col gap-1">
|
|
{hasCheckedIn ? (
|
|
<div className="flex items-center gap-4 text-sm">
|
|
<div className="flex items-center gap-1.5">
|
|
<CheckCircle2 className="h-3.5 w-3.5 text-green-600" />
|
|
<span className="text-muted-foreground">
|
|
Masuk:
|
|
</span>
|
|
<span className="font-medium">
|
|
{formatTime(todayAttendance?.check_in_at)}
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-1.5">
|
|
{hasCheckedOut ? (
|
|
<>
|
|
<CheckCircle2 className="h-3.5 w-3.5 text-green-600" />
|
|
<span className="text-muted-foreground">
|
|
Pulang:
|
|
</span>
|
|
<span className="font-medium">
|
|
{formatTime(todayAttendance?.check_out_at)}
|
|
</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Clock className="h-3.5 w-3.5 text-orange-500" />
|
|
<span className="text-muted-foreground">
|
|
Pulang:
|
|
</span>
|
|
<span className="font-medium text-orange-600">
|
|
Belum
|
|
</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : isOnLeave ? (
|
|
<p className="text-sm text-muted-foreground">
|
|
Anda sedang cuti hari ini.
|
|
</p>
|
|
) : !canCheckIn ? (
|
|
<p className="text-sm text-muted-foreground">
|
|
Anda tidak memiliki akses presensi.
|
|
</p>
|
|
) : (
|
|
<p className="text-sm text-muted-foreground">
|
|
Anda belum melakukan presensi hari ini
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
{showButtons && canCheckIn && !isOnLeave && (
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
<Button
|
|
size="sm"
|
|
onClick={onCheckIn}
|
|
disabled={hasCheckedIn || locationLoading}
|
|
>
|
|
<LogIn className="mr-1.5 h-3.5 w-3.5" />
|
|
Presensi Masuk
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onClick={onCheckOut}
|
|
disabled={
|
|
!hasCheckedIn ||
|
|
hasCheckedOut ||
|
|
locationLoading
|
|
}
|
|
>
|
|
<LogOut className="mr-1.5 h-3.5 w-3.5" />
|
|
Presensi Pulang
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</AlertDescription>
|
|
</Alert>
|
|
);
|
|
}
|