feat: only fetch when user scroll to the component

This commit is contained in:
ValdiANS
2026-05-12 14:38:19 +07:00
parent b6c2f36dd1
commit bdc7ac4d22
@@ -9,7 +9,7 @@ import { ProductWarehouseStock, StockLog } from '@/types/api/inventory/product';
import { ColumnDef } from '@tanstack/react-table'; import { ColumnDef } from '@tanstack/react-table';
import { FileDown } from 'lucide-react'; import { FileDown } from 'lucide-react';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import { useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import useSWR from 'swr'; import useSWR from 'swr';
const stockLogTableColumns: (warehouseName: string) => ColumnDef<StockLog>[] = ( const stockLogTableColumns: (warehouseName: string) => ColumnDef<StockLog>[] = (
@@ -80,6 +80,23 @@ const StockLogTable = ({
productWarehouse: ProductWarehouseStock; productWarehouse: ProductWarehouseStock;
}) => { }) => {
const [isExportLoading, setIsExportLoading] = useState(false); const [isExportLoading, setIsExportLoading] = useState(false);
const [hasBeenVisible, setHasBeenVisible] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setHasBeenVisible(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (containerRef.current) observer.observe(containerRef.current);
return () => observer.disconnect();
}, []);
const { const {
state: tableFilterState, state: tableFilterState,
@@ -108,7 +125,9 @@ const StockLogTable = ({
}; };
const { data: stockLogsResponse, isLoading: isLoadingStockLogs } = useSWR( const { data: stockLogsResponse, isLoading: isLoadingStockLogs } = useSWR(
`${StockLogApi.basePath}${getTableFilterQueryString()}`, hasBeenVisible
? `${StockLogApi.basePath}${getTableFilterQueryString()}`
: null,
StockLogApi.getAllFetcher StockLogApi.getAllFetcher
); );
@@ -117,46 +136,48 @@ const StockLogTable = ({
: []; : [];
return ( return (
<Card <div ref={containerRef}>
title={`Informasi Stock Produk - ${productWarehouse.warehouse_name}`} <Card
collapsible title={`Informasi Stock Produk - ${productWarehouse.warehouse_name}`}
variant='bordered' collapsible
className={{ variant='bordered'
wrapper: 'w-full',
}}
>
<div className='flex justify-end px-6 pt-4'>
<Button onClick={handleExportExcel} isLoading={isExportLoading}>
<FileDown size={16} />
Export Excel
</Button>
</div>
<Table<StockLog>
data={stockLogs}
columns={stockLogTableColumns(productWarehouse.warehouse_name)}
page={tableFilterState.page ?? 0}
pageSize={tableFilterState.pageSize}
onPageChange={setPage}
onPageSizeChange={setPageSize}
isLoading={isLoadingStockLogs}
totalItems={
isResponseSuccess(stockLogsResponse)
? stockLogsResponse.meta?.total_results
: 0
}
className={{ className={{
containerClassName: 'mt-4 mb-0', wrapper: 'w-full',
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',
}} }}
/> >
</Card> <div className='flex justify-end px-6 pt-4'>
<Button onClick={handleExportExcel} isLoading={isExportLoading}>
<FileDown size={16} />
Export Excel
</Button>
</div>
<Table<StockLog>
data={stockLogs}
columns={stockLogTableColumns(productWarehouse.warehouse_name)}
page={tableFilterState.page ?? 0}
pageSize={tableFilterState.pageSize}
onPageChange={setPage}
onPageSizeChange={setPageSize}
isLoading={isLoadingStockLogs}
totalItems={
isResponseSuccess(stockLogsResponse)
? stockLogsResponse.meta?.total_results
: 0
}
className={{
containerClassName: 'mt-4 mb-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',
}}
/>
</Card>
</div>
); );
}; };