diff --git a/frontend/hospital-portal/src/routes/index.tsx b/frontend/hospital-portal/src/routes/index.tsx index b3006919..a0165145 100644 --- a/frontend/hospital-portal/src/routes/index.tsx +++ b/frontend/hospital-portal/src/routes/index.tsx @@ -98,8 +98,8 @@ export default function Router() { element: , }, { - path: '/detail/:id', - element: , + path: '/claim/detail/:id', + element: , }, ], }, @@ -126,3 +126,4 @@ const Claim = Loadable(lazy(() => import('@/pages/Claim'))); const NotFound = Loadable(lazy(() => import('@/pages/Page404'))); const DetailClaimReport = Loadable(lazy(()=> import('@/sections/dashboard/Detail'))); +const DetailClaim = Loadable(lazy(()=> import('@/sections/claim/Detail'))); diff --git a/frontend/hospital-portal/src/sections/claim/Detail.tsx b/frontend/hospital-portal/src/sections/claim/Detail.tsx new file mode 100644 index 00000000..9c1ed9b8 --- /dev/null +++ b/frontend/hospital-portal/src/sections/claim/Detail.tsx @@ -0,0 +1,69 @@ +// mui +import { Container, Grid, Stack, Typography } from '@mui/material'; +// components +import Page from '../../components/Page'; +// utils +import useSettings from '../../hooks/useSettings'; +// section +import CardFamilyInformation from '../../sections/alarm-center/user-profile/CardFamilyInformation'; +// react +import { useNavigate, useParams } from 'react-router-dom'; +import ButtonBack from '../../components/ButtonBack'; +import { useEffect, useState, useContext } from 'react'; +import axios from '../../utils/axios'; +// pages +import DetailTimeline from '../../sections/dashboard/DetailTimeline'; +import DetailStepper from '../../sections/dashboard/DetailStepper'; +import { format } from 'date-fns'; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; +import { LanguageContext } from '@/contexts/LanguageContext'; + +// ---------------------------------------------------------------------- + +export default function Detail() { + const { localeData }: any = useContext(LanguageContext); + const navigate = useNavigate(); + const { themeStretch } = useSettings(); + const [data, setData] = useState(); + + const { id } = useParams(); + + useEffect(() => { + axios + .get('/detail-claim-requests/' + id) + .then((response) => { + setData(response.data); + }) + .catch((error) => { + console.error(error); + }); + + }, []); + + return ( + + + + navigate(-1)} sx={{cursor:'pointer'}}/> + Detail + {data ? ( + + {localeData.txtDialogMember5} + {(data && data.data) ? format(new Date(data.data.status.submission_date), "d MMM yyyy") : ''} + + ) : ''} + + {data ? ( + + + + + + + + + ) : ''} + + + ); +} \ No newline at end of file diff --git a/frontend/hospital-portal/src/sections/claim/DetailStepper.tsx b/frontend/hospital-portal/src/sections/claim/DetailStepper.tsx new file mode 100644 index 00000000..18dc959a --- /dev/null +++ b/frontend/hospital-portal/src/sections/claim/DetailStepper.tsx @@ -0,0 +1,58 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stepper from '@mui/material/Stepper'; +import Step from '@mui/material/Step'; +import StepLabel from '@mui/material/StepLabel'; +import { useEffect, useState } from 'react'; +import ClearIcon from '@mui/icons-material/Clear'; + +const steps = [ + 'Request', + 'Review', + 'Approval', + 'Decline', +]; + +export default function HorizontalLinearAlternativeLabelStepper({data}) { + const [active, setActive] = useState(0); + const [status, SetStatus] = useState(null); + let updatedSteps = [...steps]; + useEffect(() => { + if (data && data.data) { + if (data.data.status.status === 'requested') { + setActive(1); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if (data.data.status.status === 'reviewed') { + setActive(2); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if (data.data.status.status === 'approved') + { + setActive(3); + updatedSteps = updatedSteps.filter(step => step !== 'Decline'); + } + else if(data.data.status.status === 'declined') + { + setActive(4) + updatedSteps = updatedSteps.filter(step => step !== 'Approval'); + } + } + SetStatus(updatedSteps); + }, [data]); + + + + + return ( + + + {status?.map((label) => ( + + : ''}>{label} + + ))} + + + ); +} diff --git a/frontend/hospital-portal/src/sections/claim/DetailTimeline.tsx b/frontend/hospital-portal/src/sections/claim/DetailTimeline.tsx new file mode 100644 index 00000000..9d8b7b7f --- /dev/null +++ b/frontend/hospital-portal/src/sections/claim/DetailTimeline.tsx @@ -0,0 +1,386 @@ +import * as React from 'react'; +import Timeline from '@mui/lab/Timeline'; +import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem'; +import TimelineSeparator from '@mui/lab/TimelineSeparator'; +import TimelineConnector from '@mui/lab/TimelineConnector'; +import TimelineContent from '@mui/lab/TimelineContent'; +import TimelineDot from '@mui/lab/TimelineDot'; +import {Typography, Card, Stack, ButtonBase, Box, Divider} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import Paper from '@mui/material/Paper'; +import Button from '@mui/material/Button'; +import AddIcon from '@mui/icons-material/Add'; +import Iconify from '../../components/Iconify'; +import { useEffect, useState, useRef } from 'react'; +import { format } from 'date-fns'; +import { LoadingButton } from '@mui/lab'; +import axios from '../../utils/axios'; +import { makeFormData } from '@/utils/jsonToFormData'; +import { enqueueSnackbar } from 'notistack'; +import { useParams} from 'react-router-dom'; +import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; + +const Item1 = styled(Paper)(({ theme }) => ({ + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + backgroundColor: '#919EAB29', + color: '#637381', + width: 'fit-content', + marginRight: 'auto', +})); + +const Item2 = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, + width: 'fit-content', + marginLeft: 'auto', +})); + +export default function NoOppositeContent({data}) { + const [timeline, setTimeline] = useState(null); + const [requestFile, setRequestFile] = useState(null); + useEffect(() => { + if (data && data.data) { + setTimeline(data.data.timeline); + setRequestFile(data.data.request_files); + } + + }, [data]); + + // Diagnosis + const fileRequestDocumentInputDiagnosis = useRef(null); + const [fileDiagnosis, setFileDiagnosis] = useState([]); + const handleRequestDocumentInputChangeDiagnosis = (event) => { + if (event.target.files[0]) { + setFileDiagnosis([...fileDiagnosis, ...event.target.files]); + } + }; + const removeFileDiagnois = (filesState, index) => { + setFileDiagnosis( + filesState.filter((file, fileIndex) => { + return fileIndex != index; + }) + ); + }; + // Kondisi + const fileRequestDocumentInputKondisi = useRef(null); + const [fileKondisi, setFileKondisi] = useState([]); + const handleRequestDocumentInputChangeKondisi = (event) => { + if (event.target.files[0]) { + setFileKondisi([...fileKondisi, ...event.target.files]); + } + }; + const removeFileKondisi = (filesState, index) => { + setFileKondisi( + filesState.filter((file, fileIndex) => { + return fileIndex != index; + }) + ); + }; + // Result + const fileRequestDocumentInputResult = useRef(null); + const [fileResult, setFileResult] = useState([]); + const handleRequestDocumentInputChangeResult = (event) => { + if (event.target.files[0]) { + setFileResult([...fileResult, ...event.target.files]); + } + }; + const removeFileResult = (filesState, index) => { + setFileResult( + filesState.filter((file, fileIndex) => { + return fileIndex != index; + }) + ); + }; + const { id } = useParams(); + const [submitLoading, setSubmitLoading] = useState(false); + const submitRequestFiles = () => { + setSubmitLoading(true); + const formData = makeFormData({ + fileDiagnosis: fileDiagnosis, + fileKondisis: fileKondisi, + fileResults: fileResult + }); + axios + .post('claim-requests/'+id+'/request-files', formData) + .then((response) => { + window.location.reload(); + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' }); + }); + } + const submitButton = requestFile?.find((dataRequestFile) => dataRequestFile.check_files === null); + return ( + <> + {timeline?.map((dataTimeline, index) => ( + + {dataTimeline.date ? format(new Date(dataTimeline.date), "d MMM yyyy") : ''} + + + + + + + + + + {dataTimeline.date ? format(new Date(dataTimeline.date), "HH : mm") : ''} + {dataTimeline.txt_status} + + + Detail: + {dataTimeline.description} + + {dataTimeline.status === 'reviewed' && requestFile ? ( + <> + {submitButton ? ( + Request Document + ) : ( + Request Document Success Uploaded + )} + {/* Diagnosis */} + {requestFile?.map((dataRequestFile, index) => { + if(dataRequestFile.type !== 'claim-diagnosis' || dataRequestFile.check_files !== null){ + return null; + } + return ( + + + Diagnosis + + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileDiagnosis && + fileDiagnosis.map((file, index) => ( + + + + {file.name ? file.name : '-'} + + { + removeFileDiagnois(fileDiagnosis, index); + }} + sx={{cursor: 'pointer'}} + > + + ))} + + fileRequestDocumentInputDiagnosis.current?.click()} + > + + + + Add Result + + + handleRequestDocumentInputChangeDiagnosis(event)} + accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain, application/pdf" + /> + + + ); + })} + {/* Kondisi */} + {requestFile?.map((dataRequestFile, index) => { + if(dataRequestFile.type !== 'claim-kondisi' || dataRequestFile.check_files !== null){ + return null; + } + return ( + + + Condition + + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileKondisi && + fileKondisi.map((file, index) => ( + + + + {file.name ? file.name : '-'} + + { + removeFileKondisi(fileKondisi, index); + }} + sx={{cursor: 'pointer'}} + > + + ))} + + fileRequestDocumentInputKondisi.current?.click()} + > + + + + Add Result + + + handleRequestDocumentInputChangeKondisi(event)} + accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain, application/pdf" + /> + + + ); + })} + {/* Supporting Result */} + {requestFile?.map((dataRequestFile, index) => { + if(dataRequestFile.type !== 'claim-result' || dataRequestFile.check_files !== null){ + return null; + } + return ( + + + Supporting Result + + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileResult && + fileResult.map((file, index) => ( + + + + {file.name ? file.name : '-'} + + { + removeFileResult(fileResult, index); + }} + sx={{cursor: 'pointer'}} + > + + ))} + + fileRequestDocumentInputResult.current?.click()} + > + + + + Add Result + + + handleRequestDocumentInputChangeResult(event)} + accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, text/plain, application/pdf" + /> + + + ); + })} + {submitButton ? ( + { + submitRequestFiles(); + }} + loading={submitLoading} + > + Submit + + ) : ''} + + ) : ''} + + + + + + ))} + + ); +} diff --git a/frontend/hospital-portal/src/sections/claim/TableList.tsx b/frontend/hospital-portal/src/sections/claim/TableList.tsx index 513ea292..61badfaf 100644 --- a/frontend/hospital-portal/src/sections/claim/TableList.tsx +++ b/frontend/hospital-portal/src/sections/claim/TableList.tsx @@ -313,7 +313,7 @@ export default function TableList() { action: - + navigate ('/claim/detail/'+obj.claim_request_id)}> View diff --git a/frontend/hospital-portal/src/sections/dashboard/FormRequestLog.tsx b/frontend/hospital-portal/src/sections/dashboard/FormRequestLog.tsx index 9110d837..1f6433c2 100644 --- a/frontend/hospital-portal/src/sections/dashboard/FormRequestLog.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/FormRequestLog.tsx @@ -44,7 +44,6 @@ export default function FormRequestClaim({ member, handleSubmitSuccess }: FormRe axios .post('/request-log', formData) .then((response) => { - console.log(response); if (response && response.data && response.data.meta) { enqueueSnackbar(response.data.meta.message, { variant: 'success' }); handleSubmitSuccess(); diff --git a/frontend/hospital-portal/src/sections/dashboard/TableList.tsx b/frontend/hospital-portal/src/sections/dashboard/TableList.tsx index b1575b08..d18c3844 100644 --- a/frontend/hospital-portal/src/sections/dashboard/TableList.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/TableList.tsx @@ -363,7 +363,7 @@ function handleChangeTab(event: React.SyntheticEvent, newValue: string) { Download LOG ):''} - {obj.final_log === 0 ? ( + {obj.final_log === 0 && obj.status === 'approved' ? ( handleRequestFinalLog(obj.id, obj.full_name, obj.no_polis, obj.submission_date) }> Request Final LOG diff --git a/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx b/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx index 06dc44d8..4a71e61d 100644 --- a/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx @@ -355,7 +355,7 @@ export default function TableListFinalLog() { Download LOG ):''} - {!obj.check_claim ? ( + {!obj.check_claim && obj.status === 'approved' ? ( handleRequestClaimSubmit(obj.member_id, obj.service_code, obj.id, obj.full_name, obj.no_polis, obj.submission_date) }> Submit Claim