fixing response in transfertype
This commit is contained in:
@ -27,7 +27,7 @@ const App = () => {
|
|||||||
<PathnameProvider>
|
<PathnameProvider>
|
||||||
<AppRouting />
|
<AppRouting />
|
||||||
</PathnameProvider>
|
</PathnameProvider>
|
||||||
<Toaster />
|
<Toaster expand visibleToasts={20} duration={3000} />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { apiConfig } from '@/config/api.config';
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext';
|
import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext';
|
||||||
import {
|
import {
|
||||||
Alert,
|
|
||||||
Container,
|
Container,
|
||||||
DataGridColumnHeader,
|
DataGridColumnHeader,
|
||||||
DataGridInner,
|
DataGridInner,
|
||||||
@ -65,17 +64,14 @@ const AddDialog = () => {
|
|||||||
const [customers, setCustomers] = useState<CustomerProps[]>([]);
|
const [customers, setCustomers] = useState<CustomerProps[]>([]);
|
||||||
const { reload } = useDataGrid();
|
const { reload } = useDataGrid();
|
||||||
const { PostData, PutData } = useCallApi();
|
const { PostData, PutData } = useCallApi();
|
||||||
const [alert, setAlert] = useState({
|
|
||||||
show: false,
|
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||||
message: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
wallet_origin: '',
|
wallet_origin: '',
|
||||||
wallet_destination: '',
|
wallet_destination: '',
|
||||||
|
|
||||||
minimum_amount: 0,
|
minimum_amount: 0,
|
||||||
maximum_amount: 0,
|
maximum_amount: 0,
|
||||||
max_transaction_per_day: 0,
|
max_transaction_per_day: 0,
|
||||||
@ -92,38 +88,39 @@ const AddDialog = () => {
|
|||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
setFormField(initialState);
|
setFormField(initialState);
|
||||||
|
setErrors({});
|
||||||
};
|
};
|
||||||
|
|
||||||
const parsedUser = getAuth()?.user;
|
const parsedUser = getAuth()?.user;
|
||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const requiredFields = [
|
const requiredFields = [
|
||||||
'name',
|
{ key: 'name', label: 'Transfer Type Name' },
|
||||||
'description',
|
{ key: 'description', label: 'Description' },
|
||||||
'wallet_origin',
|
{ key: 'wallet_origin', label: 'From Account' },
|
||||||
'wallet_destination',
|
{ key: 'wallet_destination', label: 'To Account' },
|
||||||
'status',
|
{ key: 'status', label: 'Status' },
|
||||||
'status_approval',
|
{ key: 'status_approval', label: 'Status Approval' },
|
||||||
'status_kind'
|
{ key: 'status_kind', label: 'Status Kind' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const missingFields = requiredFields.filter(
|
const newErrors: Record<string, string> = {};
|
||||||
(field) =>
|
let isValid = true;
|
||||||
formField[field as keyof typeof formField] === '' ||
|
|
||||||
formField[field as keyof typeof formField] === null ||
|
|
||||||
formField[field as keyof typeof formField] === undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
if (missingFields.length > 0) {
|
requiredFields.forEach(({ key, label }) => {
|
||||||
setAlert({
|
if (
|
||||||
show: true,
|
formField[key as keyof typeof formField] === '' ||
|
||||||
message: `Please fill out all required fields: ${missingFields.join(', ')}`
|
formField[key as keyof typeof formField] === null ||
|
||||||
});
|
formField[key as keyof typeof formField] === undefined
|
||||||
return false;
|
) {
|
||||||
}
|
newErrors[key] = `${label} is required`;
|
||||||
|
toast.error(`${label} is required`);
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setAlert({ show: false, message: '' });
|
setErrors(newErrors);
|
||||||
return true;
|
return isValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
@ -162,20 +159,17 @@ const AddDialog = () => {
|
|||||||
const response = await PostData(`${API_URL}/transactiontype/create`, data);
|
const response = await PostData(`${API_URL}/transactiontype/create`, data);
|
||||||
|
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
setAlert({ show: false, message: '' });
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
setAlert({ show: true, message: response?.message || 'Failed to create transfer type' });
|
toast.error(response?.message || 'Failed to create transfer type');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setAlert({
|
toast.error(
|
||||||
show: true,
|
error instanceof Error
|
||||||
message:
|
? error.message
|
||||||
error instanceof Error
|
: 'An error occurred while creating transfer type'
|
||||||
? error.message
|
);
|
||||||
: 'An error occurred while creating transfer type'
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -226,7 +220,6 @@ const AddDialog = () => {
|
|||||||
order_direction: 'ASC'
|
order_direction: 'ASC'
|
||||||
};
|
};
|
||||||
const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params);
|
const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params);
|
||||||
// console.log(response)
|
|
||||||
if (response?.status && response?.data) {
|
if (response?.status && response?.data) {
|
||||||
setWallets(response.data.list);
|
setWallets(response.data.list);
|
||||||
} else {
|
} else {
|
||||||
@ -238,7 +231,13 @@ const AddDialog = () => {
|
|||||||
if (!showAddDialog) return;
|
if (!showAddDialog) return;
|
||||||
fetchWallets();
|
fetchWallets();
|
||||||
}, [showAddDialog]);
|
}, [showAddDialog]);
|
||||||
// console.log(formField)
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showAddDialog) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [showAddDialog]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
||||||
<DialogContent className="container-fixed max-w-[1080px] flex flex-col p-5 overflow-hidden [&>button]:hidden">
|
<DialogContent className="container-fixed max-w-[1080px] flex flex-col p-5 overflow-hidden [&>button]:hidden">
|
||||||
@ -256,7 +255,6 @@ const AddDialog = () => {
|
|||||||
className="cursor-pointer hover:opacity-100 opacity-50"
|
className="cursor-pointer hover:opacity-100 opacity-50"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleAddDialog(false);
|
handleAddDialog(false);
|
||||||
resetForm();
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<KeenIcon icon="cross" className="text-1.5xl" />
|
<KeenIcon icon="cross" className="text-1.5xl" />
|
||||||
@ -265,13 +263,6 @@ const AddDialog = () => {
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogBody className="scrollable-y px-0 pb-0" ref={parentRef}>
|
<DialogBody className="scrollable-y px-0 pb-0" ref={parentRef}>
|
||||||
<div className="flex flex-col px-0">
|
<div className="flex flex-col px-0">
|
||||||
{alert.show && (
|
|
||||||
<div className="sticky top-0 z-10 bg-white p-3">
|
|
||||||
<Alert variant="danger" className="mb-3">
|
|
||||||
<h3>{alert.message}</h3>
|
|
||||||
</Alert>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<form action="" onSubmit={handleSubmit}>
|
<form action="" onSubmit={handleSubmit}>
|
||||||
<div className="card-body grid gap-5 p-0">
|
<div className="card-body grid gap-5 p-0">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
@ -280,16 +271,20 @@ const AddDialog = () => {
|
|||||||
Transfer Type Name
|
Transfer Type Name
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className={`input ${errors.name ? 'border-red-500' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
value={formField.name}
|
value={formField.name}
|
||||||
onChange={({ target }) =>
|
onChange={({ target }) => {
|
||||||
setFormField((prev) => ({ ...prev, name: target.value }))
|
setFormField((prev) => ({ ...prev, name: target.value }));
|
||||||
}
|
if (target.value) {
|
||||||
|
setErrors((prev) => ({ ...prev, name: '' }));
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
{errors.name && <span className="text-red-500 text-xs mt-1">{errors.name}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -300,16 +295,20 @@ const AddDialog = () => {
|
|||||||
Description
|
Description
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className={`input ${errors.description ? 'border-red-500' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
value={formField.description}
|
value={formField.description}
|
||||||
onChange={({ target }) =>
|
onChange={({ target }) => {
|
||||||
setFormField((prev) => ({ ...prev, description: target.value }))
|
setFormField((prev) => ({ ...prev, description: target.value }));
|
||||||
}
|
if (target.value) {
|
||||||
|
setErrors((prev) => ({ ...prev, description: '' }));
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
{errors.description && <span className="text-red-500 text-xs mt-1">{errors.description}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -390,24 +389,26 @@ const AddDialog = () => {
|
|||||||
From Account
|
From Account
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_origin}
|
value={formField.wallet_origin}
|
||||||
onValueChange={(wallet_origin) =>
|
onValueChange={(wallet_origin) => {
|
||||||
setFormField((prev) => ({ ...prev, wallet_origin }))
|
setFormField((prev) => ({ ...prev, wallet_origin }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, wallet_origin: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.wallet_origin ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select Wallet" />
|
<SelectValue placeholder="Select Wallet" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{wallets.map((wallet, idx) => (
|
{wallets.map((wallet) => (
|
||||||
<SelectItem value={wallet.id} key={wallet.name}>
|
<SelectItem value={wallet.id} key={wallet.name}>
|
||||||
{wallet.name}
|
{wallet.name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.wallet_origin && <span className="text-red-500 text-xs mt-1">{errors.wallet_origin}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -418,24 +419,26 @@ const AddDialog = () => {
|
|||||||
To Account
|
To Account
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_destination}
|
value={formField.wallet_destination}
|
||||||
onValueChange={(wallet_destination) =>
|
onValueChange={(wallet_destination) => {
|
||||||
setFormField((prev) => ({ ...prev, wallet_destination }))
|
setFormField((prev) => ({ ...prev, wallet_destination }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, wallet_destination: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.wallet_destination ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select Wallet" />
|
<SelectValue placeholder="Select Wallet" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{wallets.map((wallet, idx) => (
|
{wallets.map((wallet) => (
|
||||||
<SelectItem value={wallet.id} key={wallet.id}>
|
<SelectItem value={wallet.id} key={wallet.id}>
|
||||||
{wallet.name}
|
{wallet.name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.wallet_destination && <span className="text-red-500 text-xs mt-1">{errors.wallet_destination}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -447,14 +450,15 @@ const AddDialog = () => {
|
|||||||
<span className="text-red-500"> *</span>
|
<span className="text-red-500"> *</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.type}
|
value={formField.type}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, type: value }))
|
setFormField((prev) => ({ ...prev, type: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, type: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.type ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -480,6 +484,7 @@ const AddDialog = () => {
|
|||||||
<SelectItem value="IC">Income Merchant</SelectItem>
|
<SelectItem value="IC">Income Merchant</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.type && <span className="text-red-500 text-xs mt-1">{errors.type}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -490,14 +495,15 @@ const AddDialog = () => {
|
|||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status_approval}
|
value={formField.status_approval}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status_approval: value }))
|
setFormField((prev) => ({ ...prev, status_approval: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status_approval: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status_approval ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -505,6 +511,7 @@ const AddDialog = () => {
|
|||||||
<SelectItem value="N">No</SelectItem>
|
<SelectItem value="N">No</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status_approval && <span className="text-red-500 text-xs mt-1">{errors.status_approval}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -515,14 +522,15 @@ const AddDialog = () => {
|
|||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status_kind}
|
value={formField.status_kind}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status_kind: value }))
|
setFormField((prev) => ({ ...prev, status_kind: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status_kind: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status_kind ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -534,6 +542,7 @@ const AddDialog = () => {
|
|||||||
<SelectItem value="N">Top Up Patner</SelectItem>
|
<SelectItem value="N">Top Up Patner</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status_kind && <span className="text-red-500 text-xs mt-1">{errors.status_kind}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -545,14 +554,15 @@ const AddDialog = () => {
|
|||||||
<span className="text-red-500"> *</span>
|
<span className="text-red-500"> *</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status}
|
value={formField.status}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status: value }))
|
setFormField((prev) => ({ ...prev, status: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -560,6 +570,7 @@ const AddDialog = () => {
|
|||||||
<SelectItem value="N">Inactive</SelectItem>
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status && <span className="text-red-500 text-xs mt-1">{errors.status}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -67,6 +67,10 @@ const EditDialog = () => {
|
|||||||
show: false,
|
show: false,
|
||||||
message: ''
|
message: ''
|
||||||
});
|
});
|
||||||
|
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
const [isLoadingWallets, setIsLoadingWallets] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
const initialState: {
|
const initialState: {
|
||||||
name: string;
|
name: string;
|
||||||
@ -106,6 +110,7 @@ const EditDialog = () => {
|
|||||||
setFormField(initialState);
|
setFormField(initialState);
|
||||||
setSelectedGroups([]);
|
setSelectedGroups([]);
|
||||||
setAlert({ show: false, message: '' });
|
setAlert({ show: false, message: '' });
|
||||||
|
setErrors({});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGroupChange = (groupId: string) => {
|
const handleGroupChange = (groupId: string) => {
|
||||||
@ -128,42 +133,33 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
const requiredFields = [
|
const requiredFields = [
|
||||||
'name',
|
{ key: 'name', label: 'Transfer Type Name' },
|
||||||
'description',
|
{ key: 'description', label: 'Description' },
|
||||||
'wallet_origin',
|
{ key: 'wallet_origin', label: 'From Account' },
|
||||||
'wallet_destination',
|
{ key: 'wallet_destination', label: 'To Account' },
|
||||||
'status',
|
{ key: 'status', label: 'Status' },
|
||||||
'status_approval',
|
{ key: 'status_approval', label: 'Status Approval' },
|
||||||
'status_kind',
|
{ key: 'status_kind', label: 'Status Kind' }
|
||||||
'type'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const missingFields = requiredFields.filter((field) => {
|
const newErrors: Record<string, string> = {};
|
||||||
return (
|
let isValid = true;
|
||||||
formField[field as keyof typeof formField] === '' ||
|
|
||||||
formField[field as keyof typeof formField] === null ||
|
requiredFields.forEach(({ key, label }) => {
|
||||||
formField[field as keyof typeof formField] === undefined
|
if (
|
||||||
);
|
formField[key as keyof typeof formField] === '' ||
|
||||||
|
formField[key as keyof typeof formField] === null ||
|
||||||
|
formField[key as keyof typeof formField] === undefined
|
||||||
|
) {
|
||||||
|
newErrors[key] = `${label} is required`;
|
||||||
|
// Show toast for each required field
|
||||||
|
toast.error(`${label} is required`);
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (missingFields.length > 0) {
|
setErrors(newErrors);
|
||||||
setAlert({
|
return isValid;
|
||||||
show: true,
|
|
||||||
message: `Please fill out all required fields: ${missingFields.join(', ')}`
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formField.permission.length === 0) {
|
|
||||||
setAlert({
|
|
||||||
show: true,
|
|
||||||
message: 'Please select at least one group permission'
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAlert({ show: false, message: '' });
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -202,7 +198,7 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
const createActivity = {
|
const createActivity = {
|
||||||
module: 'Manage Transfer Type',
|
module: 'Manage Transfer Type',
|
||||||
description: `Edit Transfer Type => ${selectedTransferType}`,
|
description: `Edit Transfer Type => ${formField.name}`,
|
||||||
action: 'U'
|
action: 'U'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -227,17 +223,18 @@ const EditDialog = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
setAlert({ show: false, message: '' });
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
setAlert({ show: true, message: response?.message || 'Failed to update transfer type' });
|
toast.error(response?.message || 'Failed to update transfer type');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
toast.error(
|
||||||
|
error instanceof Error ? error.message : 'Failed to Update Transfer Type'
|
||||||
|
);
|
||||||
setAlert({
|
setAlert({
|
||||||
show: true,
|
show: true,
|
||||||
message:
|
message: error instanceof Error ? error.message : 'Failed to Update Transfer Type'
|
||||||
error instanceof Error ? error.message : 'An error occurred while updating transfer type'
|
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -376,6 +373,37 @@ const EditDialog = () => {
|
|||||||
resetForm();
|
resetForm();
|
||||||
}
|
}
|
||||||
}, [showEditDialog]);
|
}, [showEditDialog]);
|
||||||
|
const renderSelectWithLoading = (
|
||||||
|
value: string,
|
||||||
|
onChangeHandler: (value: string) => void,
|
||||||
|
options: { id: string; name: string }[] | null,
|
||||||
|
placeholder: string,
|
||||||
|
isLoading: boolean
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<Select value={value} onValueChange={onChangeHandler} disabled={isLoading}>
|
||||||
|
<SelectTrigger>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="animate-pulse bg-gray-200 h-4 w-24 rounded"></div>
|
||||||
|
<span className="ml-2">Loading...</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<SelectValue placeholder={placeholder} />
|
||||||
|
)}
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{options &&
|
||||||
|
options.map((option) => (
|
||||||
|
<SelectItem value={option.id} key={option.id}>
|
||||||
|
{option.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={showEditDialog} onOpenChange={(open) => handleEditDialog(open, null)}>
|
<Dialog open={showEditDialog} onOpenChange={(open) => handleEditDialog(open, null)}>
|
||||||
@ -418,36 +446,48 @@ const EditDialog = () => {
|
|||||||
Transfer Type Name
|
Transfer Type Name
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className={`input ${errors.name ? 'border-red-500' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
value={formField.name}
|
value={formField.name}
|
||||||
onChange={({ target }) =>
|
onChange={({ target }) => {
|
||||||
setFormField((prev) => ({ ...prev, name: target.value }))
|
setFormField((prev) => ({ ...prev, name: target.value }));
|
||||||
}
|
if (target.value) {
|
||||||
|
setErrors((prev) => ({ ...prev, name: '' }));
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
{errors.name && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.name}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Description
|
Description
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className={`input ${errors.description ? 'border-red-500' : ''}`}
|
||||||
type="text"
|
type="text"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
value={formField.description}
|
value={formField.description}
|
||||||
onChange={({ target }) =>
|
onChange={({ target }) => {
|
||||||
setFormField((prev) => ({ ...prev, description: target.value }))
|
setFormField((prev) => ({ ...prev, description: target.value }));
|
||||||
}
|
if (target.value) {
|
||||||
|
setErrors((prev) => ({ ...prev, description: '' }));
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
{errors.description && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.description}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -528,24 +568,17 @@ const EditDialog = () => {
|
|||||||
From Account
|
From Account
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
{renderSelectWithLoading(
|
||||||
value={formField.wallet_origin}
|
formField.wallet_origin,
|
||||||
onValueChange={(wallet_origin) =>
|
(value) => setFormField({ ...formField, wallet_origin: value }),
|
||||||
setFormField((prev) => ({ ...prev, wallet_origin }))
|
wallets,
|
||||||
}
|
'Select Wallet',
|
||||||
>
|
isLoadingWallets
|
||||||
<SelectTrigger>
|
)}
|
||||||
<SelectValue placeholder="Select Wallet" />
|
{errors.wallet_origin && (
|
||||||
</SelectTrigger>
|
<span className="text-red-500 text-xs mt-1">{errors.wallet_origin}</span>
|
||||||
<SelectContent>
|
)}
|
||||||
{wallets.map((wallet) => (
|
|
||||||
<SelectItem value={wallet.id} key={wallet.id}>
|
|
||||||
{wallet.name}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -556,14 +589,15 @@ const EditDialog = () => {
|
|||||||
To Account
|
To Account
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_destination}
|
value={formField.wallet_destination}
|
||||||
onValueChange={(wallet_destination) =>
|
onValueChange={(wallet_destination) => {
|
||||||
setFormField((prev) => ({ ...prev, wallet_destination }))
|
setFormField((prev) => ({ ...prev, wallet_destination }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, wallet_destination: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.wallet_destination ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select Wallet" />
|
<SelectValue placeholder="Select Wallet" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -574,6 +608,9 @@ const EditDialog = () => {
|
|||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.wallet_destination && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.wallet_destination}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -584,14 +621,15 @@ const EditDialog = () => {
|
|||||||
Status Transaction Type
|
Status Transaction Type
|
||||||
<span className="text-red-500"> *</span>
|
<span className="text-red-500"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.type}
|
value={formField.type}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, type: value }))
|
setFormField((prev) => ({ ...prev, type: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, type: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.type ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -617,6 +655,9 @@ const EditDialog = () => {
|
|||||||
<SelectItem value="IC">Income Merchant</SelectItem>
|
<SelectItem value="IC">Income Merchant</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.type && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.type}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -627,14 +668,15 @@ const EditDialog = () => {
|
|||||||
Status Approval
|
Status Approval
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status_approval}
|
value={formField.status_approval}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status_approval: value }))
|
setFormField((prev) => ({ ...prev, status_approval: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status_approval: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status_approval ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -642,6 +684,9 @@ const EditDialog = () => {
|
|||||||
<SelectItem value="N">No</SelectItem>
|
<SelectItem value="N">No</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status_approval && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.status_approval}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -652,14 +697,15 @@ const EditDialog = () => {
|
|||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status_kind}
|
value={formField.status_kind}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status_kind: value }))
|
setFormField((prev) => ({ ...prev, status_kind: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status_kind: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status_kind ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -671,6 +717,9 @@ const EditDialog = () => {
|
|||||||
<SelectItem value="N">Top Up Patner</SelectItem>
|
<SelectItem value="N">Top Up Patner</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status_kind && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.status_kind}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -680,14 +729,15 @@ const EditDialog = () => {
|
|||||||
Status
|
Status
|
||||||
<span className="text-red-500"> *</span>
|
<span className="text-red-500"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow flex flex-col">
|
||||||
<Select
|
<Select
|
||||||
value={formField.status}
|
value={formField.status}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) => {
|
||||||
setFormField((prev) => ({ ...prev, status: value }))
|
setFormField((prev) => ({ ...prev, status: value }));
|
||||||
}
|
setErrors((prev) => ({ ...prev, status: '' }));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger className={errors.status ? 'border-red-500' : ''}>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -695,6 +745,9 @@ const EditDialog = () => {
|
|||||||
<SelectItem value="N">Inactive</SelectItem>
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.status && (
|
||||||
|
<span className="text-red-500 text-xs mt-1">{errors.status}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -738,6 +791,13 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end pt-2.5 gap-5">
|
<div className="flex justify-end pt-2.5 gap-5">
|
||||||
|
<Button
|
||||||
|
variant={'outline'}
|
||||||
|
type="button"
|
||||||
|
onClick={() => resetForm()}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
<Button variant={'default'} type="submit" disabled={isSubmitting}>
|
<Button variant={'default'} type="submit" disabled={isSubmitting}>
|
||||||
{isSubmitting ? 'Saving...' : 'Save Changes'}
|
{isSubmitting ? 'Saving...' : 'Save Changes'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -346,7 +346,7 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React
|
|||||||
setSearchTerm
|
setSearchTerm
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Toaster expand visibleToasts={9} duration={3000} />
|
{/* <Toaster expand visibleToasts={9} duration={3000} /> */}
|
||||||
|
|
||||||
<div className="px-4">
|
<div className="px-4">
|
||||||
<DataGridProvider
|
<DataGridProvider
|
||||||
|
|||||||
Reference in New Issue
Block a user