mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 23:35:45 +00:00
refactor(FE-208,213): enhance PurchaseOrderDetail and PurchaseOrderStaffApprovalForm components with initialValues prop and clean up unused code
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user