feat(FE-137): integrate SWR for fetching recordings and update table to display API data

This commit is contained in:
rstubryan
2025-10-24 11:35:11 +07:00
parent b148a09e84
commit 12a69b7c6c
@@ -1,6 +1,7 @@
'use client'; 'use client';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import useSWR from 'swr';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { SortingState } from '@tanstack/react-table'; import { SortingState } from '@tanstack/react-table';
import { cn } from '@/lib/helper'; import { cn } from '@/lib/helper';
@@ -18,52 +19,21 @@ import RowCollapseOptions from '@/components/table/RowCollapseOptions';
import { type CellContext } from '@tanstack/react-table'; import { type CellContext } from '@tanstack/react-table';
import { type Recording } from '@/types/api/production/recording'; import { type Recording } from '@/types/api/production/recording';
import { type ProjectFlock } from '@/types/api/production/project-flock'; import { type ProjectFlock } from '@/types/api/production/project-flock';
import { RecordingApi } from '@/services/api/production';
import { type BaseApiResponse } from '@/types/api/api-general';
// Extended type that includes related data // Extended type that includes related data
type RecordingWithRelations = Recording & { type RecordingWithRelations = Recording & {
project_flock?: ProjectFlock; project_flock?: ProjectFlock;
}; };
const dummyRecordings: RecordingWithRelations[] = [
{
id: 1,
project_flock_kandang_id: 1,
record_date: '2024-01-01',
ontime: true,
day: 10,
status: 1,
total_depletion: 10,
cum_depletion_rate: 1.0,
daily_gain: 50,
avg_daily_gain: 5.0,
cum_intake: 200,
fcr_value: 1.5,
total_chick: 1000,
daily_depletion_rate: 0.5,
cum_depletion: 20,
record_datetime: '2024-01-01T08:00:00Z',
created_at: '2024-01-01',
updated_at: '2024-01-01',
created_user: {
id: 1,
id_user: 1,
email: 'admin@example.com',
name: 'Admin',
image: null,
npk: '0001',
created_at: '2024-01-01',
updated_at: '2024-01-01',
},
},
];
const RowOptionsMenu = ({ const RowOptionsMenu = ({
type = 'dropdown', type = 'dropdown',
props, props,
deleteClickHandler, deleteClickHandler,
}: { }: {
type: 'dropdown' | 'collapse'; type: 'dropdown' | 'collapse';
props: CellContext<RecordingWithRelations, unknown>; props: CellContext<Recording, unknown>;
deleteClickHandler: () => void; deleteClickHandler: () => void;
}) => { }) => {
return ( return (
@@ -119,7 +89,7 @@ const RecordingTable = () => {
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10);
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
const [, setSelectedRecording] = useState<RecordingWithRelations | undefined>(undefined); const [, setSelectedRecording] = useState<Recording | undefined>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [isBulkApproveLoading, setIsBulkApproveLoading] = useState(false); const [isBulkApproveLoading, setIsBulkApproveLoading] = useState(false);
const [isBulkRejectLoading, setIsBulkRejectLoading] = useState(false); const [isBulkRejectLoading, setIsBulkRejectLoading] = useState(false);
@@ -128,6 +98,16 @@ const RecordingTable = () => {
const bulkApproveModal = useModal(); const bulkApproveModal = useModal();
const bulkRejectModal = useModal(); const bulkRejectModal = useModal();
// Fetch recordings using SWR
const {
data: recordings,
isLoading,
mutate: refreshRecordings,
} = useSWR(
`${RecordingApi.basePath}?page=${page}&limit=${pageSize}`,
RecordingApi.getAllFetcher
);
const searchChangeHandler = useCallback( const searchChangeHandler = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => { (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); setSearch(e.target.value);
@@ -146,20 +126,18 @@ const RecordingTable = () => {
); );
const paginatedData = useMemo(() => { const paginatedData = useMemo(() => {
const filteredData = dummyRecordings.filter( if (!recordings || recordings.status !== 'success') return [];
(recording: RecordingWithRelations) => {
const projectName = recording.project_flock?.name || '';
const locationName = recording.project_flock?.location?.name || '';
const coopName = recording.project_flock?.kandangs?.[0]?.name || '';
return projectName.toLowerCase().includes(search.toLowerCase()) || return recordings.data.filter(
locationName.toLowerCase().includes(search.toLowerCase()) || (recording: Recording) => {
coopName.toLowerCase().includes(search.toLowerCase()); // For now, we don't have project_flock relation data in the API response
// So we'll filter by basic recording data
return recording.project_flock_kandang_id.toString().includes(search.toLowerCase()) ||
recording.record_date.includes(search.toLowerCase()) ||
recording.created_user.name.toLowerCase().includes(search.toLowerCase());
} }
); );
const start = (page - 1) * pageSize; }, [recordings, search]);
return filteredData.slice(start, start + pageSize);
}, [page, pageSize, search]);
const selectedRowIds = Object.keys(rowSelection).map((item) => parseInt(item)); const selectedRowIds = Object.keys(rowSelection).map((item) => parseInt(item));
@@ -308,8 +286,8 @@ const RecordingTable = () => {
cell: (props) => pageSize * (page - 1) + props.row.index + 1, cell: (props) => pageSize * (page - 1) + props.row.index + 1,
}, },
{ {
header: 'Flock', header: 'Flock Kandang ID',
cell: (props) => props.row.original.project_flock?.name || '-', cell: (props) => props.row.original.project_flock_kandang_id,
}, },
{ {
accessorKey: 'record_date', accessorKey: 'record_date',
@@ -318,24 +296,25 @@ const RecordingTable = () => {
new Date(props.row.original.record_date).toLocaleDateString(), new Date(props.row.original.record_date).toLocaleDateString(),
}, },
{ {
header: 'Lokasi', header: 'Day',
cell: (props) => props.row.original.project_flock?.location?.name || '-', cell: (props) => props.row.original.day,
}, },
{ {
header: 'Kandang', header: 'Status',
cell: (props) => { cell: (props) => props.row.original.status,
const coopName = props.row.original.project_flock?.kandangs?.[0]?.name;
return coopName || '-';
},
}, },
{ {
accessorKey: 'total_depletion', accessorKey: 'total_depletion',
header: 'Total Depletion', header: 'Total Depletion',
cell: (props) => props.row.original.total_depletion, cell: (props) => props.row.original.total_depletion,
}, },
{
header: 'Created By',
cell: (props) => props.row.original.created_user.name,
},
{ {
header: 'Aksi', header: 'Aksi',
cell: (props: CellContext<RecordingWithRelations, unknown>) => { cell: (props: CellContext<Recording, unknown>) => {
const currentPageSize = const currentPageSize =
props.table.getPaginationRowModel().rows.length; props.table.getPaginationRowModel().rows.length;
const currentPageRows = const currentPageRows =
@@ -377,10 +356,10 @@ const RecordingTable = () => {
}, },
]} ]}
pageSize={pageSize} pageSize={pageSize}
page={page} page={recordings?.status === 'success' ? recordings.meta?.page : page}
totalItems={dummyRecordings.length} totalItems={recordings?.status === 'success' ? recordings.meta?.total_results : 0}
onPageChange={setPage} onPageChange={setPage}
isLoading={false} isLoading={isLoading}
sorting={sorting} sorting={sorting}
setSorting={setSorting} setSorting={setSorting}
rowSelection={rowSelection} rowSelection={rowSelection}