member kyc

This commit is contained in:
unknown
2025-03-04 23:04:31 +07:00
parent 52eee53002
commit 985ceacb42
8 changed files with 188 additions and 51 deletions

1
.gitignore vendored
View File

@ -23,3 +23,4 @@ dist-ssr
*.sln *.sln
*.sw? *.sw?
**/src/*.js **/src/*.js
yarn.lock

View File

@ -23,13 +23,14 @@ import {
import { useState } from 'react'; import { useState } from 'react';
import { Input } from './input'; import { Input } from './input';
import { Button } from './button'; import { Button } from './button';
import { KeenIcon } from '@/components';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogDescription, DialogDescription,
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger DialogTrigger,
} from './dialog'; } from './dialog';
interface DataTableProps<TData, TValue> { interface DataTableProps<TData, TValue> {
@ -109,18 +110,18 @@ export function DataTable<TData, TValue>({
))} ))}
<TableCell> <TableCell>
<div className="space-x-2"> <div className="space-x-2">
<Button <button
className="bg-blue-500 text-white px-2 py-1 rounded" className="btn btn-sm btn-icon btn-clear btn-light"
onClick={() => onUpdate(row.original)}> onClick={() => onUpdate(row.original)}>
Update <KeenIcon icon="notepad-edit" />
</Button> </button>
{ {
onDelete ? ( onDelete ? (
<Button <button
className="bg-red-500 text-white px-2 py-1 rounded" className="btn btn-sm btn-icon btn-clear btn-light"
onClick={() => onDelete(row.original)}> onClick={() => onDelete(row.original)}>
Delete <KeenIcon icon="trash" />
</Button> </button>
) : ('') ) : ('')
} }
</div> </div>

View File

@ -1,8 +1,8 @@
import { ColumnDef } from '@tanstack/react-table'; import { ColumnDef } from '@tanstack/react-table';
export type Group = { export type Group = {
id: number; no: number;
createdDate: Date; created_at: Date;
name: string; name: string;
status: string; status: string;
description: string; description: string;
@ -10,13 +10,13 @@ export type Group = {
export const columns: ColumnDef<Group>[] = [ export const columns: ColumnDef<Group>[] = [
{ {
accessorKey: 'id', accessorKey: 'no',
header: 'ID' header: 'ID'
}, },
{ {
accessorKey: 'createdDate', accessorKey: 'created_at',
header: 'Created Date', header: 'Created Date',
cell: ({ row }) => new Date(row.original.createdDate).toLocaleDateString() cell: ({ row }) => new Date(row.original.created_at).toLocaleDateString()
}, },
{ {
accessorKey: 'name', accessorKey: 'name',

View File

@ -47,7 +47,12 @@ const ManageGroups = () => {
order_direction: 'ASC' order_direction: 'ASC'
} }
}); });
setDataGroup(groups.data.data.list) let temp = 1
let resGroups = groups.data.data.list.map((el: any) => {
el.no = temp++
return el
})
setDataGroup(resGroups)
} catch (error: any) { } catch (error: any) {
alert(error.message) alert(error.message)
console.log(error); console.log(error);

View File

@ -1,7 +1,14 @@
import { DataGridInner, TDataGridProps } from '@/components'; import { DataGridInner, TDataGridProps } from '@/components';
import { DataTable } from '@/components/ui/DataTable';
import { Table } from '@tanstack/react-table'; import { Table } from '@tanstack/react-table';
import React, { createContext, useContext, useState } from 'react'; import React, { createContext, useContext, useState, useEffect } from 'react';
import { ManageKycContextProvider } from './hooks'; import { ManageKycContextProvider } from './hooks';
import { columns, initialMember } from '../manage-members/Columns';
import { useAuthContext } from '@/auth';
import { apiConfig } from '@/config/api.config';
import axios from 'axios';
const BASE_URL = apiConfig.service_customer;
import CustomerDialog from '../manage-members/CustomerDetailModal';
export interface IDataGridContextProps<TData extends object> { export interface IDataGridContextProps<TData extends object> {
props: TDataGridProps<TData>; props: TDataGridProps<TData>;
@ -24,16 +31,100 @@ export const useDataGrid = () => {
const Kyc = () => { const Kyc = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [members, setMembers] = useState([]);
const [member, setMember] = useState(initialMember);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogType, setDialogType] = useState('');
const closeDialog = () => setIsDialogOpen(false);
const { getUser } = useAuthContext();
useEffect(() => {
fetchGroups()
}, []);
async function fetchGroups() {
try {
let groups = await axios.get(`${BASE_URL}/customer/list`, {
params: {
limit: 10,
page: 1,
with_deleted: false,
order_field: 'fullname',
order_direction: 'ASC',
// type: "Reguler"
}
});
let temp = 1
let resMembers = groups.data.data.list.map((el: any) => {
el.no = temp++
el.name = el.fullname
return el
})
setMembers(resMembers)
} catch (error: any) {
alert(error.message)
console.log(error);
}
}
const handleUpdate = (data: any) => {
setMember(data)
setIsDialogOpen(true)
}
async function handleSubmit(data: any) {
setDialogType('update')
setMember(data)
setDialogOpen(true)
}
const handleYes = async () => {
let userLogin: any = await getUser();
let updateData: any = member;
let customerId = member.id;
updateData.updated_by = userLogin.data ? userLogin.data.id : ''
let today = new Date();
updateData.updated_at = today.toString();
delete updateData.id;
delete updateData.pin;
delete updateData.name;
delete updateData.longitude;
delete updateData.latitude;
delete updateData.created_at;
delete updateData.no;
delete updateData.group_id;
delete updateData.group_name;
delete updateData.group_description;
delete updateData.group_status;
delete updateData.group_created_by;
delete updateData.group_created_at;
delete updateData.group_updated_by;
delete updateData.group_updated_at;
delete updateData.group_deleted_by;
delete updateData.group_deleted_at;
try {
await axios.put(`${BASE_URL}/customer/update/${customerId}`, updateData)
await fetchGroups();
setIsDialogOpen(false)
} catch (error: any) {
alert(error.message)
setIsDialogOpen(false)
}
}
return ( return (
<div> <div>
<div className="container mx-auto py-5"> <div className="container mx-auto py-5">
<CustomerDialog open={isDialogOpen} handleClose={closeDialog} handleSubmit={handleSubmit} initialData={member} viewStats={true}/>
<h1 className="text-xl font-medium leading-none text-gray-900 mb-7">Manage Member KYC</h1> <h1 className="text-xl font-medium leading-none text-gray-900 mb-7">Manage Member KYC</h1>
<ManageKycContextProvider> <DataTable data={members} columns={columns} onUpdate={handleUpdate} onDelete={null}/>
{/* <ManageKycContextProvider>
<div className="grid gap-5 lg:gap-7.5"> <div className="grid gap-5 lg:gap-7.5">
<DataGridInner /> <DataGridInner />
</div> </div>
</ManageKycContextProvider> </ManageKycContextProvider> */}
</div> </div>
</div> </div>
); );

View File

@ -61,6 +61,20 @@ export const columns: ColumnDef<Members>[] = [
); );
} }
}, },
{
accessorKey: 'group_name',
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Group
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
}
},
{ {
accessorKey: 'email', accessorKey: 'email',
header: ({ column }) => { header: ({ column }) => {

View File

@ -15,8 +15,9 @@ import {
import Divider from '@mui/material/Divider'; import Divider from '@mui/material/Divider';
import { initialMember } from "./Columns"; import { initialMember } from "./Columns";
const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) => { const CustomerDialog = ({ open, handleClose, handleSubmit, initialData, viewStats }: any) => {
const [formData, setFormData] = useState(initialData || initialMember); const [formData, setFormData] = useState(initialData || initialMember);
const [viewOnly, setViewOnly] = useState(viewStats || false);
useEffect(() => { useEffect(() => {
setFormData(initialData || {}); // Sync formData when initialData changes setFormData(initialData || {}); // Sync formData when initialData changes
@ -42,36 +43,37 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
return ( return (
<Dialog open={open} onClose={handleClose} fullWidth maxWidth="sm"> <Dialog open={open} onClose={handleClose} fullWidth maxWidth="sm">
<DialogTitle>Customer Form</DialogTitle> <DialogTitle>Customer Form ({viewStats ? 'View' : 'Edit'})</DialogTitle>
<DialogContent> <DialogContent>
<div className="flex justify-between"> <div className="flex justify-between">
<Typography sx={{color:'grey'}}>Customer Data</Typography> <Typography sx={{color:'grey'}}>Customer Data</Typography>
<Typography sx={{color:'grey'}} display="flex" justifyContent="flex-end">Created: {generateDate(formData.created_at, 'datetime')}</Typography> <Typography sx={{color:'grey'}} display="flex" justifyContent="flex-end">Created: {generateDate(formData.created_at, 'datetime')}</Typography>
</div> </div>
<TextField fullWidth margin="dense" label="Full Name" name="fullname" value={formData.fullname} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Full Name" name="fullname" value={formData.fullname} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Email" name="email" value={formData.email} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Email" name="email" value={formData.email} onChange={handleChange} />
<TextField type="file" fullWidth margin="dense" label="Photo" name="photouser" value={formData.photouser} onChange={handleChange} /> <TextField disabled fullWidth margin="dense" label="Group" name="group" value={formData.group_name} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Username" name="username" value={formData.username} onChange={handleChange} /> <TextField disabled={viewOnly} type="file" fullWidth margin="dense" label="Photo" name="photouser" value={formData.photouser} onChange={handleChange} />
<TextField fullWidth margin="dense" label="MSISDN" name="msisdn" value={formData.msisdn} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Username" name="username" value={formData.username} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Address" name="address" value={formData.address} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="MSISDN" name="msisdn" value={formData.msisdn} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Nationality" name="nationality" value={formData.nationality} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Address" name="address" value={formData.address} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Date of Birth" name="date_birth" type="date" value={generateDate(formData.date_birth, null)} onChange={handleChange} InputLabelProps={{ shrink: true }} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Nationality" name="nationality" value={formData.nationality} onChange={handleChange} />
<TextField disabled={viewOnly} fullWidth margin="dense" label="Date of Birth" name="date_birth" type="date" value={generateDate(formData.date_birth, null)} onChange={handleChange} InputLabelProps={{ shrink: true }} />
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Gender</InputLabel> <InputLabel>Gender</InputLabel>
<Select name="gender" value={formData.gender} onChange={handleChange}> <Select disabled={viewOnly} name="gender" value={formData.gender} onChange={handleChange}>
<MenuItem value="M">Male</MenuItem> <MenuItem value="M">Male</MenuItem>
<MenuItem value="F">Female</MenuItem> <MenuItem value="F">Female</MenuItem>
</Select> </Select>
</FormControl> </FormControl>
<TextField fullWidth margin="dense" label="Identity Type" name="identity_type" value={formData.identity_type} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Identity Type" name="identity_type" value={formData.identity_type} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Identity Number" name="identity_number" value={formData.identity_number} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Identity Number" name="identity_number" value={formData.identity_number} onChange={handleChange} />
<TextField type="number" fullWidth margin="dense" label="License Number" name="license_number" value={formData.license_number} onChange={handleChange} /> <TextField disabled={viewOnly} type="number" fullWidth margin="dense" label="License Number" name="license_number" value={formData.license_number} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Profession" name="profession" value={formData.profession} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Profession" name="profession" value={formData.profession} onChange={handleChange} />
{/* <TextField fullWidth margin="dense" label="Password" name="password" type="password" value={formData.password} onChange={handleChange} /> */} {/* <TextField fullWidth margin="dense" label="Password" name="password" type="password" value={formData.password} onChange={handleChange} /> */}
{/* <TextField fullWidth margin="dense" label="PIN" name="pin" value={formData.pin} onChange={handleChange} /> */} {/* <TextField fullWidth margin="dense" label="PIN" name="pin" value={formData.pin} onChange={handleChange} /> */}
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Status</InputLabel> <InputLabel>Status</InputLabel>
<Select name="status" value={formData.status} onChange={handleChange}> <Select disabled={viewOnly} name="status" value={formData.status} onChange={handleChange}>
<MenuItem value="Y">Active</MenuItem> <MenuItem value="Y">Active</MenuItem>
<MenuItem value="N">Inactive</MenuItem> <MenuItem value="N">Inactive</MenuItem>
</Select> </Select>
@ -79,7 +81,7 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Municipio</InputLabel> <InputLabel>Municipio</InputLabel>
<Select name="municipio" value={formData.municipio} onChange={handleChange}> <Select disabled={viewOnly} name="municipio" value={formData.municipio} onChange={handleChange}>
<MenuItem value="municipio1">Municipio 1</MenuItem> <MenuItem value="municipio1">Municipio 1</MenuItem>
<MenuItem value="municipio2">Municipio 2</MenuItem> <MenuItem value="municipio2">Municipio 2</MenuItem>
</Select> </Select>
@ -87,7 +89,7 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Posto</InputLabel> <InputLabel>Posto</InputLabel>
<Select name="posto_adms" value={formData.posto_adms} onChange={handleChange}> <Select disabled={viewOnly} name="posto_adms" value={formData.posto_adms} onChange={handleChange}>
<MenuItem value="posto1">Posto 1</MenuItem> <MenuItem value="posto1">Posto 1</MenuItem>
<MenuItem value="posto2">Posto 2</MenuItem> <MenuItem value="posto2">Posto 2</MenuItem>
</Select> </Select>
@ -95,7 +97,7 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Suco</InputLabel> <InputLabel>Suco</InputLabel>
<Select name="suco" value={formData.suco} onChange={handleChange}> <Select disabled={viewOnly} name="suco" value={formData.suco} onChange={handleChange}>
<MenuItem value="posto1">suco 1</MenuItem> <MenuItem value="posto1">suco 1</MenuItem>
<MenuItem value="posto2">suco 2</MenuItem> <MenuItem value="posto2">suco 2</MenuItem>
</Select> </Select>
@ -103,7 +105,7 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
<FormControl fullWidth margin="dense"> <FormControl fullWidth margin="dense">
<InputLabel>Aldeia</InputLabel> <InputLabel>Aldeia</InputLabel>
<Select name="aldeia" value={formData.aldeia} onChange={handleChange}> <Select disabled={viewOnly} name="aldeia" value={formData.aldeia} onChange={handleChange}>
<MenuItem value="posto1">aldeia 1</MenuItem> <MenuItem value="posto1">aldeia 1</MenuItem>
<MenuItem value="posto2">aldeia 2</MenuItem> <MenuItem value="posto2">aldeia 2</MenuItem>
</Select> </Select>
@ -111,9 +113,9 @@ const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) =
<Divider className="pt-7"/> <Divider className="pt-7"/>
<Typography sx={{color:'grey'}}>Bank</Typography> <Typography sx={{color:'grey'}}>Bank</Typography>
<TextField fullWidth margin="dense" label="Bank Name" name="bank_name" value={formData.bank_name} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Bank Name" name="bank_name" value={formData.bank_name} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Bank Account" name="bank_account" value={formData.bank_account} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="Bank Account" name="bank_account" value={formData.bank_account} onChange={handleChange} />
<TextField fullWidth margin="dense" label="iBank Number" name="ibank_number" value={formData.ibank_number} onChange={handleChange} /> <TextField disabled={viewOnly} fullWidth margin="dense" label="iBank Number" name="ibank_number" value={formData.ibank_number} onChange={handleChange} />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={handleClose} color="secondary">Cancel</Button> <Button onClick={handleClose} color="secondary">Cancel</Button>

View File

@ -1,11 +1,11 @@
import { DataTable } from '@/components/ui/DataTable'; import { DataTable } from '@/components/ui/DataTable';
import { apiConfig } from '@/config/api.config'; import { apiConfig } from '@/config/api.config';
import { columns, Members } from './Columns'; import { columns, Members, initialMember } from './Columns';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import axios from 'axios'; import axios from 'axios';
import CustomerDialog from './CustomerDetailModal'; import CustomerDialog from './CustomerDetailModal';
import { initialMember } from "./Columns";
import ConfirmDialog from '@/components/confirm'; import ConfirmDialog from '@/components/confirm';
import { useAuthContext } from '@/auth';
const BASE_URL = apiConfig.service_customer; const BASE_URL = apiConfig.service_customer;
const ManageMembers = () => { const ManageMembers = () => {
@ -15,6 +15,7 @@ const ManageMembers = () => {
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
const [dialogType, setDialogType] = useState(''); const [dialogType, setDialogType] = useState('');
const closeDialog = () => setIsDialogOpen(false); const closeDialog = () => setIsDialogOpen(false);
const { getUser } = useAuthContext();
useEffect(() => { useEffect(() => {
fetchGroups() fetchGroups()
@ -29,16 +30,16 @@ const ManageMembers = () => {
with_deleted: false, with_deleted: false,
order_field: 'fullname', order_field: 'fullname',
order_direction: 'ASC', order_direction: 'ASC',
// type: "Reguler" type: "Reguler"
} }
}); });
let temp = 1 let temp = 1
let resGroups = groups.data.data.list.map((el: any) => { let resMembers = groups.data.data.list.map((el: any) => {
el.no = temp++ el.no = temp++
el.name = el.fullname el.name = el.fullname
return el return el
}) })
setMembers(resGroups) setMembers(resMembers)
} catch (error: any) { } catch (error: any) {
alert(error.message) alert(error.message)
console.log(error); console.log(error);
@ -46,21 +47,43 @@ const ManageMembers = () => {
} }
const handleUpdate = (data: any) => { const handleUpdate = (data: any) => {
console.log(data);
setMember(data) setMember(data)
setIsDialogOpen(true) setIsDialogOpen(true)
} }
async function handleSubmit(data: any) { async function handleSubmit(data: any) {
setDialogType('update') setDialogType('update')
console.log(data);
setMember(data) setMember(data)
setDialogOpen(true) setDialogOpen(true)
} }
const handleYes = async () => { const handleYes = async () => {
let userLogin: any = await getUser();
let updateData: any = member;
let customerId = member.id;
updateData.updated_by = userLogin.data ? userLogin.data.id : ''
let today = new Date();
updateData.updated_at = today.toString();
delete updateData.id;
delete updateData.pin;
delete updateData.name;
delete updateData.longitude;
delete updateData.latitude;
delete updateData.created_at;
delete updateData.no;
delete updateData.group_id;
delete updateData.group_name;
delete updateData.group_description;
delete updateData.group_status;
delete updateData.group_created_by;
delete updateData.group_created_at;
delete updateData.group_updated_by;
delete updateData.group_updated_at;
delete updateData.group_deleted_by;
delete updateData.group_deleted_at;
try { try {
await axios.put(`${BASE_URL}/customer/update/${member.id}`, member) await axios.put(`${BASE_URL}/customer/update/${customerId}`, updateData)
await fetchGroups();
setIsDialogOpen(false) setIsDialogOpen(false)
} catch (error: any) { } catch (error: any) {
alert(error.message) alert(error.message)