From f65b28107c3517e6700552b34bde363ec4b9f855 Mon Sep 17 00:00:00 2001 From: R Date: Thu, 16 Mar 2023 14:27:25 +0700 Subject: [PATCH] [WIP] Encounter --- frontend/dashboard/src/@types/doctor.tsx | 4 + .../autocomplete/AutocompleteDoctor.tsx | 63 +++++ .../autocomplete/AutocompleteHealthcare.tsx | 63 +++++ .../components/hook-form/RHFDatepicker.tsx | 15 +- frontend/dashboard/src/pages/Claims/Show.tsx | 135 +---------- .../pages/Claims/components/ClaimDetail.tsx | 217 ++++++++++++++++++ 6 files changed, 358 insertions(+), 139 deletions(-) create mode 100644 frontend/dashboard/src/components/autocomplete/AutocompleteDoctor.tsx create mode 100644 frontend/dashboard/src/components/autocomplete/AutocompleteHealthcare.tsx create mode 100644 frontend/dashboard/src/pages/Claims/components/ClaimDetail.tsx diff --git a/frontend/dashboard/src/@types/doctor.tsx b/frontend/dashboard/src/@types/doctor.tsx index 0d2925b4..a635e68c 100644 --- a/frontend/dashboard/src/@types/doctor.tsx +++ b/frontend/dashboard/src/@types/doctor.tsx @@ -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; \ No newline at end of file diff --git a/frontend/dashboard/src/components/autocomplete/AutocompleteDoctor.tsx b/frontend/dashboard/src/components/autocomplete/AutocompleteDoctor.tsx new file mode 100644 index 00000000..2dbb30ea --- /dev/null +++ b/frontend/dashboard/src/components/autocomplete/AutocompleteDoctor.tsx @@ -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(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 ( + (`${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) => ( + {getOptions(event.target.value)}}/> + )} + /> + ); +} diff --git a/frontend/dashboard/src/components/autocomplete/AutocompleteHealthcare.tsx b/frontend/dashboard/src/components/autocomplete/AutocompleteHealthcare.tsx new file mode 100644 index 00000000..eb9b51e8 --- /dev/null +++ b/frontend/dashboard/src/components/autocomplete/AutocompleteHealthcare.tsx @@ -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(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 ( + (`${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) => ( + {getOptions(event.target.value)}}/> + )} + /> + ); +} diff --git a/frontend/dashboard/src/components/hook-form/RHFDatepicker.tsx b/frontend/dashboard/src/components/hook-form/RHFDatepicker.tsx index dd386d85..c8bda14e 100755 --- a/frontend/dashboard/src/components/hook-form/RHFDatepicker.tsx +++ b/frontend/dashboard/src/components/hook-form/RHFDatepicker.tsx @@ -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 } }) => ( - { @@ -50,14 +48,15 @@ export default function RHFDatepicker({ name, ...other }: IProps & TextFieldProp {...other} /> )} - /> - {/* */} + { - field.onChange(fPostFormat(value)); + field.onChange(value) }} renderInput={(params) => } - /> */} + /> )} /> diff --git a/frontend/dashboard/src/pages/Claims/Show.tsx b/frontend/dashboard/src/pages/Claims/Show.tsx index 82412004..811306d0 100644 --- a/frontend/dashboard/src/pages/Claims/Show.tsx +++ b/frontend/dashboard/src/pages/Claims/Show.tsx @@ -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 { - 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({ - 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() { {/* Diagnosis */} - - - {/* {JSON.stringify(getValues('primary_diagnosis'))} */} - ( - - )} - /> - - ( - - )} - /> - - - - {(currentClaim?.status == 'requested' || currentClaim?.status == 'received') && ( - { - handleSaveDiagnosis(); - }} - > - Simpan Diagnosa - - )} + diff --git a/frontend/dashboard/src/pages/Claims/components/ClaimDetail.tsx b/frontend/dashboard/src/pages/Claims/components/ClaimDetail.tsx new file mode 100644 index 00000000..ed09f646 --- /dev/null +++ b/frontend/dashboard/src/pages/Claims/components/ClaimDetail.tsx @@ -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 { + 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({ + 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 ( + + + + + + + ( + + )} + /> + ( + + )} + /> + + + + + + + + {/* {JSON.stringify(getValues('primary_diagnosis'))} */} + ( + + )} + /> + + ( + + )} + /> + + + + {(claim?.status == 'requested' || claim?.status == 'received') && ( + { + handleSaveDiagnosis(); + }} + > + Simpan Detail + + )} + + + ); +}