'use client'; import React, { useCallback, useState, useEffect, useMemo } from 'react'; import useSWR from 'swr'; import { Icon } from '@iconify/react'; import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; import { cn } from '@/lib/helper'; import Button from '@/components/Button'; import UniformityChart from '@/components/pages/uniformity/UniformityChart'; // import UniformityStat from '@/components/pages/uniformity/chart/UniformityStat'; import { useTableFilter } from '@/services/hooks/useTableFilter'; import { UniformityApi } from '@/services/api/uniformity'; import { type Uniformity } from '@/types/api/uniformity/uniformity'; import { isResponseSuccess } from '@/lib/api-helper'; import Table from '@/components/Table'; import Badge from '@/components/Badge'; import CheckboxInput from '@/components/input/CheckboxInput'; import RowDropdownOptions from '@/components/table/RowDropdownOptions'; import RowCollapseOptions from '@/components/table/RowCollapseOptions'; import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import toast from 'react-hot-toast'; import Card from '@/components/Card'; import UniformityTableSkeleton from './skeleton/UniformityTableSkeleton'; const statusColorMap: Record = { APPROVED: 'bg-[#00D39033]', REJECTED: 'bg-error/10', CREATED: 'bg-[#f3f3f4]', }; const statusIndicatorColorMap: Record = { APPROVED: 'bg-[#008000]', REJECTED: 'bg-error', CREATED: 'bg-[#D9D9D9]', }; const statusTextMap: Record = { APPROVED: 'Disetujui', REJECTED: 'Ditolak', CREATED: 'Pengajuan', }; const getStatusColor = (status: string): string => { return statusColorMap[status] || 'bg-info'; }; const getStatusIndicatorColor = (status: string): string => { return statusIndicatorColorMap[status] || 'bg-info'; }; const getStatusText = (status: string): string => { return statusTextMap[status] || status; }; const isUniformityLocked = (uniformity: Uniformity): boolean => { return uniformity.status === 'APPROVED' || uniformity.status === 'REJECTED'; }; const RowOptionsMenu = ({ type = 'dropdown', props, deleteClickHandler, setSelectedUniformity, openModal, }: { type: 'dropdown' | 'collapse'; props: CellContext; deleteClickHandler: () => void; setSelectedUniformity: (uniformity: Uniformity) => void; openModal: () => void; }) => { const handleDeleteClick = useCallback(() => { setSelectedUniformity(props.row.original); openModal(); }, [props.row.original, setSelectedUniformity, openModal]); return ( ); }; const UniformityTable = ({ refresh }: { refresh?: () => void }) => { const { state: tableFilterState, setPage, toQueryString: getTableFilterQueryString, } = useTableFilter({ initial: { search: '', }, paramMap: { page: 'page', pageSize: 'limit', search: 'search', }, }); const [sorting, setSorting] = useState([]); const [rowSelection, setRowSelection] = useState>({}); const [selectedUniformity, setSelectedUniformity] = useState< Uniformity | undefined >(undefined); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const singleDeleteModal = useModal(); const { data: uniformities, isLoading, mutate: refreshUniformities, } = useSWR( `${UniformityApi.basePath}${getTableFilterQueryString()}`, UniformityApi.getAllFetcher ); const singleDeleteHandler = useCallback(async () => { setIsDeleteLoading(true); await UniformityApi.delete(selectedUniformity?.id as number); refreshUniformities(); singleDeleteModal.closeModal(); toast.success('Successfully delete Uniformity!'); setIsDeleteLoading(false); }, [selectedUniformity?.id, refreshUniformities, singleDeleteModal]); useEffect(() => { if (isResponseSuccess(uniformities) && uniformities.data) { const newSelection: Record = {}; Object.entries(rowSelection).forEach(([rowId, isSelected]) => { if (isSelected) { const uniformity = uniformities.data.find( (r) => r.id === parseInt(rowId) ); if (uniformity && !isUniformityLocked(uniformity)) { newSelection[rowId] = true; } } }); if ( Object.keys(newSelection).length !== Object.keys(rowSelection).length ) { setRowSelection(newSelection); } } }, [uniformities, rowSelection]); // ===== TABLE COLUMNS DEFINITION ===== const uniformityColumns: ColumnDef[] = useMemo( () => [ { id: 'select', header: ({ table }) => { const allRows = table.getRowModel().rows; const selectableRows = allRows.filter((row) => { const uniformity = row.original; return !isUniformityLocked(uniformity); }); const hasNoSelectableRows = selectableRows.length === 0; const handleSelectAll = () => { const isAllSelected = selectableRows.every((row) => row.getIsSelected() ); selectableRows.forEach((row) => { row.toggleSelected(!isAllSelected); }); }; const isAllSelected = selectableRows.length > 0 && selectableRows.every((row) => row.getIsSelected()); const isSomeSelected = selectableRows.some((row) => row.getIsSelected() ); return (
); }, cell: ({ row }) => { const uniformity = row.original; const isDisabled = isUniformityLocked(uniformity); return (
); }, }, { accessorKey: 'location.name', header: 'Lokasi', cell: (props) => props.row.original.location.name || '-', }, { accessorKey: 'project_flock_kandang_id', header: 'Flock', cell: (props) => `Flock ${props.row.original.project_flock_kandang_id}`, }, { accessorKey: 'kandang.name', header: 'Kandang', cell: (props) => props.row.original.kandang.name || '-', }, { accessorKey: 'week', header: 'Tanggal (Week)', cell: (props) => `Week ${props.row.original.week}`, }, { accessorKey: 'status', header: 'Status', cell: (props) => { const status = props.row.original.status; return (
{getStatusText(status)}
); }, }, { accessorKey: 'uniformity', header: 'Uniformity', cell: (props) => { const uniformity = props.row.original.uniformity; return {uniformity}%; }, }, { id: 'actions', header: 'Aksi', cell: (props: CellContext) => { const currentPageSize = props.table.getPaginationRowModel().rows.length; const currentPageRows = props.table.getPaginationRowModel().flatRows; const currentRowRelativeIndex = currentPageRows.findIndex((r) => r.id === props.row.id) + 1; const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; return ( <> {currentPageSize > 2 && ( { setSelectedUniformity(props.row.original); singleDeleteModal.openModal(); }} setSelectedUniformity={setSelectedUniformity} openModal={singleDeleteModal.openModal} /> )} {currentPageSize <= 2 && ( { setSelectedUniformity(props.row.original); singleDeleteModal.openModal(); }} setSelectedUniformity={setSelectedUniformity} openModal={singleDeleteModal.openModal} /> )} ); }, }, ], [] ); return ( <>
{/*
*/}
data={isResponseSuccess(uniformities) ? uniformities?.data : []} columns={uniformityColumns} pageSize={tableFilterState.pageSize} page={isResponseSuccess(uniformities) ? uniformities?.meta?.page : 0} totalItems={ isResponseSuccess(uniformities) ? uniformities?.meta?.total_results : 0 } onPageChange={setPage} isLoading={isLoading} sorting={sorting} setSorting={setSorting} rowSelection={rowSelection} setRowSelection={setRowSelection} className={{ containerClassName: cn({ 'mb-20': isResponseSuccess(uniformities) && uniformities?.data?.length === 0, }), tableWrapperClassName: 'overflow-x-auto min-h-full ', tableClassName: 'font-inter w-full table-auto min-h-full!', headerRowClassName: 'border-b border-b-gray-200', headerColumnClassName: 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', bodyRowClassName: 'border-b border-b-gray-200', bodyColumnClassName: 'px-6 py-3 last:flex last:flex-row last:justify-end', }} emptyContent={} /> ); }; export default UniformityTable;