refactor(FE): Refactor table components to improve styling and structure

This commit is contained in:
rstubryan
2026-02-19 10:43:37 +07:00
parent 944db8dba7
commit 4c70ec7cab
9 changed files with 539 additions and 509 deletions
@@ -82,7 +82,7 @@ const FinanceClosingTable = ({
}, [finance]); }, [finance]);
return ( return (
<div className='flex flex-col gap-4'> <div className='flex flex-col gap-4 p-0 sm:p-3'>
{isLoading ? ( {isLoading ? (
<FinanceClosingSkeleton /> <FinanceClosingSkeleton />
) : !isResponseSuccess(finance) ? ( ) : !isResponseSuccess(finance) ? (
@@ -96,10 +96,13 @@ const FinanceClosingTable = ({
<Card <Card
variant='bordered' variant='bordered'
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
> >
<div className='grid grid-cols-2 gap-6'> <div className='p-4 grid grid-cols-2 gap-6'>
<div className='flex flex-col gap-1'> <div className='flex flex-col gap-1'>
<div>Laba Rugi Brutto</div> <div>Laba Rugi Brutto</div>
<div className='text-lg font-bold'> <div className='text-lg font-bold'>
@@ -127,10 +130,13 @@ const FinanceClosingTable = ({
variant='bordered' variant='bordered'
collapsible collapsible
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
> >
<div className='mt-6 p-0 mb-0'> <div className='p-0'>
<Table<HppItem> <Table<HppItem>
data={hppTableData} data={hppTableData}
isLoading={isLoading} isLoading={isLoading}
@@ -263,6 +269,24 @@ const FinanceClosingTable = ({
], ],
}, },
]} ]}
className={{
containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}}
renderCustomRow={(row) => { renderCustomRow={(row) => {
const rowData = row.original; const rowData = row.original;
if (rowData.code === 'custom_row') { if (rowData.code === 'custom_row') {
@@ -296,10 +320,13 @@ const FinanceClosingTable = ({
variant='bordered' variant='bordered'
collapsible collapsible
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
> >
<div className='mt-6 p-0 mb-0'> <div className='p-0'>
<Table<ProfitLossItem> <Table<ProfitLossItem>
data={profitLossTableData} data={profitLossTableData}
isLoading={isLoading} isLoading={isLoading}
@@ -363,6 +390,25 @@ const FinanceClosingTable = ({
), ),
}, },
]} ]}
className={{
containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
paginationClassName: 'hidden',
}}
renderCustomRow={(row) => { renderCustomRow={(row) => {
const rowData = row.original; const rowData = row.original;
if (rowData.code === 'custom_row') { if (rowData.code === 'custom_row') {
@@ -404,9 +450,6 @@ const FinanceClosingTable = ({
} }
return null; return null;
}} }}
className={{
paginationClassName: 'hidden',
}}
renderFooter={isResponseSuccess(finance)} renderFooter={isResponseSuccess(finance)}
/> />
</div> </div>
@@ -91,15 +91,18 @@ const HppExpeditionClosingTable = ({
); );
return ( return (
<> <div className='w-full p-0 sm:p-3'>
<section className='w-full'>
<div className='p-4'>
<h2 className='text-xl font-semibold mb-4'>HPP Ekspedisi</h2>
<Card <Card
className={{ className={{
wrapper: 'w-full bg-base-100', wrapper: 'w-full rounded-lg border-none',
body: 'p-0', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='HPP Ekspedisi'
collapsible
defaultCollapsed={false}
> >
{isLoading ? ( {isLoading ? (
<HppExpeditionClosingSkeleton <HppExpeditionClosingSkeleton
@@ -117,11 +120,13 @@ const HppExpeditionClosingTable = ({
isLoading={isLoading} isLoading={isLoading}
renderFooter={costOfRevenueExpeditionData.length > 0} renderFooter={costOfRevenueExpeditionData.length > 0}
className={{ className={{
tableWrapperClassName: 'overflow-x-auto', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm', tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200', headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName: headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end whitespace-nowrap', 'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName: bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200', 'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName: bodyColumnClassName:
@@ -136,8 +141,6 @@ const HppExpeditionClosingTable = ({
)} )}
</Card> </Card>
</div> </div>
</section>
</>
); );
}; };
@@ -209,15 +209,18 @@ const OverheadClosingTable = ({
); );
return ( return (
<> <div className='w-full p-0 sm:p-3'>
<Card <Card
className={{
wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}}
variant='bordered'
title='Pengeluaran Overhead' title='Pengeluaran Overhead'
collapsible collapsible
defaultCollapsed={false} defaultCollapsed={false}
className={{
wrapper: 'w-full',
body: 'p-4 shadow',
}}
> >
{isLoadingOverhead ? ( {isLoadingOverhead ? (
<OverheadClosingSkeleton columns={columns} /> <OverheadClosingSkeleton columns={columns} />
@@ -243,11 +246,24 @@ const OverheadClosingTable = ({
} }
columns={columns} columns={columns}
className={{ className={{
containerClassName: 'my-4', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName: cn( headerColumnClassName: cn(
TABLE_DEFAULT_STYLING.headerColumnClassName, 'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
'whitespace-nowrap' 'whitespace-nowrap'
), ),
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
isLoading={isLoadingOverhead} isLoading={isLoadingOverhead}
renderFooter={ renderFooter={
@@ -312,7 +328,7 @@ const OverheadClosingTable = ({
</Card> </Card>
)} )}
</Card> </Card>
</> </div>
); );
}; };
@@ -316,15 +316,18 @@ const SalesClosingTable = ({ projectFlockId }: SalesClosingTableProps) => {
); );
return ( return (
<> <div className='w-full p-0 sm:p-3'>
<section className='w-full'>
<div className='p-4'>
<h2 className='text-xl font-semibold mb-4'>Penjualan</h2>
<Card <Card
className={{ className={{
wrapper: 'w-full bg-base-100', wrapper: 'w-full rounded-lg border-none',
body: 'p-0', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='Penjualan'
collapsible
defaultCollapsed={false}
> >
{isLoading ? ( {isLoading ? (
<SalesClosingSkeleton columns={salesColumns} /> <SalesClosingSkeleton columns={salesColumns} />
@@ -340,12 +343,15 @@ const SalesClosingTable = ({ projectFlockId }: SalesClosingTableProps) => {
isLoading={isLoading} isLoading={isLoading}
renderFooter={salesData.length > 0} renderFooter={salesData.length > 0}
className={{ className={{
tableWrapperClassName: 'overflow-x-auto', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm', tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName: headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-500 whitespace-nowrap border-l border-l-gray-200 border-r border-r-gray-200 border-t border-t-gray-200 border-gray-200 border-b-0', 'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName: bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-gray-200 first:border-t first:border-t-gray-200 border-l border-l-gray-200 border-r border-r-gray-200', 'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName: bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap', 'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName: tableFooterClassName:
@@ -358,8 +364,6 @@ const SalesClosingTable = ({ projectFlockId }: SalesClosingTableProps) => {
)} )}
</Card> </Card>
</div> </div>
</section>
</>
); );
}; };
@@ -179,7 +179,7 @@ const SapronakCalculationClosingTable = ({
); );
return ( return (
<div className='flex flex-col gap-4'> <div className='flex flex-col gap-4 p-0 sm:p-3'>
{/* Table DOC jika kategori Project Flock Growing */} {/* Table DOC jika kategori Project Flock Growing */}
<Card <Card
title={ title={
@@ -190,9 +190,12 @@ const SapronakCalculationClosingTable = ({
collapsible collapsible
defaultCollapsed={false} defaultCollapsed={false}
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-4 shadow', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
> >
{isLoading ? ( {isLoading ? (
<SapronakCalculationClosingSkeleton columns={docColumns} /> <SapronakCalculationClosingSkeleton columns={docColumns} />
@@ -213,7 +216,22 @@ const SapronakCalculationClosingTable = ({
} }
columns={docColumns} columns={docColumns}
className={{ className={{
containerClassName: 'my-4', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
renderFooter={ renderFooter={
isResponseSuccess(sapronakCalculation) && isResponseSuccess(sapronakCalculation) &&
@@ -229,7 +247,10 @@ const SapronakCalculationClosingTable = ({
collapsible collapsible
defaultCollapsed={true} defaultCollapsed={true}
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
> >
{isLoading ? ( {isLoading ? (
@@ -251,7 +272,22 @@ const SapronakCalculationClosingTable = ({
} }
columns={ovkColumns} columns={ovkColumns}
className={{ className={{
containerClassName: 'my-4', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
renderFooter={ renderFooter={
isResponseSuccess(sapronakCalculation) && isResponseSuccess(sapronakCalculation) &&
@@ -267,7 +303,10 @@ const SapronakCalculationClosingTable = ({
collapsible collapsible
defaultCollapsed={true} defaultCollapsed={true}
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
> >
{isLoading ? ( {isLoading ? (
@@ -289,7 +328,22 @@ const SapronakCalculationClosingTable = ({
} }
columns={pakanColumns} columns={pakanColumns}
className={{ className={{
containerClassName: 'my-4', containerClassName: 'w-full mb-0!',
tableWrapperClassName:
'overflow-x-auto rounded-tr-none rounded-tl-none',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
renderFooter={ renderFooter={
isResponseSuccess(sapronakCalculation) && isResponseSuccess(sapronakCalculation) &&
@@ -5,12 +5,10 @@ import { useSearchParams } from 'next/navigation';
import useSWR from 'swr'; import useSWR from 'swr';
import { ColumnDef, SortingState } from '@tanstack/react-table'; import { ColumnDef, SortingState } from '@tanstack/react-table';
import { Icon } from '@iconify/react';
import Table from '@/components/Table'; import Table from '@/components/Table';
import Card from '@/components/Card'; import Card from '@/components/Card';
import Collapse from '@/components/Collapse';
import { cn, formatNumber } from '@/lib/helper'; import { formatNumber } from '@/lib/helper';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter'; import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing'; import { ClosingApi } from '@/services/api/closing';
@@ -56,8 +54,6 @@ const ClosingIncomingSapronaksSummaryTable = ({
} }
); );
const [open, setOpen] = useState(true);
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
@@ -94,44 +90,20 @@ const ClosingIncomingSapronaksSummaryTable = ({
} }
}, [sorting, updateFilter]); }, [sorting, updateFilter]);
useEffect(() => {
if (!open) {
setOpen(
isResponseSuccess(incomingSapronakSummaries)
? incomingSapronakSummaries.data.length > 0
: false
);
}
}, [incomingSapronakSummaries, isResponseSuccess]);
return ( return (
<div className='w-full p-0 sm:p-3'>
<Card <Card
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-4 shadow', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='Ringkasan Sapronak Masuk'
collapsible
defaultCollapsed={false}
> >
<Collapse
open={open}
onOpenChange={setOpen}
title={
<div className='card-actions p-4 justify-between items-center w-full'>
<div className='card-title'>Ringkasan Sapronak Masuk</div>
<Icon
icon='material-symbols:keyboard-arrow-down'
width={24}
height={24}
className={cn('text-primary transition-transform', {
'-rotate-180': open,
})}
/>
</div>
}
className='w-full!'
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
{isLoadingIncomingSapronakSummaries ? ( {isLoadingIncomingSapronakSummaries ? (
<SapronakClosingSkeleton <SapronakClosingSkeleton
type='incoming' type='incoming'
@@ -174,17 +146,22 @@ const ClosingIncomingSapronaksSummaryTable = ({
rowSelection={rowSelection} rowSelection={rowSelection}
setRowSelection={setRowSelection} setRowSelection={setRowSelection}
className={{ className={{
containerClassName: cn({ containerClassName: 'w-full mb-0!',
'w-full mb-20': tableWrapperClassName:
isResponseSuccess(incomingSapronakSummaries) && 'overflow-x-auto rounded-tr-none rounded-tl-none',
incomingSapronakSummaries?.data?.length === 0, tableClassName: 'w-full table-auto text-sm',
}), headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
/> />
)} )}
</div>
</Collapse>
</Card> </Card>
</div>
); );
}; };
@@ -5,13 +5,11 @@ import { useSearchParams } from 'next/navigation';
import useSWR from 'swr'; import useSWR from 'swr';
import { ColumnDef, SortingState } from '@tanstack/react-table'; import { ColumnDef, SortingState } from '@tanstack/react-table';
import { Icon } from '@iconify/react';
import Table from '@/components/Table'; import Table from '@/components/Table';
import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import Card from '@/components/Card'; import Card from '@/components/Card';
import Collapse from '@/components/Collapse';
import { cn, formatDate, formatNumber } from '@/lib/helper'; import { formatDate, formatNumber } from '@/lib/helper';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter'; import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing'; import { ClosingApi } from '@/services/api/closing';
@@ -52,8 +50,6 @@ const ClosingIncomingSapronaksTable = ({
ClosingApi.getAllIncomingSapronakFetcher ClosingApi.getAllIncomingSapronakFetcher
); );
const [open, setOpen] = useState(true);
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
@@ -118,44 +114,20 @@ const ClosingIncomingSapronaksTable = ({
} }
}, [sorting, updateFilter]); }, [sorting, updateFilter]);
useEffect(() => {
if (!open) {
setOpen(
isResponseSuccess(incomingSapronaks)
? incomingSapronaks.data.length > 0
: false
);
}
}, [incomingSapronaks, isResponseSuccess]);
return ( return (
<div className='w-full p-0 sm:p-3'>
<Card <Card
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-4 shadow', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='Sapronak Masuk'
collapsible
defaultCollapsed={false}
> >
<Collapse
open={open}
onOpenChange={setOpen}
title={
<div className='card-actions p-4 justify-between items-center w-full'>
<div className='card-title'>Sapronak Masuk</div>
<Icon
icon='material-symbols:keyboard-arrow-down'
width={24}
height={24}
className={cn('text-primary transition-transform', {
'-rotate-180': open,
})}
/>
</div>
}
className='w-full!'
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
<div className='flex flex-col gap-2 mb-4'> <div className='flex flex-col gap-2 mb-4'>
<div className='w-full flex flex-col sm:flex-row justify-start items-end sm:items-center gap-4'> <div className='w-full flex flex-col sm:flex-row justify-start items-end sm:items-center gap-4'>
<DebouncedTextInput <DebouncedTextInput
@@ -210,17 +182,22 @@ const ClosingIncomingSapronaksTable = ({
rowSelection={rowSelection} rowSelection={rowSelection}
setRowSelection={setRowSelection} setRowSelection={setRowSelection}
className={{ className={{
containerClassName: cn({ containerClassName: 'w-full mb-0!',
'w-full mb-20': tableWrapperClassName:
isResponseSuccess(incomingSapronaks) && 'overflow-x-auto rounded-tr-none rounded-tl-none',
incomingSapronaks?.data?.length === 0, tableClassName: 'w-full table-auto text-sm',
}), headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
/> />
)} )}
</div>
</Collapse>
</Card> </Card>
</div>
); );
}; };
@@ -5,12 +5,10 @@ import { useSearchParams } from 'next/navigation';
import useSWR from 'swr'; import useSWR from 'swr';
import { ColumnDef, SortingState } from '@tanstack/react-table'; import { ColumnDef, SortingState } from '@tanstack/react-table';
import { Icon } from '@iconify/react';
import Table from '@/components/Table'; import Table from '@/components/Table';
import Card from '@/components/Card'; import Card from '@/components/Card';
import Collapse from '@/components/Collapse';
import { cn, formatNumber } from '@/lib/helper'; import { formatNumber } from '@/lib/helper';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter'; import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing'; import { ClosingApi } from '@/services/api/closing';
@@ -56,8 +54,6 @@ const ClosingOutgoingSapronaksSummaryTable = ({
} }
); );
const [open, setOpen] = useState(true);
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
@@ -94,44 +90,20 @@ const ClosingOutgoingSapronaksSummaryTable = ({
} }
}, [sorting, updateFilter]); }, [sorting, updateFilter]);
useEffect(() => {
if (!open) {
setOpen(
isResponseSuccess(outgoingSapronakSummaries)
? outgoingSapronakSummaries.data.length > 0
: false
);
}
}, [outgoingSapronakSummaries, isResponseSuccess]);
return ( return (
<div className='w-full p-0 sm:p-3'>
<Card <Card
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-4 shadow', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='Ringkasan Sapronak Keluar'
collapsible
defaultCollapsed={false}
> >
<Collapse
open={open}
onOpenChange={setOpen}
title={
<div className='card-actions p-4 justify-between items-center w-full'>
<div className='card-title'>Ringkasan Sapronak Keluar</div>
<Icon
icon='material-symbols:keyboard-arrow-down'
width={24}
height={24}
className={cn('text-primary transition-transform', {
'-rotate-180': open,
})}
/>
</div>
}
className='w-full!'
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
{isLoadingOutgoingSapronakSummaries ? ( {isLoadingOutgoingSapronakSummaries ? (
<SapronakClosingSkeleton <SapronakClosingSkeleton
type='outgoing' type='outgoing'
@@ -174,17 +146,23 @@ const ClosingOutgoingSapronaksSummaryTable = ({
rowSelection={rowSelection} rowSelection={rowSelection}
setRowSelection={setRowSelection} setRowSelection={setRowSelection}
className={{ className={{
containerClassName: cn({ containerClassName: 'w-full mb-0!',
'w-full mb-20': tableWrapperClassName:
isResponseSuccess(outgoingSapronakSummaries) && 'overflow-x-auto rounded-tr-none rounded-tl-none',
outgoingSapronakSummaries?.data?.length === 0, tableClassName: 'w-full table-auto text-sm',
}), headerRowClassName:
'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
/> />
)} )}
</div>
</Collapse>
</Card> </Card>
</div>
); );
}; };
@@ -5,13 +5,11 @@ import { useSearchParams } from 'next/navigation';
import useSWR from 'swr'; import useSWR from 'swr';
import { ColumnDef, SortingState } from '@tanstack/react-table'; import { ColumnDef, SortingState } from '@tanstack/react-table';
import { Icon } from '@iconify/react';
import Table from '@/components/Table'; import Table from '@/components/Table';
import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import Card from '@/components/Card'; import Card from '@/components/Card';
import Collapse from '@/components/Collapse';
import { cn, formatDate, formatNumber } from '@/lib/helper'; import { formatDate, formatNumber } from '@/lib/helper';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter'; import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing'; import { ClosingApi } from '@/services/api/closing';
@@ -52,8 +50,6 @@ const ClosingOutgoingSapronaksTable = ({
ClosingApi.getAllOutgoingSapronakFetcher ClosingApi.getAllOutgoingSapronakFetcher
); );
const [open, setOpen] = useState(true);
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({}); const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
@@ -118,44 +114,20 @@ const ClosingOutgoingSapronaksTable = ({
} }
}, [sorting, updateFilter]); }, [sorting, updateFilter]);
useEffect(() => {
if (!open) {
setOpen(
isResponseSuccess(outgoingSapronaks)
? outgoingSapronaks.data.length > 0
: false
);
}
}, [outgoingSapronaks, isResponseSuccess]);
return ( return (
<div className='w-full p-0 sm:p-3'>
<Card <Card
className={{ className={{
wrapper: 'w-full', wrapper: 'w-full rounded-lg border-none',
body: 'p-4 shadow', body: 'p-0',
title: 'px-2 py-1.5 font-normal text-sm bg-primary text-white',
collapsible: 'rounded-lg',
}} }}
variant='bordered'
title='Sapronak Keluar'
collapsible
defaultCollapsed={false}
> >
<Collapse
open={open}
onOpenChange={setOpen}
title={
<div className='card-actions p-4 justify-between items-center w-full'>
<div className='card-title'>Sapronak Keluar</div>
<Icon
icon='material-symbols:keyboard-arrow-down'
width={24}
height={24}
className={cn('text-primary transition-transform', {
'-rotate-180': open,
})}
/>
</div>
}
className='w-full!'
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
<div className='flex flex-col gap-2 mb-4'> <div className='flex flex-col gap-2 mb-4'>
<div className='w-full flex flex-col sm:flex-row justify-start items-end sm:items-center gap-4'> <div className='w-full flex flex-col sm:flex-row justify-start items-end sm:items-center gap-4'>
<DebouncedTextInput <DebouncedTextInput
@@ -210,17 +182,23 @@ const ClosingOutgoingSapronaksTable = ({
rowSelection={rowSelection} rowSelection={rowSelection}
setRowSelection={setRowSelection} setRowSelection={setRowSelection}
className={{ className={{
containerClassName: cn({ containerClassName: 'w-full mb-0!',
'w-full mb-20': tableWrapperClassName:
isResponseSuccess(outgoingSapronaks) && 'overflow-x-auto rounded-tr-none rounded-tl-none',
outgoingSapronaks?.data?.length === 0, tableClassName: 'w-full table-auto text-sm',
}), headerRowClassName:
'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}} }}
/> />
)} )}
</div>
</Collapse>
</Card> </Card>
</div>
); );
}; };