add dropdown msisdn on disbursement module
- set limit 50, filter implemented
This commit is contained in:
@ -4,7 +4,7 @@ import { Breadcrumbs, Link } from '@mui/material';
|
|||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import { useCallApi } from '@/hooks';
|
import { useCallApi } from '@/hooks';
|
||||||
import { apiConfig } from '@/config/api.config';
|
import { apiConfig } from '@/config/api.config';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
@ -24,17 +24,57 @@ const TransactionDisbursement = () => {
|
|||||||
|
|
||||||
const [form, setForm] = useState(initialForm);
|
const [form, setForm] = useState(initialForm);
|
||||||
const [wallets, setWallets] = useState([]);
|
const [wallets, setWallets] = useState([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [customerMsisdn, setCustomerMsisdn] = useState<{ value: string; label: string }[]>([]);
|
||||||
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||||
const { GetData, PostData } = useCallApi();
|
const { GetData, PostData } = useCallApi();
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [showConfirmation, setShowConfirmation] = useState(false);
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||||
const parsedUser = getAuth()?.user;
|
const parsedUser = getAuth()?.user;
|
||||||
const API_URL = apiConfig.transaction;
|
const API_URL = apiConfig.transaction;
|
||||||
const API_URL_WALLET = apiConfig.service_wallet;
|
const API_URL_WALLET = apiConfig.service_wallet;
|
||||||
|
const API_URL_CUSTOMER = apiConfig.service_customer;
|
||||||
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const [alert, setAlert] = useState({
|
const [alert, setAlert] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
message: ''
|
message: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fetchCustomerMsisdn = async (sorting: any, filterValue: string) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
const filter: any =
|
||||||
|
filterValue.trim().length === 0 ? {} : { msisdn: { like: `%${filterValue}%` } };
|
||||||
|
|
||||||
|
const query: any = {
|
||||||
|
limit: 50,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc ? 'DESC' : 'ASC'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter && Object.keys(filter).length > 0) {
|
||||||
|
query.filter = JSON.stringify(filter);
|
||||||
|
// query.page = page + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, query);
|
||||||
|
setCustomerMsisdn(
|
||||||
|
response?.data.list.map((item: any) => ({
|
||||||
|
value: item.msisdn,
|
||||||
|
label: `${item.msisdn} - ${item.fullname}`
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('Failed to fetch customer msisdn');
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchWallets = async () => {
|
const fetchWallets = async () => {
|
||||||
try {
|
try {
|
||||||
@ -53,6 +93,18 @@ const TransactionDisbursement = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchWallets();
|
fetchWallets();
|
||||||
|
fetchCustomerMsisdn([{ id: 'msisdn', desc: false }], '');
|
||||||
|
|
||||||
|
const handleClickOutside = (event: any) => {
|
||||||
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||||
|
setDropdownOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const doPostData = async (form: typeof initialForm) => {
|
const doPostData = async (form: typeof initialForm) => {
|
||||||
@ -99,6 +151,22 @@ const TransactionDisbursement = () => {
|
|||||||
setShowConfirmation(false);
|
setShowConfirmation(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleMsisdnSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSearchTerm(e.target.value);
|
||||||
|
setDropdownOpen(true);
|
||||||
|
fetchCustomerMsisdn([{ id: 'msisdn', desc: false }], e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMsisdnSelect = (msisdn: string) => {
|
||||||
|
setForm({ ...form, msisdn });
|
||||||
|
setDropdownOpen(false);
|
||||||
|
setSearchTerm(msisdn);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredMsisdn = customerMsisdn
|
||||||
|
.filter((item) => item.label.toLowerCase().includes(searchTerm.toLowerCase()))
|
||||||
|
.slice(0, 10);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
@ -147,16 +215,40 @@ const TransactionDisbursement = () => {
|
|||||||
)}
|
)}
|
||||||
{/* form */}
|
{/* form */}
|
||||||
<form onSubmit={handleSubmit} className="space-y-6 mt-5">
|
<form onSubmit={handleSubmit} className="space-y-6 mt-5">
|
||||||
<div>
|
<div className="relative" ref={dropdownRef}>
|
||||||
<label htmlFor="msisdn">Destination MSISDN</label>
|
<label htmlFor="msisdn">MSISDN (Phone Number)</label>
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
<Input
|
<div className="relative">
|
||||||
id="msisdn"
|
<Input
|
||||||
type="number"
|
id="msisdn"
|
||||||
value={form.msisdn}
|
type="text"
|
||||||
onChange={(e) => setForm({ ...form, msisdn: e.target.value })}
|
value={searchTerm}
|
||||||
/>
|
onChange={handleMsisdnSearch}
|
||||||
|
placeholder="Search MSISDN"
|
||||||
|
onClick={() => setDropdownOpen(true)}
|
||||||
|
/>
|
||||||
|
{dropdownOpen && (
|
||||||
|
<div className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-60 overflow-y-auto">
|
||||||
|
{filteredMsisdn.length > 0 ? (
|
||||||
|
filteredMsisdn.map((item, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="px-4 py-2 hover:bg-gray-100 cursor-pointer"
|
||||||
|
onClick={() => handleMsisdnSelect(item.value)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="px-4 py-2 text-gray-500">
|
||||||
|
{isLoading ? 'Loading...' : 'No results found'}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="amount">Amount</label>
|
<label htmlFor="amount">Amount</label>
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user