Merge branch 'feature/flag-log-status' into staging

This commit is contained in:
Iqbal
2026-05-05 14:35:21 +07:00
37 changed files with 812 additions and 263 deletions

View File

@@ -142,7 +142,9 @@
"txtDPPJ": "DPJP",
"txtSpecialist": "Specialist",
"txtWarningDPPJ": "Please input DPJP",
"txtWarningSpecialist": "Please select Specialist"
"txtWarningSpecialist": "Please select Specialist",
"txtLogType": "LOG Type",
"txtStatusFinalLog": "Final LOG Status"
}

View File

@@ -142,5 +142,7 @@
"txtDPPJ": "DPJP",
"txtSpecialist": "Spesialis",
"txtWarningDPPJ": "Mohon isi DPJP",
"txtWarningSpecialist": "Mohon pilih Spesialis"
"txtWarningSpecialist": "Mohon pilih Spesialis",
"txtLogType": "Tipe LOG",
"txtStatusFinalLog": "Status Final LOG"
}

View File

@@ -679,4 +679,4 @@ export default function DialogBenefit({requestLog, setOpenDialog, openDialog, cl
maxWidth="xl"
/>
);
}
}

View File

@@ -73,7 +73,7 @@ export default function DialogConfirmation({requestLog, setOpenDialog, openDialo
}
const handleSubmit = () => {
if (formData.type_of_member == "" && requestLog?.corporate_id == 5) { // corporate vale
if (formData.type_of_member == "" && requestLog?.view_type_member) { // corporate vale
setError(true);
alert('Silakan pilih Type Of Member sebelum mengirimkan data.');
}
@@ -121,10 +121,12 @@ export default function DialogConfirmation({requestLog, setOpenDialog, openDialo
<Typography variant='subtitle2' sx={style1} gutterBottom>Member ID</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.member_id}</Typography>
</Stack>
{requestLog?.view_type_member ? (
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Member Of Type</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.type_of_member}</Typography>
</Stack>
):('')}
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Policy Number</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.policy_number}</Typography>
@@ -189,24 +191,26 @@ export default function DialogConfirmation({requestLog, setOpenDialog, openDialo
)}
/>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member*</Typography>
<Select
fullWidth
value={formData.type_of_member}
onChange={(e) => handleChange('type_of_member', e.target.value)}
variant="outlined"
displayEmpty
required
error={error}
>
<MenuItem value="" disabled>
Type Member
</MenuItem>
<MenuItem value="OMT">OMT</MenuItem>
<MenuItem value="Non OMT">Non OMT</MenuItem>
</Select>
</Stack>
{requestLog?.view_type_member ? (
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member</Typography>
<Select
fullWidth
value={formData.type_of_member}
onChange={(e) => handleChange('type_of_member', e.target.value)}
variant="outlined"
displayEmpty
required
error={error}
>
<MenuItem value="" disabled>
Type Member
</MenuItem>
<MenuItem value="OMT">OMT</MenuItem>
<MenuItem value="Non OMT">Non OMT</MenuItem>
</Select>
</Stack>
):('')}
</Card>
</Grid>
<DialogActions>

View File

@@ -79,7 +79,6 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
const amountApproved = parseFloat(watch('amount_approved'));
const amountNotApproved = parseFloat(watch('amount_not_approved'));
const excessPaid = parseFloat(watch('excess_paid'));
// Hitung total baru
const totalAmountIncurred = total.totalAmountIncurred - data?.amount_incurred + amountIncurred;
const totalAmountApproved = total.totalAmountApproved - data?.amount_approved + amountApproved;
@@ -203,7 +202,6 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
<Typography variant="subtitle1" sx={{ fontWeight: 'bold'}}>
{data?.benefit?.description}
</Typography>
</Grid>
<Grid item xs={2}>
<Grid container spacing={2}>
@@ -445,4 +443,4 @@ export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,
maxWidth="xl"
/>
);
}
}

View File

@@ -29,7 +29,9 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
icdCodes: requestLog?.diagnosis,
reason: requestLog?.reason,
type_of_member: requestLog?.type_of_member,
organization_id: requestLog?.organization_id || 0,
status: 'requested',
edit: true
});
const [error, setError] = useState(false);
@@ -62,8 +64,11 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
icdCodes: requestLog?.diagnosis|| [],
reason: requestLog?.reason|| '',
type_of_member: requestLog?.type_of_member|| '',
organization_id: requestLog?.organization_id || 0,
status: 'requested',
edit: true
});
setIdProvider(requestLog?.organization_id || 0); // ✅ sekalian sync UI
}, [requestLog]);
@@ -98,7 +103,7 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
const handleSubmit = () => {
if (formData.type_of_member == "" && requestLog?.corporate_id == 5) {
if (formData.type_of_member == "" && requestLog?.view_type_member) {
setError(true);
alert('Silakan pilih Type Of Member sebelum mengirimkan data.');
}
@@ -109,7 +114,9 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
enqueueSnackbar('Request Final LOG Success', { variant: 'success' });
setOpenDialog(false);
navigate('/detail-request-final-log/' + requestLog?.id)
window.location.reload()
setTimeout(() => {
window.location.reload();
}, 1000); // 1000 ms = 1 detik
})
.catch(({ response }) => {
enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' });
@@ -144,7 +151,9 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
icdCodes: requestLog?.diagnosis ?? [],
reason: requestLog?.reason ?? '',
type_of_member: requestLog?.type_of_member ?? '',
status: 'requested'
organization_id: requestLog?.organization_id || 0,
status: 'requested',
edit: true
});
};
const [isReasonSelected, setIsReasonSelected] = useState(true);
@@ -159,9 +168,28 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
{ value: 'endorsement', label: 'Endorsement' },
{ value: 'renewal', label: 'Renewal' },
{ value: 'wrong_setting', label: 'Wrong Setting' },
{ value: 'approval', label: 'Approval' },
// Add more options as needed
];
const [providers, setProviders] = useState([]);
const [idProvider, setIdProvider] = useState(0);
useEffect(() => {
axios
.get('/organizations')
.then((res) => {
setProviders(res.data.data || []);
})
.catch((err) => console.error(err));
}, []);
useEffect(() => {
if (requestLog?.organization_id) {
setIdProvider(requestLog.organization_id);
}
}, [requestLog]);
// console.log(formData.type_of_member)
const getContent = () => (
@@ -196,6 +224,26 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
</Card>
<Card sx={{padding:2, marginTop:2}} >
<Stack direction="row" spacing={2} sx={marginBottom2}>
<Typography variant="subtitle2" sx={style1} gutterBottom>
Provider
</Typography>
<Autocomplete
options={providers}
getOptionLabel={(option) => option.name?.trim() || '-'}
value={providers.find((item) => item.id == idProvider) || null}
onChange={(event, newValue) => {
const id = newValue?.id || 0;
setIdProvider(id);
handleChange('organization_id', id);
}}
renderInput={(params) => (
<TextField {...params} label="Provider" fullWidth />
)}
fullWidth
/>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Invoice Provider</Typography>
<TextField
@@ -216,24 +264,26 @@ export default function DialogEditFinalLOG({requestLog, setOpenDialog, openDialo
onChange={(e) => handleChange('billing_no', e.target.value)}
/>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member*</Typography>
<Select
fullWidth
value={formData.type_of_member}
onChange={(e) => handleChange('type_of_member', e.target.value)}
variant="outlined"
displayEmpty
required
error={error}
>
<MenuItem value="" disabled>
Type Member
</MenuItem>
<MenuItem value="OMT">OMT</MenuItem>
<MenuItem value="Non OMT">Non OMT</MenuItem>
</Select>
</Stack>
{requestLog?.view_type_member ? (
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member</Typography>
<Select
fullWidth
value={formData.type_of_member}
onChange={(e) => handleChange('type_of_member', e.target.value)}
variant="outlined"
displayEmpty
required
error={error}
>
<MenuItem value="" disabled>
Type Member
</MenuItem>
<MenuItem value="OMT">OMT</MenuItem>
<MenuItem value="Non OMT">Non OMT</MenuItem>
</Select>
</Stack>
):('')}
<Stack direction='row' spacing={2} sx={marginBottom2}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Discharge Date</Typography>
<TextField

View File

@@ -296,10 +296,10 @@ export default function DetailRequestFinalLog() {
>([])
useEffect(() => {
if (!requestLog?.id && !Log_id) return
if (!requestLog?.id_member) return
axios
.get('service-member/' + (requestLog?.id ?? Log_id))
.get('service-member/' + (requestLog?.id_member ?? null))
.then((res) => setServiceOptions(res.data))
.catch(console.error)
@@ -307,7 +307,7 @@ export default function DetailRequestFinalLog() {
.get('specialis')
.then((res) => setSpecialisOptions(res.data))
.catch(console.error)
}, [requestLog?.id, Log_id])
}, [requestLog?.id_member])
const [serviceCode, setServiceCode] = useState<string>('')
@@ -356,7 +356,7 @@ export default function DetailRequestFinalLog() {
}
setSubmitLoading(true);
const formData = makeFormData({
request_logs_id: Log_id,
request_logs_id: requestLog?.id,
// result_files: fileHasilPenunjangs,
// diagnosa_files: fileDiagnosas,
// kondisi_files: fileKondisis,
@@ -364,6 +364,7 @@ export default function DetailRequestFinalLog() {
service_code: serviceCode,
spescialis_id: idSpecialities,
dppj: inputDppj,
edit: true
});
axios
.post('/request-final-log', formData)
@@ -424,7 +425,7 @@ export default function DetailRequestFinalLog() {
Detail
</Typography>
</Grid>
{requestLog?.status_final_log != 'requested' ? (
{requestLog?.status_final_log != 'approved' ? (
<Grid item xs={6} sx={{ display: 'flex', placeContent: 'end' }}>
<MoreMenu
actions={
@@ -457,10 +458,13 @@ export default function DetailRequestFinalLog() {
<Typography variant='subtitle2' sx={style1} gutterBottom>Member ID</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.member_id}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.type_of_member}</Typography>
</Stack>
{requestLog?.view_type_member ? (
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Type Of Member</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.type_of_member}</Typography>
</Stack>
):('')}
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Policy Number</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.policy_number}</Typography>
@@ -512,7 +516,7 @@ export default function DetailRequestFinalLog() {
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.specialities_id ? requestLog?.specialities_id : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>DPPJ</Typography>
<Typography variant='subtitle2' sx={style1} gutterBottom>DPJP</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{requestLog?.dppj ? requestLog?.dppj : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
@@ -639,7 +643,7 @@ export default function DetailRequestFinalLog() {
<Stack direction="row" spacing={2}>
<Stack spacing={2} sx={{ width: '100%' }}>
<Typography variant='subtitle1'>DPPJ </Typography>
<Typography variant='subtitle1'>DPJP </Typography>
<TextField
id='dppj'
variant='outlined'
@@ -893,7 +897,14 @@ export default function DetailRequestFinalLog() {
!isReversal ? (
<Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}} onClick={() => {
if (!requestLog?.discharge_date || !requestLog?.service_code || !requestLog?.specialitiesID || !requestLog?.dppj) {
alert('Lengkapi Tanggal Keluar, Service Code, Specialities, dan DPPJ terlebih dahulu, lalu simpan');
alert(
'Lengkapi:\n\n' +
'- Tanggal Keluar\n' +
'- Service Code\n' +
'- Specialities\n' +
'- DPPJ\n\n' +
'Terlebih dahulu, lalu simpan'
);
return;
}
setDialogBenefit(true);
@@ -1307,8 +1318,15 @@ export default function DetailRequestFinalLog() {
!(requestLog?.files?.length > 0)
) {
alert(
'Lengkapi Tanggal Keluar, Service Code, Specialities, DPPJ, isi benefit, dan upload files terlebih dahulu, lalu simpan'
);
'Lengkapi:\n\n' +
'- Tanggal Keluar\n' +
'- Service Code\n' +
'- Specialities\n' +
'- DPJP\n' +
'- Isi Benefit\n' +
'- Upload Files\n\n' +
'Terlebih dahulu, lalu simpan'
);
return;
}
@@ -1316,7 +1334,7 @@ export default function DetailRequestFinalLog() {
setOpenDialogSubmit(true);
}}
>
Request Final LOG
{requestLog?.status_final_log == 'requested' ? 'Update' : 'Request Final LOG'}
</Button>
</div>
@@ -1330,7 +1348,6 @@ export default function DetailRequestFinalLog() {
</Stack>
</Grid>
) : null}
</Grid>
</Container>
</Page>

View File

@@ -35,6 +35,12 @@ export type DetailFinalLogType = {
id : number,
code : string,
member_id : string,
view_type_member : any,
organization_id : any,
id_member : string,
service_code : string,
specialitiesID : any,
dppj : any,
invoice_no : string,
billing_no : string,
provider : string,

View File

@@ -188,7 +188,7 @@ export default function TableListFinalLog() {
// enqueueSnackbar('Mohon isi alasan', { variant: 'warning' });
// return false;
// }
axios.post('/submit-claims', {
axios.post('/submit-claims', {
selectedRows: selectedRows
})
.then((response) => {
@@ -202,7 +202,7 @@ export default function TableListFinalLog() {
enqueueSnackbar(response.data.meta.message, {variant : "error"});
}
getData();
setSelectedRows([]);
setSelectedRows([]);
})
.catch(({response}) => {
enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.meta.message : 'Opps, Something went Wrong!'), {variant : "error"})
@@ -344,6 +344,12 @@ export default function TableListFinalLog() {
label: localeData.txtServiceType,
isSort: true,
},
{
id: 'log_type',
align: 'center',
label: 'LOG Type',
isSort: true,
},
{
id: 'discharge_date',
align: 'center',
@@ -365,8 +371,8 @@ export default function TableListFinalLog() {
];
function handleSearchMember(noPolis:any, birthDate:any) {
setLoadingClaim(false)
axios.post('/search-member', {
no_polis: noPolis,
axios.post('/search-member', {
no_polis: noPolis,
birth_date: birthDate ? fPostFormat(birthDate, 'yyyy-MM-dd') : null,
type: 'view'
})
@@ -447,6 +453,24 @@ export default function TableListFinalLog() {
Pending
</Label>
),
log_type:
obj.log_type === 'final' ? (
<Label color='info'>
Final
</Label>
) : obj.log_type === 'prescription' ? (
<Label color='warning'>
Prescription
</Label>
) : obj.log_type === 'reference' ? (
<Label color='secondary'>
Reference
</Label>
) : (
<Label color='default'>
-
</Label>
),
submission_date:
<Label>
{obj.submission_date ? fDateTime(obj.submission_date) : ''}
@@ -466,6 +490,27 @@ export default function TableListFinalLog() {
<Iconify icon="eva:eye-fill" />
View
</MenuItem>
{obj.status !== 'approved' ? (
<MenuItem
onClick={() =>
navigate('/detail-request-final-log/'+obj.id, {
state: {
Log_id: obj.id,
full_name: obj.full_name,
no_polis: obj.no_polis,
submission_date: obj.submission_date,
service_code: obj.service_code,
member_id: obj.member_id,
specialities_id: obj.specialities_id,
dppj: obj.dppj,
},
})
}
>
<Iconify icon="fa:file-text" />
Edit
</MenuItem>
):''}
{obj.status === 'approved' ? (
<MenuItem onClick={() => handleDownloadLog(obj.id, obj.service_code, obj.no_polis, obj.full_name, obj.provider, obj.approved_final_log_at)}>
<Iconify icon="eva:download-fill" />
@@ -542,7 +587,7 @@ export default function TableListFinalLog() {
DialogMember(currentMember, () => setOpenDialogBenefit(false))
}
maxWidth="sm"
/>
/>
<MuiDialog
title={{name: dataViewClaimSubmit?.full_name}}
openDialog={openDialogClaimSubmit}
@@ -573,7 +618,7 @@ export default function TableListFinalLog() {
</Stack>
</DialogTitle>
<DialogContent>
<Stack spacing={2} padding={2}>
<Typography variant='body1'>{localeData.txtDialogConfirmation}</Typography>
{valDialog == "decline" ? (
@@ -596,7 +641,7 @@ export default function TableListFinalLog() {
<Button variant="outlined" sx={{color: '#212B36', borderColor: '#919EAB52'}} onClick={handleCloseDialogSubmit}>{localeData.txtCancel}</Button>
<Button sx={{backgroundColor: (valDialog === 'decline' ? '' : '#19BBBB'), color: (valDialog === 'decline' ? '#FF4842' : ''), borderColor: '#FF4842'}} onClick={handleSubmitData} variant={(valDialog === 'decline' ? 'outlined' : 'contained')}>{(valDialog === "decline" ? localeData.txtDeclaine : 'Submit')}</Button>
</DialogActions>
</Dialog>
</Dialog>
</>
);
}

View File

@@ -294,6 +294,12 @@ export default function TableList() {
label: localeData.txtRequestCode,
isSort: true,
},
{
id: 'log_type',
align: 'left',
label: localeData.txtLogType,
isSort: true,
},
{
id: 'provider',
align: 'left',
@@ -318,6 +324,12 @@ export default function TableList() {
label: localeData.txtStatus,
isSort: true,
},
{
id: 'status_final_log',
align: 'center',
label: localeData.txtStatusFinalLog,
isSort: true,
},
{
id: 'action',
align: 'right',
@@ -399,6 +411,34 @@ export default function TableList() {
...obj,
provider:obj.provider,
full_name:formatTitleCase(obj.full_name),
log_type:
obj.log_type === 'reference' ? (
<Label color='info'>
Rujukan
</Label>
) : obj.log_type === 'prescription' ? (
<Label color='warning'>
Resep
</Label>
) : obj.log_type === 'consultation' ? (
<Label color='primary'>
Konsultasi
</Label>
) : (
<Label color='default'>
-
</Label>
),
status_final_log:
obj.final_log === 1 ? (
<Label color='primary'>
Request
</Label>
) : (
<Label color='error'>
Belum Dibuat
</Label>
),
status:
obj.status === 'requested' ? (
<Label color='primary'>