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

This commit is contained in:
rstubryan
2026-01-17 20:19:51 +07:00
10 changed files with 249 additions and 92 deletions
+8 -11
View File
@@ -34,7 +34,7 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => {
}, },
{ {
label: 'Pihak', label: 'Pihak',
value: finance.party.id ? finance.party.name : '-', value: finance.party?.id ? finance.party?.name : '-',
}, },
{ {
label: 'Tanggal', label: 'Tanggal',
@@ -56,25 +56,21 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => {
}, },
{ {
label: 'Nomor Rekening', label: 'Nomor Rekening',
value: `${finance.bank.alias} - ${finance.bank.account_number} - ${finance.bank.owner}`, value: `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}`,
}, },
{ {
label: `Rekening ${formatTitleCase(finance.party.type)}`, label: `Rekening ${formatTitleCase(finance.party?.type)}`,
value: finance.party.account_number, value: finance.party?.account_number,
}, },
{ {
label: 'Nominal', label: 'Nominal',
value: formatCurrency(finance.expense_amount), value: formatCurrency(finance.nominal),
},
{
label: 'Sisa',
value: formatCurrency(finance.income_amount),
}, },
].filter((item) => { ].filter((item) => {
// Hide party account number row if transaction type is INJECTION // Hide party account number row if transaction type is INJECTION
if ( if (
FINANCE_INJECTION_STATUS.includes(finance.transaction_type) && FINANCE_INJECTION_STATUS.includes(finance.transaction_type) &&
item.label === `Rekening ${formatTitleCase(finance.party.type)}` item.label === `Rekening ${formatTitleCase(finance.party?.type)}`
) { ) {
return false; return false;
} }
@@ -148,7 +144,8 @@ const FinanceDetail = ({ finance }: { finance: Finance }) => {
</Card> </Card>
<div className='flex flex-row gap-2 justify-end'> <div className='flex flex-row gap-2 justify-end'>
{FINANCE_TRANSACTION_STATUS.includes(finance.transaction_type) && ( {FINANCE_TRANSACTION_STATUS.includes(finance.transaction_type) &&
finance.party?.type !== 'SUPPLIER' && (
<RequirePermission permissions='lti.finance.payments.update'> <RequirePermission permissions='lti.finance.payments.update'>
<Button <Button
color='warning' color='warning'
+48 -29
View File
@@ -22,7 +22,7 @@ import {
} from '@/config/constant'; } from '@/config/constant';
import { FinanceApi } from '@/services/api/finance'; import { FinanceApi } from '@/services/api/finance';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { BankApi } from '@/services/api/master-data'; import { BankApi, CustomerApi, SupplierApi } from '@/services/api/master-data';
import { Bank } from '@/types/api/master-data/bank'; import { Bank } from '@/types/api/master-data/bank';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModal from '@/components/modal/ConfirmationModal';
@@ -65,7 +65,8 @@ const RowOptionsMenu = ({
{FINANCE_TRANSACTION_STATUS.includes( {FINANCE_TRANSACTION_STATUS.includes(
props.row.original.transaction_type props.row.original.transaction_type
) && ( ) &&
props.row.original.party?.type !== 'SUPPLIER' && (
<RequirePermission permissions='lti.finance.payments.update'> <RequirePermission permissions='lti.finance.payments.update'>
<Button <Button
href={`/finance/detail/edit?financeId=${props.row.original.id}`} href={`/finance/detail/edit?financeId=${props.row.original.id}`}
@@ -73,7 +74,11 @@ const RowOptionsMenu = ({
color='warning' color='warning'
className='justify-start text-sm' className='justify-start text-sm'
> >
<Icon icon='material-symbols:edit-outline' width={16} height={16} /> <Icon
icon='material-symbols:edit-outline'
width={16}
height={16}
/>
Edit Edit
</Button> </Button>
</RequirePermission> </RequirePermission>
@@ -194,20 +199,25 @@ const FinanceTable = () => {
// ===== Options ===== // ===== Options =====
const transactionTypeOptions = useMemo(() => { const transactionTypeOptions = useMemo(() => {
return [
{ label: 'Transfer', value: 'TRANSFER' },
{ label: 'Cash', value: 'CASH' },
{ label: 'Card', value: 'CARD' },
{ label: 'Cheque', value: 'CHEQUE' },
{ label: 'Saldo', value: 'SALDO' },
];
}, []);
const partyTypeOptions = useMemo(() => {
return [ return [
{ label: 'Customer', value: 'CUSTOMER' }, { label: 'Customer', value: 'CUSTOMER' },
{ label: 'Supplier', value: 'SUPPLIER' }, { label: 'Supplier', value: 'SUPPLIER' },
]; ];
}, []); }, []);
const {
options: partyTypeOptions,
isLoadingOptions: partyTypeIsLoadingOptions,
setInputValue: partyTypeInputValue,
loadMore: partyTypeLoadMore,
} = useSelect(
selectedTransactionType
? selectedTransactionType.value === 'CUSTOMER'
? CustomerApi.basePath
: SupplierApi.basePath
: '',
'id',
'name'
);
const sortByOptions = useMemo(() => { const sortByOptions = useMemo(() => {
return [ return [
{ label: 'Tanggal Pembayaran', value: 'payment_date' }, { label: 'Tanggal Pembayaran', value: 'payment_date' },
@@ -336,10 +346,10 @@ const FinanceTable = () => {
}, },
{ {
header: 'Pihak', header: 'Pihak',
accessorFn: (finance: Finance) => finance.party.name, accessorFn: (finance: Finance) => finance.party?.name,
cell: (props: CellContext<Finance, unknown>) => { cell: (props: CellContext<Finance, unknown>) => {
if (props.row.original.party.id) { if (props.row.original.party?.id) {
return <span>{props.row.original.party.name}</span>; return <span>{props.row.original.party?.name}</span>;
} }
return <span>{'-'}</span>; return <span>{'-'}</span>;
}, },
@@ -360,12 +370,12 @@ const FinanceTable = () => {
{ {
header: 'Bank', header: 'Bank',
accessorFn: (finance: Finance) => accessorFn: (finance: Finance) =>
`${finance.bank.alias} - ${finance.bank.account_number} - ${finance.bank.owner}`, `${finance.bank?.alias} - ${finance.bank?.account_number} - ${finance.bank?.owner}`,
}, },
{ {
header: 'Pengeluaran (Rp)', header: 'Pengeluaran (Rp)',
accessorFn: (finance: Finance) => accessorFn: (finance: Finance) =>
formatCurrency(finance.expense_amount), formatCurrency(Math.abs(finance.expense_amount)),
}, },
{ {
header: 'Pemasukan (Rp)', header: 'Pemasukan (Rp)',
@@ -468,25 +478,41 @@ const FinanceTable = () => {
<div className='grid grid-cols-4 gap-6'> <div className='grid grid-cols-4 gap-6'>
<SelectInput <SelectInput
options={transactionTypeOptions} options={transactionTypeOptions}
label='Jenis Transaksi' label='Tipe Transaksi'
value={selectedTransactionType} value={selectedTransactionType}
onChange={transactionTypeChangeHandler} onChange={transactionTypeChangeHandler}
isClearable isClearable
/> />
<SelectInput
options={partyTypeOptions}
label={
selectedTransactionType
? selectedTransactionType.value === 'CUSTOMER'
? 'Pelanggan'
: 'Supplier'
: 'Pihak'
}
value={selectedPartyType}
onChange={partyTypeChangeHandler}
onInputChange={partyTypeInputValue}
onMenuScrollToBottom={partyTypeLoadMore}
isLoading={partyTypeIsLoadingOptions}
isClearable
/>
<SelectInput <SelectInput
options={ options={
isResponseSuccess(bankRawData) isResponseSuccess(bankRawData)
? bankOptions.map((bank) => ({ ? bankOptions.map((bank) => ({
label: label:
bankRawData.data.find((data) => data.id === bank.value) bankRawData.data.find((data) => data.id === bank?.value)
?.alias + ?.alias +
' - ' + ' - ' +
bankRawData.data.find((data) => data.id === bank.value) bankRawData.data.find((data) => data.id === bank?.value)
?.account_number + ?.account_number +
' - ' + ' - ' +
bankRawData.data.find((data) => data.id === bank.value) bankRawData.data.find((data) => data.id === bank?.value)
?.owner, ?.owner,
value: bank.value, value: bank?.value,
})) }))
: [] : []
} }
@@ -497,13 +523,6 @@ const FinanceTable = () => {
onMenuScrollToBottom={bankLoadMore} onMenuScrollToBottom={bankLoadMore}
isClearable isClearable
/> />
<SelectInput
options={partyTypeOptions}
label='Pihak'
value={selectedPartyType}
onChange={partyTypeChangeHandler}
isClearable
/>
<DebouncedTextInput <DebouncedTextInput
name='search' name='search'
label='Cari' label='Cari'
@@ -32,8 +32,10 @@ import {
import { Bank } from '@/types/api/master-data/bank'; import { Bank } from '@/types/api/master-data/bank';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import Alert from '@/components/Alert';
import { Icon } from '@iconify/react';
interface FormFinanceAddProps { interface FormFinanceAddProps {
type?: 'add' | 'edit'; type?: 'add' | 'edit';
@@ -51,18 +53,22 @@ const FormFinanceAdd = ({
initialValues, initialValues,
}: FormFinanceAddProps) => { }: FormFinanceAddProps) => {
const router = useRouter(); const router = useRouter();
const [serverErrorMessage, setServerErrorMessage] = useState('');
const [isSupplier, setIsSupplier] = useState(
initialValues?.party?.type === 'SUPPLIER'
);
// ===== Formik ===== // ===== Formik =====
const formikInitialValues = useMemo((): FinanceFormValues => { const formikInitialValues = useMemo((): FinanceFormValues => {
return { return {
party_type_option: party_type_option:
FINANCE_PARTY_TYPE_OPTIONS.find( FINANCE_PARTY_TYPE_OPTIONS.find(
(option) => option.value === initialValues?.party.type (option) => option.value === initialValues?.party?.type
) || null, ) || null,
party_id_option: initialValues?.party party_id_option: initialValues?.party
? { ? {
label: initialValues?.party.name || '', label: initialValues?.party?.name || '',
value: initialValues?.party.id || 0, value: initialValues?.party?.id || 0,
} }
: null, : null,
payment_date: initialValues?.payment_date || '', payment_date: initialValues?.payment_date || '',
@@ -72,11 +78,11 @@ const FormFinanceAdd = ({
) || null, ) || null,
bank_id_option: initialValues?.bank bank_id_option: initialValues?.bank
? { ? {
label: initialValues.bank.name, label: initialValues?.bank?.name,
value: initialValues.bank.id, value: initialValues?.bank?.id,
} }
: null, : null,
party_account_number: initialValues?.party.account_number || '', party_account_number: initialValues?.party?.account_number || '',
reference_number: initialValues?.reference_number || '', reference_number: initialValues?.reference_number || '',
nominal: initialValues?.nominal.toString() || '', nominal: initialValues?.nominal.toString() || '',
notes: initialValues?.notes || '', notes: initialValues?.notes || '',
@@ -153,6 +159,7 @@ const FormFinanceAdd = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -168,6 +175,7 @@ const FormFinanceAdd = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -207,6 +215,7 @@ const FormFinanceAdd = ({
? formik.errors.party_type_option ? formik.errors.party_type_option
: '' : ''
} }
isDisabled={type === 'edit' || isSupplier}
required required
isClearable isClearable
/> />
@@ -245,7 +254,7 @@ const FormFinanceAdd = ({
} }
required required
isClearable isClearable
isDisabled={!formik.values.party_type_option?.value} isDisabled={!formik.values.party_type_option?.value || isSupplier}
/> />
<DateInput <DateInput
label='Tanggal' label='Tanggal'
@@ -263,6 +272,7 @@ const FormFinanceAdd = ({
: '' : ''
} }
required required
disabled={isSupplier}
/> />
<SelectInput <SelectInput
label='Metode Pembayaran' label='Metode Pembayaran'
@@ -284,6 +294,7 @@ const FormFinanceAdd = ({
} }
required required
isClearable isClearable
isDisabled={isSupplier}
/> />
<SelectInput <SelectInput
label='Bank' label='Bank'
@@ -324,6 +335,7 @@ const FormFinanceAdd = ({
} }
required required
isClearable isClearable
isDisabled={isSupplier}
/> />
<TextInput <TextInput
label={`Nomor Rekening ${formik.values.party_type_option?.value ? formatTitleCase(formik.values.party_type_option.value as string) : 'Pihak'}`} label={`Nomor Rekening ${formik.values.party_type_option?.value ? formatTitleCase(formik.values.party_type_option.value as string) : 'Pihak'}`}
@@ -344,6 +356,7 @@ const FormFinanceAdd = ({
} }
required required
readOnly readOnly
disabled={isSupplier}
/> />
<TextInput <TextInput
label='Nomor Referensi' label='Nomor Referensi'
@@ -363,6 +376,7 @@ const FormFinanceAdd = ({
: '' : ''
} }
required required
disabled={isSupplier}
/> />
<NumberInput <NumberInput
label='Nominal' label='Nominal'
@@ -378,6 +392,7 @@ const FormFinanceAdd = ({
: '' : ''
} }
required required
disabled={isSupplier}
/> />
<TextArea <TextArea
label='Catatan' label='Catatan'
@@ -393,8 +408,18 @@ const FormFinanceAdd = ({
: '' : ''
} }
required required
disabled={isSupplier}
/> />
<AlertErrorList formErrorList={formErrorList} onClose={close} /> <AlertErrorList formErrorList={formErrorList} onClose={close} />
{serverErrorMessage && (
<Alert color='error'>
<Icon icon='mdi:alert' />
{serverErrorMessage}
<Button color='error' onClick={() => setServerErrorMessage('')}>
<Icon icon='mdi:close' />
</Button>
</Alert>
)}
<div className='flex justify-center gap-4'> <div className='flex justify-center gap-4'>
<Button <Button
type='reset' type='reset'
@@ -27,13 +27,7 @@ export const InitialBalanceFormSchema = Yup.object().shape({
'Pihak wajib diisi', 'Pihak wajib diisi',
(value) => value !== null && value !== undefined (value) => value !== null && value !== undefined
), ),
bank_id_option: Yup.mixed() bank_id_option: Yup.mixed().nullable(),
.nullable()
.test(
'is-valid-option',
'Bank wajib diisi',
(value) => value !== null && value !== undefined
),
reference_number: Yup.string().required('Nomor referensi wajib diisi'), reference_number: Yup.string().required('Nomor referensi wajib diisi'),
initial_balance_type_option: Yup.mixed() initial_balance_type_option: Yup.mixed()
.nullable() .nullable()
@@ -29,8 +29,9 @@ import { Bank } from '@/types/api/master-data/bank';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import Alert from '@/components/Alert';
interface FormFinanceAddInitialBalanceProps { interface FormFinanceAddInitialBalanceProps {
type?: 'add' | 'edit'; type?: 'add' | 'edit';
@@ -42,6 +43,7 @@ const FormFinanceAddInitialBalance = ({
initialValues, initialValues,
}: FormFinanceAddInitialBalanceProps) => { }: FormFinanceAddInitialBalanceProps) => {
const router = useRouter(); const router = useRouter();
const [serverErrorMessage, setServerErrorMessage] = useState('');
// ===== Formik ===== // ===== Formik =====
const formikInitialValues = useMemo((): InitialBalanceFormValues => { const formikInitialValues = useMemo((): InitialBalanceFormValues => {
@@ -53,18 +55,18 @@ const FormFinanceAddInitialBalance = ({
return { return {
party_type_option: party_type_option:
FINANCE_PARTY_TYPE_OPTIONS.find( FINANCE_PARTY_TYPE_OPTIONS.find(
(option) => option.value === initialValues?.party.type (option) => option.value === initialValues?.party?.type
) || null, ) || null,
party_id_option: initialValues?.party party_id_option: initialValues?.party
? { ? {
label: initialValues.party.name, label: initialValues.party?.name,
value: initialValues.party.id, value: initialValues.party?.id,
} }
: null, : null,
bank_id_option: initialValues?.bank bank_id_option: initialValues?.bank
? { ? {
label: initialValues.bank.name, label: initialValues.bank?.name,
value: initialValues.bank.id, value: initialValues.bank?.id,
} }
: null, : null,
reference_number: initialValues?.reference_number || '', reference_number: initialValues?.reference_number || '',
@@ -147,6 +149,7 @@ const FormFinanceAddInitialBalance = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -166,6 +169,7 @@ const FormFinanceAddInitialBalance = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -211,6 +215,7 @@ const FormFinanceAddInitialBalance = ({
: '' : ''
} }
required required
isDisabled={type === 'edit'}
isClearable isClearable
/> />
<SelectInput <SelectInput
@@ -277,7 +282,6 @@ const FormFinanceAddInitialBalance = ({
? formik.errors.bank_id_option ? formik.errors.bank_id_option
: '' : ''
} }
required
isClearable isClearable
/> />
<TextInput <TextInput
@@ -362,7 +366,18 @@ const FormFinanceAddInitialBalance = ({
} }
required required
/> />
<AlertErrorList formErrorList={formErrorList} onClose={close} /> <AlertErrorList formErrorList={formErrorList} onClose={close} />
{serverErrorMessage && (
<Alert color='error'>
<Icon icon='mdi:alert' />
{serverErrorMessage}
<Button color='error' onClick={() => setServerErrorMessage('')}>
<Icon icon='mdi:close' />
</Button>
</Alert>
)}
<div className='flex justify-center gap-4'> <div className='flex justify-center gap-4'>
<Button <Button
type='reset' type='reset'
@@ -24,8 +24,10 @@ import {
import { Bank } from '@/types/api/master-data/bank'; import { Bank } from '@/types/api/master-data/bank';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import Alert from '@/components/Alert';
import { Icon } from '@iconify/react';
interface FormFinanceInjectionProps { interface FormFinanceInjectionProps {
type?: 'add' | 'edit'; type?: 'add' | 'edit';
@@ -37,14 +39,15 @@ const FormFinanceInjection = ({
initialValues, initialValues,
}: FormFinanceInjectionProps) => { }: FormFinanceInjectionProps) => {
const router = useRouter(); const router = useRouter();
const [serverErrorMessage, setServerErrorMessage] = useState('');
// ===== Formik ===== // ===== Formik =====
const formikInitialValues = useMemo((): InjectionFormValues => { const formikInitialValues = useMemo((): InjectionFormValues => {
return { return {
bank_id_option: initialValues?.bank bank_id_option: initialValues?.bank
? { ? {
label: initialValues.bank.name, label: initialValues.bank?.name,
value: initialValues.bank.id, value: initialValues.bank?.id,
} }
: null, : null,
adjustment_date: initialValues?.payment_date || '', adjustment_date: initialValues?.payment_date || '',
@@ -103,6 +106,7 @@ const FormFinanceInjection = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -119,6 +123,7 @@ const FormFinanceInjection = ({
if (isResponseError(response)) { if (isResponseError(response)) {
toast.error(response.message); toast.error(response.message);
setServerErrorMessage(response.message);
return; return;
} }
@@ -230,6 +235,15 @@ const FormFinanceInjection = ({
required required
/> />
<AlertErrorList formErrorList={formErrorList} onClose={close} /> <AlertErrorList formErrorList={formErrorList} onClose={close} />
{serverErrorMessage && (
<Alert color='error'>
<Icon icon='mdi:alert' />
{serverErrorMessage}
<Button color='error' onClick={() => setServerErrorMessage('')}>
<Icon icon='mdi:close' />
</Button>
</Alert>
)}
<div className='flex justify-center gap-4'> <div className='flex justify-center gap-4'>
<Button <Button
type='reset' type='reset'
@@ -91,7 +91,7 @@ const InventoryProductDetail = ({
<td>:</td> <td>:</td>
<td> <td>
{inventoryProduct?.tax {inventoryProduct?.tax
? formatCurrency(inventoryProduct?.tax) ? formatNumber(inventoryProduct?.tax) + '%'
: '-'} : '-'}
</td> </td>
</tr> </tr>
@@ -16,7 +16,7 @@ import { TableRowSizeSelector } from '@/components/table/TableRowSizeSelector';
import { TableToolbar } from '@/components/table/TableToolbar'; import { TableToolbar } from '@/components/table/TableToolbar';
import { ROWS_OPTIONS } from '@/config/constant'; import { ROWS_OPTIONS } from '@/config/constant';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { cn, formatCurrency, formatDate } from '@/lib/helper'; import { cn, formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
import { import {
MarketingApi, MarketingApi,
SalesOrderApi, SalesOrderApi,
@@ -33,6 +33,7 @@ import RequirePermission from '@/components/helper/RequirePermission';
import { useAuth } from '@/services/hooks/useAuth'; import { useAuth } from '@/services/hooks/useAuth';
import { CustomerApi, ProductApi } from '@/services/api/master-data'; import { CustomerApi, ProductApi } from '@/services/api/master-data';
import { MARKETING_APPROVAL_LINE } from '@/config/approval-line'; import { MARKETING_APPROVAL_LINE } from '@/config/approval-line';
import Badge from '@/components/Badge';
const RowsOptionsMenu = ({ const RowsOptionsMenu = ({
type = 'dropdown', type = 'dropdown',
@@ -520,8 +521,53 @@ const MarketingTable = () => {
}, },
}, },
{ {
accessorKey: 'latest_approval.step_name', accessorKey: 'approval.step_name',
header: 'Status', header: 'Status',
cell: (props) => {
const approval = props.row.original.latest_approval;
const isRejected = approval?.action == 'REJECTED';
const isApproved = approval?.action == 'APPROVED';
return (
<Badge
variant='soft'
className={{
badge:
'rounded-lg px-2 w-full flex flex-row justify-start whitespace-nowrap',
}}
color={
isRejected
? 'error'
: isApproved
? approval?.step_number == 1
? 'neutral'
: approval?.step_number == 2
? 'primary'
: approval?.step_number == 3
? 'success'
: 'neutral'
: 'neutral'
}
>
<Icon
icon='mdi:circle'
width={12}
height={12}
color={
approval?.step_number == 1
? 'neutral'
: approval?.step_number == 2
? 'primary'
: approval?.step_number == 3
? 'success'
: 'neutral'
}
/>
{isRejected
? 'Ditolak'
: formatTitleCase(approval?.step_name || '')}
</Badge>
);
},
}, },
{ {
accessorKey: 'customer.name', accessorKey: 'customer.name',
@@ -16,6 +16,7 @@ import {
formatCurrency, formatCurrency,
formatDate, formatDate,
formatNumber, formatNumber,
formatTitleCase,
formatVechicleNumber, formatVechicleNumber,
} from '@/lib/helper'; } from '@/lib/helper';
import { import {
@@ -34,6 +35,7 @@ import toast from 'react-hot-toast';
import SalesOrderExport from '@/components/pages/marketing/pdf/SalesOrderExport'; import SalesOrderExport from '@/components/pages/marketing/pdf/SalesOrderExport';
import DeliveryOrderExport from '@/components/pages/marketing/pdf/DeliveryOrderExport'; import DeliveryOrderExport from '@/components/pages/marketing/pdf/DeliveryOrderExport';
import RequirePermission from '@/components/helper/RequirePermission'; import RequirePermission from '@/components/helper/RequirePermission';
import Badge from '@/components/Badge';
const MarketingDetail = ({ const MarketingDetail = ({
initialValues, initialValues,
@@ -121,6 +123,10 @@ const MarketingDetail = ({
); );
}; };
const approval = initialValues?.latest_approval;
const isRejected = approval?.action == 'REJECTED';
const isApproved = approval?.action == 'APPROVED';
return ( return (
<> <>
<div className='flex flex-col w-full gap-4'> <div className='flex flex-col w-full gap-4'>
@@ -230,7 +236,46 @@ const MarketingDetail = ({
<tr> <tr>
<td className='font-semibold'>Status</td> <td className='font-semibold'>Status</td>
<td>:</td> <td>:</td>
<td>{initialValues?.latest_approval?.step_name}</td> <td>
<Badge
variant='soft'
className={{
badge:
'rounded-lg px-2 w-fit flex flex-row justify-start whitespace-nowrap',
}}
color={
isRejected
? 'error'
: isApproved
? approval?.step_number == 1
? 'neutral'
: approval?.step_number == 2
? 'primary'
: approval?.step_number == 3
? 'success'
: 'neutral'
: 'neutral'
}
>
<Icon
icon='mdi:circle'
width={12}
height={12}
color={
approval?.step_number == 1
? 'neutral'
: approval?.step_number == 2
? 'primary'
: approval?.step_number == 3
? 'success'
: 'neutral'
}
/>
{isRejected
? 'Ditolak'
: formatTitleCase(approval?.step_name || '')}
</Badge>
</td>
</tr> </tr>
<tr> <tr>
<td className='font-semibold'>Tanggal Penjualan</td> <td className='font-semibold'>Tanggal Penjualan</td>
@@ -621,7 +621,9 @@ const MarketingForm = ({
isClearable isClearable
placeholder='Pilih Pelanggan' placeholder='Pilih Pelanggan'
isDisabled={ isDisabled={
formType === 'add_deliver' || formType === 'edit_deliver' formType === 'add_deliver' ||
formType === 'edit_deliver' ||
formType === 'edit'
} }
/> />
<DateInput <DateInput