Files
aso/frontend/dashboard/src/pages/EPrescription/Livechat/View.tsx
2024-05-06 11:36:22 +07:00

678 lines
24 KiB
TypeScript

import * as Yup from 'yup';
import { useSnackbar } from 'notistack';
import { useNavigate } from 'react-router-dom';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import MenuItem from '@mui/material/MenuItem';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import * as React from 'react';
// form
import {useFieldArray, useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
// @mui
import { styled } from '@mui/material/styles';
import { LoadingButton } from '@mui/lab';
import {
Box,
Autocomplete,
Avatar,
Button,
ButtonGroup,
Card,
FormHelperText,
Grid,
Stack,
Typography,
TextField,
Chip,
Badge,
Divider,
} from '@mui/material';
import CancelIcon from '@mui/icons-material/Cancel';
// components
import {
FormProvider,
RHFTextField,
RHFRadioGroup,
RHFUploadAvatar,
RHFSwitch,
RHFEditor,
RHFDatepicker,
RHFMultiCheckbox,
RHFCheckbox,
RHFCustomMultiCheckbox,
} from '../../../components/hook-form';
import axios from '../../../utils/axios';
import { fCurrency } from '../../../utils/formatNumber';
import { Appointment } from '../../../@types/doctor';
import RHFTextFieldMoney from "@/components/hook-form/v2/RHFTextFieldMoney";
import { Label, Rowing, Spa } from '@mui/icons-material';
import { border, padding } from '@mui/system';
import { IconButton } from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import RemoveIcon from '@mui/icons-material/Remove';
const LabelStyle = styled(Typography)(({ theme }) => ({
...theme.typography.subtitle2,
color: theme.palette.text.secondary,
marginBottom: theme.spacing(1),
}));
const HeaderStyle = styled('header')(({ theme }) => ({
paddingBottom: theme.spacing(5),
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}));
const Title = styled(Typography)(({ theme }) => ({
...theme.typography.h4,
boxShadow: 'none',
// paddingBottom: theme.spacing(3),
fontWeight: 700,
color: '#005B7F',
}));
interface FormValuesProps extends Partial<Appointment> {
taxes: boolean;
inStock: boolean;
}
type Props = {
isEdit: boolean;
id: number;
currentAppointment?: Appointment;
};
const Span = styled(Typography)(({ theme }) => ({
boxShadow: 'none',
paddingBottom: theme.spacing(1),
}));
const Text = styled(Typography)(({ theme }) => ({
boxShadow: 'none',
paddingBottom: theme.spacing(3),
}));
export default function AppointmentForm({ isEdit, id, currentAppointment }: Props) {
const navigate = useNavigate();
// const [ errors, setErrors ] = useState<{ [key: string]: string }>({});
const { enqueueSnackbar } = useSnackbar();
const NewCorporateSchema = Yup.object().shape({
// name: Yup.string().required('Name is required'),
// file: Yup.boolean().required('Corporate Status is required'),
});
const defaultValues = useMemo(
() => ({
id: currentAppointment?.id,
name: currentAppointment?.name || '',
address: currentAppointment?.address || '',
birth_date: currentAppointment?.birth_date || '',
gender: currentAppointment?.gender || '',
description: currentAppointment?.description || '',
birth_place: currentAppointment?.birth_place || '',
active: currentAppointment?.active === 1 ? true : false,
avatar_url: currentAppointment?.avatar_url || '',
doctor_id: currentAppointment?.doctor_id || '',
organizations: currentAppointment?.organizations || [],
specialities: currentAppointment?.specialities || [],
diagnosis: currentAppointment?.diagnosis || '',
hospital: currentAppointment?.hospital || null,
medicine : currentAppointment?.medicine || [
{
drug_id: 0,
qty: 0,
signa: '',
unit_id: 0,
note: '', // input to database
}
],
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[currentAppointment]
);
console.log()
const methods = useForm<FormValuesProps>({
// resolver: yupResolver(NewCorporateSchema),
defaultValues,
});
const {fields, append, remove} = useFieldArray({name: 'medicine',control: methods.control})
// Autocomplite ICD
const [icdOptions, setIcdOptions] = useState([]);
useEffect(() => {
// Ambil data dari API dan atur opsi ICD
axios.get('diagnosis')
.then((response) => {
setIcdOptions(response.data.data);
})
.catch((error) => {
console.error('Error fetching ICD options:', error);
});
}, []); // useEffect dijalankan hanya sekali saat komponen dimount
// Menggunakan selectedIcdOptions sebagai state untuk nilai default
const [selectedIcdOptions, setSelectedIcdOptions] = useState([]);
const codes = defaultValues.diagnosis.split(',');
useEffect(() => {
// Pastikan bahwa icdOptions sudah terisi sebelum memfilter
if (icdOptions.length > 0) {
const selectedCodes = icdOptions.filter((icd) => {
return codes.includes(icd.value);
});
setSelectedIcdOptions(selectedCodes);
// setValue('diagnosis', selectedCodes); // Ini bisa Anda hilangkan jika tidak diperlukan
}
}, [icdOptions, defaultValues.diagnosis]);
// Autocomplite Rumah Sakit
const [hospitalOptions, setHospitalOptions] = useState([]);
const [selectedHospitalOption, setSelectedHospitalOption] = useState(null);
// Ambil data dari API dan atur opsi rumah sakit
useEffect(() => {
axios.get('hospitals')
.then((response) => {
setHospitalOptions(response.data.data);
})
.catch((error) => {
console.error('Error fetching hospital options:', error);
});
}, []); // useEffect dijalankan hanya sekali saat komponen dimount
// Set default value saat hospitalOptions berubah
useEffect(() => {
const selectedId = hospitalOptions.find((hospital) => {
return hospital.value == defaultValues.hospital
});
setSelectedHospitalOption(selectedId);
setValue('hospital', defaultValues.hospital)
}, [hospitalOptions, defaultValues]);
// Autocomplite drugs
const [drugOptions, setDrugsOptions] = useState([]);
const [selectedDrugsOptions, setSelectedDrugsOptions] = useState({});
const handleAutocompleteChange = (newValue, index) => {
setSelectedDrugsOptions((prevState) => ({
...prevState,
[index]: newValue
}));
setValue(`medicine.${index}.drug_id`, newValue ? newValue.value : '');
};
// Ambil data dari API dan atur opsi rumah sakit
useEffect(() => {
axios.get('drugs')
.then((response) => {
setDrugsOptions(response.data.data);
})
.catch((error) => {
console.error('Error fetching drug options:', error);
});
}, []); // useEffect dijalankan hanya sekali saat komponen dimount
// Autocomplite unit
const [unitOptions, setUnitsOptions] = useState([]);
const [selectedUnitsOptions, setSelectedUnitsOptions] = useState({});
const handleAutocompleteChangeUnit = (newValue, index) => {
setSelectedUnitsOptions((prevState) => ({
...prevState,
[index]: newValue
}));
setValue(`medicine.${index}.unit_id`, newValue ? newValue.value : '');
};
// Ambil data dari API dan atur opsi rumah sakit
useEffect(() => {
axios.get('units')
.then((response) => {
setUnitsOptions(response.data.data);
})
.catch((error) => {
console.error('Error fetching unit options:', error);
});
}, []); // useEffect dijalankan hanya sekali saat komponen dimount
useEffect(() => {
if (defaultValues.medicine.length > 0) {
defaultValues.medicine.map((med, index) => {
const selectedDrugId = drugOptions.find((drug) => {
return drug.value == med.drug_id
});
handleAutocompleteChange(selectedDrugId,index)
const selectedUnitId = unitOptions.find((unit) => {
return unit.value == med.unit_id
});
handleAutocompleteChangeUnit(selectedUnitId,index)
// Contoh: Lakukan tindakan lainnya sesuai kebutuhan Anda
});
} else {
console.log('Medicine is empty');
}
}, [defaultValues.medicine]);
const {
reset,
watch,
control,
setValue,
getValues,
setError,
handleSubmit,
formState: { isSubmitting },
} = methods;
const values = watch();
useEffect(() => {
if (isEdit && currentAppointment) {
reset(defaultValues);
}
if (!isEdit) {
reset(defaultValues);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isEdit, currentAppointment]);
const onSubmit = async (data: FormValuesProps) => {
try {
const formData = new FormData();
formData.append('id', data.id);
formData.append('diagnosis', data.diagnosis);
formData.append('hospital', data.hospital);
// Iterasi melalui setiap objek dalam array medicine dan menambahkannya ke FormData
data.medicine.forEach((medicineObj, index) => {
// Anda dapat menambahkan setiap properti dari objek medicine ke FormData
formData.append(`medicine[${index}][drug_id]`, medicineObj.drug_id);
formData.append(`medicine[${index}][qty]`, medicineObj.qty);
formData.append(`medicine[${index}][unit_id]`, medicineObj.unit_id);
formData.append(`medicine[${index}][signa]`, medicineObj.signa);
formData.append(`medicine[${index}][note]`, medicineObj.note);
});
const response = await axios.post('/prescription', formData);
reset();
enqueueSnackbar('Berhasil menambahkan resep', {
variant: 'success',
});
navigate('/e-prescription/live-chat');
} catch (error: any) {
console.log(error, 'submit')
enqueueSnackbar(error.message ?? 'Failed Processing Request', { variant: 'error' });
}
const ascent = document?.querySelector('ascent');
if (ascent != null) {
ascent.innerHTML = '';
}
};
const handleDownloadEPrescription = (id: number) => {
axios
.get(`prescription-download/${id}`, {
responseType: 'blob',
})
.then((response) => {
window.open(URL.createObjectURL(response.data));
})
.catch((response) => {
enqueueSnackbar(response.message, { variant: 'error' });
});
}
return (
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={3}>
<Box sx={{ width: '100%' }}>
{/* <Stack spacing={3}> */}
<Card sx={{ p: 5 }}>
<HeaderStyle>
<Grid item xs={6} md={6}>
<Stack
direction="row"
divider={<Divider orientation="vertical" flexItem />}
spacing={2}
>
<Title>Data Live Chat</Title>
</Stack>
</Grid>
</HeaderStyle>
<Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Grid item xs={12}>
<Stack direction="row" spacing={2}>
<Grid item xs={6}>
<Stack direction="row" spacing={2} alignItems="center">
<Span style={{ fontWeight: 'bold', paddingBottom: '0px' }}>
Status Appointment :
</Span>
<Chip
label={
currentAppointment?.status_appointment
? currentAppointment?.status_appointment
: '-'
}
variant="outlined"
/>
</Stack>
</Grid>
<Grid item xs={6}>
<Stack direction="row" spacing={2} alignItems="center">
<Span style={{ fontWeight: 'bold', paddingBottom: '0px' }}>
Status Chat :
</Span>
<Chip
label={
currentAppointment?.status_chat ? currentAppointment?.status_chat : '-'
}
variant="outlined"
/>
</Stack>
</Grid>
</Stack>
</Grid>
<Grid item xs={12} sx={{ marginTop: '20px' }}>
<Stack direction="row" spacing={2}>
<Grid item xs={6}>
<Stack direction="row" spacing={2}>
<Span style={{ fontWeight: 'bold' }}>Tanggal Booking :</Span>
<Text>
{currentAppointment?.date_created ? currentAppointment?.date_created : '-'}
</Text>
</Stack>
</Grid>
<Grid item xs={6}>
<Stack direction="row" spacing={2}>
<Span style={{ fontWeight: 'bold' }}>Tanggal Appointment :</Span>
<Text>
{currentAppointment?.date_appointment
? currentAppointment?.date_appointment
: '-'}
</Text>
</Stack>
</Grid>
</Stack>
</Grid>
<Grid item xs={6}>
<Span style={{ fontWeight: 'bold' }}>Nama Dokter</Span>
<Text>
{currentAppointment?.doctor_name ? currentAppointment?.doctor_name : '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Faskes</Span>
<Text>
{currentAppointment?.health_care ? currentAppointment?.health_care : '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Durasi</Span>
<Text>{currentAppointment?.duration ? currentAppointment?.duration : '-'}</Text>
</Grid>
<Grid item xs={6} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Span style={{ fontWeight: 'bold' }}>Spesialis</Span>
<Text>{currentAppointment?.speciality ? currentAppointment?.speciality : '-'}</Text>
<Span style={{ fontWeight: 'bold' }}>Appointment Via Web/App</Span>
<Text>
{currentAppointment?.appointment_media
? currentAppointment?.appointment_media
: '-'}
</Text>
</Grid>
</Grid>
</Card>
<Card sx={{ mt: 5, p: 5 }}>
<HeaderStyle>
<Grid item xs={6} md={6}>
<Title>Data Pembayaran</Title>
</Grid>
</HeaderStyle>
{currentAppointment?.payment_detail !== null ? (
<Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Grid item xs={6}>
<Span style={{ fontWeight: 'bold' }}>Metode Pembayaran</Span>
<Text>
{currentAppointment?.payment_method ? currentAppointment?.payment_method : '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Harga</Span>
<Text>
{currentAppointment?.payment_detail?.gross_amount
? currentAppointment?.payment_detail?.gross_amount
: '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Mata Uang</Span>
<Text>
{currentAppointment?.payment_detail?.currency
? currentAppointment?.payment_detail?.currency
: '-'}
</Text>
</Grid>
<Grid item xs={6} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Span style={{ fontWeight: 'bold' }}>Tipe Pembayaran</Span>
<Text>
{currentAppointment?.payment_detail?.payment_type
? currentAppointment?.payment_detail?.payment_type
: '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Waktu Transaksi</Span>
<Text>
{currentAppointment?.payment_detail?.transaction_time
? currentAppointment?.payment_detail?.transaction_time
: '-'}
</Text>
<Span style={{ fontWeight: 'bold' }}>Status</Span>
<Text>
{currentAppointment?.payment_detail?.status_message
? currentAppointment?.payment_detail?.status_message
: '-'}
</Text>
</Grid>
</Grid>
) : (
<Span>Belum ada pembayaran</Span>
)}
</Card>
<Card sx={{ mt: 5, p: 5 }}>
<HeaderStyle>
<Grid item xs={12} md={12}>
<Title>E-Prescription</Title>
</Grid>
</HeaderStyle>
<Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Grid item xs={12} columnSpacing={{ xs: 1, sm: 2, md: 3 }} sx={{marginBottom: 4}}>
<Span style={{ fontWeight: 'bold' }}>Diagnosa</Span>
<Autocomplete
multiple
options={icdOptions}
getOptionLabel={(option) => option.label}
fullWidth
value={selectedIcdOptions}
onChange={(e, newValues) => {
const selectedCodes = newValues.map((value) => value.value);
setValue('diagnosis', selectedCodes);
setSelectedIcdOptions(newValues);
}}
renderInput={(params) => (
<TextField
{...params}
label="Diagnosis ICD - X"
variant="outlined"
// required
/>
)}
/>
</Grid>
{/* <Grid item xs={12} columnSpacing={{ xs: 1, sm: 2, md: 3 }} sx={{marginBottom: 4}}>
<Span style={{ fontWeight: 'bold' }}>Rumah Sakit</Span>
<Autocomplete
options={hospitalOptions}
getOptionLabel={(option) => option.label}
fullWidth
value={selectedHospitalOption}
onChange={(e, newValue) => {
setSelectedHospitalOption(newValue);
setValue('hospital', newValue ? newValue.value : ''); // Simpan nilai rumah sakit
}}
renderInput={(params) => (
<TextField
{...params}
label="Rumah Sakit"
variant="outlined"
// required
/>
)}
/>
</Grid> */}
<Grid item xs={12} columnSpacing={{ xs: 1, sm: 2, md: 3 }}>
<Stack direction="row" alignItems="center" sx={{marginBottom: 4}}>
<Typography variant='subtitle1' gutterBottom>Obat</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
{fields.map((field, index) => (
<Grid container spacing={2} key={index} sx={{ marginBottom: '15px' }}>
<Grid item xs={3}>
<Autocomplete
options={drugOptions}
getOptionLabel={(option) => option.label}
fullWidth
value={selectedDrugsOptions[index] || null}
onChange={(e, newValue) => handleAutocompleteChange(newValue, index)}
renderInput={(params) => (
<TextField
{...params}
label="Drugs"
variant="outlined"
required
/>
)}
/>
</Grid>
<Grid item xs={1}>
<RHFTextField
id={`qty_${index}`}
name={`medicine.${index}.qty`}
label="Qty"
required
type="number"
placeholder="Qty"
fullWidth
/>
</Grid>
<Grid item xs={2}>
<Autocomplete
options={unitOptions}
getOptionLabel={(option) => option.label}
fullWidth
value={selectedUnitsOptions[index] || null}
onChange={(e, newValue) => handleAutocompleteChangeUnit(newValue, index)}
renderInput={(params) => (
<TextField
{...params}
label="Units"
variant="outlined"
required
/>
)}
/>
</Grid>
<Grid item xs={2}>
<RHFTextField
id={`signa_${index}`}
name={`medicine.${index}.signa`}
label="Signa"
required
placeholder="Signa"
fullWidth
/>
</Grid>
<Grid item xs={3}>
<RHFTextField
id={`note_${index}`}
name={`medicine.${index}.note`}
label="Note"
required
placeholder="Note"
fullWidth
/>
</Grid>
{
index === 0 ? (
<Grid item xs={1} sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<IconButton size='large' color='primary' onClick={() => append({medicine_name: '', medicine_price: 0, request_log_id: 1 })}>
<AddIcon />
</IconButton>
</Grid>
) : (
index == (fields.length-1) ? (
<Grid item xs={1} sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<IconButton size='large' color='error' onClick={() => remove(index)}>
<RemoveIcon />
</IconButton>
</Grid>
) : (
<Grid item xs={1} sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<IconButton size='large' color='primary' onClick={() => append({medicine_name: '', medicine_price: 0, request_log_id: 1 })}>
<AddIcon />
</IconButton>
</Grid>
)
)
}
</Grid>
))}
</Grid>
<Grid item xs={12} md={12} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button
sx={{ boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)', marginRight: '10px' }}
onClick={() => handleDownloadEPrescription(id)}
variant="contained"
size="large"
>
Download
</Button>
<LoadingButton
sx={{ boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)' }}
type="submit"
variant="contained"
size="large"
loading={isSubmitting}
>
{!isEdit ? 'Save' : 'Update'}
</LoadingButton>
</Grid>
</Grid>
</Card>
</Box>
</Stack>
</FormProvider>
);
}