368 lines
18 KiB
TypeScript
368 lines
18 KiB
TypeScript
import { apiConfig } from '@/config/api.config';
|
|
import { Alert, useDataGrid } from '@/components';
|
|
import { useCallApi } from '@/hooks';
|
|
import { getAuth } from '@/auth';
|
|
import axios from 'axios';
|
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { toast } from 'sonner';
|
|
import {
|
|
Dialog,
|
|
DialogBody,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle
|
|
} from '@/components/ui/dialog';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue
|
|
} from '@/components/ui/select';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Button } from '@/components/ui/button';
|
|
const BASE_URL_MASTER_DATA = apiConfig.service_master_data;
|
|
const URL_NATIONALITY = apiConfig.nationality;
|
|
import { initialMember } from "../Columns";
|
|
import AdmAccess from './AdmAccess';
|
|
import CustomerWallet from './CustomerWallet';
|
|
|
|
const DetailMember = ({ showAddDialog, setShowAddDialog, handleSubmit, initialData, handleReject, page, fetchCustomers,
|
|
handleClose, profession
|
|
}: any) => {
|
|
const [formData, setFormData] = useState(initialData || initialMember);
|
|
const [viewOnly, setViewOnly] = useState(false);
|
|
const [nationality, setNationality] = useState([]);
|
|
const [municipios, setMunicipios] = useState([]);
|
|
const [aldeias, setAldeias] = useState([]);
|
|
const [postoAdm, setPostoAdm] = useState([]);
|
|
const [sucos, setSucos] = useState<any>([]);
|
|
const [genders] = useState([ { name: 'Male',id: 'M' }, { name: 'Female',id: 'F' }])
|
|
const [status] = useState([
|
|
{ name: 'Active',id: 'Y' }, { name: 'Inactive',id: 'N' }, { name: 'Suspend PIN',id: 'P' }, { name: 'Suspend OTP',id: 'O' }
|
|
])
|
|
const [banks] = useState([
|
|
{ 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({
|
|
show: false,
|
|
message: ''
|
|
});
|
|
|
|
useEffect(() => {
|
|
setFormData(initialData || {});
|
|
// fetchMasterData()
|
|
}, [initialData]);
|
|
|
|
const handleChange = async (e: any) => {
|
|
const { name, value } = e.target;
|
|
if (name === "file_selfie" || name === "photouser" || name === 'file_document_id' || name === "file_document_id_selfie" ||
|
|
name === "file_commercial_license") { // FOR FILE ONLY
|
|
setFormData({ ...formData, [name]: e.target.files[0] });
|
|
} else if(name === "nationality") {
|
|
let getNationality = await axios.get(`${URL_NATIONALITY}/${value}`);
|
|
setNationality(getNationality.data.data)
|
|
setFormData({ ...formData, [name]: value });
|
|
} else {
|
|
setFormData({ ...formData, [name]: value });
|
|
if (name === 'municipio' || name === 'posto_adms' || name === 'suco') await getMasterAfter(name, value);
|
|
}
|
|
};
|
|
|
|
async function getMasterAfter(name: string, id: any) {
|
|
if (name === 'municipio') {
|
|
let getMunicipiosPosto = await axios.get(`${BASE_URL_MASTER_DATA}/municipios/postoadms/${id}`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setPostoAdm(getMunicipiosPosto.data.data)
|
|
}
|
|
if (name === 'posto_adms') {
|
|
let getPostoSuco = await axios.get(`${BASE_URL_MASTER_DATA}/postoadms/sucos/${id}`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setSucos(getPostoSuco.data.data)
|
|
}
|
|
if (name === 'suco') {
|
|
let getSucoAldeias = await axios.get(`${BASE_URL_MASTER_DATA}/sucos/aldeias/${id}`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setAldeias(getSucoAldeias.data.data)
|
|
}
|
|
}
|
|
|
|
const handleAddDialog = (show:boolean) => {
|
|
if (show) {
|
|
setShowAddDialog(show)
|
|
} else {
|
|
handleClose()
|
|
setShowAddDialog(show)
|
|
}
|
|
}
|
|
|
|
async function fetchMasterData() {
|
|
try {
|
|
let getMunicipios = await axios.get(`${BASE_URL_MASTER_DATA}/municipios/list`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setMunicipios(getMunicipios.data.data.list)
|
|
let getPostoAdms = await axios.get(`${BASE_URL_MASTER_DATA}/postoadms/list`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setPostoAdm(getPostoAdms.data.data.list)
|
|
let getSucos = await axios.get(`${BASE_URL_MASTER_DATA}/sucos/list`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setSucos(getSucos.data.data.list)
|
|
let getAldeias = await axios.get(`${BASE_URL_MASTER_DATA}/aldeias/list`, {
|
|
params: {
|
|
limit: 50,
|
|
page: 1,
|
|
with_deleted: false,
|
|
order_field: 'name',
|
|
order_direction: 'ASC',
|
|
}
|
|
});
|
|
setAldeias(getAldeias.data.data.list)
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
function buttonOnSubmit(e:any) {
|
|
e.preventDefault();
|
|
if (page === 'kyc' && formData.destinationGroup === "Premium" && !formData.approval_description_premium) return toast.warning(`Approval Premium Description needed!`)
|
|
if (page === 'kyc' && formData.destinationGroup === "Agent" && !formData.approval_description_premium) return toast.warning(`Approval Agent Description needed!`)
|
|
if (page === 'kyc' && !formData.description) return toast.warning(`Description for approval needed!`)
|
|
handleSubmit(formData);
|
|
}
|
|
|
|
function btnPrevDef(e:any) {
|
|
e.preventDefault();
|
|
viewOnly ? setViewOnly(false) : setViewOnly(true)
|
|
}
|
|
|
|
const onReject = () => {
|
|
handleReject(formData);
|
|
handleClose();
|
|
}
|
|
|
|
return (
|
|
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
|
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5">
|
|
<DialogHeader>
|
|
<DialogTitle>Member - View/Edit</DialogTitle>
|
|
<DialogDescription></DialogDescription>
|
|
</DialogHeader>
|
|
<DialogBody ref={parentRef}>
|
|
<div className="flex flex-col">
|
|
{alert.show && (
|
|
<Alert variant="danger">
|
|
<h3>{alert.message}</h3>
|
|
</Alert>
|
|
)}
|
|
|
|
{/* <form> */}
|
|
{/* onSubmit={(e) => buttonOnSubmit(e, formData)} */}
|
|
<div className="card-body grid gap-5">
|
|
|
|
{formData.id ? generateInput(formData, handleChange, 'Group', 'group_name', 'text', true, true): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Username', 'username', 'text', true, true): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Full Name', 'fullname', 'text', true, viewOnly): ''}
|
|
{formData.id ? generateImage(formData, handleChange, 'Photo', 'photouser'): ''}
|
|
{formData.id ? generateList(formData, handleChange, genders, 'gender', 'Gender', null, true): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Date of Birth', 'date_birth', 'date', true, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Phone Number', 'msisdn', 'text', true, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Email', 'email', 'text', true, viewOnly): ''}
|
|
{/* {generateList(formData, handleChange, status, 'status', 'Status', null, true)} */}
|
|
{formData.id ? generateList(formData, handleChange, profession, 'profession', 'Profession', null, false): ''}
|
|
{formData.id ? generateList(formData, handleChange, municipios, 'municipio', 'Municipio', null, false): ''}
|
|
{formData.id ? generateList(formData, handleChange, postoAdm, 'posto_adms', 'Posto', 'posto_adms_id', false): ''}
|
|
{formData.id ? generateList(formData, handleChange, sucos, 'suco', 'Suco', 'sucos_id', false): ''}
|
|
{formData.id ? generateList(formData, handleChange, aldeias, 'aldeia', 'Aldeia', null, false): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Nationality', 'nationality', 'text', true, viewOnly): ''}
|
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label className="form-label flex items-center gap-1 max-w-56"></label>
|
|
<ul className="">
|
|
{nationality.map((item: any, index) => (
|
|
<li key={index} value={item.name}
|
|
onClick={() => handleChange({target:{name: 'nationality', value: item.name }})}
|
|
className="bg-gray-100 px-4 py-2 rounded hover:bg-gray-200 cursor-default transition">
|
|
{item.name}
|
|
</li>
|
|
))}
|
|
{formData.nationality && nationality.length === 0 && (
|
|
<li className="text-gray-500">No results found.</li>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
{formData.id ? generateInput(formData, handleChange, 'Address', 'address', 'text', true, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Mother Fullname', 'mother_fullname', 'text', true, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Identity Number', 'identity_number', 'text', false, viewOnly): ''}
|
|
|
|
{formData.id ? generateInput(formData, handleChange, 'License Number', 'license_number', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Merchant Name', 'agent_name', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Merchant Address', 'merchantaddress', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Longitude Merchant', 'longitudemerchant', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Latitude Merchant', 'latitudemerchant', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateImage(formData, handleChange, 'File Selfie', 'file_selfie'): ''}
|
|
{formData.id ? generateImage(formData, handleChange, 'File Document', 'file_document_id'): ''}
|
|
{formData.id ? generateImage(formData, handleChange, 'File Document & Selfie', 'file_document_id_selfie'): ''}
|
|
{formData.id ? generateImage(formData, handleChange, 'File Commercial License', 'file_commercial_license'): ''}
|
|
|
|
{formData.id ? generateList(formData, handleChange, banks, 'bank_name', 'Bank Name', null, false): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Bank Account', 'bank_account', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'iBank Number', 'ibank_number', 'text', false, viewOnly): ''}
|
|
|
|
{formData.id ? generateInput(formData, handleChange, 'Approval Premium Description', 'approval_description_premium', 'text', false, viewOnly): ''}
|
|
{formData.id ? generateInput(formData, handleChange, 'Approval Agent Description', 'approval_description_agent', 'text', false, viewOnly): ''}
|
|
|
|
{(formData.id && page!=='kyc') ? AdmAccess(page, formData, handleClose,fetchCustomers, viewOnly, setViewOnly): ""}
|
|
{(formData.id && page!=='kyc') ? CustomerWallet(formData.id) : ""}
|
|
|
|
<div className="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> */}
|
|
{
|
|
formData.isneedapproval == 1 && page === 'kyc' ? (
|
|
<Button onClick={onReject} variant="destructive" color="warning">Reject</Button>
|
|
) : ('')
|
|
}
|
|
<Button onClick={(e) => buttonOnSubmit(e)} color="primary" variant="default">
|
|
{ formData.id ? (formData.isneedapproval == 1 && page === 'kyc' ? (`Edit & Approve`) : (`Edit`)) : ("Create") }
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
{/* </form> */}
|
|
</div>
|
|
</DialogBody>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|
|
export default DetailMember;
|
|
{/* <span className="text-red-500 text-[10px] lowercase align-middle ml-1">(agent)</span> */}
|
|
|
|
function generateInput(formData:any, handleChange:any, label:string, name:string, type: string, required: boolean, disabled: boolean) {
|
|
function generateDate(isoString: string) {
|
|
const date = new Date(isoString);
|
|
return date.toISOString().slice(0, 10); // "2000-01-18"
|
|
}
|
|
return (
|
|
<>
|
|
<div className="w-full">
|
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label className="form-label flex items-center gap-1 max-w-56">
|
|
{label}<span className="text-red-500">{required?"*":""}</span>
|
|
</label>
|
|
<Input
|
|
className="input"
|
|
readOnly={disabled}
|
|
required={required}
|
|
type={type}
|
|
name={name}
|
|
value={formData[name]?(type === 'date' ? generateDate(formData[name]) : formData[name]):""}
|
|
onChange={handleChange}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
// ON DEV (DI SELECT MASI HILANG)
|
|
function generateList(formData:any, handleChange: any, list:any, name:string, label: string, difId: any, required: boolean) {
|
|
return (
|
|
<>
|
|
<div className="w-full">
|
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
|
<label className="form-label flex items-center gap-1 max-w-56">{label}
|
|
<span className="text-red-600">{required?"*":""}</span></label>
|
|
<Select required={required} value={formData[name]} onValueChange={(e) => (handleChange({ target : { name, value: e }}))}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder={`Select ${label}`} />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{list.map((el: any, idx: any) => (
|
|
<SelectItem key={idx} value={el.id}>{el.name}</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
// ON DEV (UPDATENYA)
|
|
function generateImage(formData:any, handleChange:any, label:string, name:string) {
|
|
const imagePreview = (file:any) => {
|
|
if (file && file.type && file.type.startsWith('image/')) {
|
|
const previewURL = URL.createObjectURL(file);
|
|
return previewURL
|
|
}
|
|
return file
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<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>
|
|
</label>
|
|
<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={formData[name]} src={formData[name]} alt={name} style={{borderRadius: 10}}/> */}
|
|
</div>
|
|
) : (<span>No Data</span>)}
|
|
<label className="bg-red-600 text-white px-2 py-1 rounded-full flex items-center cursor-pointer hover:bg-red-800">
|
|
<span style={{fontSize: 13}}>Upload</span>
|
|
<input type="file" className="hidden" name={name} onChange={handleChange} accept="image/*" />
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|