Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/debt-supplier

This commit is contained in:
randy-ar
2026-01-14 10:41:24 +07:00
15 changed files with 418 additions and 168 deletions
@@ -2,6 +2,7 @@ import { useState, useMemo, useCallback } from 'react';
import useSWR from 'swr';
import { Icon } from '@iconify/react';
import Card from '@/components/Card';
import Badge from '@/components/Badge';
import SelectInput, {
useSelect,
OptionType,
@@ -46,7 +47,6 @@ const CustomerPaymentTab = () => {
const [filterSales, setFilterSales] = useState<OptionType[]>([]);
const [filterStartDate, setFilterStartDate] = useState('');
const [filterEndDate, setFilterEndDate] = useState('');
const [filterErrors, setFilterErrors] = useState<Record<string, string>>({});
const filterModal = useModal();
@@ -68,6 +68,38 @@ const CustomerPaymentTab = () => {
[]
);
const getPaymentStatusColor = (notes: string) => {
const normalizedValue = notes.toLowerCase();
if (normalizedValue === 'lunas') {
return 'bg-info/10 text-info border-info';
}
if (normalizedValue.includes('belum')) {
return 'bg-warning/10 text-warning border-warning';
}
return 'bg-gray-100 text-gray-600 border-gray-300';
};
const getPaymentStatusIndicatorColor = (notes: string) => {
const normalizedValue = notes.toLowerCase();
if (normalizedValue === 'lunas') {
return 'bg-info';
}
if (normalizedValue.includes('belum')) {
return 'bg-warning';
}
return 'bg-gray-400';
};
const getPaymentStatusText = (notes: string) => {
return notes;
};
// ===== FILTER HANDLERS =====
const handleResetFilters = useCallback(() => {
setIsSubmitted(false);
@@ -75,27 +107,13 @@ const CustomerPaymentTab = () => {
setFilterSales([]);
setFilterStartDate('');
setFilterEndDate('');
setFilterErrors({});
}, []);
const handleApplyFilters = useCallback(() => {
const errors: Record<string, string> = {};
if (!filterStartDate) {
errors.start_date = 'Tanggal mulai wajib diisi';
}
if (!filterEndDate) {
errors.end_date = 'Tanggal akhir wajib diisi';
}
setFilterErrors(errors);
if (Object.keys(errors).length === 0) {
setIsSubmitted(true);
setCurrentPage(1);
filterModal.closeModal();
}
}, [filterModal, filterStartDate, filterEndDate]);
setIsSubmitted(true);
setCurrentPage(1);
filterModal.closeModal();
}, [filterModal]);
// ===== DATA FETCHING =====
const { data: customerPayment, isLoading } = useSWR(
@@ -218,7 +236,22 @@ const CustomerPaymentTab = () => {
return;
}
await generateCustomerPaymentPDF({ data: allDataForExport });
await generateCustomerPaymentPDF({
data: allDataForExport,
params: {
customer_name:
filterCustomer.length > 0
? filterCustomer.map((c) => c.label).join(', ')
: undefined,
sales:
filterSales.length > 0
? filterSales.map((s) => s.label).join(', ')
: undefined,
start_date: filterStartDate || undefined,
end_date: filterEndDate || undefined,
filter_by: 'do_date',
},
});
toast.success('PDF berhasil dibuat dan diunduh.');
} catch {
toast.error('Gagal membuat PDF. Silakan coba lagi.');
@@ -435,7 +468,9 @@ const CustomerPaymentTab = () => {
accessorKey: 'accounts_receivable',
cell: (props) => {
const value = props.row.original.accounts_receivable;
return <div className='text-right'>{formatCurrency(value)}</div>;
return (
<div className='text-right text-error'>{formatCurrency(value)}</div>
);
},
footer: () => (
<div className='text-right font-semibold text-gray-900'>
@@ -449,7 +484,23 @@ const CustomerPaymentTab = () => {
accessorKey: 'notes',
cell: (props) => {
const value = props.row.original.notes;
return value || '-';
if (!value) {
return '-';
}
return (
<Badge
statusIndicator={true}
variant='soft'
className={{
badge: `rounded-xl justify-start border border-gray-200 ${getPaymentStatusColor(value)}`,
status: getPaymentStatusIndicatorColor(value),
}}
>
{getPaymentStatusText(value)}
</Badge>
);
},
},
{
@@ -538,15 +589,9 @@ const CustomerPaymentTab = () => {
value={filterStartDate}
onChange={(e) => {
setFilterStartDate(e.target.value);
setFilterErrors((prev) => ({ ...prev, start_date: '' }));
}}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.start_date && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.start_date}
</p>
)}
</div>
<div>
@@ -556,15 +601,9 @@ const CustomerPaymentTab = () => {
value={filterEndDate}
onChange={(e) => {
setFilterEndDate(e.target.value);
setFilterErrors((prev) => ({ ...prev, end_date: '' }));
}}
className={{ wrapper: 'w-full' }}
/>
{filterErrors.end_date && (
<p className='text-red-500 text-sm mt-1'>
{filterErrors.end_date}
</p>
)}
</div>
</div>
@@ -659,14 +698,13 @@ const CustomerPaymentTab = () => {
total_accounts_receivable: 0,
};
const totalAccountsReceivable = summary.total_accounts_receivable;
const tableColumns = getTableColumns(summary);
return (
<Card
key={customerReport.customer.id}
title={customerReport.customer.name}
subtitle={`${customerReport.customer.address || ''}\nSaldo Piutang: ${formatCurrency(totalAccountsReceivable)}`}
subtitle={`${customerReport.customer.address || ''}`}
className={{ wrapper: 'w-full' }}
variant='bordered'
collapsible={true}