feat(FE): Add skeleton components for closing pages

This commit is contained in:
rstubryan
2026-02-19 10:03:25 +07:00
parent 9c953ca382
commit 8fe19feaac
18 changed files with 1262 additions and 613 deletions
@@ -0,0 +1,36 @@
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
import Table from '@/components/Table';
import { ColumnDef } from '@tanstack/react-table';
const ClosingTabSkeleton = <T extends object>({
columns,
icon,
title,
subtitle,
}: {
columns: ColumnDef<T>[];
icon: React.ReactNode;
title: string;
subtitle: string;
}) => {
return (
<div className='relative size-full'>
<Table
data={[]}
columns={columns as ColumnDef<T>[]}
isLoading={true}
className={{
skeletonCellClassName: 'animate-none w-full h-5 bg-base-content/4',
headerColumnClassName: 'whitespace-nowrap',
containerClassName: 'mb-0 overflow-hidden',
tableWrapperClassName: 'overflow-hidden',
}}
/>
<div className='absolute inset-0 flex items-center justify-center'>
<DataStateSkeleton icon={icon} title={title} description={subtitle} />
</div>
</div>
);
};
export default ClosingTabSkeleton;
@@ -0,0 +1,40 @@
import { Icon } from '@iconify/react';
import Card from '@/components/Card';
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
const FinanceClosingSkeleton = ({
title = 'Data Keuangan Belum Tersedia',
subtitle = 'Tidak ada data keuangan untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
title?: string;
subtitle?: string;
iconName?: string;
}) => {
return (
<Card
variant='bordered'
className={{
wrapper: 'w-full',
body: 'p-8',
}}
>
<div className='flex items-center justify-center p-8'>
<DataStateSkeleton
icon={
<Icon
icon={iconName}
className='text-white'
width={20}
height={20}
/>
}
title={title}
description={subtitle}
/>
</div>
</Card>
);
};
export default FinanceClosingSkeleton;
@@ -0,0 +1,44 @@
import { Icon } from '@iconify/react';
import ClosingTabSkeleton from './ClosingTabSkeleton';
import { BaseExpeditionCost } from '@/types/api/closing';
import { ColumnDef } from '@tanstack/react-table';
const HppExpeditionClosingSkeleton = ({
columns,
title = 'Data HPP Ekspedisi Belum Tersedia',
subtitle = 'Tidak ada data HPP ekspedisi untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
columns?: ColumnDef<BaseExpeditionCost>[];
title?: string;
subtitle?: string;
iconName?: string;
}) => {
const defaultColumns: ColumnDef<BaseExpeditionCost>[] = [
{
id: 'id',
header: 'No',
},
{
id: 'expedition_vendor_name',
header: 'Nama Ekspedisi',
},
{
id: 'hpp_amount',
header: 'HPP Ekspedisi',
},
];
return (
<ClosingTabSkeleton<BaseExpeditionCost>
columns={columns || defaultColumns}
icon={
<Icon icon={iconName} className='text-white' width={20} height={20} />
}
title={title}
subtitle={subtitle}
/>
);
};
export default HppExpeditionClosingSkeleton;
@@ -0,0 +1,72 @@
import { Icon } from '@iconify/react';
import ClosingTabSkeleton from './ClosingTabSkeleton';
import { Overhead } from '@/types/api/closing';
import { ColumnDef } from '@tanstack/react-table';
const OverheadClosingSkeleton = ({
columns,
title = 'Data Overhead Belum Tersedia',
subtitle = 'Tidak ada data overhead untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
columns?: ColumnDef<Overhead>[];
title?: string;
subtitle?: string;
iconName?: string;
}) => {
const defaultColumns: ColumnDef<Overhead>[] = [
{
id: 'name',
header: 'Nama Overhead',
},
{
id: 'budget_quantity',
header: 'Budget Pengajuan - Jumlah',
},
{
id: 'budget_unit_price',
header: 'Budget Pengajuan - Harga Satuan',
},
{
id: 'budget_total_amount',
header: 'Budget Pengajuan - Total',
},
{
id: 'actual_quantity',
header: 'Realisasi - Jumlah',
},
{
id: 'actual_unit_price',
header: 'Realisasi - Harga Satuan',
},
{
id: 'actual_total_amount',
header: 'Realisasi - Total',
},
{
id: 'difference_quantity',
header: 'Selisih - Jumlah',
},
{
id: 'difference_unit_price',
header: 'Selisih - Harga Satuan',
},
{
id: 'difference_total_amount',
header: 'Selisih - Total',
},
];
return (
<ClosingTabSkeleton<Overhead>
columns={columns || defaultColumns}
icon={
<Icon icon={iconName} className='text-white' width={20} height={20} />
}
title={title}
subtitle={subtitle}
/>
);
};
export default OverheadClosingSkeleton;
@@ -0,0 +1,33 @@
import { Icon } from '@iconify/react';
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
const ProductionDataClosingSkeleton = ({
title = 'Data Produksi Belum Tersedia',
subtitle = 'Tidak ada data produksi untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
title?: string;
subtitle?: string;
iconName?: string;
}) => {
return (
<div className='w-full rounded-xl p-8 shadow-sm'>
<div className='flex items-center justify-center p-12'>
<DataStateSkeleton
icon={
<Icon
icon={iconName}
className='text-white'
width={20}
height={20}
/>
}
title={title}
description={subtitle}
/>
</div>
</div>
);
};
export default ProductionDataClosingSkeleton;
@@ -0,0 +1,84 @@
import { Icon } from '@iconify/react';
import ClosingTabSkeleton from './ClosingTabSkeleton';
import { BaseSales } from '@/types/api/closing';
import { ColumnDef } from '@tanstack/react-table';
const SalesClosingSkeleton = ({
columns,
title = 'Data Penjualan Belum Tersedia',
subtitle = 'Tidak ada data penjualan untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
columns?: ColumnDef<BaseSales>[];
title?: string;
subtitle?: string;
iconName?: string;
}) => {
const defaultColumns: ColumnDef<BaseSales>[] = [
{
id: 'realization_date',
header: 'Tanggal Realisasi',
},
{
id: 'age',
header: 'Umur',
},
{
id: 'do_number',
header: 'No. DO',
},
{
id: 'product',
header: 'Produk',
},
{
id: 'customer',
header: 'Customer',
},
{
id: 'qty',
header: 'Kuantitas',
},
{
id: 'weight',
header: 'Kg',
},
{
id: 'avg_weight',
header: 'AVG (Kg)',
},
{
id: 'sales_price',
header: 'Harga Sales (Rp)',
},
{
id: 'total_sales_price',
header: 'Total Sales (Rp)',
},
{
id: 'actual_price',
header: 'Harga Act (Rp)',
},
{
id: 'total_actual_price',
header: 'Total Act (Rp)',
},
{
id: 'kandang',
header: 'Kandang',
},
];
return (
<ClosingTabSkeleton<BaseSales>
columns={columns || defaultColumns}
icon={
<Icon icon={iconName} className='text-white' width={20} height={20} />
}
title={title}
subtitle={subtitle}
/>
);
};
export default SalesClosingSkeleton;
@@ -0,0 +1,72 @@
import { Icon } from '@iconify/react';
import ClosingTabSkeleton from './ClosingTabSkeleton';
import { RowSapronakCalculation } from '@/types/api/closing';
import { ColumnDef } from '@tanstack/react-table';
const SapronakCalculationClosingSkeleton = ({
columns,
title = 'Data Perhitungan Sapronak Belum Tersedia',
subtitle = 'Tidak ada data perhitungan sapronak untuk periode ini.',
iconName = 'heroicons:chart-bar',
}: {
columns?: ColumnDef<RowSapronakCalculation>[];
title?: string;
subtitle?: string;
iconName?: string;
}) => {
const defaultColumns: ColumnDef<RowSapronakCalculation>[] = [
{
id: 'date',
header: 'Tanggal',
},
{
id: 'reference_number',
header: 'No. Referensi',
},
{
id: 'qty_in',
header: 'QTY Masuk',
},
{
id: 'qty_out',
header: 'QTY Keluar',
},
{
id: 'qty_used',
header: 'QTY Pakai',
},
{
id: 'balance',
header: 'Saldo',
},
{
id: 'unit_price_in',
header: 'Harga Masuk',
},
{
id: 'unit_price_out',
header: 'Harga Keluar',
},
{
id: 'total_price_in',
header: 'Total Harga Masuk',
},
{
id: 'total_price_out',
header: 'Total Harga Keluar',
},
];
return (
<ClosingTabSkeleton<RowSapronakCalculation>
columns={columns || defaultColumns}
icon={
<Icon icon={iconName} className='text-white' width={20} height={20} />
}
title={title}
subtitle={subtitle}
/>
);
};
export default SapronakCalculationClosingSkeleton;
@@ -0,0 +1,126 @@
import { Icon } from '@iconify/react';
import ClosingTabSkeleton from './ClosingTabSkeleton';
import { ClosingIncomingSapronak } from '@/types/api/closing';
import { ColumnDef } from '@tanstack/react-table';
const SapronakClosingSkeleton = ({
columns,
type = 'incoming',
title,
subtitle,
iconName = 'heroicons:chart-bar',
}: {
columns?: ColumnDef<ClosingIncomingSapronak>[];
type?: 'incoming' | 'outgoing';
title?: string;
subtitle?: string;
iconName?: string;
}) => {
const defaultIncomingColumns: ColumnDef<ClosingIncomingSapronak>[] = [
{
id: '#',
header: '#',
},
{
id: 'date',
header: 'Tanggal',
},
{
id: 'reference_number',
header: 'No. Referensi',
},
{
id: 'transaction_type',
header: 'Jenis Transaksi',
},
{
id: 'product_name',
header: 'Produk',
},
{
id: 'product_category',
header: 'Kategori Produk',
},
{
id: 'source_warehouse',
header: 'Gudang Asal',
},
{
id: 'destination_warehouse',
header: 'Gudang Tujuan',
},
{
id: 'quantity',
header: 'Kuantitas',
},
{
id: 'notes',
header: 'Keterangan',
},
];
const defaultOutgoingColumns: ColumnDef<ClosingIncomingSapronak>[] = [
{
id: '#',
header: '#',
},
{
id: 'date',
header: 'Tanggal',
},
{
id: 'reference_number',
header: 'No. Referensi',
},
{
id: 'transaction_type',
header: 'Jenis Transaksi',
},
{
id: 'product_name',
header: 'Produk',
},
{
id: 'product_category',
header: 'Kategori Produk',
},
{
id: 'source_warehouse',
header: 'Gudang Asal',
},
{
id: 'quantity',
header: 'Kuantitas',
},
{
id: 'notes',
header: 'Keterangan',
},
];
const defaultTitle =
type === 'incoming'
? 'Data Sapronak Masuk Belum Tersedia'
: 'Data Sapronak Keluar Belum Tersedia';
const defaultSubtitle =
type === 'incoming'
? 'Silakan pilih periode atau filter untuk melihat data sapronak masuk.'
: 'Silakan pilih periode atau filter untuk melihat data sapronak keluar.';
return (
<ClosingTabSkeleton<ClosingIncomingSapronak>
columns={
columns ||
(type === 'incoming' ? defaultIncomingColumns : defaultOutgoingColumns)
}
icon={
<Icon icon={iconName} className='text-white' width={20} height={20} />
}
title={title || defaultTitle}
subtitle={subtitle || defaultSubtitle}
/>
);
};
export default SapronakClosingSkeleton;
@@ -5,6 +5,7 @@ import useSWR from 'swr';
import { ClosingApi } from '@/services/api/closing';
import { isResponseSuccess } from '@/lib/api-helper';
import { formatNumber } from '@/lib/helper';
import ProductionDataClosingSkeleton from '@/components/pages/closing/skeleton/ProductionDataClosingSkeleton';
interface ProductionDataClosingTabProps {
projectFlockId: number;
@@ -22,18 +23,16 @@ const ProductionDataClosingTab = ({
);
if (isLoading) {
return (
<div className='w-full flex justify-center py-8'>
<span className='loading loading-spinner loading-lg' />
</div>
);
return <ProductionDataClosingSkeleton />;
}
if (!productionData || !isResponseSuccess(productionData)) {
return (
<div className='w-full text-center py-8 text-gray-500'>
Gagal memuat data produksi.
</div>
<ProductionDataClosingSkeleton
iconName='heroicons:exclamation-circle'
title='Gagal Memuat Data Produksi'
subtitle='Terjadi kesalahan saat memuat data produksi. Silakan coba lagi.'
/>
);
}
@@ -7,6 +7,7 @@ import { HppItem, ProfitLossItem } from '@/types/api/closing';
import { useSearchParams } from 'next/navigation';
import { useMemo } from 'react';
import useSWR from 'swr';
import FinanceClosingSkeleton from '@/components/pages/closing/skeleton/FinanceClosingSkeleton';
const FinanceClosingTable = ({
projectFlockId,
@@ -82,6 +83,15 @@ const FinanceClosingTable = ({
return (
<div className='flex flex-col gap-4'>
{isLoading ? (
<FinanceClosingSkeleton />
) : !isResponseSuccess(finance) ? (
<FinanceClosingSkeleton
iconName='heroicons:chart-bar'
title='Data Keuangan Tidak Ditemukan'
subtitle='Tidak ada data keuangan untuk periode ini.'
/>
) : (
<>
<Card
variant='bordered'
@@ -174,8 +184,8 @@ const FinanceClosingTable = ({
return props.column.id === 'budgeting_rp_per_kg' &&
isResponseSuccess(finance)
? formatCurrency(
finance.data.hpp.summary?.budgeting?.rp_per_kg ||
0
finance.data.hpp.summary?.budgeting
?.rp_per_kg || 0
)
: '-';
},
@@ -208,7 +218,8 @@ const FinanceClosingTable = ({
accessorFn: (item) =>
formatCurrency(item.realization?.rp_per_bird || 0),
footer: (props) => {
return props.column.id === 'realization_rp_per_bird' &&
return props.column.id ===
'realization_rp_per_bird' &&
isResponseSuccess(finance)
? formatCurrency(
finance.data.hpp.summary?.realization
@@ -243,7 +254,8 @@ const FinanceClosingTable = ({
return props.column.id === 'realization_amount' &&
isResponseSuccess(finance)
? formatCurrency(
finance.data.hpp.summary?.realization?.amount || 0
finance.data.hpp.summary?.realization?.amount ||
0
)
: '-';
},
@@ -359,22 +371,30 @@ const FinanceClosingTable = ({
key={row.id}
className={TABLE_DEFAULT_STYLING.footerRowClassName}
>
<td className={TABLE_DEFAULT_STYLING.bodyColumnClassName}>
<td
className={TABLE_DEFAULT_STYLING.bodyColumnClassName}
>
<div className='font-bold ps-6 uppercase'>
{formatTitleCase(rowData.label ?? '-')}
</div>
</td>
<td className={TABLE_DEFAULT_STYLING.bodyColumnClassName}>
<td
className={TABLE_DEFAULT_STYLING.bodyColumnClassName}
>
<div className='font-bold'>
{formatCurrency(rowData.rp_per_bird ?? 0)}
</div>
</td>
<td className={TABLE_DEFAULT_STYLING.bodyColumnClassName}>
<td
className={TABLE_DEFAULT_STYLING.bodyColumnClassName}
>
<div className='font-bold'>
{formatCurrency(rowData.rp_per_kg ?? 0)}
</div>
</td>
<td className={TABLE_DEFAULT_STYLING.bodyColumnClassName}>
<td
className={TABLE_DEFAULT_STYLING.bodyColumnClassName}
>
<div className='font-bold'>
{formatCurrency(rowData.amount ?? 0)}
</div>
@@ -392,6 +412,7 @@ const FinanceClosingTable = ({
</div>
</Card>
</>
)}
</div>
);
};
@@ -10,6 +10,7 @@ import { BaseExpeditionCost } from '@/types/api/closing';
import { ClosingApi } from '@/services/api/closing';
import { useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import HppExpeditionClosingSkeleton from '@/components/pages/closing/skeleton/HppExpeditionClosingSkeleton';
interface HppExpeditionClosingTableProps {
projectFlockId: number;
@@ -100,6 +101,16 @@ const HppExpeditionClosingTable = ({
body: 'p-0',
}}
>
{isLoading ? (
<HppExpeditionClosingSkeleton
columns={costOfRevenueExpeditionColumns}
/>
) : costOfRevenueExpeditionData.length === 0 ? (
<HppExpeditionClosingSkeleton
columns={costOfRevenueExpeditionColumns}
iconName='heroicons:chart-bar'
/>
) : (
<Table
data={costOfRevenueExpeditionData}
columns={costOfRevenueExpeditionColumns}
@@ -122,6 +133,7 @@ const HppExpeditionClosingTable = ({
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}}
/>
)}
</Card>
</div>
</section>
@@ -14,6 +14,7 @@ import { ColumnDef } from '@tanstack/react-table';
import { useSearchParams } from 'next/navigation';
import { useMemo } from 'react';
import useSWR from 'swr';
import OverheadClosingSkeleton from '@/components/pages/closing/skeleton/OverheadClosingSkeleton';
interface OverheadClosingTableProps {
projectFlockId: number;
@@ -209,6 +210,18 @@ const OverheadClosingTable = ({
return (
<>
{isLoadingOverhead ? (
<OverheadClosingSkeleton columns={columns} />
) : !isResponseSuccess(overhead) ||
(!kandangId && overhead.data?.overheads.length === 0) ||
(kandangId && !isResponseSuccess(overheadKandang)) ? (
<OverheadClosingSkeleton
columns={columns}
iconName='heroicons:chart-bar'
title='Data Overhead Tidak Ditemukan'
subtitle='Tidak ada data overhead untuk periode ini.'
/>
) : (
<Card
title='Pengeluaran Overhead'
collapsible
@@ -260,8 +273,8 @@ const OverheadClosingTable = ({
<div className='flex flex-col flex-1 gap-1.5'>
<div className='flex flex-row gap-1.5 text-center items-center justify-center font-medium'>
Populasi Akhir KANDANG{' '}
<Icon icon='heroicons:x-mark' className='inline' /> Pemakaian
Di FARM
<Icon icon='heroicons:x-mark' className='inline' />{' '}
Pemakaian Di FARM
</div>
<hr className='w-full h-fit m-0 p-0 text-base-content/65' />
<div className='flex flex-row gap-1.5 text-center items-center justify-center font-medium'>
@@ -298,6 +311,7 @@ const OverheadClosingTable = ({
</Card>
)}
</Card>
)}
</>
);
};
@@ -17,6 +17,7 @@ import { Kandang } from '@/types/api/master-data/kandang';
import { ClosingApi } from '@/services/api/closing';
import { useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import SalesClosingSkeleton from '@/components/pages/closing/skeleton/SalesClosingSkeleton';
interface SalesClosingTableProps {
projectFlockId: number;
@@ -325,6 +326,14 @@ const SalesClosingTable = ({ projectFlockId }: SalesClosingTableProps) => {
body: 'p-0',
}}
>
{isLoading ? (
<SalesClosingSkeleton columns={salesColumns} />
) : salesData.length === 0 ? (
<SalesClosingSkeleton
columns={salesColumns}
iconName='heroicons:chart-bar'
/>
) : (
<Table
data={salesData}
columns={salesColumns}
@@ -346,6 +355,7 @@ const SalesClosingTable = ({ projectFlockId }: SalesClosingTableProps) => {
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}}
/>
)}
</Card>
</div>
</section>
@@ -15,6 +15,7 @@ import { ClosingApi } from '@/services/api/closing';
import { isResponseSuccess } from '@/lib/api-helper';
import { ClosingGeneralInformation } from '@/types/api/closing';
import { useSearchParams } from 'next/navigation';
import SapronakCalculationClosingSkeleton from '@/components/pages/closing/skeleton/SapronakCalculationClosingSkeleton';
interface SapronakCalculationClosingTableProps {
projectFlockId: number;
@@ -193,6 +194,16 @@ const SapronakCalculationClosingTable = ({
body: 'p-4 shadow',
}}
>
{isLoading ? (
<SapronakCalculationClosingSkeleton />
) : isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.doc?.rows?.length === 0 ? (
<SapronakCalculationClosingSkeleton
iconName='heroicons:chart-bar'
title='Data Perhitungan Sapronak Tidak Ditemukan'
subtitle='Tidak ada data perhitungan sapronak untuk periode ini.'
/>
) : (
<Table<RowSapronakCalculation>
data={
isResponseSuccess(sapronakCalculation)
@@ -205,9 +216,10 @@ const SapronakCalculationClosingTable = ({
}}
renderFooter={
isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.doc?.rows.length > 0
sapronakCalculation.data?.doc?.rows?.length > 0
}
/>
)}
</Card>
<Card
@@ -219,6 +231,16 @@ const SapronakCalculationClosingTable = ({
wrapper: 'w-full',
}}
>
{isLoading ? (
<SapronakCalculationClosingSkeleton />
) : isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.ovk?.rows?.length === 0 ? (
<SapronakCalculationClosingSkeleton
iconName='heroicons:chart-bar'
title='Data Perhitungan Sapronak Tidak Ditemukan'
subtitle='Tidak ada data perhitungan sapronak untuk periode ini.'
/>
) : (
<Table<RowSapronakCalculation>
data={
isResponseSuccess(sapronakCalculation)
@@ -231,9 +253,10 @@ const SapronakCalculationClosingTable = ({
}}
renderFooter={
isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.ovk?.rows.length > 0
sapronakCalculation.data?.ovk?.rows?.length > 0
}
/>
)}
</Card>
<Card
@@ -245,6 +268,16 @@ const SapronakCalculationClosingTable = ({
wrapper: 'w-full',
}}
>
{isLoading ? (
<SapronakCalculationClosingSkeleton />
) : isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.pakan?.rows?.length === 0 ? (
<SapronakCalculationClosingSkeleton
iconName='heroicons:chart-bar'
title='Data Perhitungan Sapronak Tidak Ditemukan'
subtitle='Tidak ada data perhitungan sapronak untuk periode ini.'
/>
) : (
<Table<RowSapronakCalculation>
data={
isResponseSuccess(sapronakCalculation)
@@ -257,9 +290,10 @@ const SapronakCalculationClosingTable = ({
}}
renderFooter={
isResponseSuccess(sapronakCalculation) &&
sapronakCalculation.data?.pakan?.rows.length > 0
sapronakCalculation.data?.pakan?.rows?.length > 0
}
/>
)}
</Card>
</div>
);
@@ -15,6 +15,7 @@ import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing';
import { ClosingIncomingSapronakSummary } from '@/types/api/closing';
import SapronakClosingSkeleton from '@/components/pages/closing/skeleton/SapronakClosingSkeleton';
interface ClosingIncomingSapronaksSummaryTableProps {
projectFlockId: number;
@@ -131,6 +132,17 @@ const ClosingIncomingSapronaksSummaryTable = ({
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
{isLoadingIncomingSapronakSummaries ? (
<SapronakClosingSkeleton type='incoming' />
) : isResponseSuccess(incomingSapronakSummaries) &&
incomingSapronakSummaries.data.length === 0 ? (
<SapronakClosingSkeleton
type='incoming'
iconName='heroicons:chart-bar'
title='Ringkasan Sapronak Masuk Tidak Ditemukan'
subtitle='Tidak ada ringkasan sapronak masuk untuk periode ini.'
/>
) : (
<Table<ClosingIncomingSapronakSummary>
data={
isResponseSuccess(incomingSapronakSummaries)
@@ -165,6 +177,7 @@ const ClosingIncomingSapronaksSummaryTable = ({
}),
}}
/>
)}
</div>
</Collapse>
</Card>
@@ -16,6 +16,7 @@ import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing';
import { ClosingIncomingSapronak } from '@/types/api/closing';
import SapronakClosingSkeleton from '@/components/pages/closing/skeleton/SapronakClosingSkeleton';
interface ClosingIncomingSapronaksTableProps {
projectFlockId: number;
@@ -167,6 +168,17 @@ const ClosingIncomingSapronaksTable = ({
</div>
</div>
{isLoadingIncomingSapronaks ? (
<SapronakClosingSkeleton type='incoming' />
) : isResponseSuccess(incomingSapronaks) &&
incomingSapronaks.data.length === 0 ? (
<SapronakClosingSkeleton
type='incoming'
iconName='heroicons:chart-bar'
title='Data Sapronak Masuk Tidak Ditemukan'
subtitle='Tidak ada data sapronak masuk untuk periode ini.'
/>
) : (
<Table<ClosingIncomingSapronak>
data={
isResponseSuccess(incomingSapronaks)
@@ -201,6 +213,7 @@ const ClosingIncomingSapronaksTable = ({
}),
}}
/>
)}
</div>
</Collapse>
</Card>
@@ -15,6 +15,7 @@ import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing';
import { ClosingOutgoingSapronakSummary } from '@/types/api/closing';
import SapronakClosingSkeleton from '@/components/pages/closing/skeleton/SapronakClosingSkeleton';
interface ClosingOutgoingSapronaksSummaryTableProps {
projectFlockId: number;
@@ -131,6 +132,17 @@ const ClosingOutgoingSapronaksSummaryTable = ({
titleClassName='w-full p-0!'
>
<div className='w-full p-0'>
{isLoadingOutgoingSapronakSummaries ? (
<SapronakClosingSkeleton type='outgoing' />
) : isResponseSuccess(outgoingSapronakSummaries) &&
outgoingSapronakSummaries.data.length === 0 ? (
<SapronakClosingSkeleton
type='outgoing'
iconName='heroicons:chart-bar'
title='Ringkasan Sapronak Keluar Tidak Ditemukan'
subtitle='Tidak ada ringkasan sapronak keluar untuk periode ini.'
/>
) : (
<Table<ClosingOutgoingSapronakSummary>
data={
isResponseSuccess(outgoingSapronakSummaries)
@@ -165,6 +177,7 @@ const ClosingOutgoingSapronaksSummaryTable = ({
}),
}}
/>
)}
</div>
</Collapse>
</Card>
@@ -16,6 +16,7 @@ import { isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { ClosingApi } from '@/services/api/closing';
import { ClosingOutgoingSapronak } from '@/types/api/closing';
import SapronakClosingSkeleton from '@/components/pages/closing/skeleton/SapronakClosingSkeleton';
interface ClosingOutgoingSapronaksTableProps {
projectFlockId: number;
@@ -167,6 +168,17 @@ const ClosingOutgoingSapronaksTable = ({
</div>
</div>
{isLoadingOutgoingSapronaks ? (
<SapronakClosingSkeleton type='outgoing' />
) : isResponseSuccess(outgoingSapronaks) &&
outgoingSapronaks.data.length === 0 ? (
<SapronakClosingSkeleton
type='outgoing'
iconName='heroicons:chart-bar'
title='Data Sapronak Keluar Tidak Ditemukan'
subtitle='Tidak ada data sapronak keluar untuk periode ini.'
/>
) : (
<Table<ClosingOutgoingSapronak>
data={
isResponseSuccess(outgoingSapronaks)
@@ -201,6 +213,7 @@ const ClosingOutgoingSapronaksTable = ({
}),
}}
/>
)}
</div>
</Collapse>
</Card>