mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
feat: implement marketing export progress input
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import axios from 'axios';
|
||||
import Button from '@/components/Button';
|
||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||
import DateInput from '@/components/input/DateInput';
|
||||
@@ -36,6 +37,43 @@ import MarketingFilterModal from '@/components/pages/marketing/MarketingFilter';
|
||||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||
import MarketingTableSkeleton from '@/components/pages/marketing/skeleton/MarketingTableSkeleton';
|
||||
|
||||
const getExportErrorMessage = async (
|
||||
error: unknown,
|
||||
fallbackMessage: string
|
||||
) => {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const responseData = error.response?.data;
|
||||
|
||||
if (responseData instanceof Blob) {
|
||||
try {
|
||||
const parsed = JSON.parse(await responseData.text()) as {
|
||||
message?: string;
|
||||
};
|
||||
return parsed.message || fallbackMessage;
|
||||
} catch {
|
||||
return fallbackMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
responseData &&
|
||||
typeof responseData === 'object' &&
|
||||
'message' in responseData &&
|
||||
typeof responseData.message === 'string'
|
||||
) {
|
||||
return responseData.message;
|
||||
}
|
||||
|
||||
return error.message || fallbackMessage;
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
return fallbackMessage;
|
||||
};
|
||||
|
||||
const RowsOptionsMenu = ({
|
||||
props,
|
||||
deleteClickHandler,
|
||||
@@ -161,6 +199,9 @@ const MarketingTable = () => {
|
||||
const [bulkDeliveryNotes, setBulkDeliveryNotes] = useState('');
|
||||
const [isSubmittingBulkDelivery, setIsSubmittingBulkDelivery] =
|
||||
useState(false);
|
||||
const [isExportProgressLoading, setIsExportProgressLoading] = useState(false);
|
||||
const [exportProgressStartDate, setExportProgressStartDate] = useState('');
|
||||
const [exportProgressEndDate, setExportProgressEndDate] = useState('');
|
||||
|
||||
const router = useRouter();
|
||||
const deleteModal = useModal();
|
||||
@@ -168,6 +209,7 @@ const MarketingTable = () => {
|
||||
const productsModal = useModal();
|
||||
const deliveryModal = useModal();
|
||||
const bulkDeliveryModal = useModal();
|
||||
const exportProgressInputModal = useModal();
|
||||
const filterModal = useModal();
|
||||
|
||||
const {
|
||||
@@ -439,6 +481,56 @@ const MarketingTable = () => {
|
||||
setIsLoadingExportingToExcel(false);
|
||||
};
|
||||
|
||||
const resetExportProgressForm = useCallback(() => {
|
||||
setExportProgressStartDate('');
|
||||
setExportProgressEndDate('');
|
||||
}, []);
|
||||
|
||||
const exportProgressStartDateChangeHandler: ChangeEventHandler<HTMLInputElement> =
|
||||
useCallback((e) => {
|
||||
setExportProgressStartDate(e.target.value);
|
||||
}, []);
|
||||
|
||||
const exportProgressEndDateChangeHandler: ChangeEventHandler<HTMLInputElement> =
|
||||
useCallback((e) => {
|
||||
setExportProgressEndDate(e.target.value);
|
||||
}, []);
|
||||
|
||||
const exportProgressInputToExcelClickHandler = useCallback(() => {
|
||||
resetExportProgressForm();
|
||||
exportProgressInputModal.openModal();
|
||||
}, [exportProgressInputModal, resetExportProgressForm]);
|
||||
|
||||
const submitExportProgressInputHandler = useCallback(async () => {
|
||||
if (!exportProgressStartDate || !exportProgressEndDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsExportProgressLoading(true);
|
||||
|
||||
try {
|
||||
await MarketingApi.exportInputProgressToExcel(
|
||||
exportProgressStartDate,
|
||||
exportProgressEndDate
|
||||
);
|
||||
|
||||
exportProgressInputModal.closeModal();
|
||||
resetExportProgressForm();
|
||||
toast.success('Ekspor berhasil');
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
await getExportErrorMessage(error, 'Gagal mengekspor input progress')
|
||||
);
|
||||
} finally {
|
||||
setIsExportProgressLoading(false);
|
||||
}
|
||||
}, [
|
||||
exportProgressEndDate,
|
||||
exportProgressInputModal,
|
||||
exportProgressStartDate,
|
||||
resetExportProgressForm,
|
||||
]);
|
||||
|
||||
const columns = useMemo<ColumnDef<Marketing>[]>(() => {
|
||||
return [
|
||||
{
|
||||
@@ -745,6 +837,16 @@ const MarketingTable = () => {
|
||||
<Icon icon='heroicons:table-cells' width={20} height={20} />
|
||||
Export to Excel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant='ghost'
|
||||
color='none'
|
||||
onClick={exportProgressInputToExcelClickHandler}
|
||||
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} />
|
||||
Ekspor Input Progress (Excel)
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
@@ -928,6 +1030,75 @@ const MarketingTable = () => {
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal
|
||||
ref={exportProgressInputModal.ref}
|
||||
className={{
|
||||
modalBox: 'max-w-lg rounded-lg p-0',
|
||||
}}
|
||||
closeOnBackdrop
|
||||
>
|
||||
<div className='flex flex-col'>
|
||||
<div className='flex items-center justify-between border-b border-base-content/10 p-4'>
|
||||
<h4 className='text-sm font-semibold text-base-content'>
|
||||
Ekspor Input Progress
|
||||
</h4>
|
||||
<Button
|
||||
variant='ghost'
|
||||
color='none'
|
||||
onClick={() => {
|
||||
exportProgressInputModal.closeModal();
|
||||
resetExportProgressForm();
|
||||
}}
|
||||
className='p-1'
|
||||
>
|
||||
<Icon icon='mdi:close' width={20} height={20} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-4 p-4'>
|
||||
<DateInput
|
||||
name='export_progress_start_date'
|
||||
label='Tanggal Mulai'
|
||||
value={exportProgressStartDate}
|
||||
onChange={exportProgressStartDateChangeHandler}
|
||||
isNestedModal
|
||||
required
|
||||
/>
|
||||
|
||||
<DateInput
|
||||
name='export_progress_end_date'
|
||||
label='Tanggal Selesai'
|
||||
value={exportProgressEndDate}
|
||||
onChange={exportProgressEndDateChangeHandler}
|
||||
isNestedModal
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex justify-end gap-3 border-t border-base-content/10 p-4'>
|
||||
<Button
|
||||
variant='outline'
|
||||
color='none'
|
||||
onClick={() => {
|
||||
exportProgressInputModal.closeModal();
|
||||
resetExportProgressForm();
|
||||
}}
|
||||
className='px-3 py-2.5'
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
<Button
|
||||
color='success'
|
||||
onClick={submitExportProgressInputHandler}
|
||||
isLoading={isExportProgressLoading}
|
||||
disabled={!exportProgressStartDate || !exportProgressEndDate}
|
||||
className='px-3 py-2.5'
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
ref={productsModal.ref}
|
||||
|
||||
@@ -189,6 +189,33 @@ class MarketingExportService extends BaseApiService<
|
||||
toast.error('Gagal melakukan export marketing! Coba lagi.');
|
||||
}
|
||||
}
|
||||
|
||||
async exportInputProgressToExcel(startDate: string, endDate: string) {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
params.set('export', 'excel');
|
||||
params.set('type', 'progress');
|
||||
params.set('start_date', formatDate(startDate, 'YYYY-MM-DD'));
|
||||
params.set('end_date', formatDate(endDate, 'YYYY-MM-DD'));
|
||||
|
||||
const queryString = `?${params.toString()}`;
|
||||
|
||||
const res = await httpClient<Blob>(`${this.basePath}${queryString}`, {
|
||||
method: 'GET',
|
||||
responseType: 'blob',
|
||||
});
|
||||
|
||||
const url = window.URL.createObjectURL(new Blob([res]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
|
||||
const fileName = `input-progres-penjualan-${formatDate(startDate, 'DD-MM-YYYY')}-ke-${formatDate(endDate, 'DD-MM-YYYY')}.xlsx`;
|
||||
link.setAttribute('download', fileName);
|
||||
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
}
|
||||
}
|
||||
|
||||
export const SalesOrderApi = new SalesOrderService('/marketing/sales-orders');
|
||||
|
||||
Reference in New Issue
Block a user