mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
785 lines
26 KiB
TypeScript
785 lines
26 KiB
TypeScript
'use client';
|
|
|
|
import Button from '@/components/Button';
|
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
|
import Modal, { useModal } from '@/components/Modal';
|
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
|
import Table from '@/components/Table';
|
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
import { cn, formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
|
|
import {
|
|
MarketingApi,
|
|
SalesOrderApi,
|
|
} from '@/services/api/marketing/marketing';
|
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
|
import {
|
|
BaseSalesOrder,
|
|
Marketing,
|
|
MarketingFilter,
|
|
} from '@/types/api/marketing/marketing';
|
|
import { Icon } from '@iconify/react';
|
|
import { CellContext, ColumnDef, Row } from '@tanstack/react-table';
|
|
import { useRouter } from 'next/navigation';
|
|
import { useMemo, useState } from 'react';
|
|
import toast from 'react-hot-toast';
|
|
import useSWR from 'swr';
|
|
import RequirePermission from '@/components/helper/RequirePermission';
|
|
import Dropdown from '@/components/Dropdown';
|
|
import PopoverButton from '@/components/popover/PopoverButton';
|
|
import PopoverContent from '@/components/popover/PopoverContent';
|
|
import StatusBadge from '@/components/helper/StatusBadge';
|
|
import MarketingFilterModal from '@/components/pages/marketing/MarketingFilter';
|
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
|
import MarketingTableSkeleton from '@/components/pages/marketing/skeleton/MarketingTableSkeleton';
|
|
|
|
const RowsOptionsMenu = ({
|
|
props,
|
|
deleteClickHandler,
|
|
deliveryClickHandler,
|
|
popoverPosition,
|
|
}: {
|
|
type: 'dropdown' | 'collapse';
|
|
props: CellContext<Marketing, unknown>;
|
|
deleteClickHandler: () => void;
|
|
deliveryClickHandler?: () => void;
|
|
popoverPosition?: 'top' | 'bottom';
|
|
}) => {
|
|
const popoverId = `marketing#${props.row.original.id}`;
|
|
const popoverAnchorName = `--anchor-marketing#${props.row.original.id}`;
|
|
|
|
const isDeliveryRejected =
|
|
props.row.original.latest_approval.action === 'REJECTED' &&
|
|
props.row.original.latest_approval.step_number === 3;
|
|
|
|
return (
|
|
<div className='relative'>
|
|
<PopoverButton
|
|
tabIndex={0}
|
|
variant='ghost'
|
|
color='none'
|
|
popoverTarget={popoverId}
|
|
anchorName={popoverAnchorName}
|
|
>
|
|
<Icon icon='material-symbols:more-vert' width={16} height={16} />
|
|
</PopoverButton>
|
|
<PopoverContent
|
|
id={popoverId}
|
|
anchorName={popoverAnchorName}
|
|
position={popoverPosition === 'bottom' ? 'bottom-start' : 'left'}
|
|
className='w-full max-w-40 rounded-xl border border-base-content/5 shadow-sm'
|
|
>
|
|
<div className='flex flex-col bg-base-100 rounded-xl'>
|
|
<RequirePermission permissions='lti.marketing.delivery_order.detail'>
|
|
<Button
|
|
href={`/marketing?action=detail&id=${props.row.original.id}`}
|
|
variant='ghost'
|
|
color='none'
|
|
className='p-3 justify-start text-sm font-semibold w-full'
|
|
>
|
|
<Icon icon='heroicons:eye' width={20} height={20} />
|
|
View Details
|
|
</Button>
|
|
</RequirePermission>
|
|
{props.row.original.latest_approval.step_number != 1 &&
|
|
!isDeliveryRejected && (
|
|
<>
|
|
<RequirePermission
|
|
permissions={
|
|
props.row.original.latest_approval.step_number == 3
|
|
? 'lti.marketing.delivery_order.update'
|
|
: 'lti.marketing.delivery_order.create'
|
|
}
|
|
>
|
|
<Button
|
|
href={
|
|
props.row.original.latest_approval.step_number == 3
|
|
? `/marketing?action=edit_delivery&id=${props.row.original.id}`
|
|
: props.row.original.latest_approval.step_number == 2
|
|
? `/marketing?action=add_delivery&id=${props.row.original.id}`
|
|
: undefined
|
|
}
|
|
onClick={() => {
|
|
if (props.row.original.latest_approval.step_number == 2) {
|
|
deliveryClickHandler?.();
|
|
}
|
|
}}
|
|
variant='ghost'
|
|
color='none'
|
|
className='p-3 justify-start text-sm font-semibold w-full'
|
|
>
|
|
<Icon icon='heroicons:truck' width={20} height={20} />
|
|
{props.row.original.latest_approval.step_number == 2
|
|
? 'Deliver Item'
|
|
: 'Edit Delivery'}
|
|
</Button>
|
|
</RequirePermission>
|
|
</>
|
|
)}
|
|
{props.row.original.latest_approval.step_number != 3 && (
|
|
<>
|
|
<RequirePermission permissions='lti.marketing.sales_order.update'>
|
|
<Button
|
|
href={`/marketing?action=edit&id=${props.row.original.id}`}
|
|
variant='ghost'
|
|
color='none'
|
|
className='p-3 justify-start text-sm font-semibold w-full'
|
|
>
|
|
<Icon icon='heroicons:pencil-square' width={20} height={20} />
|
|
Edit Item
|
|
</Button>
|
|
</RequirePermission>
|
|
</>
|
|
)}
|
|
<RequirePermission permissions='lti.marketing.sales_order.delete'>
|
|
<Button
|
|
onClick={deleteClickHandler}
|
|
variant='ghost'
|
|
color='none'
|
|
className='relative p-3 overflow-hidden justify-start text-sm font-semibold w-full text-error before:content-[""] before:absolute before:h-px before:p-3 before:top-0 before:left-0 before:right-0 before:border-t before:border-base-content/5'
|
|
>
|
|
<Icon icon='heroicons:trash' width={20} height={20} />
|
|
Delete Item
|
|
</Button>
|
|
</RequirePermission>
|
|
</div>
|
|
</PopoverContent>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const MarketingTable = () => {
|
|
const [approveAction, setApproveAction] = useState<'APPROVED' | 'REJECTED'>(
|
|
'APPROVED'
|
|
);
|
|
const [selectedItem, setSelectedItem] = useState<Marketing | null>(null);
|
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
|
|
|
const router = useRouter();
|
|
const deleteModal = useModal();
|
|
const confirmationModal = useModal();
|
|
const productsModal = useModal();
|
|
const deliveryModal = useModal();
|
|
const filterModal = useModal();
|
|
|
|
const {
|
|
state: tableFilterState,
|
|
updateFilter,
|
|
setPage,
|
|
setPageSize,
|
|
toQueryString: getTableFilterToQueryString,
|
|
} = useTableFilter({
|
|
initial: {
|
|
search: '',
|
|
product_ids: '',
|
|
status: '',
|
|
customer_id: '',
|
|
},
|
|
paramMap: {
|
|
page: 'page',
|
|
pageSize: 'limit',
|
|
product_ids: 'product_ids',
|
|
status: 'status',
|
|
customer_id: 'customer_id',
|
|
},
|
|
});
|
|
|
|
// ===== FETCH DATA =====
|
|
const {
|
|
data: marketing,
|
|
isLoading: isLoadingMarketing,
|
|
mutate: refreshMarketing,
|
|
} = useSWR(
|
|
`${MarketingApi.basePath}${getTableFilterToQueryString()}`,
|
|
MarketingApi.getAllFetcher
|
|
);
|
|
|
|
// ===== HANDLER =====
|
|
const filterSubmitHandler = (values: MarketingFilter) => {
|
|
updateFilter(
|
|
'product_ids',
|
|
values.product_ids?.map((item) => item.toString()).join(',')
|
|
);
|
|
updateFilter('status', values.status ? values.status.toString() : '');
|
|
updateFilter(
|
|
'customer_id',
|
|
values.customer_id ? values.customer_id.toString() : ''
|
|
);
|
|
};
|
|
|
|
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
|
|
useState(false);
|
|
|
|
const filterResetHandler = () => {
|
|
updateFilter('product_ids', '');
|
|
updateFilter('status', '');
|
|
updateFilter('customer_id', '');
|
|
};
|
|
|
|
const approveClickHandler = () => {
|
|
setApproveAction('APPROVED');
|
|
confirmationModal.openModal();
|
|
};
|
|
|
|
const rejectClickHandler = () => {
|
|
setApproveAction('REJECTED');
|
|
confirmationModal.openModal();
|
|
};
|
|
|
|
const productsClickHandler = (item: Marketing) => {
|
|
setSelectedItem(item);
|
|
productsModal.openModal();
|
|
};
|
|
|
|
const deleteMarketingHandler = async () => {
|
|
const deleteMarketingRes = await MarketingApi.delete(
|
|
selectedItem?.id as number
|
|
);
|
|
if (isResponseSuccess(deleteMarketingRes)) {
|
|
confirmationModal.closeModal();
|
|
toast.success(deleteMarketingRes?.message as string);
|
|
}
|
|
if (isResponseError(deleteMarketingRes)) {
|
|
confirmationModal.closeModal();
|
|
toast.error(deleteMarketingRes?.message as string);
|
|
}
|
|
refreshMarketing();
|
|
deleteModal.closeModal();
|
|
};
|
|
|
|
const allData = isResponseSuccess(marketing) ? marketing.data : [];
|
|
const selectedRowsData = allData.filter(
|
|
(row) => rowSelection[row.id.toString()]
|
|
);
|
|
|
|
const hasApprovable = selectedRowsData.some(
|
|
(row) =>
|
|
row.latest_approval.step_number === 1 &&
|
|
row.latest_approval.action !== 'REJECTED'
|
|
);
|
|
const hasRejectable = selectedRowsData.some(
|
|
(row) =>
|
|
row.latest_approval.step_number === 1 &&
|
|
row.latest_approval.action !== 'REJECTED'
|
|
);
|
|
|
|
const disableApprove = !hasApprovable;
|
|
const disableReject = !hasRejectable;
|
|
|
|
const idsToProcess =
|
|
approveAction === 'APPROVED'
|
|
? selectedRowsData
|
|
.filter((row) => row.latest_approval.step_number === 1)
|
|
.map((row) => row.id)
|
|
: selectedRowsData
|
|
.filter((row) => row.latest_approval.step_number === 2)
|
|
.map((row) => row.id);
|
|
|
|
const approveMarketingHandler = async (notes: string) => {
|
|
let idsToProcess: number[] = [];
|
|
|
|
idsToProcess = selectedRowsData
|
|
.filter((row) => row.latest_approval.step_number === 1)
|
|
.map((row) => row.id);
|
|
|
|
if (idsToProcess.length === 0) {
|
|
toast.error(`Tidak ada data yang valid untuk di ${approveAction}.`);
|
|
confirmationModal.closeModal();
|
|
return;
|
|
}
|
|
|
|
const approveMarketingRes = await SalesOrderApi.bulkApprovals(
|
|
idsToProcess,
|
|
approveAction,
|
|
notes
|
|
);
|
|
|
|
if (isResponseSuccess(approveMarketingRes)) {
|
|
confirmationModal.closeModal();
|
|
toast.success(approveMarketingRes?.message as string);
|
|
setRowSelection({});
|
|
}
|
|
if (isResponseError(approveMarketingRes)) {
|
|
confirmationModal.closeModal();
|
|
toast.error(approveMarketingRes?.message as string);
|
|
}
|
|
refreshMarketing();
|
|
};
|
|
|
|
const confirmationModalDeliveryClickHandler = async (notes: string) => {
|
|
const res = await SalesOrderApi.delivery(selectedItem?.id as number, notes);
|
|
deliveryModal.closeModal();
|
|
toast.success(res?.message as string);
|
|
refreshMarketing?.();
|
|
router.push(
|
|
`/marketing/detail/delivery-orders/edit?id=${selectedItem?.id}`
|
|
);
|
|
};
|
|
|
|
const getRowCanSelect = (row: Row<Marketing>): boolean => {
|
|
const approval = row.original.latest_approval;
|
|
return approval?.step_number === 1 && approval?.action !== 'REJECTED';
|
|
};
|
|
|
|
const exportToExcelHandler = async () => {
|
|
setIsLoadingExportingToExcel(true);
|
|
|
|
await MarketingApi.exportToExcel(getTableFilterToQueryString());
|
|
|
|
setIsLoadingExportingToExcel(false);
|
|
};
|
|
|
|
const columns = useMemo<ColumnDef<Marketing>[]>(() => {
|
|
return [
|
|
{
|
|
id: 'select',
|
|
size: 1,
|
|
header: ({ table }) => {
|
|
const allRows = table.getRowModel().rows;
|
|
const selectableRows = allRows.filter(getRowCanSelect);
|
|
|
|
const allSelected =
|
|
selectableRows.length > 0 &&
|
|
selectableRows.every((row) => row.getIsSelected());
|
|
|
|
const someSelected =
|
|
selectableRows.some((row) => row.getIsSelected()) && !allSelected;
|
|
|
|
const toggleSelectableRows = () => {
|
|
const shouldSelect = !allSelected;
|
|
selectableRows.forEach((row) => row.toggleSelected(shouldSelect));
|
|
};
|
|
|
|
return (
|
|
<div className='w-fit flex flex-row justify-start'>
|
|
<CheckboxInput
|
|
name='allRow'
|
|
checked={allSelected}
|
|
indeterminate={someSelected}
|
|
onChange={toggleSelectableRows}
|
|
disabled={selectableRows.length === 0}
|
|
/>
|
|
</div>
|
|
);
|
|
},
|
|
cell: ({ row }) => {
|
|
const canSelect = getRowCanSelect(row);
|
|
return (
|
|
<div className='w-fit flex flex-row justify-start'>
|
|
<CheckboxInput
|
|
name='row'
|
|
checked={row.getIsSelected()}
|
|
disabled={!canSelect}
|
|
indeterminate={row.getIsSomeSelected()}
|
|
onChange={row.getToggleSelectedHandler()}
|
|
/>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'so_do_number',
|
|
header: 'No. Order',
|
|
cell: (props) => {
|
|
return props.row.original.do_number
|
|
? props.row.original.do_number
|
|
: props.row.original.so_number;
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'so_date',
|
|
header: 'Tanggal',
|
|
cell: (props) => {
|
|
return formatDate(props.row.original.so_date, 'DD MMM yyyy');
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'approval.step_name',
|
|
header: 'Status',
|
|
cell: (props) => {
|
|
const approval = props.row.original.latest_approval;
|
|
const isRejected = approval?.action == 'REJECTED';
|
|
const isApproved = approval?.action == 'APPROVED';
|
|
const isUpdated = approval?.action == 'UPDATED';
|
|
return (
|
|
<StatusBadge
|
|
color={
|
|
isRejected
|
|
? 'error'
|
|
: isApproved || isUpdated
|
|
? approval?.step_number == 1
|
|
? 'neutral'
|
|
: approval?.step_number == 2
|
|
? 'info'
|
|
: approval?.step_number == 3
|
|
? 'success'
|
|
: 'neutral'
|
|
: 'neutral'
|
|
}
|
|
text={
|
|
isRejected
|
|
? 'Ditolak'
|
|
: formatTitleCase(approval?.step_name || '')
|
|
}
|
|
className={{
|
|
badge: 'whitespace-nowrap',
|
|
}}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'customer.name',
|
|
header: 'Customer',
|
|
},
|
|
{
|
|
accessorFn: (row) =>
|
|
row.sales_order
|
|
?.map((product) => product.total_price)
|
|
.reduce((a, b) => a + b, 0) ?? 0,
|
|
header: 'Grand Total',
|
|
cell: (props) => {
|
|
return formatCurrency(
|
|
props.row.original?.sales_order
|
|
?.map((product) => product.total_price)
|
|
.reduce((a, b) => a + b, 0) ?? 0
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'marketing_products.length',
|
|
header: 'Product Details',
|
|
cell: (props) => {
|
|
if (props?.row?.original?.sales_order?.length) {
|
|
if (props?.row?.original?.sales_order?.length > 1) {
|
|
return (
|
|
<Button
|
|
variant='link'
|
|
className='p-0 text-none text-sm'
|
|
onClick={() => {
|
|
productsClickHandler(props?.row?.original);
|
|
}}
|
|
>
|
|
Lihat {props?.row?.original?.sales_order?.length} Produk
|
|
</Button>
|
|
);
|
|
} else {
|
|
const product = props?.row?.original?.sales_order[0];
|
|
return <>{product?.product_warehouse?.product?.name}</>;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: 'actions',
|
|
maxSize: 80,
|
|
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 deleteClickHandler = () => {
|
|
setSelectedItem(props.row.original);
|
|
deleteModal.openModal();
|
|
};
|
|
|
|
const deliveryClickHandler = () => {
|
|
setSelectedItem(props.row.original);
|
|
deliveryModal.openModal();
|
|
};
|
|
|
|
return (
|
|
<RowsOptionsMenu
|
|
type='dropdown'
|
|
props={props}
|
|
deleteClickHandler={deleteClickHandler}
|
|
deliveryClickHandler={deliveryClickHandler}
|
|
popoverPosition={isLast2Rows ? 'top' : 'bottom'}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<div className='flex flex-col'>
|
|
<div className='flex flex-row justify-between p-3 border-b border-base-content/10'>
|
|
<div className='flex flex-row gap-3'>
|
|
<RequirePermission permissions='lti.marketing.sales_order.create'>
|
|
<Button
|
|
href={{
|
|
pathname: '/marketing',
|
|
query: {
|
|
action: 'add',
|
|
},
|
|
}}
|
|
className='font-semibold text-base-100 text-sm rounded-lg shadow-button-soft px-3 py-2.5'
|
|
>
|
|
<Icon icon='heroicons:plus' width={20} height={20} />
|
|
Add Sales Order
|
|
</Button>
|
|
</RequirePermission>
|
|
{idsToProcess.length > 0 && (
|
|
<>
|
|
<div className='divider divider-horizontal w-px p-0 m-0 bg-base-content/10 text-base-content/10 before:bg-base-content/10 before:w-px after:bg-base-content/10 after:w-px'></div>
|
|
<RequirePermission permissions='lti.marketing.sales_order.approve'>
|
|
<Button
|
|
color='error'
|
|
onClick={rejectClickHandler}
|
|
className='justify-start text-sm shadow-button-soft rounded-lg bg-base-100 text-base-content/50 px-3 py-2.5 border border-base-content/10'
|
|
disabled={disableReject}
|
|
>
|
|
<Icon
|
|
icon='heroicons:x-mark'
|
|
className='text-error'
|
|
width={20}
|
|
height={20}
|
|
/>
|
|
Reject
|
|
</Button>
|
|
</RequirePermission>
|
|
<RequirePermission permissions='lti.marketing.sales_order.approve'>
|
|
<Button
|
|
color='none'
|
|
onClick={approveClickHandler}
|
|
className='justify-start text-sm shadow-button-soft rounded-lg bg-base-100 text-base-content/50 px-3 py-2.5 border border-base-content/10'
|
|
disabled={disableApprove}
|
|
>
|
|
<Icon
|
|
icon='heroicons:check'
|
|
className='text-success'
|
|
width={20}
|
|
height={20}
|
|
/>
|
|
Approve
|
|
</Button>
|
|
</RequirePermission>
|
|
</>
|
|
)}
|
|
</div>
|
|
<div className='flex flex-row gap-3'>
|
|
<ButtonFilter
|
|
values={tableFilterState}
|
|
excludeFields={['page', 'pageSize', 'search']}
|
|
onClick={() => {
|
|
filterModal.openModal();
|
|
}}
|
|
className='px-3 py-2.5'
|
|
/>
|
|
<Dropdown
|
|
align='end'
|
|
direction='bottom'
|
|
trigger={
|
|
<Button
|
|
variant='outline'
|
|
color='none'
|
|
className={cn(
|
|
'px-3 py-2.5 rounded-lg font-semibold text-sm gap-1.5',
|
|
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
|
|
)}
|
|
>
|
|
<Icon
|
|
width={20}
|
|
height={20}
|
|
icon='heroicons:cloud-arrow-down'
|
|
/>
|
|
Export
|
|
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'>
|
|
<Icon
|
|
width={14}
|
|
height={14}
|
|
icon='heroicons:chevron-down'
|
|
/>
|
|
</div>
|
|
</Button>
|
|
}
|
|
className={{
|
|
content:
|
|
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
|
|
}}
|
|
>
|
|
<Button
|
|
variant='ghost'
|
|
color='none'
|
|
onClick={exportToExcelHandler}
|
|
isLoading={isLoadingExportingToExcel}
|
|
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
|
|
>
|
|
<Icon icon='heroicons:table-cells' width={20} height={20} />
|
|
Export to Excel
|
|
</Button>
|
|
</Dropdown>
|
|
</div>
|
|
</div>
|
|
<div className='flex flex-col mb-4'>
|
|
{isLoadingMarketing ? (
|
|
<div className='w-full flex flex-row justify-center items-center p-4'>
|
|
<span className='loading loading-spinner loading-xl' />
|
|
</div>
|
|
) : !isResponseSuccess(marketing) || marketing.data?.length === 0 ? (
|
|
<div className='p-3'>
|
|
<MarketingTableSkeleton
|
|
columns={columns}
|
|
icon={
|
|
<Icon
|
|
icon='heroicons:document-text'
|
|
className='text-white'
|
|
width={20}
|
|
height={20}
|
|
/>
|
|
}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<Table
|
|
rowSelection={rowSelection}
|
|
setRowSelection={setRowSelection}
|
|
onPageChange={setPage}
|
|
onPageSizeChange={setPageSize}
|
|
data={allData}
|
|
columns={columns}
|
|
pageSize={tableFilterState.pageSize}
|
|
page={isResponseSuccess(marketing) ? marketing?.meta?.page : 1}
|
|
totalItems={
|
|
isResponseSuccess(marketing)
|
|
? marketing?.meta?.total_results
|
|
: 0
|
|
}
|
|
isLoading={isLoadingMarketing}
|
|
className={{
|
|
containerClassName: cn('p-3 mb-0'),
|
|
bodyColumnClassName:
|
|
'last:text-end last:w-17 first:text-start first:w-5',
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<ConfirmationModal
|
|
ref={deleteModal.ref}
|
|
type='error'
|
|
text={`Apakah anda yakin ingin menghapus data Project Flock ini?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'error',
|
|
}}
|
|
/>
|
|
|
|
<ConfirmationModalWithNotes
|
|
ref={confirmationModal.ref}
|
|
type={approveAction === 'APPROVED' ? 'success' : 'error'}
|
|
text={`Apakah anda yakin ingin ${approveAction == 'APPROVED' ? 'approve' : 'reject'} data penjualan (${idsToProcess.length} data)?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
onClick: confirmationModal.closeModal,
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: approveAction === 'APPROVED' ? 'success' : 'error',
|
|
onClick: approveMarketingHandler,
|
|
}}
|
|
/>
|
|
<ConfirmationModal
|
|
ref={deleteModal.ref}
|
|
type='error'
|
|
text={`Apakah anda yakin ingin menghapus data penjualan ini?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
onClick: deleteModal.closeModal,
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'error',
|
|
onClick: deleteMarketingHandler,
|
|
}}
|
|
/>
|
|
<ConfirmationModalWithNotes
|
|
ref={deliveryModal.ref}
|
|
type={'success'}
|
|
text={`Apakah anda yakin ingin deliver penjualan ${selectedItem?.so_number}?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'success',
|
|
onClick: confirmationModalDeliveryClickHandler,
|
|
}}
|
|
/>
|
|
|
|
<Modal
|
|
ref={productsModal.ref}
|
|
className={{
|
|
modalBox: 'xs:max-w-2/5 z-100 rounded-lg p-0 flex flex-col',
|
|
modal: 'rounded-lg',
|
|
}}
|
|
closeOnBackdrop
|
|
>
|
|
<div className='flex flex-row justify-between items-center border-b border-base-content/10 p-4'>
|
|
<h4 className='flex items-center justify-center gap-2 text-sm font-medium text-base-content'>
|
|
<Icon icon='heroicons:information-circle' width={20} height={20} />{' '}
|
|
Daftar Produk
|
|
</h4>
|
|
<Button
|
|
variant='ghost'
|
|
color='none'
|
|
onClick={productsModal.closeModal}
|
|
className='justify-start text-sm p-1'
|
|
>
|
|
<Icon icon='mdi:close' width={20} height={20} />
|
|
</Button>
|
|
</div>
|
|
<Table<BaseSalesOrder>
|
|
data={
|
|
isResponseSuccess(marketing) && selectedItem
|
|
? (selectedItem?.sales_order ?? [])
|
|
: []
|
|
}
|
|
columns={[
|
|
{
|
|
header: 'Kandang',
|
|
accessorFn(row) {
|
|
return row.product_warehouse.warehouse.name;
|
|
},
|
|
},
|
|
{
|
|
header: 'Produk',
|
|
accessorFn(row) {
|
|
return row.product_warehouse.product.name;
|
|
},
|
|
},
|
|
{
|
|
header: 'Harga Satuan (Rp)',
|
|
accessorFn(row) {
|
|
return formatCurrency(row.unit_price);
|
|
},
|
|
},
|
|
]}
|
|
className={{
|
|
containerClassName: 'p-4',
|
|
headerColumnClassName: 'whitespace-nowrap',
|
|
bodyColumnClassName: 'last:flex last:flex-row last:justify-end',
|
|
paginationClassName: 'hidden',
|
|
}}
|
|
isLoading={isLoadingMarketing}
|
|
/>
|
|
</Modal>
|
|
<MarketingFilterModal
|
|
ref={filterModal.ref}
|
|
onSubmit={filterSubmitHandler}
|
|
onReset={filterResetHandler}
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
export default MarketingTable;
|