'use client'; import { useState } from 'react'; import { Plus, MoreVertical, Pencil, Trash2, Search, Loader2, } from 'lucide-react'; import { Card, CardContent } from '@/figma-make/components/base/card'; import { Button } from '@/figma-make/components/base/button'; import { Label } from '@/figma-make/components/base/label'; import { Input } from '@/figma-make/components/base/input'; import { Badge } from '@/figma-make/components/base/badge'; import { MultiSelect } from '@/figma-make/components/base/multi-select'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/figma-make/components/base/select'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/figma-make/components/base/dialog'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/figma-make/components/base/alert-dialog'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/figma-make/components/base/dropdown-menu'; import { toast } from 'sonner'; import useSWR from 'swr'; import { EmployeeApi } from '@/services/api/daily-checklist/employee'; import Table from '@/components/Table'; import { Employee } from '@/types/api/daily-checklist/employee'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { cn } from '@/lib/helper'; import { useTableFilter } from '@/services/hooks/useTableFilter'; import { ColumnDef } from '@tanstack/react-table'; import { useSelect } from '@/components/input/SelectInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import { DailyChecklistKandangApi } from '@/services/api/daily-checklist/kandang'; export function MasterEmployeeContent() { const { state: tableFilterState, updateFilter, setPage, setPageSize, toQueryString: getTableFilterQueryString, } = useTableFilter({ initial: { search: '', kandang_id: '', status: '', }, paramMap: { page: 'page', pageSize: 'limit', search: 'search', kandang_id: 'kandang_id', status: 'is_active', }, }); const { data: employees, isLoading: isLoadingEmployees, mutate: refreshEmployees, } = useSWR( `${EmployeeApi.basePath}${getTableFilterQueryString()}`, EmployeeApi.getAllFetcher, { keepPreviousData: true, } ); const { options: kandangOptions, loadMore: loadMoreKandang, isLoadingMore: isLoadingMoreKandang, } = useSelect(DailyChecklistKandangApi.basePath, 'id', 'name'); const handleKandangScroll = (e: React.UIEvent) => { const target = e.target as HTMLDivElement; if (target.scrollHeight - target.scrollTop <= target.clientHeight + 10) { if (!isLoadingMoreKandang) { loadMoreKandang(); } } }; const [showModal, setShowModal] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [employeeToDelete, setEmployeeToDelete] = useState(null); const [loading, setLoading] = useState(false); const [modalMode, setModalMode] = useState<'create' | 'edit'>('create'); const [employeeForm, setEmployeeForm] = useState({ id: 0, name: '', kandang_ids: [] as number[], status: 'Active' as 'Active' | 'Non Active', }); const employeeColumns: ColumnDef[] = [ { id: 'name', header: 'Nama ABK', accessorKey: 'name', enableSorting: false, }, { id: 'kandang', header: 'Kandang', accessorKey: 'kandangs', enableSorting: false, cell: ({ row }) => row.original.kandangs.map((kandang) => kandang.name).join(', '), }, { id: 'status', header: 'Status', accessorKey: 'is_active', enableSorting: false, cell: ({ row }) => ( {row.original.is_active ? 'Active' : 'Non Active'} ), }, { id: 'action', header: 'Aksi', accessorKey: 'action', enableSorting: false, cell: ({ row }) => ( handleEdit(row.original)}> Edit handleDeleteClick(row.original.id)} className='text-red-600' > Hapus ), }, ]; const handleAdd = () => { setModalMode('create'); setEmployeeForm({ id: 0, name: '', kandang_ids: [], status: 'Active' }); setShowModal(true); }; const handleEdit = (employee: Employee) => { setModalMode('edit'); setEmployeeForm({ id: employee.id, name: employee.name, kandang_ids: employee.kandangs ? employee.kandangs.map((k) => k.id) : [], status: employee.is_active ? 'Active' : 'Non Active', }); setShowModal(true); }; const handleSave = async () => { if (!employeeForm.name.trim() || employeeForm.kandang_ids.length === 0) { toast.error('Nama ABK dan minimal satu Kandang harus diisi'); return; } setLoading(true); try { if (modalMode === 'create') { const createEmployeeResponse = await EmployeeApi.create({ is_active: employeeForm.status === 'Active', kandang_ids: employeeForm.kandang_ids, name: employeeForm.name.trim(), }); if (isResponseError(createEmployeeResponse)) { console.error( 'Error creating employee:', createEmployeeResponse.message ); toast.error( 'Gagal menambahkan ABK: ' + createEmployeeResponse.message ); return; } refreshEmployees(); toast.success('ABK berhasil ditambahkan'); } else { const updateEmployeeResponse = await EmployeeApi.update( employeeForm.id, { is_active: employeeForm.status === 'Active', kandang_ids: employeeForm.kandang_ids, name: employeeForm.name.trim(), } ); if (isResponseError(updateEmployeeResponse)) { console.error( 'Error updating employee:', updateEmployeeResponse.message ); toast.error( 'Gagal memperbarui ABK: ' + updateEmployeeResponse.message ); return; } refreshEmployees(); toast.success('ABK berhasil diubah'); } setShowModal(false); setEmployeeForm({ id: 0, name: '', kandang_ids: [], status: 'Active' }); } catch (error) { console.error('Error saving employee:', error); toast.error('Terjadi kesalahan saat menyimpan ABK'); } finally { setLoading(false); } }; const handleDeleteClick = (employeeId: number) => { setEmployeeToDelete(employeeId); setShowDeleteConfirm(true); }; const handleConfirmDelete = async () => { if (!employeeToDelete) return; setLoading(true); try { const deleteEmployeeResponse = await EmployeeApi.delete(employeeToDelete); if (isResponseError(deleteEmployeeResponse)) { console.error( 'Error deleting employee:', deleteEmployeeResponse.message ); toast.error('Gagal menghapus ABK'); return; } refreshEmployees(); toast.success('ABK berhasil dihapus'); setShowDeleteConfirm(false); setEmployeeToDelete(null); // await fetchEmployees(); } catch (error) { console.error('Error deleting employee:', error); toast.error('Terjadi kesalahan saat menghapus ABK'); } finally { setLoading(false); } }; if (isLoadingEmployees && !employees) { return (

Master Employee (ABK)

Master Data •{' '} Employee (ABK)

Memuat data...
); } return (
{/* Page Title */}

Master Employee (ABK)

Master Data • Employee (ABK)

{/* Main Card */} {/* Single Toolbar Row */}
{/* LEFT: Search + Filters */}
updateFilter('search', e.target.value)} className={{ wrapper: 'w-full sm:w-[280px] border-gray-200', inputWrapper: 'px-3 py-2 h-fit rounded-md', input: 'text-sm', }} startAdornment={ } />
{/* RIGHT: Export + Add */}
{/* Table */} data={isResponseSuccess(employees) ? employees?.data : []} columns={employeeColumns} pageSize={tableFilterState.pageSize} onPageSizeChange={setPageSize} rowOptions={[10, 20, 50, 100]} page={isResponseSuccess(employees) ? employees?.meta?.page : 0} totalItems={ isResponseSuccess(employees) ? employees?.meta?.total_results : 0 } onPageChange={setPage} isLoading={isLoadingEmployees} className={{ containerClassName: cn({ 'w-full mb-20': isResponseSuccess(employees) && employees?.data?.length === 0, }), tableWrapperClassName: 'overflow-x-auto border border-solid border-base-content/10 rounded-none', headerRowClassName: 'bg-gray-50/50', headerColumnClassName: 'text-left py-3.5 px-6 text-sm font-semibold text-gray-700', paginationClassName: 'px-4', }} />
{/* Add/Edit Modal */} {modalMode === 'create' ? 'Tambah ABK' : 'Edit ABK'} {modalMode === 'create' ? 'Masukkan detail ABK baru' : 'Ubah detail ABK'}
setEmployeeForm({ ...employeeForm, name: e.target.value }) } placeholder='Masukkan nama ABK' className='mt-1.5' disabled={loading} />
({ value: String(k.value), label: k.label, }))} selected={employeeForm.kandang_ids.map((id) => String(id))} onChange={(selected) => setEmployeeForm({ ...employeeForm, kandang_ids: selected.map((id) => Number(id)), }) } onLoadMore={() => { if (!isLoadingMoreKandang) { loadMoreKandang(); } }} isLoadingMore={isLoadingMoreKandang} placeholder='Pilih kandang' className='mt-1.5' />
{/* Delete Confirmation */} Hapus ABK? Data ABK akan dihapus secara permanen. Batal {loading ? 'Menghapus...' : 'Hapus'}
); }