Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu

This commit is contained in:
rstubryan
2026-01-15 15:50:28 +07:00
12 changed files with 1134 additions and 199 deletions
@@ -9,9 +9,9 @@ import SelectInput, {
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import Modal, { useModal } from '@/components/Modal';
import Table from '@/components/Table';
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
import { isResponseSuccess } from '@/lib/api-helper';
import { formatCurrency, formatDate, formatNumber } from '@/lib/helper';
import { cn, formatCurrency, formatDate, formatNumber } from '@/lib/helper';
import { SupplierApi } from '@/services/api/master-data';
import {
DebtRow,
@@ -31,10 +31,48 @@ import {
DebtSupplierFilterSchema,
DebtSupplierFilterType,
} from '@/components/pages/report/finance/filter/DebtSupplierFilter';
import { getFilledFormikValuesCount } from '@/lib/formik-helper';
import ButtonFilter from '@/components/helper/ButtonFilter';
import Badge from '@/components/Badge';
import { Color } from '@/types/theme';
import { Supplier } from '@/types/api/master-data/supplier';
const dueStatus: Record<string, Color> = {
'Sudah Jatuh Tempo': 'error',
'Belum Jatuh Tempo': 'success',
'Mendekati Jatuh Tempo': 'warning',
};
const paymentStatus: Record<string, Color> = {
'Belum Lunas': 'warning',
Lunas: 'primary',
Pembayaran: 'success',
};
const getPillBadge = (
statusText: string,
type: 'due' | 'payment' = 'payment'
) => {
// Get color based on type
const color =
type === 'due'
? dueStatus[statusText] || 'neutral'
: paymentStatus[statusText] || 'neutral';
return (
<Badge
color={color as Color}
size='sm'
variant='soft'
className={{
badge: `py-2.5 px-2 font-medium text-base-content rounded-full border border-${color}`,
}}
statusIndicator
>
{statusText}
</Badge>
);
};
const DebtSupplierTab = () => {
// ===== STATE MANAGEMENT =====
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
@@ -212,7 +250,17 @@ const DebtSupplierTab = () => {
return;
}
await generateDebtSupplierPDF({ data: allDataForExport });
await generateDebtSupplierPDF({
data: allDataForExport,
params: {
supplier_name: formik.values.supplierIds
?.map((v) => v.label)
.join(', '),
filter_by: formik.values.filterBy?.label,
start_date: formik.values.startDate || undefined,
end_date: formik.values.endDate || undefined,
},
});
toast.success('PDF berhasil dibuat dan diunduh.');
} catch {
toast.error('Gagal membuat PDF. Silakan coba lagi.');
@@ -227,6 +275,7 @@ const DebtSupplierTab = () => {
header: 'No',
enableSorting: false,
cell: (props) => props.row.index,
footer: () => 'Total',
},
{
id: 'pr_number',
@@ -331,7 +380,7 @@ const DebtSupplierTab = () => {
enableSorting: false,
cell: (props) => {
const value = props.row.original.due_status;
return value || '-';
return value ? (value != '-' ? getPillBadge(value, 'due') : '-') : '-';
},
},
{
@@ -407,7 +456,11 @@ const DebtSupplierTab = () => {
enableSorting: false,
cell: (props) => {
const value = props.row.original.status;
return value || '-';
return value
? value != '-'
? getPillBadge(value, 'payment')
: '-'
: '-';
},
},
{
@@ -475,9 +528,15 @@ const DebtSupplierTab = () => {
<Card
key={supplierReport.supplier.id}
title={supplierReport.supplier.name}
className={{ wrapper: 'w-full' }}
className={{
wrapper: 'w-full !rounded-lg',
body: 'p-0 rounded-lg',
title:
'ps-2 pt-1 pb-1 font-normal text-md bg-primary text-white',
}}
variant='bordered'
collapsible={true}
defaultCollapsed={true}
>
<Table
data={[
@@ -491,34 +550,43 @@ const DebtSupplierTab = () => {
renderFooter={supplierReport.rows.length > 0}
className={{
containerClassName: 'w-full',
tableWrapperClassName: 'overflow-x-auto mt-4',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableWrapperClassName: 'overflow-x-auto',
headerColumnClassName: cn(
TABLE_DEFAULT_STYLING.headerColumnClassName,
'whitespace-nowrap'
),
bodyColumnClassName: cn(
TABLE_DEFAULT_STYLING.bodyColumnClassName,
'whitespace-nowrap'
),
footerRowClassName: cn(
TABLE_DEFAULT_STYLING.footerRowClassName,
'bg-white'
),
footerColumnClassName: cn(
TABLE_DEFAULT_STYLING.footerColumnClassName,
'whitespace-nowrap p-3'
),
paginationClassName: 'hidden',
}}
renderCustomRow={(row) => {
if (row.index == 0) {
return (
<tr
className='hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200'
className={cn(TABLE_DEFAULT_STYLING.bodyRowClassName)}
key={row.index}
>
<td
className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'
className={cn(
TABLE_DEFAULT_STYLING.bodyColumnClassName
)}
colSpan={12}
></td>
<td className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'>
<td
className={cn(
TABLE_DEFAULT_STYLING.bodyColumnClassName
)}
>
<div
className={`text-right ${row.original.balance < 0 ? 'text-red-500' : ''}`}
>
@@ -526,7 +594,9 @@ const DebtSupplierTab = () => {
</div>
</td>
<td
className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'
className={cn(
TABLE_DEFAULT_STYLING.bodyColumnClassName
)}
colSpan={2}
></td>
</tr>