add dropdown msisdn on disbursement module

- set limit 50, filter implemented
This commit is contained in:
Wikzyy
2025-04-24 14:19:43 +07:00
parent 908d963829
commit 943f1233fd

View File

@ -4,7 +4,7 @@ import { Breadcrumbs, Link } from '@mui/material';
import { Helmet } from 'react-helmet';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import { useCallApi } from '@/hooks';
import { apiConfig } from '@/config/api.config';
import { toast } from 'sonner';
@ -24,17 +24,57 @@ const TransactionDisbursement = () => {
const [form, setForm] = useState(initialForm);
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 [isSubmitting, setIsSubmitting] = useState(false);
const [showConfirmation, setShowConfirmation] = useState(false);
const parsedUser = getAuth()?.user;
const API_URL = apiConfig.transaction;
const API_URL_WALLET = apiConfig.service_wallet;
const API_URL_CUSTOMER = apiConfig.service_customer;
const dropdownRef = useRef<HTMLDivElement>(null);
const [alert, setAlert] = useState({
show: false,
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(() => {
const fetchWallets = async () => {
try {
@ -53,6 +93,18 @@ const TransactionDisbursement = () => {
};
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) => {
@ -99,6 +151,22 @@ const TransactionDisbursement = () => {
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 (
<>
<Helmet>
@ -147,16 +215,40 @@ const TransactionDisbursement = () => {
)}
{/* form */}
<form onSubmit={handleSubmit} className="space-y-6 mt-5">
<div>
<label htmlFor="msisdn">Destination MSISDN</label>
<div className="relative" ref={dropdownRef}>
<label htmlFor="msisdn">MSISDN (Phone Number)</label>
<span className="text-red-500">*</span>
<Input
id="msisdn"
type="number"
value={form.msisdn}
onChange={(e) => setForm({ ...form, msisdn: e.target.value })}
/>
<div className="relative">
<Input
id="msisdn"
type="text"
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>
<label htmlFor="amount">Amount</label>
<span className="text-red-500">*</span>