merge claim detail

This commit is contained in:
2023-11-01 22:46:59 +07:00
parent 01fcaf7181
commit 5b3cddf5fe
18 changed files with 4371 additions and 3416 deletions

View File

@@ -119,24 +119,31 @@ class ClaimController extends Controller
$claim = Claim::query()
->with([
'member',
'member.currentPlan',
'member.currentPlan.benefits',
// 'member.currentPlan',
// 'member.currentPlan.benefits',
'member.currentCorporate',
'member.currentPolicy',
// 'diagnosis',
'diagnoses',
'diagnoses.icd',
'benefit',
'files',
'claimRequest',
'claimRequest.files',
'items',
'items.claim_itemable',
'encounters',
'encounters.doctors',
'encounters.primaryDiagnoses',
'encounters.primaryDiagnoses.diagnosis',
'encounters.healthcare'
// 'member.currentPolicy',
// // 'diagnosis',
// 'diagnoses',
// 'diagnoses.icd',
// 'benefit',
// 'files',
// 'claimRequest',
// 'claimRequest.files',
// 'items',
// 'items.claim_itemable',
// 'encounters',
// 'encounters.doctors',
// 'encounters.primaryDiagnoses',
// 'encounters.primaryDiagnoses.diagnosis',
// 'encounters.healthcare',
'historyHospitalCare',
'historyHospitalCare.person',
'historyHospitalCare.practitioner',
'historyHospitalCare.organization',
'historyHospitalCare.icd',
'historyHospitalCare.comparativeDiagnosis',
'historyHospitalCare.comparativeDiagnosis.icd',
])
->findOrFail($id);

View File

@@ -40,6 +40,22 @@ class DiagnosisExclusionController extends Controller
return Helper::paginateResources(DiagnosisExclusionResource::collection($exclusions));
}
public function listDiagnosis(Request $request, $corporate_id){
$exclusion = Exclusion::query()
->where('corporate_id', $corporate_id)
->where('type', 'diagnosis')
->where('deleted_at', null)
// ->with(['rules'])
->get('exclusionable_id')->toArray();
$icd = Icd::query()
->whereNotIn('id', $exclusion)
->limit(100)
->get()
->toArray();
return Helper::responseJson($icd);
}
/**
* Show the form for creating a new resource.
* @return Renderable

View File

@@ -246,15 +246,17 @@ class FormulariumTemplateController extends Controller
public function activation(Request $request, $id)
{
$request->validate([
'active' => 'required'
]);
$Icd = FormulariumTemplate::findOrFail($id);
$Icd->active = $request->active == '1';
$formulariumTemplate = FormulariumTemplate::find($id);
if ($Icd->save()) {
$formulariumTemplate->active = $request->active == 1 ? 0 : 1;
if ($formulariumTemplate->save()) {
return response()->json([
'icd' => $Icd,
'data' => $formulariumTemplate,
'message' => 'Status Updated Successfully'
]);
}

View File

@@ -108,6 +108,7 @@ Route::prefix('internal')->group(function () {
Route::get('corporates/{corporate_id}/hospitals/data', [HospitalController::class, 'dataHospital']);
Route::post('corporates/{corporate_id}/hospitals/save', [HospitalController::class, 'store']);
Route::put('corporates/{corporate_id}/hospitals/{id}/edit', [HospitalController::class, 'update']);
Route::get('corporates/{corporate_id}/members', [CorporateMemberController::class, 'index']);
Route::get('corporates/{corporate_id}/members/list', [CorporateMemberController::class, 'generateMemberList']);
@@ -115,6 +116,8 @@ Route::prefix('internal')->group(function () {
Route::put('members/{member_id}/activation', [CorporateMemberController::class, 'activation']);
Route::get('corporates/{corporate_id}/diagnosis', [DiagnosisExclusionController::class, 'listDiagnosis']);
Route::get('corporates/{corporate_id}/diagnosis-exclusions', [DiagnosisExclusionController::class, 'index']);
Route::get('corporates/{corporate_id}/diagnosis-exclusions/{id_exclusion}', [DiagnosisExclusionController::class, 'detilExclusion']); // By Bagaskoro, get detil exclusion
Route::post('corporates/{corporate_id}/diagnosis-exclusions/store', [DiagnosisExclusionController::class, 'storeExclusion']);
@@ -137,6 +140,8 @@ Route::prefix('internal')->group(function () {
Route::post('corporates/{corporate_id}/formulariums/import', [CorporateFormulariumController::class, 'import']);
Route::put('corporates/{corporate_id}/formulariums-update-status/{id}', [CorporateFormulariumController::class, 'active']);
Route::put('corporates/{corporate_id}/formulariums/{formularium_id}/{action}', [CorporateFormulariumController::class, 'updateStatus']);
Route::controller(CorporateController::class)->group(function () {
Route::post('add-files-doc', 'addFilesDoc');
Route::post('get-files-doc', 'getFilesDoc');

View File

@@ -3,6 +3,9 @@
namespace Modules\Internal\Transformers;
use App\Models\Benefit;
use App\Models\CorporateEmployee;
use App\Models\ClaimRequest;
use App\Models\Icd;
use Illuminate\Http\Resources\Json\JsonResource;
class ClaimShowResource extends JsonResource
@@ -15,34 +18,55 @@ class ClaimShowResource extends JsonResource
*/
public function toArray($request)
{
$data = parent::toArray($request);
// $data['']
$data['benefit_items'] = $this->items
->filter(function ($item) {
return $item->claim_itemable_type == Benefit::class;
})
->map(function ($item) {
$itemData = $item->claim_itemable->toArray();
$itemData['nominal_dicover'] = $item['nominal_dicover'] ?? 0;
$itemData['nominal_ditagihkan'] = $item['nominal_ditagihkan'] ?? 0;
$itemData['nominal_total'] = $item['nominal_total'] ?? 0;
// For React Frotnend
$itemData['biaya_diajukan'] = $itemData['nominal_ditagihkan'];
$itemData['biaya_disetujui'] = $itemData['nominal_dicover'];
$claim = parent::toArray($request);
return $itemData;
});
$member_data = CorporateEmployee::where('member_id', $claim['member_id'])->first();
$claim_request = ClaimRequest::where('id', $claim['claim_request_id'])->first();
$data['primary_diagnosis'] = $this->diagnoses->filter(function($diagnosis){ return $diagnosis->type == 'primary';})->values();
$data['secondary_diagnosis'] = $this->diagnoses->filter(function($diagnosis){ return $diagnosis->type == 'secondary';})->values();
$data['encounters'] = $this->encounters->map(function($encounter) {
$encounterData = EncounterResource::make($encounter);
return $encounterData;
});
// $memberDiagnosisHistories = $this->member->
$data = [
'id' => $claim['id'],
'uuid' => $claim['uuid'],
'code' => $claim['code'],
'claim_request_id' => $claim['claim_request_id'],
'member_id' => $claim['member_id'],
'currency' => $claim['currency'],
'total_claim' => $claim['total_claim'],
'plan_id' => $claim['plan_id'],
'benefit_id' => $claim['benefit_id'],
'organization_id' => $claim['organization_id'],
'benefit_code' => $claim['benefit_code'],
'benefit_desc' => $claim['benefit_desc'],
'amount_incurred' => $claim['amount_incurred'],
'amount_approved' => $claim['amount_approved'],
'amount_not_approved' => $claim['amount_not_approved'],
'excess_paid' => $claim['excess_paid'],
'final_encounter_id' => $claim['final_encounter_id'],
'status' => $claim['status'],
'created_at' => $claim['created_at'],
'corporate_id' => $member_data->corporate_id,
'service_code' => $claim_request->service_code
// "uuid" => "9a59bff7-857f-4e48-8c6b-242ad1286395"
// "" => "CLM-00035"
// "" => 66
// "member_id" => 3
// "" => "IDR"
// "" => null
// "" => 1
// "" => null
// "" => 0
// "benefit_code" => ""
// "benefit_desc" => "erwraf"
// "" => 10000
// "" => 123000
// "amount_not_approved" => 122000
// "excess_paid" => 230000
// "final_encounter_id" => null
// "status" => "received"
// "created_at" => "2023-10-12T09:23:54.000000Z"
];
// $data['benefit_items'] = $this->items
$data['history_hospital_care'] = $claim['history_hospital_care'];
// $data['main_diagnosis']
return $data;
}

View File

@@ -264,5 +264,11 @@ class Claim extends Model
{
return $this->items->sum('nominal_ditagihkan');
}
public function historyHospitalCare()
{
return $this->hasMany(ClaimHistoryCare::class, 'claim_id');
}
}

View File

@@ -42,6 +42,19 @@ class ClaimHistoryCare extends Model
return $this->belongsTo(Icd::class, 'main_diagnosis_id');
}
public function claim()
{
return $this->hasOne(Claim::class, 'claim_id');
}
public function person()
{
return $this->belongsTo(Person::class, 'practitioner_id');
}
public function comparativeDiagnosis()
{
return $this->hasMany(DiagnosisSecondaryClaimHistoryCare::class, 'claim_history_care_id');
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -57,6 +57,24 @@ export type Plan = {
code: string;
}
export type ClaimHistoryCare = {
id: number;
claim_id: number;
service_code: string;
admision_date: string;
discharge_date: string;
main_diagnosis_id: number;
main_diagnosis_name: string;
medical_record_number: string;
organization_id: number;
practitioner_id: number;
organization_name: string;
practitioner_name: string;
secondary_diagnosis_id: number[];
sign: string;
symptoms: string;
name: any;
}
export type Organizations = {
id: number;

View File

@@ -0,0 +1,59 @@
import { FormHelperText } from "@mui/material";
import { Autocomplete, TextField } from "@mui/material";
import { Controller, useFormContext } from "react-hook-form";
type Props = {
name: string,
label: string,
options: string[];
disabled?: boolean,
}
const RHFAutocompleteNonTerminology = ({ ...props }: Props) => {
const { control } = useFormContext();
return (
<Controller
name={props.name}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => {
let xValue = (value && value.codingCode!=="" ? value : null );
return (
<>
<Autocomplete
handleHomeEndKeys
fullWidth
options={props.options}
value={xValue}
disabled={props.disabled}
freeSolo={false}
onChange={(e, newValue) => {
onChange(newValue);
}}
renderInput={(params) => (
<TextField
{...params}
label={props.label}
name={props.name}
error={!!error}
variant="outlined"
/>
)}
/>
{!!error && (
<FormHelperText error sx={{ px: 2 }}>
{error.message}
</FormHelperText>
)}
</>
)
}}
/>
)
}
export default RHFAutocompleteNonTerminology

View File

@@ -0,0 +1,102 @@
// form
import { useFormContext, Controller } from 'react-hook-form';
// @mui
import { Autocomplete, AutocompleteProps, FormHelperText, TextField, UseAutocompleteProps } from '@mui/material';
import { useState } from 'react';
import { FilterOptionsState } from '@mui/material/useAutocomplete';
// ----------------------------------------------------------------------
interface IProps {
name: string,
label: string,
options: any,
getOptionLabel: (option: any) => string,
isOptionEqualToValue: any,
disableClearable: boolean,
freeSolo: boolean,
renderOption?: any,
onInputChange?: any,
onKeyDown?: any,
onKeyPress?: any,
noOptionsText?: string,
popupIcon?: any,
disabled?: boolean,
sx?: any,
sxTextField?: any,
InputProps?: any,
onSelect?: (option: any) => void,
filterOptions?: (options: any[], state: FilterOptionsState<any>) => any[];
}
const RHFAutocompleteV2 = ( {name, label, options, ...rest} : IProps ) => {
const { control } = useFormContext();
const {
sx, sxTextField, InputProps,
onSelect,
getOptionLabel, filterOptions,
popupIcon,
isOptionEqualToValue, disableClearable,
freeSolo, renderOption,
onInputChange, onKeyDown, onKeyPress,
noOptionsText, disabled } = rest;
return (
<Controller
name={name}
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => {
return (
<>
<Autocomplete
disabled={disabled}
handleHomeEndKeys
getOptionLabel={getOptionLabel}
options={options}
freeSolo={freeSolo}
disableClearable={disableClearable}
isOptionEqualToValue={isOptionEqualToValue}
value={value}
filterOptions={filterOptions}
renderOption={renderOption}
onInputChange={onInputChange}
onKeyDown={onKeyDown}
onKeyPress={onKeyPress}
sx={sx}
popupIcon={popupIcon}
noOptionsText={noOptionsText}
renderInput={(params) => (
<TextField
{...params}
label={label}
sx={sxTextField}
InputProps={{
...params.InputProps,
...InputProps
}}
/>
)}
onChange={(e, newValue) => {
onChange(newValue);
onSelect && onSelect(newValue);
}}
/>
{!!error && (
<FormHelperText error sx={{ px: 2 }}>
{error.message}
</FormHelperText>
)}
</>
);
}}
/>
);
}
export default RHFAutocompleteV2;

View File

@@ -55,6 +55,6 @@ export default function TableMoreMenu({ actions, disableRipple }: Props) {
>
{actions}
</MenuPopover>
    </>
  );
</>
);
}

View File

@@ -1,3 +1,4 @@
import * as Yup from 'yup';
// mui
import {
Container,
@@ -9,20 +10,20 @@ import {
Divider,
ButtonBase,
Box,
IconButton,
IconButton,
Autocomplete,
FormControl,
InputLabel,
Select,
FormHelperText,
MenuItem,
} from '@mui/material';
MenuItem } from '@mui/material';
// components
import Page from '../../components/Page';
// utils
import useSettings from '../../hooks/useSettings';
// react
import { useNavigate, useParams, useLocation } from 'react-router-dom';
import { useEffect, useState, useRef } from 'react';
import { useEffect, useState, useRef, useMemo } from 'react';
import axios from '../../utils/axios';
// pages
import { format } from 'date-fns';
@@ -38,14 +39,27 @@ import Checkbox from '@mui/material/Checkbox';
import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { fPostFormat } from '@/utils/formatTime';
import { fDate, fDateTime } from '../../utils/formatTime';
import ListItemText from '@mui/material/ListItemText';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import TableMoreMenu from '@/components/table/TableMoreMenu';
import { enqueueSnackbar } from 'notistack';
import { FormProvider, RHFDatepicker, RHFSelect, RHFTextField } from '@/components/hook-form';
import { useFieldArray, useForm } from 'react-hook-form';
import { ClaimHistoryCare } from '@/@types/claims';
import { yupResolver } from '@hookform/resolvers/yup';
import { LoadingButton } from '@mui/lab';
import { Delete, Edit, EditOffOutlined, EditTwoTone, LoopOutlined, RefreshOutlined } from '@mui/icons-material';
import { fDate, fDateOnly, fDateTimeSuffix } from '@/utils/formatTime';
import TableMoreMenu from '@/components/table/TableMoreMenu';
import Label from '@/components/Label';
import RHFAutocomplete from '../../components/hook-form/RHFAutocompleteV2';
import RHFAutocompleteNonTerminology from '@/components/hook-form/RHFAutocompleteNonTerminology';
import RHFAutocompleteV2 from '../../components/hook-form/RHFAutocompleteV2';
import DialogUpdateStatus from '@/components/DialogUpdateStatus';
import hospitals from '../Corporates/Hospital/Index';
import BenefitConfigurationList from './components/BenefitConfigurationList';
import { map } from 'lodash';
// import { values } from 'lodash';
// ----------------------------------------------------------------------
@@ -81,9 +95,9 @@ export default function Detail() {
});
getService();
}, []);
}, []);
function toTitleCase(str) {
function toTitleCase(str: string | null) {
return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
@@ -102,10 +116,16 @@ export default function Detail() {
//Request
const [openDialogRequest, setOpenDialogRequest] = useState(false);
const handleCloseDialogRequest = () => {
setOpenDialogRequest(false);
}
const handleCloseDialogUpdate = () => {
setOpenDialogRequest(false);
reset()
}
const [conditionChecked, setConditionChecked] = useState(true);
const [diagnosisChecked, setDiagnosisChecked] = useState(false);
const [supportingResultChecked, setSupportingResultChecked] = useState(false);
@@ -127,8 +147,128 @@ export default function Detail() {
const isRequiredFieldsFilled = () => {
return noteField.trim() !== '';
};
const handelRequestDocument = () => {
/*---------------------- Handle History Hospital Care ----------------------------*/
interface FormValuesProps extends Partial<ClaimHistoryCare> {
taxes: boolean;
inStock: boolean;
}
/**------------- Handle History Hospital Care ---------------------*/
const [currentClaimHistoryCare, setCurrentClaimHistoryCare] = useState(null);
const [organization, setOrganization] = useState([]); // Untuk Hospital
const [doctor, setDoctor] = useState([]); // Untuk Docter
const [corporate_id, setCorporateId] = useState(null); // Untuk Corporate
const [main_diagnosis, setMainDiagnosis] = useState([]); // Untuk Main diagnosis
const [claimHistoryId,setClaimHistoryId] = useState<number|null>(null); // Untuk edit Claim History
const [carehistory, setCarehistory] = useState<ClaimHistoryCare|null>(null);
const [isEdit,setEdit] = useState(false);
const [claim, setClaim] = useState<ClaimHistoryCare|null>([])
useEffect( () => {
axios
.get('claims/'+id)
.then((response) => {
setCorporateId(response.data.data.corporate_id)
setCurrentClaimHistoryCare(response.data.data.history_hospital_care)
setClaim(response.data.data)
})
}, [])
useEffect( () => {
// setMainDiagnosis
axios
.get(`corporates/${corporate_id}/diagnosis`)
.then((response) => {
setMainDiagnosis(response.data.data)
})
// setOrganization atau hospital atau location
axios
.get(`corporates/${corporate_id}/hospitals`)
.then((response) => {
setOrganization(response.data.data)
})
}, [corporate_id])
useEffect( () => {
// setCarehistory
if (claimHistoryId != null) {
axios
.get('/claims/carehistory/'+claimHistoryId)
.then((response) => {
reset({
service_code: response.data.data.service_code,
admision_date: response.data.data.admision_date,
discharge_date: response.data.data.discharge_date,
organization_id: response.data.data.organization_id,
practitioner_id: response.data.data.practitioner_id,
medical_record_number: response.data.data.medical_record_number,
symptoms: response.data.data.symptoms,
sign: response.data.data.sign,
main_diagnosis_id: response.data.data.main_diagnosis_id,
});
setCarehistory(response.data.data);
})
.catch((error) => {
console.error(error);
});
// setDoctor atau practioner
axios
.get('/doctors?search=&organization_id='+values.organization_id)
.then((response) => {
setDoctor(response.data.data);
})
.catch((error) => {
console.error(error);
});
}
}, [claimHistoryId])
useEffect( () => {
reset(defaultValues);
}, [isEdit])
const [openDialogHospitalCare, setOpenHospitalCare] = useState(false);
const handleCloseDialogHospitalCare = () => {
setEdit(false)
setOpenHospitalCare(false);
setClaimHistoryId(null)
reset();
}
const [openDialogApproval, setOpenDialogApproval] = useState(false);
const handleCloseDialogApprove = () => {
setOpenDialogApproval(false);
setClaimHistoryId(null);
reset();
}
/* Handle For Approve Claim */
const handleApproveClaim = (id: number|null, claim_id: number|null) =>{
let data = {
status: 1
}
axios.post(`/claims/carehistory/${id}/approval`, data);
setOpenDialogApproval(false)
enqueueSnackbar(
'Claim Approve Successfully!',
{ variant: 'success' }
);
window.location.reload();
}
const handelRequestDocument = (event) => {
const dataForm = {
claim_id: id,
condition: conditionChecked,
@@ -147,7 +287,196 @@ export default function Detail() {
enqueueSnackbar('Something Went Wrong', { variant: 'error' });
})
}
//Service
// Handle Location Change
const handleLocationChange = (organization_id:number) => {
// if (newValue) {
const selectedValue = organization_id;
setValue('organization_id', selectedValue);
// let data = {
// ...values,
// practitioner_id: 0
// }
// reset(data)
axios
.get('/doctors?search=&organization_id=' + selectedValue)
.then((response) => {
setDoctor(response.data.data);
})
.catch((error) => {
console.error(error);
});
// }
}
const handleDoctorChange = (event, newValue) => {
if (newValue) {
const selectedValue = newValue.id;
setValue('practitioner_id', selectedValue);
}
}
const handleMainDiagnosisChange = (event, newValue) => {
if (newValue) {
const selectedValue = newValue.id;
setValue('main_diagnosis_id', selectedValue);
}
}
const defaultValues = useMemo(
() => ({
service_code: 'OP',
secondary_diagnosis_id: [{
value: {
name: "",
value: 0
}
}],
admision_date: isEdit ? carehistory?.admision_date : '',
discharge_date: isEdit ? carehistory?.discharge_date : '',
organization_id: isEdit ? carehistory?.organization_id : '',
practitioner_id: isEdit ? carehistory?.practitioner_id : '',
medical_record_number: isEdit ? carehistory?.medical_record_number : '',
symptoms: isEdit ? carehistory?.symptoms : '',
sign: isEdit ? carehistory?.sign : '',
main_diagnosis_id: isEdit ? carehistory?.main_diagnosis_id : 0,
}),
[]
)
let NewClaimHistoryCareSchema = Yup.object().shape({
service_code: Yup.string().required('Name is required'),
// admision_date: Yup.date().required('Admisision Date is required'),
// discharge_date: Yup.date().required('Discharge Date is required'),
// organization_id: Yup.number().required('Location is required'),
// practitioner_id: Yup.number().required('Doctor is required'),
// medical_record_number: Yup.string().required('Medical Record is required'),
// symptoms: Yup.string().required('Symptoms is required'),
// sign: Yup.string().required('Sign is required'),
// main_diagnosis_id: Yup.number().required('Main Diagnosis is required'),
});
const methods = useForm<FormValuesProps>({
resolver: yupResolver(NewClaimHistoryCareSchema),
defaultValues,
});
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
resetField,
formState: { isSubmitting },
} = methods;
const values = watch();
console.log(values, 'debugs')
const {fields, append, remove} = useFieldArray<FormValuesProps>({name: "secondary_diagnosis_id", control})
const onSubmit = async (data: FormValuesProps) => {
if (isEdit){
let newData = {
service_code: data.service_code,
admision_date: data.admision_date ? fDateOnly(data.admision_date) : null,
discharge_date: data.discharge_date ? fDateOnly(data.discharge_date) : null,
organization_id: data.organization_id,
practitioner_id: data.practitioner_id,
medical_record_number: data.medical_record_number,
symptoms: data.symptoms,
sign: data.sign,
secondary_diagnosis_id: data.secondary_diagnosis_id ? data.secondary_diagnosis_id.map((row) => row.value.id) : null,
main_diagnosis_id: data.main_diagnosis_id,
}
const response:any = await axios.post(`/claims/carehistory/${claimHistoryId}/update`, newData);
// if (response.status == 'success'){
setOpenHospitalCare(false)
enqueueSnackbar(
'Claim Update Successfully!',
{ variant: 'success' }
);
navigate('/claims/detail/'+id);
window.location.reload();
// }
} else {
let newData = {
service_code: data.service_code,
admision_date: data.admision_date ? fDateOnly(data.admision_date) : null,
discharge_date: data.discharge_date ? fDateOnly(data.discharge_date) : null,
organization_id: data.organization_id,
practitioner_id: data.practitioner_id,
medical_record_number: data.medical_record_number,
symptoms: data.symptoms,
sign: data.sign,
secondary_diagnosis_id: data.secondary_diagnosis_id ? data.secondary_diagnosis_id.map((row) => row.value.id) : null,
main_diagnosis_id: data.main_diagnosis_id,
}
const response:any = await axios.post(`/claims/${id}/carehistory`, newData);
// if (response.status == 'success'){
setOpenHospitalCare(false)
enqueueSnackbar(
'Claim Insert Successfully!',
{ variant: 'success' }
);
navigate('/claims/detail/'+id);
// }
}
reset();
}
function secondaryDiagnosisOption() {
return fields.map((item, index) => {
return (
<Card key={item.id} sx={{ paddingX: 2, paddingY: 2, marginBottom: 2 }}>
<Typography variant='subtitle1' marginBottom={2}>{`#${index+1}`}</Typography>
<Box sx={{display: "flex", placeContent: 'space-between', placeItems: "center", gap: 2}}>
<Box sx={{width: "100%"}}>
<RHFAutocomplete
name={`secondary_diagnosis_id.${index}.value`}
options={main_diagnosis}
disableClearable
freeSolo
getOptionLabel={(opt) => opt.name}
isOptionEqualToValue={(opt, val) => opt.name === val.name}
label='Comparative Diagnosis (ICD-X)'
/>
</Box>
<IconButton color='error' onClick={() => remove(index)}>
<Delete />
</IconButton>
</Box>
</Card>
)
})
}
function handleNewHospitalCare() {
setEdit(false);
setOpenHospitalCare(true);
reset(defaultValues);
}
function handleEditHospitalCare(id: number) {
setClaimHistoryId(id);
setEdit(true);
setOpenHospitalCare(true);
}
//Service
const [openDialogService, setOpenDialogService] = useState(false);
const handleCloseDialogService = () => {
setOpenDialogService(false);
@@ -299,6 +628,8 @@ export default function Detail() {
});
}
return (
<Page title='Detail'>
<Container maxWidth={themeStretch ? false : 'xl'}>
@@ -407,7 +738,7 @@ export default function Detail() {
))}
</Stack>
{/* Dialog Request Documents */}
<Dialog open={openDialogRequest} onClose={handleCloseDialogRequest} fullWidth={true}>
<Dialog open={openDialogRequest} onClose={handleCloseDialogRequest} fullWidth={true} >
<DialogTitle sx={{ backgroundColor: '#19BBBB', color: '#FFF', padding: 2 }}>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Stack direction="row" alignItems='center' spacing={1}>
@@ -463,12 +794,293 @@ export default function Detail() {
<Card sx={{padding: 3}}>
<Stack direction="row" alignItems="center" sx={{marginBottom: 4}}>
<Typography variant='subtitle1' sx={{color: '#19BBBB'}} gutterBottom>History of Hospital Care</Typography>
<Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}}>
<Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}} onClick={handleNewHospitalCare}>
<Typography variant="button" display="block">History</Typography>
</Button>
</Stack>
<Stack direction="column" spacing={2} sx={{marginBottom: 2}}>
{currentClaimHistoryCare?.map((claimHistoryCare, index) =>
claimHistoryCare.status === 0 ? (
<Grid item xs={12} md={12} key={index}> {/* Tambahkan key untuk setiap elemen dalam loop */}
<Card sx={{padding: 2}}>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{marginBottom: 4}}>
<Label variant="outlined" color='primary' >
<Typography variant="button" display="block">{claimHistoryCare.service_code = 'OP' ? 'Outpatient' : 'Inpatient'}</Typography>
</Label>
<TableMoreMenu actions={
<>
<MenuItem onClick={() => handleEditHospitalCare(claimHistoryCare.id)}>
<EditTwoTone />Edit
</MenuItem>
<MenuItem onClick={() => {setOpenDialogApproval(true); setClaimHistoryId(claimHistoryCare.id)}}>
<LoopOutlined />Update Status
</MenuItem>
</>
}/>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Admission Date :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ fDate(claimHistoryCare.admision_date)}</Typography> {/* Perbaikan typo di 'admission_date' */}
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Discharge Date :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ fDate(claimHistoryCare.discharge_date)}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Location :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{toTitleCase(claimHistoryCare.organization?.name)}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Doctor :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{toTitleCase(claimHistoryCare.practitioner?.code)} - {claimHistoryCare.person?.name}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Status :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{claimHistoryCare.status == 0 ? 'Pending' : 'Approv'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Diagnosis :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>#{index+1} {claimHistoryCare.icd?.code} - {claimHistoryCare.icd?.name}</Typography>
</Stack>
</Card>
</Grid>
) : null
)}
</Stack>
{/* Dialog for input and update */}
<Dialog open={openDialogHospitalCare} onClose={handleCloseDialogHospitalCare} fullWidth={true} maxWidth={'xl'}>
<DialogTitle sx={{ backgroundColor: '#19BBBB', color: '#FFF', padding: 2 }}>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Stack direction="row" alignItems='center' spacing={1}>
<Typography variant="h6">{isEdit ? 'Update' : 'Add'} History of Hospital Care</Typography>
</Stack>
<IconButton sx={{ color: '#FFF' }} onClick={handleCloseDialogHospitalCare}>
<CloseIcon />
</IconButton>
</Stack>
</DialogTitle>
<DialogContent>
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2} sx={{marginTop: 2, padding: 2}}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant='subtitle1' marginBottom={1}>Service Code</Typography>
<RHFSelect
name="service_code"
label="Service Code"
placeholder="Service Code"
disabled
>
<option value="" />
<option value="IP">Inpatient</option>
<option value="OP">Outpatient</option>
</RHFSelect>
</Grid>
<Grid item xs={6} md={6}>
<Typography variant="subtitle1" sx={{marginBottom: '10px'}}>Admission Date*</Typography>
<RHFDatepicker name="admision_date" label="Admission Date" required/>
</Grid>
<Grid item xs={6} md={6}>
<Typography variant="subtitle1" sx={{marginBottom: '10px'}}>Discharge Date*</Typography>
<RHFDatepicker name="discharge_date" label="Discharge Date" required/>
</Grid>
{/* Location */}
<Grid item xs={12}>
<Typography variant='subtitle1' marginBottom={1}>Location*</Typography>
<Autocomplete
id="combo-box-demo"
options={organization}
fullWidth
getOptionLabel={(option) => {
return option.name ?? false
}}
isOptionEqualToValue={(option, value) =>{
return option.organization_id == value.organization_id
}}
onChange={(e, selectedOption) => {
if (selectedOption) {
const selectedOrganizationId = selectedOption.organization_id;
handleLocationChange(selectedOrganizationId);
}
}}
value={organization.find(row => row.organization_id == values.organization_id)}
renderInput={(params) => (
<RHFTextField
name="organization_id"
{...params}
label="Location"
variant="outlined"
fullWidth
required
/>
)}
/>
</Grid>
{/* Dokter */}
<Grid item xs={12}>
<Typography variant='subtitle1' marginBottom={1}>Doctor*</Typography>
<Autocomplete
id="combo-box-demo"
options={doctor}
limitTags={1}
fullWidth
getOptionLabel={(option) => {
return option.name ?? false
}}
isOptionEqualToValue={(option, value) =>{
return option.id === value.id
}}
value={doctor.find(row => row.id == values.practitioner_id)}
onChange={handleDoctorChange}
renderInput={(params) => (
<RHFTextField
name='practitioner_id'
{...params}
label="Doctor"
variant="outlined"
fullWidth
required
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Typography variant='subtitle1' color="#637381" marginBottom={1}>Medical Record Number*</Typography>
<RHFTextField name="medical_record_number" label="Medical Record Number" required placeholder='Medical Record Number' />
</Grid>
<Grid item xs={12}>
<Typography variant='subtitle1' color="#637381" marginBottom={1}>Symptoms*</Typography>
<RHFTextField name="symptoms" label="Symptoms" placeholder='Symptoms' required/>
</Grid>
<Grid item xs={12}>
<Typography variant='subtitle1' color="#637381" marginBottom={1}>Sign*</Typography>
<RHFTextField name="sign" label="Sign" placeholder='Sign' required />
</Grid>
<Grid item xs={10.8}>
<Typography variant='subtitle1' color="#637381">Diagnosis*</Typography>
</Grid>
<Grid item xs={1} justifyContent={'flex-end'}>
{/* <Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}} onClick={() => handleAddSecondaryDiagnosis()}> */}
<Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}} onClick={() => append({value: {name: "", value: 0}})}>
<Typography variant="button" display="block">Diagnosis</Typography>
</Button>
</Grid>
{/* Main Diagnosis */}
<Grid item xs={12}>
<Autocomplete
id="combo-box-demo"
options={main_diagnosis}
limitTags={1}
fullWidth
getOptionLabel={(option) => {
return option.name ?? false
}}
isOptionEqualToValue={(option, value) =>{
return option.id == value.main_diagnosis_id
}}
value={main_diagnosis.find(row => row.id == values.main_diagnosis_id)}
onChange={handleMainDiagnosisChange}
renderInput={(params) => (
<RHFTextField required {...params} label="Main Diagnosis (ICD-X)" variant="outlined" name='main_diagnosis_id' />
)}
/>
</Grid>
<Grid item xs={12}>
{secondaryDiagnosisOption()}
</Grid>
</Grid>
</Stack>
<Stack direction="row" spacing={2}>
<Grid container item xs={12} md={12} justifyContent="flex-end">
<Button variant="outlined" color='primary' onClick={handleCloseDialogHospitalCare}>Cancel</Button>
<LoadingButton
type="submit"
variant="contained"
size="medium"
loading={isSubmitting}
sx={{marginLeft:2}}
>
<Typography variant="subtitle2">{isEdit ? 'Update' : 'Save'}</Typography>
</LoadingButton>
</Grid>
</Stack>
</FormProvider>
</DialogContent>
<DialogActions>
</DialogActions>
</Dialog>
{/* Dialog for approval */}
<Dialog open={openDialogApproval} onClose={handleCloseDialogApprove} fullWidth={true} maxWidth={'sm'}>
<DialogTitle sx={{ backgroundColor: '#19BBBB', color: '#FFF', padding: 2 }}>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Stack direction="row" alignItems='center' spacing={1}>
<Typography variant="h6">Add History of Hospital Care</Typography>
</Stack>
<IconButton sx={{ color: '#FFF' }} onClick={handleCloseDialogApprove}>
<CloseIcon />
</IconButton>
</Stack>
</DialogTitle>
<DialogContent>
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={2} sx={{marginTop: 2, padding: 2}}>
<Typography variant='subtitle1'> Are you sure to approve this hospital care ?</Typography>
</Stack>
<Card sx={{padding: 2}}>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Admission Date</Typography>
<Typography variant='subtitle1' gutterBottom>{ carehistory ? fDate(carehistory?.admision_date) : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Discharge Date</Typography>
<Typography variant='subtitle1' gutterBottom>{carehistory ? fDate(carehistory.discharge_date) : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Location</Typography>
<Typography variant='subtitle1' gutterBottom>{ carehistory ? carehistory.organization_name : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Doctor</Typography>
<Typography variant='subtitle2' gutterBottom>{carehistory ? carehistory.practitioner_name : '-'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Diagnosis</Typography>
<Typography variant='subtitle2' gutterBottom>{carehistory ? carehistory?.main_diagnosis_name : '-'}</Typography>
</Stack>
</Card>
<Stack direction="row" spacing={1} marginTop={3}>
<Grid container item xs={12} md={12} justifyContent="flex-end">
<Button variant="outlined" color='inherit' onClick={handleCloseDialogApprove}>Cancel</Button>
<Button variant="contained" sx={{marginLeft:1}} onClick={()=> handleApproveClaim(carehistory?.id, carehistory?.claim_id)} >
<Typography variant="subtitle2">Approve</Typography>
</Button>
</Grid>
</Stack>
</FormProvider>
</DialogContent>
<DialogActions>
</DialogActions>
</Dialog>
</Card>
</Grid>
<Grid item xs={12}>
@@ -477,6 +1089,43 @@ export default function Detail() {
<Typography variant='subtitle1' sx={{color: '#19BBBB'}} gutterBottom>Diagnostic History</Typography>
</Stack>
<Stack direction="column" spacing={2} sx={{marginBottom: 2}}>
{currentClaimHistoryCare?.map((claimHistoryCare, index) =>
claimHistoryCare.status === 1 ? (
<Grid item xs={12} md={12} key={index}> {/* Tambahkan key untuk setiap elemen dalam loop */}
<Card sx={{padding: 2}}>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{marginBottom: 4}}>
<Label variant="outlined" color='primary' >
<Typography variant="button" display="block">{claimHistoryCare.service_code = 'OP' ? 'Outpatient' : 'Inpatient'}</Typography>
</Label>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Admission Date :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ fDate(claimHistoryCare.admision_date)}</Typography> {/* Perbaikan typo di 'admission_date' */}
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Discharge Date :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ fDate(claimHistoryCare.discharge_date)}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Location :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{toTitleCase(claimHistoryCare.organization?.name)}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Doctor :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{toTitleCase(claimHistoryCare.practitioner?.code)} - {claimHistoryCare.person?.name}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Status :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{claimHistoryCare.status == 0 ? 'Pending' : 'Approv'}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Diagnosis :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>#{index+1} {claimHistoryCare.icd?.code} - {claimHistoryCare.icd?.name}</Typography>
</Stack>
</Card>
</Grid>
) : null
)}
</Stack>
</Card>
</Grid>
@@ -484,16 +1133,57 @@ export default function Detail() {
<Card sx={{padding: 3}}>
<Stack direction="row" alignItems="center" sx={{marginBottom: 4}}>
<Typography variant='subtitle1' sx={{color: '#19BBBB'}} gutterBottom>Diagnosis Summary</Typography>
<Button variant="outlined" startIcon={<AddIcon/>} sx={{marginLeft: 'auto'}}>
<Typography variant="button" display="block">Diagnosis</Typography>
</Button>
</Stack>
<Stack direction="column" spacing={2} sx={{marginBottom: 2}}>
{currentClaimHistoryCare?.map((claimHistoryCare, index) =>
claimHistoryCare.status === 1 ? (
<Grid item xs={12} md={12} key={index}> {/* Tambahkan key untuk setiap elemen dalam loop */}
<Card sx={{padding: 2}}>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Symtomps :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ claimHistoryCare.symptoms}</Typography> {/* Perbaikan typo di 'admission_date' */}
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Sign :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{ claimHistoryCare.sign}</Typography>
</Stack>
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>Main Diagnosis :</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{claimHistoryCare.icd?.name} <Label>{claimHistoryCare.icd?.code}</Label></Typography>
</Stack>
{/* {claimHistoryCare.comparative_diagnosis?.map((comparativeDiagnosis, i) =>
(
<Stack direction='row' spacing={2} sx={marginBottom1}>
<Typography variant='subtitle2' sx={style1} gutterBottom>{i == 0 ? 'Comparative Diagnosis :' : ''}</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>{comparativeDiagnosis.icd?.name} <Label>{comparativeDiagnosis.icd?.code}</Label></Typography>
</Stack>
)
)} */}
{claimHistoryCare.comparative_diagnosis && claimHistoryCare.comparative_diagnosis.length > 0 && (
claimHistoryCare.comparative_diagnosis.map((comparativeDiagnosis, i) => (
<Stack direction='row' spacing={2} sx={marginBottom1} key={i}>
<Typography variant='subtitle2' sx={style1} gutterBottom>
{i === 0 ? 'Comparative Diagnosis :' : ''}
</Typography>
<Typography variant='subtitle2' sx={style2} gutterBottom>
{comparativeDiagnosis.icd?.name} <Label>{comparativeDiagnosis.icd?.code}</Label>
</Typography>
</Stack>
))
)}
</Card>
</Grid>
) : null
)}
</Stack>
</Card>
</Grid>
<Grid item xs={12}>
<Card sx={{padding: 3}}>
<Card sx={{padding: 2}}>
<Stack direction="row" alignItems="center" sx={{marginBottom: 4}}>
<Typography variant='subtitle1' sx={{color: '#19BBBB'}} gutterBottom>Service</Typography>
{!serviceData ? (

View File

@@ -228,6 +228,8 @@ export default function PractitionerForm({ isEdit, currentPractitioner }: Props)
useEffect(() => {
axios.get(`/search-organizations`).then((response) => {
console.log(response);
setOrganizations(
response.data.map((item: any) => ({ ...item, name: item.name, value: item.id }))
);
@@ -489,7 +491,11 @@ export default function PractitionerForm({ isEdit, currentPractitioner }: Props)
options={availableOrganizations}
value={findValueOrganization(form.organizationId) ?? ''}
getOptionLabel={(option) => option.name}
isOptionEqualToValue={(option, value) => option.value === value.value}
isOptionEqualToValue={(option, value) => {
console.log(value, option, 'test')
return option.value === value.value
}
}
onChange={(event, value) => handleOrganizationIdChange(index, value)}
renderInput={(params) => (
<TextField {...params} label="Rumah Sakit" variant="outlined" />

View File

@@ -3,7 +3,7 @@ import { format, getTime, formatDistanceToNow } from 'date-fns';
// ----------------------------------------------------------------------
export function fDate(date: Date | string | number) {
return format(new Date(date), 'dd MMMM yyyy');
return format(new Date(date), 'dd MMM yyyy');
}
export function fDateTime(date: Date | string | number) {

View File

@@ -164,6 +164,10 @@ return [
|
*/
'attributes' => [],
'attributes' => [
"MORE_THAN" => ":date_param (:date) must be greater than :date_param2 date (:start)",
"LESS_THAN" => ":date_param (:date) must be less than :date_param2 date (:end)",
],
];

View File

@@ -24,11 +24,7 @@
content="The starting point for your next project with Minimal UI Kit, built on the newest version of Material-UI ©, ready to be customized to your style" />
<meta name="keywords" content="react,material,kit,application,dashboard,admin,template" />
<meta name="author" content="Minimal UI Kit" />
<<<<<<< HEAD
<script type="module" crossorigin src="/assets/index.9b396686.js"></script>
=======
<script type="module" crossorigin src="/assets/index.da589e84.js"></script>
>>>>>>> a54708abb5d46d7d7319730306a528d33d910895
<link rel="stylesheet" href="/assets/index.c91e36b5.css">
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>