refactor(FE-208,213): enhance PurchaseOrderDetail and PurchaseOrderStaffApprovalForm components with initialValues prop and clean up unused code

This commit is contained in:
rstubryan
2025-11-18 18:22:10 +07:00
parent 75e7b9a6de
commit 8c3cd3bc53
3 changed files with 85 additions and 172 deletions
+81 -120
View File
@@ -91,7 +91,6 @@ const PurchaseTable = () => {
null null
); );
const [sorting, setSorting] = useState<SortingState>([]); const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
// ===== TABLE FILTER STATE ===== // ===== TABLE FILTER STATE =====
const { const {
@@ -134,104 +133,94 @@ const PurchaseTable = () => {
PurchaseRequestApi.getAllFetcher PurchaseRequestApi.getAllFetcher
); );
// ===== COMPUTED VALUES =====
const selectedRowIds = useMemo(
() => Object.keys(rowSelection).map((item) => parseInt(item)),
[rowSelection]
);
// ===== TABLE COLUMNS DEFINITION ===== // ===== TABLE COLUMNS DEFINITION =====
const purchaseColumns: ColumnDef<Purchase>[] = useMemo( const purchaseColumns: ColumnDef<Purchase>[] = [
() => [ {
{ header: 'No. PR/PO',
header: 'No. PR/PO', cell: (props) => {
cell: (props) => { const { pr_number, po_number } = props.row.original;
const { pr_number, po_number } = props.row.original; return po_number ? po_number : pr_number;
return po_number ? po_number : pr_number;
},
}, },
{ },
accessorKey: 'supplier', {
header: 'Vendor', accessorKey: 'supplier',
cell: (props) => props.row.original.supplier.name, header: 'Vendor',
cell: (props) => props.row.original.supplier.name,
},
{
accessorKey: 'po_date',
header: 'Tgl. PO',
cell: (props) =>
props.row.original.po_date
? formatDate(props.row.original.po_date, 'DD MMM YYYY')
: '-',
},
{
accessorKey: 'due_date',
header: 'Jatuh Tempo',
cell: (props) =>
props.row.original.due_date
? formatDate(props.row.original.due_date, 'DD MMM YYYY')
: '-',
},
{
header: 'Aging',
cell: (props) => {
const purchase = props.row.original;
if (!purchase.po_date) return '-';
const poDate = new Date(purchase.po_date);
const today = new Date();
const diffTime = Math.abs(today.getTime() - poDate.getTime());
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return `${diffDays} hari`;
}, },
{ },
accessorKey: 'po_date', {
header: 'Tgl. PO', accessorKey: 'grand_total',
cell: (props) => header: 'Total (Rp.)',
props.row.original.po_date cell: (props) => formatCurrency(props.row.original.grand_total),
? formatDate(props.row.original.po_date, 'DD MMM YYYY') },
: '-', {
}, header: 'Aksi',
{ cell: (props) => {
accessorKey: 'due_date', const currentPageSize = props.table.getPaginationRowModel().rows.length;
header: 'Jatuh Tempo', const currentPageRows = props.table.getPaginationRowModel().flatRows;
cell: (props) => const currentRowRelativeIndex =
props.row.original.due_date currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
? formatDate(props.row.original.due_date, 'DD MMM YYYY')
: '-',
},
{
header: 'Aging',
cell: (props) => {
const purchase = props.row.original;
if (!purchase.po_date) return '-';
const poDate = new Date(purchase.po_date);
const today = new Date();
const diffTime = Math.abs(today.getTime() - poDate.getTime());
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return `${diffDays} hari`;
},
},
{
accessorKey: 'grand_total',
header: 'Total (Rp.)',
cell: (props) => formatCurrency(props.row.original.grand_total),
},
{
header: 'Aksi',
cell: (props) => {
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; const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
const deleteClickHandler = () => { const deleteClickHandler = () => {
setSelectedPurchase(props.row.original); setSelectedPurchase(props.row.original);
deleteModal.openModal(); deleteModal.openModal();
}; };
return ( return (
<> <>
{currentPageSize > 2 && ( {currentPageSize > 2 && (
<RowDropdownOptions isLast2Rows={isLast2Rows}> <RowDropdownOptions isLast2Rows={isLast2Rows}>
<RowOptionsMenu <RowOptionsMenu
type='dropdown' type='dropdown'
props={props} props={props}
deleteClickHandler={deleteClickHandler} deleteClickHandler={deleteClickHandler}
/> />
</RowDropdownOptions> </RowDropdownOptions>
)} )}
{currentPageSize <= 2 && ( {currentPageSize <= 2 && (
<RowCollapseOptions> <RowCollapseOptions>
<RowOptionsMenu <RowOptionsMenu
type='collapse' type='collapse'
props={props} props={props}
deleteClickHandler={deleteClickHandler} deleteClickHandler={deleteClickHandler}
/> />
</RowCollapseOptions> </RowCollapseOptions>
)} )}
</> </>
); );
},
}, },
], },
[] ];
);
// ===== EVENT HANDLERS ===== // ===== EVENT HANDLERS =====
const confirmationModalDeleteClickHandler = useCallback(async () => { const confirmationModalDeleteClickHandler = useCallback(async () => {
@@ -287,7 +276,7 @@ const PurchaseTable = () => {
<div className='w-full p-0 sm:p-4'> <div className='w-full p-0 sm:p-4'>
<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 xl:flex-row justify-between items-end xl:items-center gap-2'> <div className='w-full flex flex-col xl:flex-row justify-between items-end xl:items-center gap-2'>
<div className='w-full sm:w-fit flex flex-col sm:flex-row self-start gap-2'> <div className='w-full flex flex-row gap-2'>
<Button <Button
href='/purchase/add' href='/purchase/add'
variant='outline' variant='outline'
@@ -297,32 +286,6 @@ const PurchaseTable = () => {
<Icon icon='ic:round-plus' width={24} height={24} /> <Icon icon='ic:round-plus' width={24} height={24} />
Tambah Tambah
</Button> </Button>
{selectedRowIds.length > 0 && (
<Button
variant='outline'
color='error'
onClick={() => {
setSelectedPurchase(
isResponseSuccess(purchaseRequests)
? purchaseRequests?.data?.find((p: Purchase) =>
selectedRowIds.includes(p.id)
) || null
: null
);
deleteModal.openModal();
}}
disabled={selectedRowIds.length === 0}
className='w-full sm:w-fit'
>
<Icon
icon='material-symbols:delete-outline-rounded'
width={24}
height={24}
/>
Hapus ({selectedRowIds.length})
</Button>
)}
</div> </div>
<DebouncedTextInput <DebouncedTextInput
@@ -400,8 +363,6 @@ const PurchaseTable = () => {
isLoading={isLoading} isLoading={isLoading}
sorting={sorting} sorting={sorting}
setSorting={setSorting} setSorting={setSorting}
rowSelection={rowSelection}
setRowSelection={setRowSelection}
className={{ className={{
containerClassName: cn({ containerClassName: cn({
'mb-20': 'mb-20':
@@ -170,7 +170,7 @@ const PurchaseOrderStaffApprovalForm = ({
if (initialValues?.items) { if (initialValues?.items) {
return initialValues.items.map((item) => ({ return initialValues.items.map((item) => ({
value: item.id, value: item.id,
label: `${item.product.name} (${item.quantity} ${item.product.uom?.name || 'unit'})`, label: `${item.product.name} ${item.quantity}`,
id: item.id, id: item.id,
quantity: item.quantity, quantity: item.quantity,
product: { product: {
@@ -184,57 +184,8 @@ const PurchaseOrderStaffApprovalForm = ({
})); }));
} }
return [ return [];
{ }, [initialValues?.items]);
value: 1,
label: 'SEALYTE SPARK 1 x 87 gr (14 SACHET)',
id: 1,
quantity: 14,
product: {
name: 'SEALYTE SPARK 1 x 87 gr',
product_category: 'Bahan Baku',
uom: {
name: 'SACHET',
},
},
warehouse: {
name: 'GUDANG CIANGSANA 1 (ARCA P15)',
},
},
{
value: 2,
label: 'CID-2000 @ 5 KG (2 KILOGRAM)',
id: 2,
quantity: 2,
product: {
name: 'CID-2000 @ 5 KG',
product_category: 'Bahan Baku',
uom: {
name: 'Kilogram',
},
},
warehouse: {
name: 'GUDANG CIANGSANA 2 (ARCA P15)',
},
},
{
value: 3,
label: 'VITAMIN AYAM (10 DOSIS)',
id: 3,
quantity: 10,
product: {
name: 'VITAMIN AYAM',
product_category: 'Bahan Baku',
uom: {
name: 'DOSIS',
},
},
warehouse: {
name: 'GUDANG CIANGSANA 3 (ARCA P15)',
},
},
];
}, [initialValues?.items, searchParams]);
const getPurchaseItemOptions = useCallback(() => { const getPurchaseItemOptions = useCallback(() => {
return purchaseItems; return purchaseItems;
@@ -758,6 +758,7 @@ const PurchaseOrderDetail = ({
> >
<PurchaseOrderStaffApprovalForm <PurchaseOrderStaffApprovalForm
type='add' type='add'
initialValues={purchaseData}
onCancel={staffApprovalModal.closeModal} onCancel={staffApprovalModal.closeModal}
/> />
</Modal> </Modal>