fix(FE): adding color to negative value excel and change select UI

This commit is contained in:
randy-ar
2026-01-21 14:27:59 +07:00
parent f73672f65c
commit c7ffae68d8
4 changed files with 223 additions and 108 deletions
+4 -20
View File
@@ -4463,7 +4463,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
@@ -4474,7 +4473,6 @@
"integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true,
"peerDependencies": { "peerDependencies": {
"@types/react": "^19.2.0" "@types/react": "^19.2.0"
} }
@@ -4547,7 +4545,6 @@
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2", "@typescript-eslint/types": "8.46.2",
@@ -5071,7 +5068,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -6002,8 +5998,7 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/d3-array": { "node_modules/d3-array": {
"version": "3.2.4", "version": "3.2.4",
@@ -6430,8 +6425,7 @@
"version": "8.6.0", "version": "8.6.0",
"resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
"integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==",
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/embla-carousel-react": { "node_modules/embla-carousel-react": {
"version": "8.6.0", "version": "8.6.0",
@@ -6701,7 +6695,6 @@
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@@ -6875,7 +6868,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@rtsao/scc": "^1.1.0", "@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9", "array-includes": "^3.1.9",
@@ -8508,7 +8500,6 @@
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.4.tgz", "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.4.tgz",
"integrity": "sha512-dc6oQ8y37rRcHn316s4ngz/nOjayLF/FFxBF4V9zamQKRqXxyiH1zagkCdktdWhtoQId5K20xt1lB90XzkB+hQ==", "integrity": "sha512-dc6oQ8y37rRcHn316s4ngz/nOjayLF/FFxBF4V9zamQKRqXxyiH1zagkCdktdWhtoQId5K20xt1lB90XzkB+hQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4", "@babel/runtime": "^7.28.4",
"fast-png": "^6.2.0", "fast-png": "^6.2.0",
@@ -9961,7 +9952,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -9992,7 +9982,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"scheduler": "^0.27.0" "scheduler": "^0.27.0"
}, },
@@ -10060,8 +10049,7 @@
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/react-number-format": { "node_modules/react-number-format": {
"version": "5.4.4", "version": "5.4.4",
@@ -10078,7 +10066,6 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@types/use-sync-external-store": "^0.0.6", "@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0" "use-sync-external-store": "^1.4.0"
@@ -10291,8 +10278,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
@@ -11205,7 +11191,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -11391,7 +11376,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
+70
View File
@@ -0,0 +1,70 @@
'use client';
import { useMemo } from 'react';
import {
OptionProps,
GroupBase,
components as ReactSelectComponents,
} from 'react-select';
import SelectInput, { OptionType, SelectInputProps } from './SelectInput';
import { cn } from '@/lib/helper';
interface SelectInputRadioProps<T = OptionType>
extends Omit<SelectInputProps<T>, 'closeMenuOnSelect' | 'optionComponent'> {
closeMenuOnSelect?: boolean;
}
const RadioOption = <
T extends OptionType,
IsMulti extends boolean,
Group extends GroupBase<T>,
>(
props: OptionProps<T, IsMulti, Group>
) => {
const { isSelected, label, innerRef, innerProps, className } = props;
return (
<div
ref={innerRef}
{...innerProps}
className={cn(
'flex items-center gap-2 px-3 py-2 cursor-pointer',
className
)}
>
<input
type='radio'
checked={isSelected}
onChange={() => null}
className='radio radio-sm radio-primary pointer-events-none'
/>
<label className='cursor-pointer flex-1 select-none'>{label}</label>
</div>
);
};
const SelectInputRadio = <T extends OptionType>(
props: SelectInputRadioProps<T>
) => {
const { closeMenuOnSelect = true, className, ...restProps } = props;
const customComponents = useMemo(() => {
return {
Option: RadioOption as typeof ReactSelectComponents.Option,
};
}, []);
return (
<SelectInput<T>
{...restProps}
closeMenuOnSelect={closeMenuOnSelect}
className={{
...className,
select: cn(className?.select, 'select-radio'),
}}
components={customComponents}
/>
);
};
export default SelectInputRadio;
@@ -1,6 +1,6 @@
'use client'; 'use client';
import * as XLSX from 'xlsx'; import ExcelJS from 'exceljs';
import { formatDate } from '@/lib/helper'; import { formatDate } from '@/lib/helper';
import { DebtRow, DebtSupplier } from '@/types/api/report/debt-supplier'; import { DebtRow, DebtSupplier } from '@/types/api/report/debt-supplier';
@@ -8,115 +8,174 @@ interface DebtSupplierExportExcelParams {
data: DebtSupplier[]; data: DebtSupplier[];
} }
export const generateDebtSupplierExcel = ( export const generateDebtSupplierExcel = async (
params: DebtSupplierExportExcelParams params: DebtSupplierExportExcelParams
): void => { ): Promise<void> => {
if (!params.data || params.data.length === 0) { if (!params.data || params.data.length === 0) {
return; return;
} }
const workbook = XLSX.utils.book_new(); const workbook = new ExcelJS.Workbook();
params.data.forEach((supplierReport) => { const columns = [
{ header: 'No', key: 'no', width: 5 },
{ header: 'Nomor PR', key: 'prNumber', width: 14 },
{ header: 'Nomor PO', key: 'poNumber', width: 14 },
{ header: 'Tanggal Terima/Bayar', key: 'receivedDate', width: 20 },
{ header: 'Tanggal PO', key: 'poDate', width: 10 },
{ header: 'Aging (Hari)', key: 'aging', width: 10 },
{ header: 'Area', key: 'area', width: 15 },
{ header: 'Gudang', key: 'warehouse', width: 15 },
{ header: 'Jatuh Tempo', key: 'dueDate', width: 12 },
{ header: 'Status Jatuh Tempo', key: 'dueStatus', width: 20 },
{ header: 'Nominal Pembelian (Rp)', key: 'totalPrice', width: 20 },
{ header: 'Pembayaran (Rp)', key: 'paymentPrice', width: 15 },
{ header: 'Sisa Saldo Hutang (Rp)', key: 'balance', width: 20 },
{ header: 'Status', key: 'status', width: 12 },
{ header: 'Nomor Perjalanan', key: 'travelNumber', width: 15 },
];
for (const supplierReport of params.data) {
const supplierData = supplierReport.rows; const supplierData = supplierReport.rows;
const supplierName = supplierReport.supplier.name || 'Unknown Supplier'; const supplierName = supplierReport.supplier.name || 'Unknown Supplier';
const excelData: { [key: string]: string | number }[] = [ const worksheet = workbook.addWorksheet(supplierName.substring(0, 31));
{ worksheet.columns = columns;
No: '',
'Nomor PR': '', // Add initial balance row
'Nomor PO': '', const initialRow = worksheet.addRow({
'Tanggal Terima/Bayar': '', no: '',
'Tanggal PO': '', prNumber: '',
'Aging (Hari)': '', poNumber: '',
Area: '', receivedDate: '',
Gudang: '', poDate: '',
'Jatuh Tempo': '', aging: '',
'Status Jatuh Tempo': '', area: '',
'Nominal Pembelian (Rp)': '', warehouse: '',
'Pembayaran (Rp)': '', dueDate: '',
'Sisa Saldo Hutang (Rp)': supplierReport.initial_balance || 0, dueStatus: '',
Status: '', totalPrice: '',
'Nomor Perjalanan': '', paymentPrice: '',
}, balance: supplierReport.initial_balance || 0,
...supplierData.map((item, index) => ({ status: '',
No: index + 1, travelNumber: '',
'Nomor PR': item.pr_number || '', });
'Nomor PO': item.po_number || '',
'Tanggal Terima/Bayar': item.received_date // Apply red color if initial balance is negative
const initialBalanceCell = initialRow.getCell('balance');
if (
typeof supplierReport.initial_balance === 'number' &&
supplierReport.initial_balance < 0
) {
initialBalanceCell.font = { color: { argb: 'FFFF0000' } };
}
// Add data rows
supplierData.forEach((item, index) => {
const row = worksheet.addRow({
no: index + 1,
prNumber: item.pr_number || '',
poNumber: item.po_number || '',
receivedDate: item.received_date
? item.received_date != '-' ? item.received_date != '-'
? formatDate(item.received_date, 'MM/DD/YYYY') ? formatDate(item.received_date, 'MM/DD/YYYY')
: '-' : '-'
: '-', : '-',
'Tanggal PO': item.po_date poDate: item.po_date
? item.po_date != '-' ? item.po_date != '-'
? formatDate(item.po_date, 'MM/DD/YYYY') ? formatDate(item.po_date, 'MM/DD/YYYY')
: '-' : '-'
: '-', : '-',
'Aging (Hari)': item.aging || 0, aging: item.aging || 0,
Area: item.area?.name || '', area: item.area?.name || '',
Gudang: item.warehouse?.name || '', warehouse: item.warehouse?.name || '',
'Jatuh Tempo': item.due_date dueDate: item.due_date
? item.due_date != '-' ? item.due_date != '-'
? formatDate(item.due_date, 'MM/DD/YYYY') ? formatDate(item.due_date, 'MM/DD/YYYY')
: '-' : '-'
: '-', : '-',
'Status Jatuh Tempo': item.due_status || '', dueStatus: item.due_status || '',
'Nominal Pembelian (Rp)': item.total_price || 0, totalPrice: item.total_price || 0,
'Pembayaran (Rp)': item.payment_price || 0, paymentPrice: item.payment_price || 0,
'Sisa Saldo Hutang (Rp)': item.balance || 0, balance: item.balance || 0,
Status: item.status || '', status: item.status || '',
'Nomor Perjalanan': item.travel_number || '', travelNumber: item.travel_number || '',
})),
];
if (supplierReport.total) {
excelData.push({
No: 'Total',
'Nomor PR': '',
'Nomor PO': '',
'Tanggal Terima/Bayar': '',
'Tanggal PO': '',
'Aging (Hari)': supplierReport.total.aging || 0,
Area: '',
Gudang: '',
'Jatuh Tempo': '',
'Status Jatuh Tempo': '',
'Nominal Pembelian (Rp)': supplierReport.total.total_price || 0,
'Pembayaran (Rp)': supplierReport.total.payment_price || 0,
'Sisa Saldo Hutang (Rp)': supplierReport.total.debt_price || 0,
Status: '',
'Nomor Perjalanan': '',
}); });
// Apply red color for negative values
const totalPriceCell = row.getCell('totalPrice');
if (typeof item.total_price === 'number' && item.total_price < 0) {
totalPriceCell.font = { color: { argb: 'FFFF0000' } };
}
const paymentPriceCell = row.getCell('paymentPrice');
if (typeof item.payment_price === 'number' && item.payment_price < 0) {
paymentPriceCell.font = { color: { argb: 'FFFF0000' } };
}
const balanceCell = row.getCell('balance');
if (typeof item.balance === 'number' && item.balance < 0) {
balanceCell.font = { color: { argb: 'FFFF0000' } };
}
});
// Add total row
if (supplierReport.total) {
const totalRow = worksheet.addRow({
no: 'Total',
prNumber: '',
poNumber: '',
receivedDate: '',
poDate: '',
aging: supplierReport.total.aging || 0,
area: '',
warehouse: '',
dueDate: '',
dueStatus: '',
totalPrice: supplierReport.total.total_price || 0,
paymentPrice: supplierReport.total.payment_price || 0,
balance: supplierReport.total.debt_price || 0,
status: '',
travelNumber: '',
});
// Apply red color for negative totals
const totalPriceCell = totalRow.getCell('totalPrice');
if (
typeof supplierReport.total.total_price === 'number' &&
supplierReport.total.total_price < 0
) {
totalPriceCell.font = { color: { argb: 'FFFF0000' } };
}
const paymentPriceCell = totalRow.getCell('paymentPrice');
if (
typeof supplierReport.total.payment_price === 'number' &&
supplierReport.total.payment_price < 0
) {
paymentPriceCell.font = { color: { argb: 'FFFF0000' } };
}
const balanceCell = totalRow.getCell('balance');
if (
typeof supplierReport.total.debt_price === 'number' &&
supplierReport.total.debt_price < 0
) {
balanceCell.font = { color: { argb: 'FFFF0000' } };
}
} }
}
const worksheet = XLSX.utils.json_to_sheet(excelData);
const colWidths = [
{ wch: 5 }, // No
{ wch: 10 }, // Nomor PR
{ wch: 10 }, // Nomor PO
{ wch: 20 }, // Tanggal Terima/Bayar
{ wch: 10 }, // Tanggal PO
{ wch: 10 }, // Aging
{ wch: 15 }, // Area
{ wch: 15 }, // Gudang
{ wch: 12 }, // Jatuh Tempo
{ wch: 20 }, // Status Jatuh Tempo
{ wch: 20 }, // Nominal Pembelian (Rp)
{ wch: 15 }, // Pembayaran (Rp)
{ wch: 20 }, // Sisa Saldo Hutang (Rp)
{ wch: 12 }, // Status
{ wch: 15 }, // Nomor Perjalanan
];
worksheet['!cols'] = colWidths;
const sheetName =
supplierName.length > 31 ? supplierName.substring(0, 31) : supplierName;
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
});
const filename = `laporan-hutang-supplier-${formatDate(new Date(), 'YYYY-MM-DD-HHmm')}.xlsx`; const filename = `laporan-hutang-supplier-${formatDate(new Date(), 'YYYY-MM-DD-HHmm')}.xlsx`;
XLSX.writeFile(workbook, filename); const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.click();
window.URL.revokeObjectURL(url);
}; };
@@ -35,6 +35,8 @@ import ButtonFilter from '@/components/helper/ButtonFilter';
import Badge from '@/components/Badge'; import Badge from '@/components/Badge';
import { Color } from '@/types/theme'; import { Color } from '@/types/theme';
import { Supplier } from '@/types/api/master-data/supplier'; import { Supplier } from '@/types/api/master-data/supplier';
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
import SelectInputRadio from '@/components/input/SelectInputRadio';
const dueStatus: Record<string, Color> = { const dueStatus: Record<string, Color> = {
'Sudah Jatuh Tempo': 'error', 'Sudah Jatuh Tempo': 'error',
@@ -671,7 +673,7 @@ const DebtSupplierTab = () => {
</div> </div>
<div> <div>
<SelectInput <SelectInputCheckbox
label='Supplier' label='Supplier'
placeholder='Pilih Supplier' placeholder='Pilih Supplier'
isMulti isMulti
@@ -696,7 +698,7 @@ const DebtSupplierTab = () => {
</div> </div>
<div> <div>
<SelectInput <SelectInputRadio
label='Filter Berdasarkan' label='Filter Berdasarkan'
placeholder='Pilih Filter Berdasarkan' placeholder='Pilih Filter Berdasarkan'
options={dataTypeOptions} options={dataTypeOptions}