member agent

This commit is contained in:
unknown
2025-05-26 18:59:10 +07:00
parent b70b2f027d
commit c3c49da778
6 changed files with 157 additions and 86 deletions

View File

@ -52,6 +52,7 @@
"date-fns": "^3.0.0",
"formik": "^2.4.6",
"helmet": "^8.1.0",
"html2canvas": "^1.4.1",
"https": "^1.0.0",
"leaflet": "^1.9.4",
"lucide-react": "^0.456.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

View File

@ -2,6 +2,7 @@ import { DataTable } from '@/components/ui/DataTable';
import { getColumns } from './Column';
import { apiConfig } from '@/config/api.config';
import axios, { AxiosResponse } from 'axios';
import html2canvas from 'html2canvas';
import { Helmet } from 'react-helmet';
import {
DialogContent,
@ -18,7 +19,7 @@ import {
Breadcrumbs,
Link
} from '@mui/material';
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import CloseIcon from '@mui/icons-material/Close';
import Divider from '@mui/material/Divider';
import ConfirmDialog from '@/components/confirm';
@ -27,6 +28,7 @@ import { Container, DataGridLoader, DataGridProvider, LoaderTransparant } from '
import { ListToolBar } from './ListToolbar';
import { RefreshCw } from 'lucide-react';
import { setgroups } from 'process';
import { toAbsoluteUrl } from '@/utils';
const BASE_URL = apiConfig.service_customer;
let initBalance = {
@ -51,6 +53,8 @@ const AgentBalance = () => {
const [dialogType, setDialogType] = useState('');
const [dialogOpen, setDialogOpen] = useState(false);
const [isReloading, setIsReloading] = useState(false);
const [barcode, setBarcode] = useState('');
// const [selectedMember, setSelectedMember] = useState(initBalance);
useEffect(() => {
fetchAgentBalance();
@ -94,7 +98,9 @@ const AgentBalance = () => {
openDialog();
}
const handleUpdate = (group: any) => {
const handleUpdate = async (data: any) => {
await getQrCode(data.id);
setFormData(data)
setDialogType('update');
setIsDialogOpen(true);
};
@ -104,6 +110,18 @@ const AgentBalance = () => {
fetchAgentBalance();
};
async function getQrCode(customerId:any): Promise<void> {
try {
setBarcode(`https://img.freepik.com/free-vector/scan-me-qr-code_78370-2915.jpg?semt=ais_hybrid&w=740`)
let getToken = await axios.get(`${BASE_URL}/token/get`, { params: { id: customerId }});
console.log(getToken.data.data);
// setBarcode(getToken.data.data.qrCode);
} catch (error: any) {
toast.warning(error.message)
console.log(error);
}
}
if (loading) return <LoaderTransparant />;
return (
@ -160,78 +178,134 @@ const AgentBalance = () => {
</div>
{/* </div> */}
{/* <Dialog open={isDialogOpen} onClose={closeDialog}>
<DialogContent className="w-full">
<div className="flex justify-between">
<DialogTitle>
{dialogType === 'create' ? 'Create New Group' : 'Update Group'}
</DialogTitle>
<Box display="flex" justifyContent="flex-end">
<Button
variant="outlined"
sx={{ borderColor: 'white', color: 'grey' }}
onClick={closeDialog}
>
<CloseIcon />
</Button>
</Box>
</div>
<Divider />
<div className="p-5 mt-5">
<form onSubmit={handleSubmit} className="flex flex-col gap-4 w-full">
<div className="grid grid-cols-4 items-center gap-4 w-full">
<label className="form-label text-sm">
<span className="text-red-500">*</span>Group Name:
</label>
<input
type="text"
name="groupName"
className="input w-full col-span-3"
value={formData.groupName}
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>Active Status:
</label>
<FormControl>
<RadioGroup name="status" row value={formData.status} onChange={handleChange}>
<FormControlLabel
value="Y"
checked={formData.status === 'Y'}
control={<Radio />}
label="Yes"
/>
<FormControlLabel
value="N"
checked={formData.status === 'N'}
control={<Radio />}
label="No"
/>
</RadioGroup>
</FormControl>
</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>Description:
</label>
<input
type="text"
name="description"
className="input w-full col-span-3"
value={formData.description}
onChange={handleChange}
/>
</div>
<Button type="submit">Submit</Button>
</form>
<Dialog open={isDialogOpen} onClose={closeDialog}>
<DialogContent className="w-full flex justify-center items-center">
<div className="relative">
<PaymentCard barcode={barcode} customerId={formData.id} agent_name={formData.agent_name}/>
</div>
</DialogContent>
</Dialog> */}
</Dialog>
</Container>
</>
);
};
const PaymentCard = ({ barcode, agent_name, customerId }:any) => {
const cardRef:any = useRef(null);
// useEffect(() => {
// fetchToken();
// }, []);
// async function fetchToken(): Promise<void> {
// try {
// let getToken = await axios.get(`${BASE_URL}/token/get`, { params: { id: customerId }});
// console.log(getToken.data.data);
// // setBarcode(getToken.data.data.qrCode);
// setBarcode(`https://img.freepik.com/free-vector/scan-me-qr-code_78370-2915.jpg?semt=ais_hybrid&w=740`)
// } catch (error: any) {
// toast.warning(error.message)
// console.log(error);
// }
// }
const handleDownload = async () => {
if (!cardRef.current) return;
const img = cardRef.current.querySelector('img');
if (!img || !img.complete) {
// Wait until the barcode image has fully loaded
await new Promise((resolve) => {
img.onload = resolve;
});
}
const canvas = await html2canvas(cardRef.current, {
useCORS: true, // Important for external images
});
const dataUrl = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = dataUrl;
link.download = `${agent_name}_barcode_card.png`;
link.click();
};
return (
<div className="flex flex-col items-center">
{/* Card content to render */}
<div ref={cardRef}
className="relative w-[320px] h-[460px] rounded-xl overflow-hidden shadow-xl bg-white"
>
<div className="absolute inset-0 z-10 flex flex-col items-center justify-start pt-[50px] px-4 text-center">
<p className="text-[24px] font-semibold text-[#5b0066] mb-5">
{agent_name}
</p>
{barcode && (
<img
src={barcode}
alt="Barcode"
className="w-56 h-56 object-contain mb-2"
/>
)}
</div>
</div>
{/* Download Button */}
<button
onClick={handleDownload}
className="mt-4 border border-red-400 text-red-500 px-4 py-1 rounded hover:bg-red-50 text-sm"
>
Print QR
</button>
</div>
);
return (
<div className="relative w-[320px] h-[460px] rounded-xl overflow-hidden shadow-xl">
<div className="absolute inset-0 z-10 flex flex-col items-center justify-start pt-[50px] px-4 text-center">
<p className="text-[24px] font-semibold text-[#5b0066] mb-5">
{agent_name}
</p>
{barcode && (
<img
src={barcode}
alt="Barcode"
className="w-70 h-70 object-contain mb-2"
/>
)}
</div>
</div>
);
// return (
// <div className="relative w-[320px] h-[460px] rounded-xl overflow-hidden shadow-lg">
// {/* Background Card Image */}
// <img
// src={toAbsoluteUrl("/media/images/card.png")}
// alt="Card Template"
// className="absolute inset-0 w-full h-full object-cover"
// />
// {/* Content Overlay */}
// <div className="absolute inset-0 z-10 flex flex-col items-center justify-start pt-32 px-4 text-center">
// {/* Agent Name at Top */}
// <p className="text-sm font-semibold text-[#5b0066] mb-4">
// {agent_name}
// </p>
// {/* Barcode */}
// {barcode && (
// <img
// src={barcode}
// alt="Barcode"
// className="w-40 h-40 object-contain mb-4"
// />
// )}
// </div>
// </div>
// );
};
export default AgentBalance;

View File

@ -143,4 +143,15 @@ export const getColumns = (handleUpdate: (data: any) => void): ColumnDef<AgentBa
);
}
},
{
id: 'actions',
cell: ({ row }) => {
const dataMembers = row.original;
return (
<button className="btn btn-sm btn-icon btn-clear btn-light" onClick={() => handleUpdate(dataMembers)}>
<KeenIcon icon="notepad-edit" />
</button>
);
}
}
];

View File

@ -121,22 +121,7 @@ const ManageMembers = () => {
sorting: any,
filter: any
) => {
// [ SAMPLE
// {
// "id": "username",
// "value": "d"
// },
// {
// "id": "group_name",
// "value": "Bank"
// },
// {
// "id": "msisdn",
// "value": "88"
// }
// ]
sorting = sorting.length == 0 ? [{ id: 'name', desc: true }] : sorting;
// filter = filter.length ? { any: filter[0].value?.toLowerCase() } : {};
filter = filter.length ? filter : {};
const res = await axios.get(`${BASE_URL}/customer/list`, {

View File

@ -49,7 +49,7 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
img: ''
});
const [banks] = useState([
{ name: 'BNCTL',id: 'BNCTL' }, { name: 'BRI',id: 'BRI' }, { name: 'BNU',id: 'BNU' }, { name: 'Mandiri',id: 'Mandiri' }
{ name: 'BNCTL',id: 'BNCTL' }, { name: 'BRI',id: 'BRI' }, { name: 'BNU',id: 'BNU' }, { name: 'MANDIRI',id: 'MANDIRI' }
])
const parentRef = useRef<any | null>(null);
const [alert, setAlert] = useState({
@ -214,7 +214,7 @@ const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialDa
{(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 === "create"||false): ''}
{(formData.id || dialogType === "create") ? generateInput(formData, handleChange, 'Phone Number', 'msisdn', 'text', true, dialogType === "create"?false:true): ''}
{(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): ''}