import { Head, router } from '@inertiajs/react'; import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Separator } from '@/components/ui/separator'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import AppLayout from '@/layouts/app-layout'; import { Search } from 'lucide-react'; import { useDebounce } from 'use-debounce'; import * as XLSX from 'xlsx'; import { AttendanceMapModal } from '@/components/AttendanceMapModal'; interface Attendance { id: number; employee_name: string; employee_nik: string; date: string; check_in: string | null; check_out: string | null; status: 'present' | 'leave' | 'dispensation'; notes: string | null; total_hours: string | null; latitude_in?: string | null; longitude_in?: string | null; latitude_out?: string | null; longitude_out?: string | null; } interface PageProps { attendances: Attendance[]; filters: { search?: string; date?: string; status?: string }; [key: string]: unknown; } export default function Index({ attendances, filters }: PageProps) { const [search, setSearch] = useState(filters.search || ''); const [date, setDate] = useState(filters.date || ''); const [status, setStatus] = useState(filters.status || 'all'); const [debouncedSearch] = useDebounce(search, 500); useEffect(() => { if (debouncedSearch !== filters.search || date !== filters.date || (status !== 'all' && status !== filters.status)) { router.get( '/admin/attendances', { search: debouncedSearch, date, status: status === 'all' ? '' : status }, { preserveState: true, replace: true } ); } }, [debouncedSearch, date, status]); const exportExcel = () => { const rows = attendances.map((a, i) => ({ No: i + 1, Nama: a.employee_name, NIK: a.employee_nik, Tanggal: a.date, 'Jam Masuk': a.check_in || '-', 'Jam Keluar': a.check_out || '-', Status: a.status === 'present' ? 'Hadir' : a.status === 'leave' ? 'Izin/Cuti' : 'Dispensasi', 'Total Jam': a.total_hours ? `${a.total_hours} Jam` : '-', Catatan: a.notes || '-', })); const ws = XLSX.utils.json_to_sheet(rows); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, 'Absensi'); XLSX.writeFile(wb, `Data_Absensi_${new Date().toISOString().slice(0, 10)}.xlsx`); }; const formatStatus = (status: string) => { switch (status) { case 'present': return Hadir; case 'leave': return Izin/Cuti; case 'dispensation': return Dispensasi; default: return {status}; } }; return (

Rekap Absensi Karyawan

Monitoring kehadiran, izin, dan dispensasi karyawan.

Daftar Absensi
setSearch(e.target.value)} />
setDate(e.target.value)} />
Nama NIK Tanggal Jam Masuk Jam Keluar Lokasi Peta Keterangan Total Jam Kerja {attendances.length > 0 ? ( attendances.map((attendance) => ( {attendance.employee_name} {attendance.employee_nik} {attendance.date} {attendance.check_in || '-'} {attendance.check_out || '-'}
{formatStatus(attendance.status)} {attendance.notes && ( {attendance.notes} )}
{attendance.total_hours ? `${attendance.total_hours} Jam` : '-'}
)) ) : ( Belum ada data absensi. )}
); }