/* eslint-disable @typescript-eslint/no-explicit-any */ import { Head, Link, router, usePage } from '@inertiajs/react'; import React, { useEffect, useState } from 'react'; import { useDebounce } from 'use-debounce'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Separator } from '@/components/ui/separator'; import AppLayout from '@/layouts/app-layout'; interface Attendance { id: number; date: string; shift: 'Pagi' | 'Siang' | 'Malam'; status: 'hadir' | 'izin' | 'sakit' | 'alpha'; check_in: string | null; check_out: string | null; notes: string | null; employee: { id: number; name: string; nip: string; department: { id: number; name: string; } | null; }; } interface PageProps { attendances: { data: Attendance[]; links: any[]; }; departments: { id: number; name: string }[]; filters: { search?: string; status?: string; date?: string; department_id?: string; }; [key: string]: unknown; } interface SharedData { flash: { success?: string; error?: string; }; } const statusClass: Record = { hadir: 'bg-emerald-100 text-emerald-700 hover:bg-emerald-100', izin: 'bg-blue-100 text-blue-700 hover:bg-blue-100', sakit: 'bg-amber-100 text-amber-700 hover:bg-amber-100', alpha: 'bg-rose-100 text-rose-700 hover:bg-rose-100', }; function formatDate(value: string): string { return new Date(value).toLocaleDateString('id-ID', { day: '2-digit', month: 'long', year: 'numeric', }); } function formatTime(value: string | null): string { if (!value) return '-'; return new Date(value).toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', }); } export default function Index({ attendances, departments, filters }: PageProps) { const { flash } = usePage().props as SharedData; const [search, setSearch] = useState(filters.search || ''); const [status, setStatus] = useState(filters.status || 'all'); const [departmentId, setDepartmentId] = useState(filters.department_id || 'all'); const [date, setDate] = useState(filters.date || ''); const [debouncedSearch] = useDebounce(search, 500); useEffect(() => { router.get( '/admin/attendance', { search: debouncedSearch || '', status: status === 'all' ? '' : status, department_id: departmentId === 'all' ? '' : departmentId, date, }, { preserveState: true, replace: true } ); }, [debouncedSearch, status, departmentId, date]); return (

Manajemen Absensi

Pantau absensi harian karyawan berdasarkan tanggal, status, dan departemen.

{flash?.success && (
{flash.success}
)} {flash?.error && (
{flash.error}
)} Daftar Absensi
setSearch(e.target.value)} /> setDate(e.target.value)} />
{attendances.data.length > 0 ? ( attendances.data.map((attendance) => ( )) ) : ( )}
Tanggal Karyawan Shift Masuk Pulang Status Catatan
{formatDate(attendance.date)}
{attendance.employee.name}
NIP: {attendance.employee.nip} | {attendance.employee.department?.name || '-'}
{attendance.shift} {formatTime(attendance.check_in)} {formatTime(attendance.check_out)} {attendance.status.toUpperCase()} {attendance.notes || '-'}
Belum ada data absensi.
); }