522 lines
19 KiB
TypeScript
522 lines
19 KiB
TypeScript
import * as Yup from 'yup';
|
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
import {
|
|
Autocomplete,
|
|
Box,
|
|
Button,
|
|
Card,
|
|
Collapse,
|
|
Container,
|
|
Divider,
|
|
Grid,
|
|
InputAdornment,
|
|
Paper,
|
|
Stack,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableRow,
|
|
TextField,
|
|
Typography,
|
|
} from '@mui/material';
|
|
import { useParams } from 'react-router-dom';
|
|
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
|
|
import Page from '../../components/Page';
|
|
import useSettings from '../../hooks/useSettings';
|
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
import { styled } from '@mui/system';
|
|
import axios from '../../utils/axios';
|
|
import { enqueueSnackbar } from 'notistack';
|
|
import { LoadingButton } from '@mui/lab';
|
|
import { fDate } from '@/utils/formatTime';
|
|
import Iconify from '../../components/Iconify';
|
|
import Documents from './components/Documents';
|
|
import DiagnosisHistory from './components/DiagnosisHistory';
|
|
import ClaimItems from './components/ClaimItems';
|
|
import DialogMemberBenefit from './components/DialogMemberBenefit';
|
|
import ClaimDetail from './components/ClaimDetail';
|
|
import DialogHistoryPerawatan from './components/DialogHistoryPerawatan';
|
|
import { IconButton } from '@mui/material';
|
|
import { Tooltip } from '@mui/material';
|
|
import { useSelector } from 'react-redux';
|
|
|
|
export default function ClaimsCreateUpdate() {
|
|
const { themeStretch } = useSettings();
|
|
const { id } = useParams();
|
|
|
|
const isEdit = id ? true : false;
|
|
|
|
const [currentClaim, setCurrentClaim] = useState();
|
|
const [documents, setDocuments] = useState([]);
|
|
|
|
const claimsHistoryData = useSelector((state) => state.claimsHistory)
|
|
|
|
console.log(claimsHistoryData)
|
|
|
|
const Item = styled(Paper)(({ theme }) => ({
|
|
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
|
|
...theme.typography.body2,
|
|
padding: theme.spacing(1),
|
|
textAlign: 'center',
|
|
color: theme.palette.text.secondary,
|
|
}));
|
|
|
|
// --------------------------------------------------------------
|
|
// Claim Item
|
|
const [claimItems, setClaimItems] = useState([]);
|
|
const [dialogAddClaimItemOpen, setDialogAddClaimItemOpen] = useState(false);
|
|
const [loadingClaimItems, setLoadingClaimItems] = useState(false);
|
|
|
|
const handleAddClaimItems = (items) => {
|
|
setClaimItems([...claimItems, ...items]);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if(claimsHistoryData) {
|
|
setClaimItems(claimsHistoryData)
|
|
}
|
|
},[claimsHistoryData])
|
|
|
|
const handleSaveClaimItems = () => {
|
|
console.log('Storing ', claimItems);
|
|
setLoadingClaimItems(true);
|
|
axios
|
|
.post(`claims/${id}/update-items`, {
|
|
benefit_items: claimItems.map((benefit) => {
|
|
return {
|
|
id: benefit.id,
|
|
biaya_diajukan: benefit.biaya_diajukan,
|
|
biaya_disetujui: benefit.biaya_disetujui,
|
|
};
|
|
}),
|
|
})
|
|
.then((res) => {
|
|
enqueueSnackbar(res.data.message, { variant: 'success' });
|
|
})
|
|
.catch((err) => {
|
|
setLoadingClaimItems(false);
|
|
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
|
|
})
|
|
.then(() => {
|
|
setLoadingClaimItems(false);
|
|
});
|
|
};
|
|
|
|
const handlePrimaryDiagnosisChange = (diagnosisOption) => {
|
|
console.log('handle', diagnosisOption);
|
|
if (diagnosisOption) {
|
|
const { title, value } = diagnosisOption;
|
|
setPrimaryDiagnosis(value);
|
|
} else {
|
|
setPrimaryDiagnosis(null);
|
|
}
|
|
};
|
|
|
|
const handleSecondaryDiagnosisChange = ({ title, value }) => {
|
|
setSecondaryDiagnosis(value);
|
|
};
|
|
|
|
const handleDecline = () => {
|
|
axios
|
|
.post(`claims/${id}/decline`)
|
|
.then((res) => {
|
|
enqueueSnackbar(res.data.message, { variant: 'success' });
|
|
setCurrentClaim({ ...currentClaim, status: 'declined' });
|
|
})
|
|
.catch((err) => {
|
|
// setLoadingDiagnosis(false)
|
|
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
|
|
})
|
|
.then(() => {
|
|
// setLoadingDiagnosis(false)
|
|
});
|
|
};
|
|
|
|
const handleApprove = () => {
|
|
axios
|
|
.post(`claims/${id}/approve`)
|
|
.then((res) => {
|
|
enqueueSnackbar(res.data.message, { variant: 'success' });
|
|
setCurrentClaim({ ...currentClaim, status: 'approved' });
|
|
})
|
|
.catch((err) => {
|
|
// setLoadingDiagnosis(false)
|
|
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
|
|
})
|
|
.then(() => {
|
|
// setLoadingDiagnosis(false)
|
|
});
|
|
};
|
|
|
|
const handleReOpen = () => {
|
|
axios
|
|
.post(`claims/${id}/re-open`)
|
|
.then((res) => {
|
|
enqueueSnackbar(res.data.message, { variant: 'success' });
|
|
setCurrentClaim({ ...currentClaim, status: 'received' });
|
|
})
|
|
.catch((err) => {
|
|
// setLoadingDiagnosis(false)
|
|
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
|
|
})
|
|
.then(() => {
|
|
// setLoadingDiagnosis(false)
|
|
});
|
|
};
|
|
|
|
// ---------------------------------------------------------------
|
|
// Initial LOG
|
|
const [loadingLog, setLoadingLog] = useState(false);
|
|
|
|
const handleDownloadLog = (claim_id) => {
|
|
setLoadingLog(true);
|
|
axios
|
|
.post(`generate-log/${claim_id}`, {
|
|
responseType: 'blob',
|
|
})
|
|
.then((response) => {
|
|
window.open(URL.createObjectURL(response.data));
|
|
setLoadingLog(false);
|
|
setOpenDialog(false);
|
|
})
|
|
.catch((response) => {
|
|
enqueueSnackbar(response.message, { variant: 'error' });
|
|
setLoadingLog(false);
|
|
});
|
|
};
|
|
|
|
// -------------------------------------------------
|
|
// Final LOG
|
|
const [loadingFinalLog, setLoadingFinalLog] = useState(false);
|
|
const handleDownloadFinalLog = (claim_id) => {
|
|
setLoadingFinalLog(true);
|
|
axios
|
|
.get(`final-log/${claim_id}`, {
|
|
responseType: 'blob',
|
|
})
|
|
.then((response) => {
|
|
window.open(URL.createObjectURL(response.data));
|
|
setLoadingFinalLog(false);
|
|
})
|
|
.catch((response) => {
|
|
enqueueSnackbar(response.message, { variant: 'error' });
|
|
setLoadingFinalLog(false);
|
|
});
|
|
};
|
|
|
|
// ----------------------------------------------------------------
|
|
// History Perawatan
|
|
const [openDialogHistoryPerawatan, setOpenDialogHistoryPerawatan] = useState(false);
|
|
|
|
useEffect(() => {
|
|
axios.get('/claims/' + id).then(({ data }) => {
|
|
const claim = data.data;
|
|
const allFiles = [...(claim.claim_request ? claim.claim_request.files : []), ...claim.files];
|
|
|
|
setCurrentClaim(claim);
|
|
setDocuments(allFiles);
|
|
setClaimItems(claim.benefit_items);
|
|
});
|
|
}, [id]);
|
|
|
|
const handleSetFinalEncounter = (encounter) => {
|
|
const tempLastFinalEncounterId = currentClaim.final_encounter_id
|
|
axios.post(`/claims/${id}/set-final-encounter`, {
|
|
encounter_id: encounter.id
|
|
})
|
|
.then((res) => {
|
|
setCurrentClaim({...currentClaim, ...{final_encounter_id: encounter.id}})
|
|
enqueueSnackbar(res.data.message, {variant: 'success'})
|
|
})
|
|
.catch((err) => {
|
|
setCurrentClaim({...currentClaim, ...{final_encounter_id: tempLastFinalEncounterId}})
|
|
enqueueSnackbar(err.message, {variant: 'error'})
|
|
})
|
|
setCurrentClaim({...currentClaim, ...{final_encounter_id: encounter.id}})
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// Edit History Perawatan
|
|
|
|
const [openDialogEditHistoryPerawatan, setOpenDialogEditHistoryPerawatan] = useState(false)
|
|
const [editedEncounter, setEditedEncounter] = useState(null)
|
|
|
|
const showEditEncounter = (encounter) => {
|
|
setEditedEncounter(encounter)
|
|
setOpenDialogEditHistoryPerawatan(true)
|
|
}
|
|
|
|
return (
|
|
<Page title={`Claim : ${currentClaim?.code}`}>
|
|
<Container maxWidth={themeStretch ? false : 'xl'}>
|
|
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
|
<HeaderBreadcrumbs
|
|
heading={`Claim : ${currentClaim?.code}`}
|
|
links={[
|
|
{ name: 'Dashboard', href: '/dashboard' },
|
|
{
|
|
name: 'Claim',
|
|
href: '/claims',
|
|
},
|
|
{ name: currentClaim?.code ?? '' },
|
|
]}
|
|
/>
|
|
|
|
{/* Action Button */}
|
|
<Stack direction="row" spacing={2} sx={{ position: 'relative', bottom: '15px' }}>
|
|
{(currentClaim?.status == 'requested' || currentClaim?.status == 'received') && (
|
|
<>
|
|
<LoadingButton
|
|
loading={false}
|
|
variant="outlined"
|
|
color="error"
|
|
onClick={() => {
|
|
handleDecline();
|
|
}}
|
|
>
|
|
Decline
|
|
</LoadingButton>
|
|
<LoadingButton
|
|
loading={false}
|
|
variant="contained"
|
|
onClick={() => {
|
|
handleApprove();
|
|
}}
|
|
>
|
|
Approve
|
|
</LoadingButton>
|
|
</>
|
|
)}
|
|
{(currentClaim?.status == 'declined' || currentClaim?.status == 'approved') && (
|
|
<LoadingButton
|
|
loading={false}
|
|
variant="contained"
|
|
onClick={() => {
|
|
handleReOpen();
|
|
}}
|
|
>
|
|
Re-Open
|
|
</LoadingButton>
|
|
)}
|
|
</Stack>
|
|
</Stack>
|
|
|
|
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2, marginY: 2 }}>
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
<Typography>Status : {currentClaim?.status}</Typography>
|
|
{currentClaim?.status == 'approved' && (
|
|
<LoadingButton
|
|
loading={loadingFinalLog}
|
|
variant="contained"
|
|
onClick={() => {
|
|
handleDownloadFinalLog(currentClaim.id);
|
|
}}
|
|
>
|
|
Download Final LOG
|
|
</LoadingButton>
|
|
)}
|
|
</Stack>
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
<Typography>Admission Date : {currentClaim?.claim_request?.submission_date}</Typography>
|
|
</Stack>
|
|
</Paper>
|
|
|
|
<Box sx={{ flexGrow: 1 }}>
|
|
<Grid container spacing={2}>
|
|
<Grid item xs={5}>
|
|
{/* Dokumen Tambahan */}
|
|
<Documents files={documents}></Documents>
|
|
|
|
{/* Riwayat Diagnosa */}
|
|
<DiagnosisHistory diagnosis={[]}></DiagnosisHistory>
|
|
|
|
{/* Ringkasan Data Member */}
|
|
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2, marginTop: 2 }}>
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
<Iconify icon="eva:bell-fill" />
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Ringkasan Data Nasabah
|
|
</Typography>
|
|
</Stack>
|
|
<Iconify icon="eva:eye-fill" />
|
|
</Stack>
|
|
|
|
<Paper sx={{ background: 'white', marginTop: 2, p: 2 }}>
|
|
<Stack>
|
|
<Box sx={{ flexGrow: 1 }}>
|
|
<Grid container spacing={2}>
|
|
<Grid item xs={12}>
|
|
<Stack>
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Nama Lengkap
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
{currentClaim?.member?.full_name}
|
|
</Typography>
|
|
</Stack>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Nomor Polis
|
|
</Typography>
|
|
<Typography variant="body2">{currentClaim?.member?.current_policy?.code}</Typography>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Member ID
|
|
</Typography>
|
|
<Typography variant="body2">{currentClaim?.member?.member_id}</Typography>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Tipe Claim
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
{currentClaim?.claim_request?.payment_type_name}
|
|
</Typography>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="body2" fontWeight={600}>
|
|
Tipe Nasabah
|
|
</Typography>
|
|
<Typography variant="body2">
|
|
{currentClaim?.member?.current_corporate?.name}
|
|
</Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
</Stack>
|
|
</Paper>
|
|
</Paper>
|
|
</Grid>
|
|
|
|
<Grid item xs={7}>
|
|
{/* Claim Detail */}
|
|
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2 }}>
|
|
<Stack
|
|
direction="row"
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
sx={{ marginBottom: 2 }}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
<Iconify icon="eva:bell-fill" />
|
|
<Typography variant="body2" fontWeight={600}>
|
|
History Perawatan
|
|
</Typography>
|
|
</Stack>
|
|
<Typography
|
|
onClick={() => {
|
|
setOpenDialogHistoryPerawatan(true);
|
|
}}
|
|
>
|
|
+ Tambah History Perawatan
|
|
</Typography>
|
|
</Stack>
|
|
|
|
{/* For Creation History Perawatan / Encounter */}
|
|
<DialogHistoryPerawatan
|
|
openDialog={openDialogHistoryPerawatan}
|
|
setOpenDialog={setOpenDialogHistoryPerawatan}
|
|
onChange={() => {}}
|
|
claim={currentClaim}
|
|
></DialogHistoryPerawatan>
|
|
|
|
<Paper sx={{ background: 'white', marginY: 2, p: 2 }}>
|
|
<Stack sx={{ maxHeight: '250px', overflowY: 'scroll' }}>
|
|
{currentClaim?.encounters && currentClaim?.encounters.map((encounter, index) => (
|
|
<React.Fragment key={index}>
|
|
<Stack
|
|
direction="row"
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
sx={{ marginY: 1 }}
|
|
>
|
|
<Stack>
|
|
<Typography fontWeight={'bold'} onClick={() => {showEditEncounter(encounter)}}><a href="#">{ encounter.class_name }</a></Typography>
|
|
<Typography sx={{ color: '#777', fontSize: '10px' }}>
|
|
({ fDate(encounter.start) } - { fDate(encounter.end) })
|
|
</Typography>
|
|
<Typography variant="body2">Diagnosis: { encounter.primary_diagnosis ? (`(${encounter.primary_diagnosis.diagnosis?.code}) ${encounter.primary_diagnosis.diagnosis?.name}`) : '-'}</Typography>
|
|
<Typography variant="body2">Dokter: { encounter.primary_doctor ? (`${encounter.primary_doctor.name}`) : '-'}</Typography>
|
|
</Stack>
|
|
<Tooltip title="Diagnosa Final">
|
|
<IconButton onClick={() => {handleSetFinalEncounter(encounter)}}>
|
|
<Iconify
|
|
icon="eva:checkmark-circle-2-fill"
|
|
color={currentClaim.final_encounter_id == encounter.id ? "green" : "gray"}
|
|
sx={{ margin: 2 }}
|
|
></Iconify>
|
|
</IconButton>
|
|
</Tooltip>
|
|
|
|
</Stack>
|
|
<Divider />
|
|
</React.Fragment>
|
|
))}
|
|
|
|
{(!currentClaim?.encounters || currentClaim?.encounters.length == 0) && (
|
|
<Typography>Belum ada History Perawatan</Typography>
|
|
)}
|
|
</Stack>
|
|
</Paper>
|
|
|
|
{/* For Editing History Perawatan / Encounter */}
|
|
<DialogHistoryPerawatan
|
|
openDialog={openDialogEditHistoryPerawatan}
|
|
setOpenDialog={setOpenDialogEditHistoryPerawatan}
|
|
onChange={() => {}}
|
|
claim={currentClaim}
|
|
encounter={editedEncounter}
|
|
></DialogHistoryPerawatan>
|
|
|
|
{/* <ClaimDetail claim={currentClaim} /> */}
|
|
</Paper>
|
|
|
|
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2, marginTop: 2 }}>
|
|
<Stack direction="row" justifyContent="space-between">
|
|
<Typography sx={{ marginBottom: 1 }}>Client Benefit Configuration</Typography>
|
|
<Typography
|
|
onClick={() => {
|
|
setDialogAddClaimItemOpen(true);
|
|
}}
|
|
>
|
|
+ Add Benefit
|
|
</Typography>
|
|
</Stack>
|
|
<ClaimItems items={claimItems} setItems={setClaimItems}></ClaimItems>
|
|
<Stack alignItems={'flex-end'}>
|
|
{(currentClaim?.status == 'requested' || currentClaim?.status == 'received') && (
|
|
<LoadingButton
|
|
variant="contained"
|
|
sx={{ marginTop: 2 }}
|
|
loading={loadingClaimItems}
|
|
onClick={() => {
|
|
handleSaveClaimItems();
|
|
}}
|
|
>
|
|
Simpan Claim Item
|
|
</LoadingButton>
|
|
)}
|
|
</Stack>
|
|
|
|
<DialogMemberBenefit
|
|
openDialog={dialogAddClaimItemOpen}
|
|
setOpenDialog={setDialogAddClaimItemOpen}
|
|
member={currentClaim?.member ?? null}
|
|
onSubmit={handleAddClaimItems}
|
|
/>
|
|
</Paper>
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
</Container>
|
|
</Page>
|
|
);
|
|
}
|