yarn and member

This commit is contained in:
unknown
2025-03-04 18:37:15 +07:00
parent 19fa2febad
commit 52eee53002
6 changed files with 250 additions and 110 deletions

3
.gitignore vendored
View File

@ -22,5 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
**/src/*.js
yarn.lock
**/src/*.js

View File

@ -114,11 +114,15 @@ export function DataTable<TData, TValue>({
onClick={() => onUpdate(row.original)}>
Update
</Button>
<Button
className="bg-red-500 text-white px-2 py-1 rounded"
onClick={() => onDelete(row.original)}>
Delete
</Button>
{
onDelete ? (
<Button
className="bg-red-500 text-white px-2 py-1 rounded"
onClick={() => onDelete(row.original)}>
Delete
</Button>
) : ('')
}
</div>
</TableCell>
</TableRow>

View File

@ -3,7 +3,7 @@ import { columns, Group } from './Column';
import { apiConfig } from '@/config/api.config';
import axios, { AxiosResponse } from 'axios';
import { DialogContent, MenuItem, Radio, RadioGroup, FormControlLabel, FormControl,
Dialog, DialogActions, DialogTitle, Typography, Button, Box } from '@mui/material';
Dialog, DialogTitle, Typography, Button, Box } from '@mui/material';
import { useState, useEffect } from 'react';
// import IconButton from '@mui/material/IconButton';
import CloseIcon from '@mui/icons-material/Close';
@ -27,7 +27,7 @@ const ManageGroups = () => {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [dataGroup, setDataGroup] = useState([]);
const [formData, setFormData] = useState(initGroup);
const [pageIndex, setPageIndex] = useState(0);
const [pageIndex, setPageIndex] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [dialogType, setDialogType] = useState('');
const [dialogOpen, setDialogOpen] = useState(false);
@ -40,8 +40,8 @@ const ManageGroups = () => {
try {
let groups = await axios.get(`${BASE_URL}/groups/list`, {
params: {
limit: 10,
page: 1,
limit: pageSize,
page: pageIndex,
with_deleted: false,
order_field: 'name',
order_direction: 'ASC'
@ -128,10 +128,6 @@ const ManageGroups = () => {
}
};
const handleNo = () => {
setDialogOpen(false);
};
return (
<div>
<div className="container mx-auto pt-2">
@ -141,11 +137,11 @@ const ManageGroups = () => {
title="Confirm Action"
content={`Are you sure you want to `+( dialogType === 'create' ? "create?" : ( dialogType === 'update' ? "update?" : "delete?"))}
onYes={handleYes}
onNo={handleNo}
onNo={() => setDialogOpen(false)}
/>
<h1 className="text-xl font-medium leading-none text-gray-900 p-5">Groups</h1>
<DataTable data={dataGroup} columns={columns} createGroup={createGroup} onUpdate={handleUpdate} onDelete={handleDelete} />
<Dialog open={isDialogOpen} onClose={setIsDialogOpen}>
<Dialog open={isDialogOpen} onClose={closeDialog}>
<DialogContent className="w-[600px]">
<div className="flex justify-between">
<DialogTitle>Create New Group</DialogTitle>
@ -191,51 +187,6 @@ const ManageGroups = () => {
onChange={handleChange}
/>
</div>
{/* <div className="grid grid-cols-4 items-center gap-4 w-full">
<label className="form-label text-sm">
<span className="text-red-500">*</span>PIN Length:
</label>
<input
type="text"
name="pin_length"
className="input w-full col-span-3"
value={formData.pin_length}
onChange={handleChange}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4 w-full">
<label className="form-label text-sm">
<span className="text-red-500">*</span>Max Pin Attempts:
</label>
<input
type="text"
name="max_pin_attempts"
className="input w-full col-span-3"
value={formData.max_pin_attempts}
onChange={handleChange}
/>
</div> */}
{/* <div className="grid grid-cols-4 items-center gap-4 w-full mb-5">
<label className="form-label text-sm">Default Notification:</label>
<Select
onValueChange={(e) => setFormData({ ...formData, default_notification: e })}
>
<SelectTrigger className="w-full col-span-3">
<SelectValue placeholder="Select Default Notification" />
</SelectTrigger>
<SelectContent className="w-full">
<SelectItem value="1 - notifSender">1 - notifSender</SelectItem>
<SelectItem value="2 - notifBenefeciary">2 - notifBenefeciary</SelectItem>
</SelectContent>
</Select>
<input
type="text"
name="default_notification"
className="input w-full col-span-3"
value={formData.default_notification}
onChange={handleChange}
/>
</div> */}
<Button type="submit">Submit</Button>
</form>
</div>

View File

@ -10,24 +10,24 @@ import { ColumnDef } from '@tanstack/react-table';
import { ArrowUpDown, MoreHorizontal } from 'lucide-react';
export type Members = {
id: number;
// id: number;
username: number;
name: string;
fullname: string;
group: string;
email: string;
createdDate: Date;
created_at: Date;
};
export const columns: ColumnDef<Members>[] = [
{
accessorKey: 'id',
accessorKey: 'no',
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
ID
No
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
@ -55,7 +55,7 @@ export const columns: ColumnDef<Members>[] = [
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Name
Fullname
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
@ -76,7 +76,7 @@ export const columns: ColumnDef<Members>[] = [
}
},
{
accessorKey: 'createdDate',
accessorKey: 'created_at',
header: ({ column }) => {
return (
<Button
@ -88,7 +88,7 @@ export const columns: ColumnDef<Members>[] = [
</Button>
);
},
cell: ({ row }) => new Date(row.original.createdDate).toLocaleDateString()
cell: ({ row }) => new Date(row.original.created_at).toLocaleDateString()
},
{
id: 'actions',
@ -97,23 +97,72 @@ export const columns: ColumnDef<Members>[] = [
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
{/* <DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
</DropdownMenuTrigger> */}
{/* <DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(dataMembers.id.toString())}
>
Copy account ID
</DropdownMenuItem>
{/* <DropdownMenuSeparator /> */}
</DropdownMenuContent>
</DropdownMenuContent> */}
</DropdownMenu>
);
}
}
];
export const initialMember = {
id: "",
fullname: "",
email: "",
username: "",
msisdn: "",
password: "",
pin: "",
try_pin: "",
mother_fullname: "",
agent_name: "",
bank_name: "",
bank_account: "",
ibank_number: "",
address: "",
longitude: "",
latitude: "",
nationality: "",
photouser: "",
photomerchant: "",
file_selfie: "",
file_document_id: "",
file_document_id_selfie: "",
file_commercial_license: "",
identity_type: "",
identity_number: "",
license_number: "",
date_birth: "",
gender: "",
status: "N",
isneedapproval: "",
isapproved: "",
approveddate: "",
approvedby: "",
created_by: "",
created_at: "",
updated_by: "",
updated_at: "",
deleted_by: "",
deleted_at: "",
group: "",
point_tier: "",
language: "",
municipio: "",
posto_adms: "",
suco: "",
aldeia: "",
profession: "",
}

View File

@ -0,0 +1,126 @@
import React, { useState, useEffect } from "react";
import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
TextField,
Button,
MenuItem,
Select,
InputLabel,
FormControl,
Typography
} from "@mui/material";
import Divider from '@mui/material/Divider';
import { initialMember } from "./Columns";
const CustomerDialog = ({ open, handleClose, handleSubmit, initialData }: any) => {
const [formData, setFormData] = useState(initialData || initialMember);
useEffect(() => {
setFormData(initialData || {}); // Sync formData when initialData changes
}, [initialData]);
const handleChange = (e: any) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const onSubmit = () => {
handleSubmit(formData);
handleClose();
};
function generateDate(date: any, type: any) {
if (!date) return ''
const today = new Date(date);
if (type === 'datetime') return today.toISOString().replace('T', ' ').substring(0, 19);
return today.toISOString().split('T')[0];
}
return (
<Dialog open={open} onClose={handleClose} fullWidth maxWidth="sm">
<DialogTitle>Customer Form</DialogTitle>
<DialogContent>
<div className="flex justify-between">
<Typography sx={{color:'grey'}}>Customer Data</Typography>
<Typography sx={{color:'grey'}} display="flex" justifyContent="flex-end">Created: {generateDate(formData.created_at, 'datetime')}</Typography>
</div>
<TextField 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 type="file" fullWidth margin="dense" label="Photo" name="photouser" value={formData.photouser} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Username" name="username" value={formData.username} onChange={handleChange} />
<TextField fullWidth margin="dense" label="MSISDN" name="msisdn" value={formData.msisdn} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Address" name="address" value={formData.address} onChange={handleChange} />
<TextField fullWidth margin="dense" label="Nationality" name="nationality" value={formData.nationality} 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 }} />
<FormControl fullWidth margin="dense">
<InputLabel>Gender</InputLabel>
<Select name="gender" value={formData.gender} onChange={handleChange}>
<MenuItem value="M">Male</MenuItem>
<MenuItem value="F">Female</MenuItem>
</Select>
</FormControl>
<TextField 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 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 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} /> */}
<FormControl fullWidth margin="dense">
<InputLabel>Status</InputLabel>
<Select name="status" value={formData.status} onChange={handleChange}>
<MenuItem value="Y">Active</MenuItem>
<MenuItem value="N">Inactive</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth margin="dense">
<InputLabel>Municipio</InputLabel>
<Select name="municipio" value={formData.municipio} onChange={handleChange}>
<MenuItem value="municipio1">Municipio 1</MenuItem>
<MenuItem value="municipio2">Municipio 2</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth margin="dense">
<InputLabel>Posto</InputLabel>
<Select name="posto_adms" value={formData.posto_adms} onChange={handleChange}>
<MenuItem value="posto1">Posto 1</MenuItem>
<MenuItem value="posto2">Posto 2</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth margin="dense">
<InputLabel>Suco</InputLabel>
<Select name="suco" value={formData.suco} onChange={handleChange}>
<MenuItem value="posto1">suco 1</MenuItem>
<MenuItem value="posto2">suco 2</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth margin="dense">
<InputLabel>Aldeia</InputLabel>
<Select name="aldeia" value={formData.aldeia} onChange={handleChange}>
<MenuItem value="posto1">aldeia 1</MenuItem>
<MenuItem value="posto2">aldeia 2</MenuItem>
</Select>
</FormControl>
<Divider className="pt-7"/>
<Typography sx={{color:'grey'}}>Bank</Typography>
<TextField 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 fullWidth margin="dense" label="iBank Number" name="ibank_number" value={formData.ibank_number} onChange={handleChange} />
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="secondary">Cancel</Button>
<Button onClick={onSubmit} color="primary" variant="contained">Submit</Button>
</DialogActions>
</Dialog>
);
};
export default CustomerDialog;

View File

@ -3,37 +3,18 @@ import { apiConfig } from '@/config/api.config';
import { columns, Members } from './Columns';
import { useState, useEffect } from 'react';
import axios from 'axios';
import CustomerDialog from './CustomerDetailModal';
import { initialMember } from "./Columns";
import ConfirmDialog from '@/components/confirm';
const BASE_URL = apiConfig.service_customer;
const dataMembers: Members[] = [
{
id: 37026,
username: 67076807158,
name: 'Jumentino Carlos Luis da Costa',
group: 'REGULER',
email: 'Jumentinocldacoata@gmail.com',
createdDate: new Date('2025-02-21')
},
{
id: 37027,
username: 67071827345,
name: 'Diego Costa',
group: 'REGULER',
email: 'DiegoCosta@gmail.com',
createdDate: new Date('2025-02-21')
},
{
id: 37028,
username: 56123764212,
name: 'Luis Da Vista',
group: 'SUPERVISOR',
email: 'LuisdaVista@gmail.com',
createdDate: new Date('2024-01-21')
}
];
const ManageMembers = () => {
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);
useEffect(() => {
fetchGroups()
@ -47,30 +28,60 @@ const ManageMembers = () => {
page: 1,
with_deleted: false,
order_field: 'fullname',
order_direction: 'ASC'
order_direction: 'ASC',
// type: "Reguler"
}
});
setMembers(groups.data.data.list)
let temp = 1
let resGroups = groups.data.data.list.map((el: any) => {
el.no = temp++
el.name = el.fullname
return el
})
setMembers(resGroups)
} catch (error: any) {
alert(error.message)
console.log(error);
}
}
const handleUpdate = (member: any) => {
console.log(members);
const handleUpdate = (data: any) => {
console.log(data);
setMember(data)
setIsDialogOpen(true)
}
const handleDelete = (member: any) => {
async function handleSubmit(data: any) {
setDialogType('update')
console.log(data);
setMember(data)
setDialogOpen(true)
}
const handleYes = async () => {
try {
await axios.put(`${BASE_URL}/customer/update/${member.id}`, member)
setIsDialogOpen(false)
} catch (error: any) {
alert(error.message)
setIsDialogOpen(false)
}
}
return (
<div>
<div className="container mx-auto p-5">
<ConfirmDialog
open={dialogOpen}
onClose={() => setDialogOpen(false)}
title="Confirm Action"
content={`Are you sure you want to `+( dialogType === 'create' ? "create?" : ( dialogType === 'update' ? "update?" : "delete?"))}
onYes={handleYes}
onNo={() => setDialogOpen(false)}
/>
<CustomerDialog open={isDialogOpen} handleClose={closeDialog} handleSubmit={handleSubmit} initialData={member}/>
<h1 className="text-xl font-medium leading-none text-gray-900">Manage Members</h1>
<DataTable data={dataMembers} columns={columns} onUpdate={handleUpdate} onDelete={handleDelete}/>
<DataTable data={members} columns={columns} onUpdate={handleUpdate} onDelete={null}/>
</div>
</div>
);