Merge branch 'master' of https://git.shiblysolution.id/TPAY/dashboard
This commit is contained in:
@ -1,8 +1,13 @@
|
||||
import { Container, DataGridInner, DataGridProvider, TDataGridProps } from '@/components';
|
||||
import {
|
||||
Container,
|
||||
DataGridInner,
|
||||
DataGridProvider,
|
||||
TDataGridProps,
|
||||
useDataGrid
|
||||
} from '@/components';
|
||||
import { DataTable } from '@/components/ui/DataTable';
|
||||
import { Table } from '@tanstack/react-table';
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
import { ManageKycContextProvider } from './hooks';
|
||||
import { getColumns, initialMember } from './Columns';
|
||||
import { useAuthContext } from '@/auth';
|
||||
import { LoaderTransparant } from '@/components';
|
||||
@ -17,6 +22,7 @@ import DetailMember from '../manage-members/blocks/DetailMember';
|
||||
import { Breadcrumbs, Link } from '@mui/material';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ListToolBar } from './blocks/ListToolBar';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
|
||||
const Kyc = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -26,6 +32,7 @@ const Kyc = () => {
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [dialogType, setDialogType] = useState('');
|
||||
const [isReloading, setIsReloading] = useState(false);
|
||||
const closeDialog = () => setIsDialogOpen(false);
|
||||
const { getUser } = useAuthContext();
|
||||
|
||||
@ -65,6 +72,9 @@ const Kyc = () => {
|
||||
} catch (error: any) {
|
||||
toast.error(error.message);
|
||||
console.log(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setIsReloading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,12 +99,16 @@ const Kyc = () => {
|
||||
setMember(initialMember);
|
||||
};
|
||||
|
||||
const handleReload = () => {
|
||||
setIsReloading(true);
|
||||
fetchCustomers();
|
||||
};
|
||||
|
||||
const handleYes = async () => {
|
||||
setLoading(true);
|
||||
const userLogin: any = await getUser();
|
||||
const updateData: any = member;
|
||||
const customerId = member.id;
|
||||
const description = member.description;
|
||||
const destinationGroup = updateData.destinationGroup;
|
||||
updateData.updated_by = userLogin.data ? userLogin.data.id : '';
|
||||
let today = new Date();
|
||||
@ -161,17 +175,16 @@ const Kyc = () => {
|
||||
description: updateData.approval_description_agent
|
||||
});
|
||||
}
|
||||
setDialogOpen(false);
|
||||
setIsDialogOpen(false);
|
||||
toast.success(`Success Update & ${dialogType} Kyc Member`);
|
||||
} catch (error: any) {
|
||||
if (error?.response?.data?.error) error.message = error?.response?.data?.error;
|
||||
setDialogOpen(false);
|
||||
setIsDialogOpen(false);
|
||||
toast.error(error.message);
|
||||
} finally {
|
||||
setDialogOpen(false);
|
||||
setIsDialogOpen(false);
|
||||
await fetchCustomers();
|
||||
setLoading(false);
|
||||
setIsReloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -179,11 +192,15 @@ const Kyc = () => {
|
||||
setIsDialogOpen(el);
|
||||
}
|
||||
|
||||
if (loading) return <LoaderTransparant />;
|
||||
// const resetForm = () => {
|
||||
// setMember(initialMember);
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDialogOpen) resetForm();
|
||||
}, [isDialogOpen]);
|
||||
// useEffect(() => {
|
||||
// if (!isDialogOpen) resetForm();
|
||||
// }, [isDialogOpen]);
|
||||
|
||||
if (loading) return <LoaderTransparant />;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -200,14 +217,6 @@ const Kyc = () => {
|
||||
onNo={() => setDialogOpen(false)}
|
||||
/>
|
||||
{member.id ? (
|
||||
// <CustomerDialog
|
||||
// open={isDialogOpen}
|
||||
// handleClose={closeDialog}
|
||||
// handleSubmit={handleSubmit}
|
||||
// initialData={member}
|
||||
// viewStats={true}
|
||||
// page={'kyc'}
|
||||
// />
|
||||
<DetailMember
|
||||
showAddDialog={isDialogOpen}
|
||||
setShowAddDialog={setShowAddDialog}
|
||||
@ -217,6 +226,7 @@ const Kyc = () => {
|
||||
initialData={member}
|
||||
fetchCustomers={fetchCustomers}
|
||||
profession={profession}
|
||||
dialogType={dialogType}
|
||||
page={'kyc'}
|
||||
/>
|
||||
) : (
|
||||
@ -237,12 +247,20 @@ const Kyc = () => {
|
||||
</Link>
|
||||
</Breadcrumbs>
|
||||
{/* <div className="w-full overflow-x-auto"> */}
|
||||
<div className="grid gap-5 lg:gap-7.5 mt-5">
|
||||
<div className="grid gap-5 lg:gap-7.5 mt-5 relative">
|
||||
{isReloading && (
|
||||
<div className="absolute inset-0 bg-white/70 z-10 flex items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<RefreshCw className="animate-spin h-8 w-8 text-slate-500 mb-2" />
|
||||
<span className="text-slate-500 font-medium">Refreshing data...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<DataGridProvider
|
||||
data={members}
|
||||
columns={getColumns(handleUpdate)}
|
||||
pagination={{ size: 25 }}
|
||||
toolbar={<ListToolBar />}
|
||||
toolbar={<ListToolBar onReload={handleReload} isReloading={isReloading} />}
|
||||
layout={{ card: true }}
|
||||
sorting={[{ id: 'created_at', desc: true }]}
|
||||
serverSide={false}
|
||||
|
||||
@ -1,40 +1,44 @@
|
||||
import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useKycContext } from '../hooks';
|
||||
import { useState } from 'react';
|
||||
|
||||
const ListToolBar = () => {
|
||||
interface ListToolbarProps {
|
||||
onReload: () => void;
|
||||
isReloading: boolean;
|
||||
}
|
||||
|
||||
const ListToolBar = ({ onReload, isReloading }: ListToolbarProps) => {
|
||||
const { table, reload } = useDataGrid();
|
||||
const [usernameFilter, setUsernameFilter] = useState('');
|
||||
|
||||
const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setUsernameFilter(e.target.value);
|
||||
table.getColumn('username')?.setFilterValue(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card-header flex-wrap gap-2 border-b-0 px-5">
|
||||
<div className="flex flex-wrap gap-2 lg:gap-5 w-full">
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex w-[50%] gap-3 items-center">
|
||||
<label className="input input-sm w-1/3">
|
||||
<KeenIcon icon="magnifier" />
|
||||
<div className="flex gap-3 items-center">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search users"
|
||||
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
|
||||
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
|
||||
placeholder="Search Username"
|
||||
value={usernameFilter}
|
||||
onChange={handleUsernameChange}
|
||||
className="input input-sm w-40"
|
||||
/>
|
||||
</label>
|
||||
<DefaultTooltip title={'Filter'} placement={'top'}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="h-7.5 disabled:bg-gray-400"
|
||||
// disabled={isLoading}
|
||||
// onClick={handleFilterData}
|
||||
>
|
||||
{/* {loadingButton === 'filter' ? <ContentLoader /> : <KeenIcon icon="filter" />} */}
|
||||
<KeenIcon icon="filter" />
|
||||
</Button>
|
||||
</DefaultTooltip>
|
||||
</div>
|
||||
<div className="flex gap-3 items-center">
|
||||
<DefaultTooltip title={'Refresh'} placement={'top'}>
|
||||
<Button variant="outline" className="h-7.5" onClick={() => reload()}>
|
||||
<DefaultTooltip title={isReloading ? 'Refreshing...' : 'Refresh'} placement={'top'}>
|
||||
<Button variant="outline" className="h-7.5" onClick={onReload} disabled={isReloading}>
|
||||
{isReloading ? (
|
||||
<div className="animate-spin">
|
||||
<KeenIcon icon="arrows-circle" />
|
||||
</div>
|
||||
) : (
|
||||
<KeenIcon icon="arrows-circle" />
|
||||
)}
|
||||
</Button>
|
||||
</DefaultTooltip>
|
||||
</div>
|
||||
|
||||
@ -1,145 +0,0 @@
|
||||
import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import { apiConfig } from '@/config/api.config';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import { createContext, useCallback, useMemo, useState } from 'react';
|
||||
import { ListToolBar } from '../blocks/ListToolBar';
|
||||
|
||||
interface SelectedUser {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
role: string;
|
||||
description: string;
|
||||
created_date: Date;
|
||||
}
|
||||
|
||||
interface ContextProps {
|
||||
showDetailDialog: boolean;
|
||||
handleDetailDialog: (show: boolean, selected_user: SelectedUser | null) => void;
|
||||
showAddDialog: boolean;
|
||||
handleAddDialog: (show: boolean) => void;
|
||||
selectedUser: SelectedUser | null;
|
||||
}
|
||||
|
||||
const initialProps: ContextProps = {
|
||||
showDetailDialog: false,
|
||||
handleDetailDialog: () => {},
|
||||
showAddDialog: false,
|
||||
handleAddDialog: () => {},
|
||||
selectedUser: null
|
||||
};
|
||||
|
||||
const ManageKycContext = createContext<ContextProps>(initialProps);
|
||||
const API_URL = apiConfig.service_dashboard;
|
||||
|
||||
const ManageKycContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const [showDetailDialog, setShowDetailDialog] = useState(false);
|
||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||
const [selectedUser, setSelectedUser] = useState<SelectedUser | null>(null);
|
||||
|
||||
const handleDetailDialog = useCallback((show: boolean, selected_user: SelectedUser | null) => {
|
||||
setSelectedUser(show ? selected_user : null);
|
||||
setShowDetailDialog(show);
|
||||
}, []);
|
||||
|
||||
const handleAddDialog = useCallback((show: boolean) => {
|
||||
setShowAddDialog(show);
|
||||
}, []);
|
||||
|
||||
const columns = useMemo<ColumnDef<any>[]>(
|
||||
() => [
|
||||
{
|
||||
accessorFn: (row) => row.id,
|
||||
id: 'id',
|
||||
header: ({ column }) => <DataGridColumnHeader title="ID" column={column} />,
|
||||
enableSorting: true,
|
||||
enableHiding: false,
|
||||
meta: {
|
||||
headerClassName: 'w-[100px]'
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.created_date,
|
||||
id: 'created_date',
|
||||
header: ({ column }) => <DataGridColumnHeader title="Created Date" column={column} />,
|
||||
enableSorting: true,
|
||||
enableHiding: false,
|
||||
meta: {
|
||||
headerClassName: 'w-[250px]'
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.name,
|
||||
id: 'name',
|
||||
header: ({ column }) => <DataGridColumnHeader title="Name" column={column} />,
|
||||
enableSorting: true,
|
||||
enableHiding: false,
|
||||
meta: {
|
||||
headerClassName: 'w-[350px]'
|
||||
}
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.description,
|
||||
id: 'description',
|
||||
header: ({ column }) => <DataGridColumnHeader title="Description" column={column} />,
|
||||
enableSorting: true,
|
||||
meta: {
|
||||
headerClassName: 'w-[350px]'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
enableSorting: false,
|
||||
header: ({ column }) => <DataGridColumnHeader title="Action" column={column} />,
|
||||
cell: (data: any) => {
|
||||
const row = data.row.original;
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||
onClick={() => handleDetailDialog(true, row.id)}
|
||||
>
|
||||
<KeenIcon icon="notepad-edit" />
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
},
|
||||
meta: {
|
||||
headerClassName: 'w-[100px]',
|
||||
cellClassName: 'text-center'
|
||||
}
|
||||
}
|
||||
],
|
||||
[handleDetailDialog]
|
||||
);
|
||||
|
||||
return (
|
||||
<ManageKycContext.Provider
|
||||
value={{
|
||||
showDetailDialog,
|
||||
handleDetailDialog,
|
||||
showAddDialog,
|
||||
handleAddDialog,
|
||||
selectedUser
|
||||
}}
|
||||
>
|
||||
<Toaster expand visibleToasts={9} duration={3000} />
|
||||
|
||||
<DataGridProvider
|
||||
columns={columns}
|
||||
pagination={{ size: 10 }}
|
||||
toolbar={<ListToolBar />}
|
||||
layout={{ card: true }}
|
||||
sorting={[{ id: 'name', desc: false }]}
|
||||
serverSide={true}
|
||||
>
|
||||
{children}
|
||||
</DataGridProvider>
|
||||
</ManageKycContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export { ManageKycContextProvider, ManageKycContext };
|
||||
export type { SelectedUser };
|
||||
@ -1,2 +0,0 @@
|
||||
export * from './ManageKycContext';
|
||||
export * from './useKycContext';
|
||||
@ -1,12 +0,0 @@
|
||||
import { useContext } from 'react';
|
||||
import { ManageKycContext } from './ManageKycContext';
|
||||
|
||||
const useKycContext = () => {
|
||||
const context = useContext(ManageKycContext);
|
||||
|
||||
if (!context) throw new Error('useKycContext must be used within AuthProvider');
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
export { useKycContext };
|
||||
@ -3,7 +3,6 @@ import { apiConfig } from '@/config/api.config';
|
||||
import { getColumns, Members, initialMember } from './Columns';
|
||||
import { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
// import CustomerDialog from './CustomerDetailModal';
|
||||
import DetailMember from './blocks/DetailMember';
|
||||
import ConfirmDialog from '@/components/confirm';
|
||||
import { useAuthContext } from '@/auth';
|
||||
@ -15,6 +14,7 @@ const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
|
||||
const BASE_URL = apiConfig.service_customer;
|
||||
import { Helmet } from 'react-helmet';
|
||||
import ListToolbar from './blocks/ListToolBar';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
const ManageMembers = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [members, setMembers] = useState([]);
|
||||
@ -24,6 +24,7 @@ const ManageMembers = () => {
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [dialogType, setDialogType] = useState('');
|
||||
const [isReloading, setIsReloading] = useState(false);
|
||||
const closeDialog = () => {
|
||||
setIsDialogOpen(false);
|
||||
setMember(initialMember);
|
||||
@ -36,7 +37,7 @@ const ManageMembers = () => {
|
||||
setLoading(false);
|
||||
}, []);
|
||||
|
||||
async function fetchCustomers() {
|
||||
async function fetchCustomers(): Promise<void> {
|
||||
try {
|
||||
let customers = await axios.get(`${BASE_URL}/customer/list`, {
|
||||
params: {
|
||||
@ -71,6 +72,9 @@ const ManageMembers = () => {
|
||||
} catch (error: any) {
|
||||
toast.error(error.message);
|
||||
console.log(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setIsReloading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,8 +96,12 @@ const ManageMembers = () => {
|
||||
setMember(data);
|
||||
setDialogOpen(true);
|
||||
}
|
||||
|
||||
const handleReload = () => {
|
||||
setIsReloading(true);
|
||||
fetchCustomers();
|
||||
};
|
||||
const handleYes = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const userLogin: any = await getUser();
|
||||
const updateData: any = member;
|
||||
@ -132,14 +140,13 @@ const ManageMembers = () => {
|
||||
delete updateData.group_deleted_by;
|
||||
delete updateData.group_deleted_at;
|
||||
delete updateData.updated_at;
|
||||
try {
|
||||
const form = new FormData();
|
||||
const formUpdate = new FormData();
|
||||
for (const property in updateData) {
|
||||
if (updateData[property]) form.append(property, updateData[property]);
|
||||
if (updateData[property]) formUpdate.append(property, updateData[property]);
|
||||
}
|
||||
|
||||
if (dialogType === 'update') {
|
||||
await axios.put(`${BASE_URL}/customer/update/${selectedMember}`, form, {
|
||||
await axios.put(`${BASE_URL}/customer/update/${selectedMember}`, formUpdate, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
@ -164,11 +171,16 @@ const ManageMembers = () => {
|
||||
delete createMember.approval_description_premium;
|
||||
delete createMember.approval_description_agent;
|
||||
delete createMember.language;
|
||||
await axios.post(`${BASE_URL}/customers/create`, member);
|
||||
const formCreate = new FormData();
|
||||
for (const property in createMember) {
|
||||
if (createMember[property]) formCreate.append(property, createMember[property]);
|
||||
}
|
||||
await axios.post(`${BASE_URL}/customers/create`, formCreate);
|
||||
toast.success('Success Create Member. PIN sent to email');
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error(error.message);
|
||||
if (error?.response?.data?.message) toast.error(error?.response?.data?.message)
|
||||
else toast.error(error.message);
|
||||
} finally {
|
||||
setDialogOpen(false);
|
||||
closeDialog();
|
||||
@ -225,14 +237,29 @@ const ManageMembers = () => {
|
||||
</Link>
|
||||
</Breadcrumbs>
|
||||
{/* <div className="w-full overflow-x-auto px-4"> */}
|
||||
<div className="grid gap-5 lg:gap-7.5 mt-5">
|
||||
|
||||
<div className="grid gap-5 lg:gap-7.5 mt-5 relative">
|
||||
{isReloading && (
|
||||
<div className="absolute inset-0 bg-white/70 z-10 flex items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<RefreshCw className="animate-spin h-8 w-8 text-slate-500 mb-2" />
|
||||
<span className="text-slate-500 font-medium">Refreshing data...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<DataGridProvider
|
||||
data={members}
|
||||
pagination={{ size: 25 }}
|
||||
columns={getColumns(handleUpdate)}
|
||||
layout={{ card: true }}
|
||||
serverSide={false}
|
||||
toolbar={<ListToolbar createMember={createMember} />}
|
||||
toolbar={
|
||||
<ListToolbar
|
||||
createMember={createMember}
|
||||
onReload={handleReload}
|
||||
isReloading={isReloading}
|
||||
/>
|
||||
}
|
||||
onRowSelectionChange={(selected, table: any) => {
|
||||
const selectedRow = table.getSelectedRowModel().rows[0];
|
||||
if (selectedRow) handleUpdate(selectedRow.original);
|
||||
|
||||
@ -26,29 +26,10 @@ export default function AdmAccess({page,groups,formData,handleClose,fetchCustome
|
||||
const [dialogType, setDialogType] = useState('');
|
||||
const [changeGroup, setChangeGroup] = useState('');
|
||||
const [changeGroupD, setChangeGroupD] = useState(false);
|
||||
// const [groups, setGroups] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// fetchGroups();
|
||||
}, []);
|
||||
|
||||
// const fetchGroups = async () => {
|
||||
// try {
|
||||
// let getGroups = await axios.get(`${BASE_URL_CUSTOMER}/groups/list`, {
|
||||
// params: {
|
||||
// limit: 50,
|
||||
// page: 1,
|
||||
// with_deleted: false,
|
||||
// order_field: 'name',
|
||||
// order_direction: 'ASC'
|
||||
// }
|
||||
// });
|
||||
// setGroups(getGroups.data.data.list);
|
||||
// } catch (error: any) {
|
||||
// toast.error(error.message);
|
||||
// }
|
||||
// };
|
||||
|
||||
const handleYes = async () => {
|
||||
try {
|
||||
if (dialogType === 'update status') {
|
||||
|
||||
@ -41,6 +41,10 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
|
||||
const [sucos, setSucos] = useState<any>([]);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [genders] = useState([ { name: 'Male',id: 'M' }, { name: 'Female',id: 'F' }])
|
||||
const [previewImg, setPreviewImg] = useState({
|
||||
status: false,
|
||||
img: ''
|
||||
});
|
||||
const [banks] = useState([
|
||||
{ name: 'BNCTL',id: 'BNCTL' }, { name: 'BRI',id: 'BRI' }, { name: 'BNU',id: 'BNU' }, { name: 'Mandiri',id: 'Mandiri' }
|
||||
])
|
||||
@ -183,7 +187,7 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
|
||||
|
||||
return (
|
||||
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
||||
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5">
|
||||
<DialogContent className="container-fixed max-w-[85%] flex flex-col p-2">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Member - {dialogType ==='create' ? "Create" : "View/Edit"}</DialogTitle>
|
||||
<DialogDescription></DialogDescription>
|
||||
@ -196,18 +200,22 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<div className="card-body grid gap-5">
|
||||
{/* <div className="card-body grid gap-5"> */}
|
||||
<div className="card-body grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, groups, 'group_id', 'Group', true, dialogType === "update"||false): ''}
|
||||
{/* {(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Group', 'group_name', 'text', true, true): ''} */}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Username', 'username', 'text', true, dialogType==='create'?false:true): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Full Name', 'fullname', 'text', true, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'Photo', 'photouser'): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'Photo', 'photouser', previewImg, setPreviewImg): ''}
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, genders, 'gender', 'Gender', true, false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Date of Birth', 'date_birth', 'date', true, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Phone Number', 'msisdn', 'text', true, dialogType === "update"||false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Email', 'email', 'text', true, viewOnly): ''}
|
||||
{/* {generateList(formData, handleChange, status, 'status', 'Status', null, true)} */}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Mother Fullname', 'mother_fullname', 'text', true, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Identity Number', 'identity_number', 'text', false, viewOnly): ''}
|
||||
<div className="bg-white space-y-6">
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, profession, 'profession', 'Profession', false, false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, municipios, 'municipio_id', 'Municipio', false, false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, postoAdm, 'posto_adms_id', 'Posto', false, false): ''}
|
||||
@ -230,22 +238,28 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
|
||||
</ul>
|
||||
</div>
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Address', 'address', 'text', true, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Mother Fullname', 'mother_fullname', 'text', true, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Identity Number', 'identity_number', 'text', false, viewOnly): ''}
|
||||
<div className="bg-white p-6 rounded-md shadow-md space-y-6">
|
||||
<h2 className="text-lg font-semibold">Bank Information</h2>
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, banks, 'bank_name', 'Bank Name', false, false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Bank Account', 'bank_account', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'iBank Number', 'ibank_number', 'text', false, viewOnly): ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-md shadow-md space-y-6">
|
||||
<h2 className="text-lg font-semibold">Agent Information</h2>
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'License Number', 'license_number', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Merchant Name', 'agent_name', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Merchant Address', 'merchantaddress', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Longitude Merchant', 'longitudemerchant', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Latitude Merchant', 'latitudemerchant', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Selfie', 'file_selfie'): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Document', 'file_document_id'): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Document & Selfie', 'file_document_id_selfie'): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Commercial License', 'file_commercial_license'): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Selfie', 'file_selfie', previewImg, setPreviewImg): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Document', 'file_document_id', previewImg, setPreviewImg): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Document & Selfie', 'file_document_id_selfie', previewImg, setPreviewImg): ''}
|
||||
{(formData.id || dialogType === "create") ? generateImage(formData, handleChange, 'File Commercial License', 'file_commercial_license', previewImg, setPreviewImg): ''}
|
||||
</div>
|
||||
|
||||
|
||||
{(formData.id || dialogType === "create") ? generateList(formData, handleChange, banks, 'bank_name', 'Bank Name', false, false): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Bank Account', 'bank_account', 'text', false, viewOnly): ''}
|
||||
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'iBank Number', 'ibank_number', 'text', false, viewOnly): ''}
|
||||
|
||||
{(formData.id&&(!page||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): ''}
|
||||
@ -257,7 +271,7 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
|
||||
<CustomerWallet customerid={formData.id}/>
|
||||
) : ""}
|
||||
|
||||
<div className="flex justify-end gap-5">
|
||||
<div className="col-span-1 md:col-span-2 flex justify-end gap-5">
|
||||
<Button onClick={(e:any) => btnPrevDef(e)} color="secondary">{ viewOnly ? (`Open Edit`) : (`Close Edit`) }</Button>
|
||||
<Button type="button" variant="outline" onClick={() => handleAddDialog(false)}>Cancel</Button>
|
||||
{/* <Button onClick={(e) => buttonOnSubmit(e, formData)} variant="default">Save Changes</Button> */}
|
||||
@ -333,7 +347,7 @@ function generateList(formData:any, handleChange: any, list:any, name:string, la
|
||||
}
|
||||
|
||||
// ON DEV (UPDATENYA)
|
||||
function generateImage(formData:any, handleChange:any, label:string, name:string) {
|
||||
function generateImage(formData:any, handleChange:any, label:string, name:string, previewImg: any, setPreviewImg:any) {
|
||||
const imagePreview = (file:any) => {
|
||||
if (file && file.type && file.type.startsWith('image/')) {
|
||||
const previewURL = URL.createObjectURL(file);
|
||||
@ -342,8 +356,21 @@ function generateImage(formData:any, handleChange:any, label:string, name:string
|
||||
return file
|
||||
};
|
||||
|
||||
function handlePrevImg(par: boolean) {
|
||||
if (par) setPreviewImg({ status: true, img: ''})
|
||||
if (!par) setPreviewImg({ status: false, img: '' })
|
||||
}
|
||||
|
||||
function onClickImg(img: any) {
|
||||
setPreviewImg({ status: true, img })
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{previewImg.status ? (
|
||||
<PreviewImage previewImgDialog={previewImg.status} handlePreviewImgDialog={handlePrevImg}
|
||||
modalImage={previewImg.img}/>
|
||||
):''}
|
||||
<div className="flex items-center justify-between w-full max-w-xl">
|
||||
<label className="form-label flex items-center gap-1 max-w-56">
|
||||
{label}<span className="text-red-500"></span>
|
||||
@ -351,7 +378,8 @@ function generateImage(formData:any, handleChange:any, label:string, name:string
|
||||
<div className="flex items-center space-x-4 w-3/4 justify-end">
|
||||
{ formData[name] ? (
|
||||
<div className="border-2 border-dashed border-red-300 rounded-md p-2">
|
||||
<img width={300} height={250} srcSet={imagePreview(formData[name])} src={imagePreview(formData[name])} alt={name} style={{borderRadius: 10}}/>
|
||||
<img width={300} height={250} srcSet={imagePreview(formData[name])} src={imagePreview(formData[name])}
|
||||
alt={name} style={{borderRadius: 10, cursor: 'pointer' }} onClick={() => onClickImg(imagePreview(formData[name]))}/>
|
||||
{/* <img width={300} height={250} srcSet={formData[name]} src={formData[name]} alt={name} style={{borderRadius: 10}}/> */}
|
||||
</div>
|
||||
) : (<span>No Data</span>)}
|
||||
@ -364,3 +392,29 @@ function generateImage(formData:any, handleChange:any, label:string, name:string
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function PreviewImage({previewImgDialog, handlePreviewImgDialog, modalImage}:any) {
|
||||
return (
|
||||
<>
|
||||
<Dialog open={previewImgDialog} onOpenChange={(open) => handlePreviewImgDialog(open)}>
|
||||
<DialogContent className="">
|
||||
<DialogTitle aria-describedby={''}></DialogTitle>
|
||||
<DialogBody>
|
||||
<button
|
||||
onClick={() => handlePreviewImgDialog(false)}
|
||||
className="absolute top-2 right-2 text-white bg-red-600 hover:bg-red-800 rounded-full px-3 py-1 text-xl font-bold"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<img
|
||||
src={modalImage}
|
||||
alt="Preview"
|
||||
className="max-w-full max-h-[80vh] rounded-lg"
|
||||
/>
|
||||
</DialogBody>
|
||||
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { UserPlus } from 'lucide-react';
|
||||
import { KeenIcon, useDataGrid } from '@/components';
|
||||
import { DefaultTooltip } from '@/components';
|
||||
import { useState } from 'react';
|
||||
|
||||
const ListToolbar = ({ createMember }: { createMember: () => void }) => {
|
||||
const { table, reload } = useDataGrid();
|
||||
const [usernameFilter, setUsernameFilter] = useState('');
|
||||
const [emailFilter, setEmailFilter] = useState('');
|
||||
interface ListToolbarProps {
|
||||
createMember: () => void;
|
||||
onReload: () => void;
|
||||
isReloading: boolean;
|
||||
}
|
||||
|
||||
const ListToolbar = ({ createMember, onReload, isReloading }: ListToolbarProps) => {
|
||||
|
||||
const [emailFilter, setEmailFilter] = useState('');
|
||||
const [usernameFilter, setUsernameFilter] = useState('');
|
||||
const {table}=useDataGrid();
|
||||
const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setUsernameFilter(e.target.value);
|
||||
table.getColumn('username')?.setFilterValue(e.target.value);
|
||||
@ -34,9 +42,20 @@ const ListToolbar = ({ createMember }: { createMember: () => void }) => {
|
||||
<Button variant="outline" className="h-7.5 text-[0.8rem]" onClick={createMember}>
|
||||
Add Data
|
||||
</Button>
|
||||
<DefaultTooltip title={'Refresh'} placement={'top'}>
|
||||
<Button variant="outline" className="h-7.5" onClick={() => reload()}>
|
||||
<DefaultTooltip title={isReloading ? 'Refreshing...' : 'Refresh'} placement={'top'}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="h-7.5"
|
||||
onClick={onReload}
|
||||
disabled={isReloading}
|
||||
>
|
||||
{isReloading ? (
|
||||
<div className="animate-spin">
|
||||
<KeenIcon icon="arrows-circle" />
|
||||
</div>
|
||||
) : (
|
||||
<KeenIcon icon="arrows-circle" />
|
||||
)}
|
||||
</Button>
|
||||
</DefaultTooltip>
|
||||
</div>
|
||||
|
||||
@ -470,6 +470,7 @@ const AddDialog = () => {
|
||||
<SelectItem value="TE">Top Up Escrow </SelectItem>
|
||||
<SelectItem value="TM">Top Up Master Agent </SelectItem>
|
||||
<SelectItem value="TA">Top Up Agent </SelectItem>
|
||||
<SelectItem value="PL">Purchase Loja</SelectItem>
|
||||
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
@ -604,6 +604,7 @@ const EditDialog = () => {
|
||||
<SelectItem value="TE">Top Up Escrow </SelectItem>
|
||||
<SelectItem value="TM">Top Up Master Agent </SelectItem>
|
||||
<SelectItem value="TA">Top Up Agent </SelectItem>
|
||||
<SelectItem value="PL">Purchase Loja</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@ -12,6 +12,7 @@ const ListToolbar = () => {
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
table.getColumn('name')?.setFilterValue(searchValue);
|
||||
table.setPageIndex(0);
|
||||
}, 200);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
|
||||
@ -185,7 +185,8 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React
|
||||
R: 'Reward Point',
|
||||
TE:'Top Up Escrow',
|
||||
TM:'Top Up Master Agent',
|
||||
TA:'Top Up Agent'
|
||||
TA:'Top Up Agent',
|
||||
PL:'Purchase Loja'
|
||||
};
|
||||
|
||||
return mapping[row.type] || 'Unknown';
|
||||
|
||||
Reference in New Issue
Block a user