This commit is contained in:
Raja Oktafrianto
2025-04-25 16:15:11 +07:00
21 changed files with 580 additions and 162 deletions

425
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ export async function doSaveLogActivity(payload: SaveLogsParams): Promise<Action
throw new Error(response.data.message ?? 'Failed to save log'); throw new Error(response.data.message ?? 'Failed to save log');
} }
console.log('Success Create logs with params =>', dtParams); // console.log('Success Create logs with params =>', dtParams);
return { status: true, message: 'Success logs users' }; return { status: true, message: 'Success logs users' };
} catch (error: any) { } catch (error: any) {

View File

@ -1,14 +1,20 @@
import { toAbsoluteUrl } from '@/utils'; import { toAbsoluteUrl } from '@/utils';
import { Loader2 } from 'lucide-react';
const LoaderTransparant = () => { const LoaderTransparant = () => {
return ( return (
<div className="flex flex-col items-center gap-2 justify-center fixed inset-0 z-50 bg-white bg-opacity-20 transition-opacity duration-700 ease-in-out"> <div className="flex flex-col items-center gap-2 justify-center fixed inset-0 z-50 bg-white bg-opacity-20 transition-opacity duration-700 ease-in-out">
<img <img
className="h-[30px] max-w-none" // className="h-[30px] max-w-none"
className="h-14 w-auto drop-shadow-md"
src={toAbsoluteUrl('/media/app/app-logo.png')} src={toAbsoluteUrl('/media/app/app-logo.png')}
alt="logo" alt="logo"
/> />
<div className="text-gray-500 font-medium text-sm">Loading...</div> {/* <div className="text-gray-500 font-medium text-sm">Loading...</div> */}
<div className="flex items-center gap-3 text-base text-muted-foreground font-medium">
<Loader2 className="animate-spin h-6 w-6 text-primary" />
Loading...
</div>
</div> </div>
); );
}; };

View File

@ -1,14 +1,20 @@
import { toAbsoluteUrl } from '@/utils'; import { toAbsoluteUrl } from '@/utils';
import { Loader2 } from 'lucide-react';
const ScreenLoader = () => { const ScreenLoader = () => {
return ( return (
<div className="flex flex-col items-center gap-2 justify-center fixed inset-0 z-50 bg-light transition-opacity duration-700 ease-in-out"> <div className="flex flex-col items-center gap-2 justify-center fixed inset-0 z-50 bg-light transition-opacity duration-700 ease-in-out">
<img <img
className="h-[30px] max-w-none" // className="h-[30px] max-w-none"
className="h-14 w-auto drop-shadow-md"
src={toAbsoluteUrl('/media/app/app-logo.png')} src={toAbsoluteUrl('/media/app/app-logo.png')}
alt="logo" alt="logo"
/> />
<div className="text-gray-500 font-medium text-sm">Loading...</div> {/* <div className="text-gray-500 font-medium text-sm">Loading...</div> */}
<div className="flex items-center gap-3 text-base text-muted-foreground font-medium">
<Loader2 className="animate-spin h-6 w-6 text-primary" />
Loading...
</div>
</div> </div>
); );
}; };

View File

@ -252,14 +252,14 @@ const DashboardHomePage = () => {
<Card <Card
title="Registered Users" title="Registered Users"
total={responseStatisticCard?.data.total_registered ?? 0} total={responseStatisticCard?.data.total_registered ?? 0}
growth={responseStatisticCard?.data.registered_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.registered_last_week.percent ?? 0).toFixed(2)) ?? 0}
surplus={responseStatisticCard?.data.registered_last_week.surplus ?? false} surplus={responseStatisticCard?.data.registered_last_week.surplus ?? false}
icon="test" icon="test"
/> />
<Card <Card
title="Unregistered Users" title="Unregistered Users"
total={responseStatisticCard?.data.total_unregistered ?? 0} total={responseStatisticCard?.data.total_unregistered ?? 0}
growth={responseStatisticCard?.data.unregistered_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.unregistered_last_week.percent ?? 0).toFixed(2)) ?? 0}
surplus={responseStatisticCard?.data.unregistered_last_week.surplus ?? false} surplus={responseStatisticCard?.data.unregistered_last_week.surplus ?? false}
icon="test" icon="test"
@ -267,28 +267,28 @@ const DashboardHomePage = () => {
<Card <Card
title="Total Cash-in" title="Total Cash-in"
total={responseStatisticCard?.data.total_cash_in ?? 0} total={responseStatisticCard?.data.total_cash_in ?? 0}
growth={responseStatisticCard?.data.cash_in_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.cash_in_last_week.percent ?? 0).toFixed(2))?? 0}
surplus={responseStatisticCard?.data.cash_in_last_week.surplus ?? false} surplus={responseStatisticCard?.data.cash_in_last_week.surplus ?? false}
icon="test" icon="test"
/> />
<Card <Card
title="Total Cash-out" title="Total Cash-out"
total={responseStatisticCard?.data.total_cash_out ?? 0} total={responseStatisticCard?.data.total_cash_out ?? 0}
growth={responseStatisticCard?.data.cash_out_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.cash_out_last_week.percent ?? 0).toFixed(2)) ?? 0}
surplus={responseStatisticCard?.data.cash_out_last_week.surplus ?? false} surplus={responseStatisticCard?.data.cash_out_last_week.surplus ?? false}
icon="test" icon="test"
/> />
<Card <Card
title="Active Event" title="Active Event"
total={responseStatisticCard?.data.total_event ?? 0} total={responseStatisticCard?.data.total_event ?? 0}
growth={responseStatisticCard?.data.event_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.event_last_week.percent ?? 0).toFixed(2)) ?? 0}
surplus={responseStatisticCard?.data.event_last_week.surplus ?? false} surplus={responseStatisticCard?.data.event_last_week.surplus ?? false}
icon="test" icon="test"
/> />
<Card <Card
title="Total Billing" title="Total Billing"
total={responseStatisticCard?.data.total_billing ?? 0} total={responseStatisticCard?.data.total_billing ?? 0}
growth={responseStatisticCard?.data.billing_last_week.percent ?? 0} growth={parseFloat((responseStatisticCard?.data?.billing_last_week.percent ?? 0).toFixed(2)) ?? 0}
surplus={responseStatisticCard?.data.billing_last_week.surplus ?? false} surplus={responseStatisticCard?.data.billing_last_week.surplus ?? false}
icon='test' icon='test'
/> />

View File

@ -42,6 +42,7 @@ const TransactionPieChart = ({ startdate, enddate }: Props) => {
{ name: 'Topup', value: parseFloat((responseTransactionValue?.data?.U ?? 0).toFixed(2)), color: '#9f7aea' }, { name: 'Topup', value: parseFloat((responseTransactionValue?.data?.U ?? 0).toFixed(2)), color: '#9f7aea' },
{ name: 'Purchase', value: parseFloat((responseTransactionValue?.data?.P ?? 0).toFixed(2)), color: '#baf7c5' }, { name: 'Purchase', value: parseFloat((responseTransactionValue?.data?.P ?? 0).toFixed(2)), color: '#baf7c5' },
{ name: 'Withdraw', value: parseFloat((responseTransactionValue?.data?.W ?? 0).toFixed(2)), color: '#f56565' }, { name: 'Withdraw', value: parseFloat((responseTransactionValue?.data?.W ?? 0).toFixed(2)), color: '#f56565' },
{ name: 'Top Up Partner', value: parseFloat((responseTransactionValue?.data?.N ?? 0).toFixed(2)), color: '#f7fa52' },
]; ];
return ( return (

View File

@ -61,6 +61,9 @@ const TransactionValue = ({ startdate, enddate }: Props) => {
case "R": case "R":
type = "Return"; type = "Return";
break; break;
case "N":
type = "Top Up Partner";
break;
default: default:
type = "Unknown"; type = "Unknown";
break; break;

View File

@ -235,7 +235,7 @@ const ManageGroups = () => {
<DataGridProvider <DataGridProvider
data={dataGroup} data={dataGroup}
columns={getColumns(handleUpdate)} columns={getColumns(handleUpdate)}
pagination={{ size: 25 }} pagination={{ size: 10 }}
toolbar={ toolbar={
<ListToolBar <ListToolBar
createGroup={createGroup} createGroup={createGroup}

View File

@ -180,7 +180,7 @@ const ManageWalletContextProvider = ({ children }: { children: React.ReactNode }
<Toaster expand visibleToasts={9} duration={3000} /> <Toaster expand visibleToasts={9} duration={3000} />
<DataGridProvider <DataGridProvider
columns={columns} columns={columns}
pagination={{ size: 25 }} pagination={{ size: 10 }}
toolbar={<ListToolbar />} toolbar={<ListToolbar />}
layout={{ card: true }} layout={{ card: true }}
sorting={[{ id: 'wallets.created_at', desc: true }]} sorting={[{ id: 'wallets.created_at', desc: true }]}

View File

@ -97,7 +97,7 @@ const EditDialog = () => {
} }
const data = response.data; const data = response.data;
console.log('Fetched data:', data); // console.log('Fetched data:', data);
setReviewNotes(data.review_notes || ''); setReviewNotes(data.review_notes || '');

View File

@ -92,7 +92,7 @@ const ManageFeedbackMemberProvider = ({ children }: { children: React.ReactNode
const columns = useMemo<ColumnDef<any>[]>( const columns = useMemo<ColumnDef<any>[]>(
() => [ () => [
{ {
accessorFn: (row) => row.customerid, accessorFn: (row) => row.fullname,
id: 'customer_id', id: 'customer_id',
header: ({ column }) => <DataGridColumnHeader title="Customer Name" column={column} />, header: ({ column }) => <DataGridColumnHeader title="Customer Name" column={column} />,
enableSorting: false, enableSorting: false,

View File

@ -22,7 +22,7 @@ const ManageKycDeletion = () => {
</Link> </Link>
<Link underline="none" color="inherit"> <Link underline="none" color="inherit">
<span className="text-sm">History Disbursement</span> <span className="text-sm">Manage KYC Deletion</span>
</Link> </Link>
</Breadcrumbs> </Breadcrumbs>
<div className="grid gap-5 lg:gap-7.5"> <div className="grid gap-5 lg:gap-7.5">

View File

@ -5,8 +5,6 @@ import {
TDataGridProps, TDataGridProps,
useDataGrid useDataGrid
} from '@/components'; } from '@/components';
import { DataTable } from '@/components/ui/DataTable';
import { Table } from '@tanstack/react-table';
import React, { createContext, useContext, useState, useEffect } from 'react'; import React, { createContext, useContext, useState, useEffect } from 'react';
import { getColumns, initialMember } from './Columns'; import { getColumns, initialMember } from './Columns';
import { useAuthContext } from '@/auth'; import { useAuthContext } from '@/auth';
@ -15,14 +13,13 @@ import { apiConfig } from '@/config/api.config';
import ConfirmDialog from '@/components/confirm'; import ConfirmDialog from '@/components/confirm';
import axios from 'axios'; import axios from 'axios';
import { toast } from 'sonner'; import { toast } from 'sonner';
const BASE_URL = apiConfig.service_customer;
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
// import CustomerDialog from '../manage-members/CustomerDetailModal';
import DetailMember from '../manage-members/blocks/DetailMember'; import DetailMember from '../manage-members/blocks/DetailMember';
import { Breadcrumbs, Link } from '@mui/material'; import { Breadcrumbs, Link } from '@mui/material';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { ListToolBar } from './blocks/ListToolBar'; import { ListToolBar } from './blocks/ListToolBar';
import { RefreshCw } from 'lucide-react'; import { RefreshCw } from 'lucide-react';
const BASE_URL = apiConfig.service_customer;
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
const Kyc = () => { const Kyc = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -33,12 +30,15 @@ const Kyc = () => {
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
const [dialogType, setDialogType] = useState(''); const [dialogType, setDialogType] = useState('');
const [isReloading, setIsReloading] = useState(false); const [isReloading, setIsReloading] = useState(false);
const closeDialog = () => setIsDialogOpen(false); const closeDialog = () => {
setIsDialogOpen(false);
setMember(initialMember);
};
const { getUser } = useAuthContext(); const { getUser } = useAuthContext();
useEffect(() => { useEffect(() => {
fetchCustomers(); fetchCustomers();
}, []); }, [member]);
async function fetchCustomers() { async function fetchCustomers() {
try { try {
@ -95,10 +95,6 @@ const Kyc = () => {
setDialogOpen(true); setDialogOpen(true);
} }
const resetForm = () => {
setMember(initialMember);
};
const handleReload = () => { const handleReload = () => {
setIsReloading(true); setIsReloading(true);
fetchCustomers(); fetchCustomers();
@ -192,14 +188,6 @@ const Kyc = () => {
setIsDialogOpen(el); setIsDialogOpen(el);
} }
// const resetForm = () => {
// setMember(initialMember);
// };
// useEffect(() => {
// if (!isDialogOpen) resetForm();
// }, [isDialogOpen]);
if (loading) return <LoaderTransparant />; if (loading) return <LoaderTransparant />;
return ( return (
@ -258,11 +246,11 @@ const Kyc = () => {
)} )}
<DataGridProvider <DataGridProvider
data={members} data={members}
pagination={{ size: 10 }}
columns={getColumns(handleUpdate)} columns={getColumns(handleUpdate)}
pagination={{ size: 25 }}
toolbar={<ListToolBar onReload={handleReload} isReloading={isReloading} />}
layout={{ card: true }} layout={{ card: true }}
sorting={[{ id: 'created_at', desc: true }]} sorting={[{ id: 'created_at', desc: true }]}
toolbar={<ListToolBar onReload={handleReload} isReloading={isReloading} />}
serverSide={false} serverSide={false}
onRowSelectionChange={(selected, table: any) => { onRowSelectionChange={(selected, table: any) => {
const selectedRow = table.getSelectedRowModel().rows[0]; const selectedRow = table.getSelectedRowModel().rows[0];

View File

@ -10,12 +10,12 @@ import { Container, DataGridInner, LoaderTransparant } from '@/components';
import { DataGridProvider } from '@/components'; import { DataGridProvider } from '@/components';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { Breadcrumbs, Link } from '@mui/material'; import { Breadcrumbs, Link } from '@mui/material';
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
const BASE_URL_CUSTOMER = apiConfig.service_customer;
const BASE_URL = apiConfig.service_customer;
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import ListToolbar from './blocks/ListToolBar'; import ListToolbar from './blocks/ListToolBar';
import { RefreshCw } from 'lucide-react'; import { RefreshCw } from 'lucide-react';
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
const BASE_URL_CUSTOMER = apiConfig.service_customer;
const BASE_URL = apiConfig.service_customer;
const ManageMembers = () => { const ManageMembers = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -113,6 +113,7 @@ const ManageMembers = () => {
setIsReloading(true); setIsReloading(true);
fetchCustomers(); fetchCustomers();
}; };
const handleYes = async () => { const handleYes = async () => {
try { try {
setLoading(true); setLoading(true);
@ -191,7 +192,9 @@ const ManageMembers = () => {
toast.success('Success Create Member. PIN sent to email'); toast.success('Success Create Member. PIN sent to email');
} }
} catch (error: any) { } catch (error: any) {
if (error?.response?.data?.message) toast.error(error?.response?.data?.message); if (error?.response?.data?.message) {
toast.error(`${error?.response?.data?.error}.\n${error?.response?.data?.message}`)
}
else toast.error(error.message); else toast.error(error.message);
} finally { } finally {
setDialogOpen(false); setDialogOpen(false);
@ -263,7 +266,7 @@ const ManageMembers = () => {
)} )}
<DataGridProvider <DataGridProvider
data={members} data={members}
pagination={{ size: 25 }} pagination={{ size: 10 }}
columns={getColumns(handleUpdate)} columns={getColumns(handleUpdate)}
layout={{ card: true }} layout={{ card: true }}
serverSide={false} serverSide={false}

View File

@ -1,7 +1,5 @@
import { apiConfig } from '@/config/api.config'; import { apiConfig } from '@/config/api.config';
import { Alert, useDataGrid } from '@/components'; import { Alert, useDataGrid } from '@/components';
import { useCallApi } from '@/hooks';
import { getAuth } from '@/auth';
import axios from 'axios'; import axios from 'axios';
import React, { useCallback, useEffect, useRef, useState } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -22,12 +20,12 @@ import {
} from '@/components/ui/select'; } from '@/components/ui/select';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
const URL_NATIONALITY = apiConfig.nationality;
const BASE_URL_CUSTOMER = apiConfig.service_customer;
import { initialMember } from "../Columns"; import { initialMember } from "../Columns";
import AdmAccess from './AdmAccess'; import AdmAccess from './AdmAccess';
import CustomerWallet from './CustomerWallet'; import CustomerWallet from './CustomerWallet';
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
const URL_NATIONALITY = apiConfig.nationality;
const BASE_URL_CUSTOMER = apiConfig.service_customer;
const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialData, handleReject, page, fetchCustomers, const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialData, handleReject, page, fetchCustomers,
handleClose, profession, dialogType handleClose, profession, dialogType
@ -268,8 +266,8 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
{(formData.id&&(!page||formData.destinationGroup === "Premium")) ? generateInput(formData, handleChange, 'Approval Premium Description', 'approval_description_premium', 'text', false, viewOnly): ''} {(formData.id&&(page==='kyc'&&formData.destinationGroup === "Premium")) ? generateInput(formData, handleChange, 'Approval Premium Description', 'approval_description_premium', 'text', false, viewOnly): ''}
{(formData.id&&(!page||formData.destinationGroup === "Agent")) ? generateInput(formData, handleChange, 'Approval Agent Description', 'approval_description_agent', 'text', false, viewOnly): ''} {(formData.id&&(page==='kyc'&&formData.destinationGroup === "Agent")) ? generateInput(formData, handleChange, 'Approval Agent Description', 'approval_description_agent', 'text', false, viewOnly): ''}
{(formData.id && page!=='kyc') ? ( {(formData.id && page!=='kyc') ? (
<AdmAccess page={page}groups={groups}formData={formData}fetchCustomers={fetchCustomers}handleClose={handleClose}viewOnly={viewOnly}setViewOnly={setViewOnly}/> <AdmAccess page={page}groups={groups}formData={formData}fetchCustomers={fetchCustomers}handleClose={handleClose}viewOnly={viewOnly}setViewOnly={setViewOnly}/>

View File

@ -292,7 +292,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode })
<DataGridProvider <DataGridProvider
columns={columns} columns={columns}
pagination={{ size: 25 }} pagination={{ size: 10 }}
toolbar={<ListToolbar />} toolbar={<ListToolbar />}
layout={{ card: true }} layout={{ card: true }}
sorting={[{ id: 'created_at', desc: true }]} sorting={[{ id: 'created_at', desc: true }]}

View File

@ -144,6 +144,7 @@ const ListToolbar = () => {
<SelectItem value="W">WITHDRAW</SelectItem> <SelectItem value="W">WITHDRAW</SelectItem>
<SelectItem value="U">TOP UP</SelectItem> <SelectItem value="U">TOP UP</SelectItem>
<SelectItem value="R">RETURN</SelectItem> <SelectItem value="R">RETURN</SelectItem>
<SelectItem value='N'>TOP UP PARTNER</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>

View File

@ -70,6 +70,7 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
case 'W': return 'WITHDRAW'; case 'W': return 'WITHDRAW';
case 'U': return 'TOP UP'; case 'U': return 'TOP UP';
case 'R': return 'RETURN'; case 'R': return 'RETURN';
case 'N': return 'TOP UP PARTNER';
default: return '_'; default: return '_';
} }
}, },

View File

@ -25,7 +25,14 @@ import { useCallApi } from '@/hooks';
import { doSaveLogActivity } from '@/actions/GlobalActions'; import { doSaveLogActivity } from '@/actions/GlobalActions';
import { getAuth } from '@/auth'; import { getAuth } from '@/auth';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command'; import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList
} from '@/components/ui/command';
const API_URL = apiConfig.service_transaction; const API_URL = apiConfig.service_transaction;
const API_URL_MASTER_DATA = apiConfig.service_master_data; const API_URL_MASTER_DATA = apiConfig.service_master_data;
@ -178,9 +185,9 @@ const EditFeeDialog = () => {
); );
if (response?.status) { if (response?.status) {
toast.success('Successfully updated transfer fee');
reload(); reload();
handleEditFeeDialog(false, null); handleEditFeeDialog(false, null);
toast.success('Successfully updated transfer fee');
const createActivity = { const createActivity = {
module: 'Manage Transfer Fee', module: 'Manage Transfer Fee',
description: `Edit Transfer Fee => ${formField.name}`, description: `Edit Transfer Fee => ${formField.name}`,
@ -197,7 +204,7 @@ const EditFeeDialog = () => {
setIsSubmitting(false); setIsSubmitting(false);
} }
}, },
[formField, selectedTransferFee, PutData, reload, handleEditFeeDialog] [formField, selectedTransferFee, handleEditFeeDialog]
); );
const fetchWallets = useCallback(async () => { const fetchWallets = useCallback(async () => {
@ -674,71 +681,78 @@ const EditFeeDialog = () => {
</div> </div>
{formField.credit_to === 'I' && ( {formField.credit_to === 'I' && (
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">
Credit Destination <span className="text-red-500">*</span> Credit Destination <span className="text-red-500">*</span>
</label> </label>
<div className="relative"> <div className="relative">
<div <div
className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer" className="flex w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 cursor-pointer"
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
> >
<span className="truncate"> <span className="truncate">
{customers.find(customer => customer.id === formField.credit_destination)?.username || 'Search customer...'} {customers.find(
</span> (customer) => customer.id === formField.credit_destination
<path d="m6 9 6 6 6-6"></path> )?.username || 'Search customer...'}
</div> </span>
<path d="m6 9 6 6 6-6"></path>
{open && ( </div>
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(customer =>
customer.username.toLowerCase().includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map(customer => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({
...formField,
credit_destination: customer.id
});
setOpen(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(customer =>
customer.username.toLowerCase().includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">No customer found</div>
)}
</div>
</div>
)}
</div>
</div>
)}
{open && (
<div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-52 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg">
<div className="sticky top-0 bg-white p-2 border-b">
<Input
className="h-8 text-sm"
type="text"
placeholder="Search customer..."
value={customerSearchTerm}
onChange={(e) => setCustomerSearchTerm(e.target.value)}
autoComplete="off"
onClick={(e) => e.stopPropagation()}
autoFocus
/>
</div>
<div>
{customers
.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
)
.map((customer) => (
<div
key={customer.id}
className="cursor-pointer px-3 py-1.5 text-sm hover:bg-gray-100"
onClick={() => {
setFormField({
...formField,
credit_destination: customer.id
});
setOpen(false);
}}
>
{customer.username}
</div>
))}
{customers.filter(
(customer) =>
customer.username
.toLowerCase()
.includes(customerSearchTerm.toLowerCase()) ||
customer.msisdn.includes(customerSearchTerm)
).length === 0 && (
<div className="px-3 py-2 text-sm text-gray-500">
No customer found
</div>
)}
</div>
</div>
)}
</div>
</div>
)}
<div className="w-full"> <div className="w-full">
<label className="form-label"> <label className="form-label">
@ -777,7 +791,9 @@ const EditFeeDialog = () => {
</label> </label>
<Select <Select
value={formField.status_include} value={formField.status_include}
onValueChange={(value) => setFormField({ ...formField, status_include: value })} onValueChange={(value) =>
setFormField({ ...formField, status_include: value })
}
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select Status" /> <SelectValue placeholder="Select Status" />
@ -808,11 +824,7 @@ const EditFeeDialog = () => {
</div> </div>
<div className="flex justify-end pt-2.5 gap-5"> <div className="flex justify-end pt-2.5 gap-5">
<Button <Button variant={'outline'} type="button" onClick={resetForm}>
variant={'outline'}
type="button"
onClick={resetForm}
>
Reset Reset
</Button> </Button>
<Button <Button
@ -839,4 +851,4 @@ const EditFeeDialog = () => {
); );
}; };
export {EditFeeDialog}; export { EditFeeDialog };

View File

@ -378,7 +378,7 @@ const ManageTransferFeeContextProvider = ({
transactionTypeId transactionTypeId
}} }}
> >
<Toaster expand visibleToasts={9} duration={3000} /> {/* <Toaster expand visibleToasts={9} duration={3000} /> */}
<DataGridProvider <DataGridProvider
columns={columns} columns={columns}
pagination={{ size: 10 }} pagination={{ size: 10 }}