[WIP] Encounter

This commit is contained in:
R
2023-03-16 14:27:25 +07:00
parent e06447bf00
commit f65b28107c
6 changed files with 358 additions and 139 deletions

View File

@@ -11,6 +11,8 @@ export type Organizations = {
active: boolean | number;
};
export type OrganizationType = Organizations;
export type PractitionerRole = {
meta: string;
practitioner_id: number;
@@ -49,3 +51,5 @@ export type Practitioner = {
organizations?: Organizations[];
specialities?: Specialities[];
};
export type PractitionerType = Practitioner;

View File

@@ -0,0 +1,63 @@
import axios from '@/utils/axios';
import { Autocomplete, TextField, CircularProgress } from '@mui/material';
import { useEffect, useMemo, useState } from 'react';
import { IcdType } from '@/@types/diagnosis';
import { Controller } from 'react-hook-form';
type autocompleteDoctorType = {
onChange: any;
textLabel: string;
currentValue: any | null;
currentOptions: IcdType[];
filter: object | null;
};
export default function AutocompleteDoctor({
onChange,
currentValue,
textLabel,
currentOptions = [],
}: autocompleteDoctorType) {
const [options, setOptions] = useState<IcdType>(currentOptions);
const [loading, setLoading] = useState(false);
function doctorsToOptions(icds: IcdType[]): IcdType[] {
return icds.map(function (icd: IcdType) {
return icd;
});
}
// To Receive Options from Props
useEffect(() => {
setOptions(doctorsToOptions(currentOptions));
}, [currentOptions]);
const getOptions = (search: string) => {
axios
.get('options?type=doctors&search=' + search)
.then((res) => {
setOptions(doctorsToOptions(res.data));
})
.then(() => {
setLoading(false);
});
};
return (
<Autocomplete
options={options}
getOptionLabel={(option) => (`${option.code} - ${option.name}`)}
value={currentValue}
isOptionEqualToValue={(option, value) => option.id == value.id}
onChange={(event: any, newValue: any) => {
// setValue('primary_diagnosis_id', newValue?.id ?? null);
onChange(newValue);
}}
loading={loading}
renderInput={(params) => (
<TextField {...params} label={textLabel} variant="outlined" fullWidth onChange={(event) => {getOptions(event.target.value)}}/>
)}
/>
);
}

View File

@@ -0,0 +1,63 @@
import axios from '@/utils/axios';
import { Autocomplete, TextField, CircularProgress } from '@mui/material';
import { useEffect, useMemo, useState } from 'react';
import { IcdType } from '@/@types/diagnosis';
import { Controller } from 'react-hook-form';
type autocompleteHealthcareType = {
onChange: any;
textLabel: string;
currentValue: any | null;
currentOptions: IcdType[];
filter: object | null;
};
export default function AutocompleteHealthcare({
onChange,
currentValue,
textLabel,
currentOptions = [],
}: autocompleteHealthcareType) {
const [options, setOptions] = useState<IcdType>(currentOptions);
const [loading, setLoading] = useState(false);
function healthcaresToOptions(healthcares: any[]): any[] {
return healthcares.map(function (healthcare: any) {
return healthcare;
});
}
// To Receive Options from Props
useEffect(() => {
setOptions(healthcaresToOptions(currentOptions));
}, [currentOptions]);
const getOptions = (search: string) => {
axios
.get('options?type=healthcares&search=' + search)
.then((res) => {
setOptions(healthcaresToOptions(res.data));
})
.then(() => {
setLoading(false);
});
};
return (
<Autocomplete
options={options}
getOptionLabel={(option) => (`${option.code} - ${option.name}`)}
value={currentValue}
isOptionEqualToValue={(option, value) => option.id == value.id}
onChange={(event: any, newValue: any) => {
// setValue('primary_diagnosis_id', newValue?.id ?? null);
onChange(newValue);
}}
loading={loading}
renderInput={(params) => (
<TextField {...params} label={textLabel} variant="outlined" fullWidth onChange={(event) => {getOptions(event.target.value)}}/>
)}
/>
);
}

View File

@@ -4,11 +4,9 @@ import * as React from 'react';
// @mui
import { IconButton, TextField, TextFieldProps } from '@mui/material';
import { LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
import { DesktopDatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
import InputAdornment from '@mui/material/InputAdornment';
import EventIcon from '@mui/icons-material/Event';
import { fPostFormat } from '../../utils/formatTime';
@@ -28,7 +26,7 @@ export default function RHFDatepicker({ name, ...other }: IProps & TextFieldProp
control={control}
render={({ field, fieldState: { error } }) => (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<MobileDatePicker
{/* <MobileDatePicker
inputFormat="yyyy-MM-dd"
value={field.value}
onChange={(value) => {
@@ -50,14 +48,15 @@ export default function RHFDatepicker({ name, ...other }: IProps & TextFieldProp
{...other}
/>
)}
/>
{/* <DesktopDatePicker
/> */}
<DesktopDatePicker
value={field.value}
inputFormat="dd/MM/yyyy"
onChange={(value) => {
field.onChange(fPostFormat(value));
field.onChange(value)
}}
renderInput={(params) => <TextField {...params} fullWidth />}
/> */}
/>
</LocalizationProvider>
)}
/>

View File

@@ -40,6 +40,9 @@ import ClaimItems from './components/ClaimItems';
import DialogMemberBenefit from './components/DialogMemberBenefit';
import AutocompleteDiagnosis from '@/components/autocomplete/AutocompleteDiagnosis';
import AutocompleteDiagnosisControlled from '@/components/autocomplete/AutocompleteDiagnosisControlled';
import { Icd, IcdType } from '@/@types/diagnosis';
import { OrganizationType, PractitionerType } from '@/@types/doctor';
import ClaimDetail from './components/ClaimDetail';
export default function ClaimsCreateUpdate() {
const { themeStretch } = useSettings();
@@ -93,14 +96,6 @@ export default function ClaimsCreateUpdate() {
});
};
// --------------------------------------------------------------
// Diagnosis
const [primaryDiagnosis, setPrimaryDiagnosis] = useState(null);
const [secondaryDiagnosis, setSecondaryDiagnosis] = useState(null);
const [loadingDiagnosis, setLoadingDiagnosis] = useState(false);
const [primaryDiagnosisOptions, setPrimaryDiagnosisOptions] = useState([]);
const [secondaryDiagnosisOptions, setSecondaryDiagnosisOptions] = useState([]);
const handlePrimaryDiagnosisChange = (diagnosisOption) => {
console.log('handle', diagnosisOption);
if (diagnosisOption) {
@@ -115,26 +110,6 @@ export default function ClaimsCreateUpdate() {
setSecondaryDiagnosis(value);
};
const handleSaveDiagnosis = () => {
setLoadingDiagnosis(true);
axios
.post(`claims/${id}/update-diagnosis`, {
primary: [primaryDiagnosis],
secondary: [secondaryDiagnosis],
})
.then((res) => {
enqueueSnackbar(res.data.message, { variant: 'success' });
})
.catch((err) => {
setLoadingDiagnosis(false);
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
})
.then(() => {
setLoadingDiagnosis(false);
});
};
const handleDecline = () => {
axios
.post(`claims/${id}/decline`)
@@ -223,42 +198,6 @@ export default function ClaimsCreateUpdate() {
});
};
// ---------------------------------------------------
// Primary ICD
const NewCorporateSchema = Yup.object().shape({
primary_diagnosis_id: Yup.string().required('Name is required'),
});
interface FormValuesProps extends Partial<any> {
primary_diagnosis_id: number;
}
const defaultValues = useMemo(
() => ({
primary_diagnosis: currentClaim?.primary_diagnosis[0]?.icd ?? null,
secondary_diagnosis: currentClaim?.secondary_diagnosis[0]?.icd ?? null
}),
[currentClaim]
);
const methods = useForm<FormValuesProps>({
resolver: yupResolver(NewCorporateSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const values = watch();
// ----------------------------------------------------------------
@@ -270,30 +209,6 @@ export default function ClaimsCreateUpdate() {
setCurrentClaim(claim);
setDocuments(allFiles);
setClaimItems(claim.benefit_items);
// SET Default Primary Diagnosis
if (claim.primary_diagnosis.length && claim.primary_diagnosis[0].icd) {
setPrimaryDiagnosisOptions(
claim.primary_diagnosis.map((diagnosis) => {
if (diagnosis.icd) {
return diagnosis.icd;
}
})
);
setValue('primary_diagnosis', claim.primary_diagnosis[0].icd);
}
// SET Default Secondary Diagnosis
if (claim.secondary_diagnosis.length && claim.secondary_diagnosis[0].icd) {
setSecondaryDiagnosisOptions(
claim.secondary_diagnosis.map((diagnosis) => {
if (diagnosis.icd) {
return diagnosis.icd;
}
})
);
setValue('secondary_diagnosis', claim.secondary_diagnosis[0].icd)
}
});
}, [id]);
@@ -446,49 +361,7 @@ export default function ClaimsCreateUpdate() {
<Grid item xs={7}>
{/* Diagnosis */}
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2 }}>
<Paper variant="outlined" sx={{ background: 'white', p: 2 }}>
<Stack spacing={2}>
{/* {JSON.stringify(getValues('primary_diagnosis'))} */}
<Controller
name="primary_diagnosis"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteDiagnosisControlled
onChange={onChange}
currentOptions={primaryDiagnosisOptions}
currentValue={value}
textLabel="Diagnosis Utama (ICD-X)"
/>
)}
/>
<Controller
name="secondary_diagnosis"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteDiagnosisControlled
onChange={onChange}
currentOptions={secondaryDiagnosisOptions}
currentValue={value}
textLabel="Diagnosis Tambahan (ICD-X)"
/>
)}
/>
</Stack>
</Paper>
{(currentClaim?.status == 'requested' || currentClaim?.status == 'received') && (
<LoadingButton
variant="contained"
sx={{ marginTop: 2 }}
loading={loadingDiagnosis}
onClick={() => {
handleSaveDiagnosis();
}}
>
Simpan Diagnosa
</LoadingButton>
)}
<ClaimDetail claim={currentClaim} />
</Paper>
<Paper variant="outlined" sx={{ background: '#f4f6f8', p: 2, marginTop: 2 }}>

View File

@@ -0,0 +1,217 @@
import * as Yup from 'yup';
import { IcdType } from '@/@types/diagnosis';
import { OrganizationType, PractitionerType } from '@/@types/doctor';
import AutocompleteDiagnosisControlled from '@/components/autocomplete/AutocompleteDiagnosisControlled';
import { LoadingButton } from '@mui/lab';
import { Paper, Stack, TextField } from '@mui/material';
import { Controller, useForm } from 'react-hook-form';
import { useEffect, useMemo, useState } from 'react';
import { yupResolver } from '@hookform/resolvers/yup';
import { enqueueSnackbar } from 'notistack';
import axios from '@/utils/axios';
import { FormProvider, RHFDatepicker, RHFTextField } from '@/components/hook-form';
import AutocompleteDoctor from '@/components/autocomplete/AutocompleteDoctor';
import AutocompleteHealthcare from '@/components/autocomplete/AutocompleteHealthcare';
export default function ClaimDetail({ claim }) {
// --------------------------------------------------------------
// Diagnosis
const [primaryDiagnosis, setPrimaryDiagnosis] = useState(null);
const [secondaryDiagnosis, setSecondaryDiagnosis] = useState(null);
const [loadingDiagnosis, setLoadingDiagnosis] = useState(false);
const [primaryDiagnosisOptions, setPrimaryDiagnosisOptions] = useState([]);
const [secondaryDiagnosisOptions, setSecondaryDiagnosisOptions] = useState([]);
const ClaimDetailSchema = Yup.object().shape({
primary_diagnosis: Yup.object().required('Diagnosis Utama Wajib dipilih'),
// secondary_diagnosis: Yup.object().required('Diagnosis Utama Wajib dipilih'),
doctor: Yup.object().required('Dokter Harus dipilih'),
healthcare: Yup.object().required('Healthcare Harus dipilih'),
});
interface FormValuesProps extends Partial<any> {
primary_diagnosis: IcdType;
secondary_diagnosis: IcdType;
doctor: PractitionerType;
healthcare: OrganizationType;
}
const defaultValues = useMemo(
() => ({
primary_diagnosis: claim?.primary_diagnosis[0]?.icd ?? null,
secondary_diagnosis: claim?.secondary_diagnosis[0]?.icd ?? null,
}),
[claim]
);
const methods = useForm<FormValuesProps>({
resolver: yupResolver(ClaimDetailSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const values = watch();
const handleSaveDiagnosis = () => {
setLoadingDiagnosis(true);
axios
.post(`claims/${claim.id}/update-diagnosis`, {
primary: [getValues('primary_diagnosis')?.id],
secondary: [getValues('secondary_diagnosis')?.id],
})
.then((res) => {
enqueueSnackbar(res.data.message, { variant: 'success' });
})
.catch((err) => {
setLoadingDiagnosis(false);
enqueueSnackbar(err.response?.data?.message ?? err?.message, { variant: 'error' });
})
.then(() => {
setLoadingDiagnosis(false);
});
};
useEffect(() => {
if (claim) {
// SET Default Primary Diagnosis
if (claim.primary_diagnosis.length && claim.primary_diagnosis[0].icd) {
setPrimaryDiagnosisOptions(
claim.primary_diagnosis.map((diagnosis) => {
if (diagnosis.icd) {
return diagnosis.icd;
}
})
);
setValue('primary_diagnosis', claim.primary_diagnosis[0].icd);
}
// SET Default Secondary Diagnosis
if (claim.secondary_diagnosis.length && claim.secondary_diagnosis[0].icd) {
setSecondaryDiagnosisOptions(
claim.secondary_diagnosis.map((diagnosis) => {
if (diagnosis.icd) {
return diagnosis.icd;
}
})
);
setValue('secondary_diagnosis', claim.secondary_diagnosis[0].icd);
}
}
}, [claim]);
function onSubmit(){
console.log('submit');
}
return (
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2}>
<Stack spacing={2} sx={{ background: 'white', p: 2 }}>
<RHFDatepicker
name="tanggal_masuk"
placeholder="DD/MM/YYYY"
label="Tanggal Masuk"
></RHFDatepicker>
<RHFDatepicker
name="tanggal_keluar"
placeholder="DD/MM/YYYY"
label="Tanggal Keluar"
></RHFDatepicker>
<Controller
name="healthcare"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteHealthcare
onChange={onChange}
currentOptions={[]}
currentValue={value}
textLabel="Tempat Dirawat"
/>
)}
/>
<Controller
name="doctor"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteDoctor
onChange={onChange}
currentOptions={[]}
currentValue={value}
textLabel="Dokter yang merawat"
/>
)}
/>
<RHFTextField
name="doktor"
placeholder="Nomor Rekam Medis di RS"
label="No. Rekam Medis"
></RHFTextField>
<RHFTextField
name="doktor"
label="Jumlah Tempat Tidur"
></RHFTextField>
<RHFTextField
name="doktor"
label="Lama Perawatan (hari)"
></RHFTextField>
</Stack>
<Paper variant="outlined" sx={{ background: 'white', p: 2 }}>
<Stack spacing={2}>
{/* {JSON.stringify(getValues('primary_diagnosis'))} */}
<Controller
name="primary_diagnosis"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteDiagnosisControlled
onChange={onChange}
currentOptions={primaryDiagnosisOptions}
currentValue={value}
textLabel="Diagnosis Utama (ICD-X)"
/>
)}
/>
<Controller
name="secondary_diagnosis"
control={control}
render={({ field: { onChange, value } }) => (
<AutocompleteDiagnosisControlled
onChange={onChange}
currentOptions={secondaryDiagnosisOptions}
currentValue={value}
textLabel="Diagnosis Tambahan (ICD-X)"
/>
)}
/>
</Stack>
</Paper>
{(claim?.status == 'requested' || claim?.status == 'received') && (
<LoadingButton
variant="contained"
sx={{ marginTop: 2 }}
loading={loadingDiagnosis}
onClick={() => {
handleSaveDiagnosis();
}}
>
Simpan Detail
</LoadingButton>
)}
</Stack>
</FormProvider>
);
}