update requst dan final log
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* Core
|
||||
* ============================================
|
||||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { Box, FormControlLabel, Grid, Checkbox, Typography, CircularProgress , Button, styled, Stack, IconButton, Card} from '@mui/material';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
|
||||
/**
|
||||
* Components
|
||||
* ============================================
|
||||
*/
|
||||
// - Global -
|
||||
import Label from '@/components/Label';
|
||||
// - Local -
|
||||
import FormCreateSearch from './FormCreateSearch';
|
||||
import FormCreateListChoose from './FormCreateListChoose';
|
||||
import FormCreateBtnUpload from './FormCreateBtnUpload';
|
||||
|
||||
/**
|
||||
* Icon, Utils, Types, Functions, theme, hook
|
||||
* ============================================
|
||||
*/
|
||||
import { ArrowBackIosNew } from '@mui/icons-material';
|
||||
import { fDateTimesecond } from '@/utils/formatTime';
|
||||
import { MemberListType } from '../Model/Types';
|
||||
import { addClaimRequest, getMemberList } from '../Model/Functions';
|
||||
import palette from '@/theme/palette';
|
||||
import FormCreateFilesUpload from './FormCreateFilesUpload';
|
||||
import useLoadOnScroll from '@/hooks/useLoadOnScroll';
|
||||
import useCollapseDrawer from '@/hooks/useCollapseDrawer';
|
||||
import FormCreateBtnChoose from './FormCreateBtnChoose';
|
||||
import axios from '../../../utils/axios';
|
||||
|
||||
export default function FormCreate() {
|
||||
const navigate = useNavigate()
|
||||
const defaultListChoosed:MemberListType[] = [];
|
||||
|
||||
// State
|
||||
// -------------------------
|
||||
const [keyword, setKeyword] = useState<string>('');
|
||||
const [listChoosed, setListChoosed] = useState<MemberListType[]>([]);
|
||||
const [isChoosed, setIsChoosed] = useState<boolean>(false);
|
||||
const [formIsLoading, setFormIsLoading] = useState<boolean>(false);
|
||||
|
||||
// List Choose - auto Scroll
|
||||
// -------------------------
|
||||
const fetchFunction = async (page: number): Promise<MemberListType[]> => getMemberList(page, keyword)
|
||||
|
||||
const {data: MemberList, isLoading: scrollIsLoading, setData, resetLastPage, refetchData} = useLoadOnScroll<MemberListType>(fetchFunction);
|
||||
|
||||
// List Choose - Search
|
||||
// -------------------------
|
||||
const handleSearch = (keyword: string) => {
|
||||
setData([])
|
||||
resetLastPage()
|
||||
setKeyword(keyword)
|
||||
refetchData()
|
||||
}
|
||||
|
||||
// Function - Clear Form
|
||||
// -----------------------------
|
||||
const clearForm = () => {
|
||||
setListChoosed(defaultListChoosed);
|
||||
setIsChoosed(false);
|
||||
}
|
||||
|
||||
// Function - Choose Patien Type
|
||||
// -----------------------------
|
||||
const handleChoosePatienType = (data: MemberListType, type: string) => {
|
||||
let newListChoosed = listChoosed.map((list) => {
|
||||
if (data.id == list.id) {
|
||||
list.patien_type = type
|
||||
}
|
||||
|
||||
return list;
|
||||
})
|
||||
setListChoosed(newListChoosed)
|
||||
}
|
||||
|
||||
// Function - Handle Btn Upload
|
||||
// -----------------------------
|
||||
const handleChangeInput = (data: MemberListType, type_file: 'kondisi'|'diagnosa'|'penunjang', file: any) => {
|
||||
let newListChoosed = listChoosed.map((list) => {
|
||||
if (data.id == list.id) {
|
||||
if (type_file == 'kondisi') {
|
||||
if (list.file_kondisi == undefined) {
|
||||
list.file_kondisi = [file];
|
||||
}
|
||||
else {
|
||||
list.file_kondisi.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_file == 'diagnosa') {
|
||||
if (list.file_diagnosa == undefined) {
|
||||
list.file_diagnosa = [file];
|
||||
}
|
||||
else {
|
||||
list.file_diagnosa.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_file == 'penunjang') {
|
||||
if (list.file_penunjang == undefined) {
|
||||
list.file_penunjang = [file];
|
||||
}
|
||||
else {
|
||||
list.file_penunjang.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
})
|
||||
|
||||
setListChoosed(newListChoosed)
|
||||
}
|
||||
|
||||
// Function - Handle Remove Fle
|
||||
// -----------------------------
|
||||
const handleRemoveFile = (data: MemberListType, type_file: 'kondisi'|'diagnosa'|'penunjang', target_index: number) => {
|
||||
let newListChoosed = listChoosed.map((list) => {
|
||||
if (data.id == list.id) {
|
||||
if (type_file == 'kondisi') {
|
||||
list.file_kondisi = list.file_kondisi?.filter((file: any, index: number) =>{
|
||||
if (target_index !== index) {
|
||||
return file;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (type_file == 'diagnosa') {
|
||||
list.file_diagnosa = list.file_diagnosa?.filter((file: any, index: number) =>{
|
||||
if (target_index !== index) {
|
||||
return file;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (type_file == 'penunjang') {
|
||||
list.file_penunjang = list.file_penunjang?.filter((file: any, index: number) =>{
|
||||
if (target_index !== index) {
|
||||
return file;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
})
|
||||
|
||||
setListChoosed(newListChoosed)
|
||||
}
|
||||
|
||||
// Function - Handle Submit Form
|
||||
// -----------------------------
|
||||
const handleSubmit = async () => {
|
||||
setFormIsLoading(true)
|
||||
let response = await addClaimRequest(listChoosed)
|
||||
setFormIsLoading(false)
|
||||
|
||||
if (response == true) {
|
||||
clearForm()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let isDirty = listChoosed.some((row) => {
|
||||
if (row.patien_type == undefined) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{/* Back Button */}
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 5}}>
|
||||
<IconButton size='large' color='inherit' onClick={() => isChoosed==false ? navigate(`/claim-requests`) : setIsChoosed(false)} >
|
||||
<ArrowBackIosNew/>
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="h5" sx={{ marginLeft: '24px' }}>
|
||||
{'Create Claim Requests'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Choose Section */}
|
||||
<Grid container spacing={4} sx={{ px: 2, position: 'relative', display: isChoosed==false ? 'inherit' : 'none' }}>
|
||||
{/* Search */}
|
||||
<Grid item xs={12}>
|
||||
<FormCreateSearch onEmpty={() => handleSearch('')} onSubmit={(keyword) => handleSearch(keyword)} />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
{/* List */}
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
{
|
||||
MemberList.map((row, index) => {
|
||||
return (
|
||||
<FormCreateListChoose
|
||||
key={index}
|
||||
data={row}
|
||||
ListChoosed={listChoosed}
|
||||
handleCheckedProp={(checked, data) => {
|
||||
checked ? setListChoosed((prevData) => [...prevData, data]) : setListChoosed((items) => items.filter(item => item.id != data.id))
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Loading */}
|
||||
<Grid item xs={12} sx={{ display: scrollIsLoading === false ? 'none' : 'flex', justifyContent: 'center', marginTop: '40px' }}>
|
||||
<CircularProgress />
|
||||
</Grid>
|
||||
|
||||
{/* Submit List */}
|
||||
<Grid item xs={12}>
|
||||
<FormCreateBtnChoose disabled={listChoosed.length==0} title={`Create Number Batch (${listChoosed.length})`} handleClickProp={() => setIsChoosed(true)} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Input Section */}
|
||||
<Grid container spacing={10} sx={{ px: 2, display: isChoosed==true ? 'inherit' : 'none' }}>
|
||||
{
|
||||
listChoosed.map((row, index) => {
|
||||
return (
|
||||
<Grid key={index} item xs={12}>
|
||||
<Grid container spacing={6}>
|
||||
{/* Patien Name */}
|
||||
<Grid item xs={12}>
|
||||
<Card sx={{ border: '1px solid rgba(0,0,0,0.05)', display: 'flex', justifyContent: 'space-between', borderRadius: '12px', px: '24px', py: '16px' }}>
|
||||
<Box>
|
||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||
{row.name}
|
||||
</Typography>
|
||||
<Typography variant="caption" color={palette.light.grey[500]} sx={{ fontWeight: 600 }}>
|
||||
{row.member_id}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Label variant="ghost" color="default">
|
||||
{fDateTimesecond(new Date())}
|
||||
</Label>
|
||||
</Card>
|
||||
</Grid>
|
||||
{/* Patien Type */}
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
{row.service_type.map((r,i) => {
|
||||
const code = r.code
|
||||
return (
|
||||
<Grid item xs={6}>
|
||||
<Button
|
||||
sx={{ padding: 2, width: '100%',border: row.patien_type === code ? '1px solid #19BBBB' : '1px solid #919EAB52' }}
|
||||
variant="outlined"
|
||||
color={row.patien_type === code ? 'primary' : 'inherit'}
|
||||
onClick={() => {
|
||||
handleChoosePatienType(row, code)
|
||||
}}
|
||||
>
|
||||
{r.name}
|
||||
</Button>
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* File Kondisi */}
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6">Condition Document</Typography>
|
||||
</Grid>
|
||||
|
||||
{row.file_kondisi && row.file_kondisi.map((file, index) => (
|
||||
<Grid item xs={12} key={index}>
|
||||
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'kondisi', index)} />
|
||||
</Grid>
|
||||
))}
|
||||
|
||||
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'kondisi', file)} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* File Diagnosa */}
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6">Diagnosis Document</Typography>
|
||||
</Grid>
|
||||
|
||||
{row.file_diagnosa && row.file_diagnosa.map((file, index) => (
|
||||
<Grid item xs={12} key={index}>
|
||||
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'diagnosa', index)} />
|
||||
</Grid>
|
||||
))}
|
||||
|
||||
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'diagnosa', file)} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* File Penunjang */}
|
||||
<Grid item xs={12}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h6">Supporting Result Document</Typography>
|
||||
</Grid>
|
||||
|
||||
{row.file_penunjang && row.file_penunjang.map((file, index) => (
|
||||
<Grid item xs={12} key={index}>
|
||||
<FormCreateFilesUpload file={file} handleRemoveFileProp={() => handleRemoveFile(row, 'penunjang', index)} />
|
||||
</Grid>
|
||||
))}
|
||||
|
||||
<Grid item xs={12} sx={{display: 'flex', gap: 1}}>
|
||||
<FormCreateBtnUpload handleChangeInputProp={(file) => handleChangeInput(row, 'penunjang', file)} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Box display="flex" gap={1}>
|
||||
<Button variant="outlined" color="inherit" onClick={() => clearForm()}>
|
||||
Cancel
|
||||
</Button>
|
||||
<LoadingButton disabled={isDirty} type="submit" variant="contained" loading={formIsLoading} onClick={() => handleSubmit()}>
|
||||
Save Changes
|
||||
</LoadingButton>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { styled, Button } from "@mui/material";
|
||||
import useCollapseDrawer from "@/hooks/useCollapseDrawer";
|
||||
|
||||
/**
|
||||
* Custom Style
|
||||
* ============================================
|
||||
*/
|
||||
const DivCustom1 = styled('div')(({ theme }) => ({
|
||||
background: 'white',
|
||||
position: 'fixed',
|
||||
left: '350px',
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
paddingLeft: '32px',
|
||||
paddingRight: '32px',
|
||||
paddingTop: '32px',
|
||||
paddingBottom: '48px',
|
||||
[theme.breakpoints.between('sm', 'lg')]: {
|
||||
left: '0px',
|
||||
},
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
disabled: boolean,
|
||||
title : string,
|
||||
handleClickProp: () => void
|
||||
}
|
||||
|
||||
export default function FormCreateBtnChoose ({disabled, title, handleClickProp}: Props) {
|
||||
const { collapseClick } = useCollapseDrawer();
|
||||
|
||||
return (
|
||||
<DivCustom1 sx={{ left: collapseClick ? '80px' : '350px' }}>
|
||||
<Button variant="contained" color="primary" disabled={disabled} sx={{ width: '100%', p: '11px' }} onClick={handleClickProp}>
|
||||
{title}
|
||||
</Button>
|
||||
</DivCustom1>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useRef } from "react";
|
||||
import { Box, ButtonBase, Typography } from "@mui/material";
|
||||
import Iconify from "@/components/Iconify";
|
||||
|
||||
type Props = {
|
||||
handleChangeInputProp: (event: any) => void
|
||||
}
|
||||
|
||||
export default function FormCreateBtnUpload ({handleChangeInputProp}: Props) {
|
||||
const fileInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
return (
|
||||
<ButtonBase sx={{ py: 5, border: '2px dashed #F9FAFB',bgcolor: '#919EAB52',borderRadius: '8px',width: '100%', height: '60px'}} onClick={() => fileInput.current?.click()}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
placeItems: 'center',
|
||||
gap: 1,
|
||||
placeContent: 'center',
|
||||
py:'11px'
|
||||
}}
|
||||
>
|
||||
<Iconify icon="icon-park-outline:upload-one" fontSize="1.5em" />
|
||||
<Typography variant="body1" fontWeight="bold" fontSize={'15px'}>
|
||||
Upload Result
|
||||
</Typography>
|
||||
</Box>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={(event) => handleChangeInputProp(event.target.files ? event.target.files[0] : {})}
|
||||
accept="application/pdf"
|
||||
/>
|
||||
</ButtonBase>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import Iconify from "@/components/Iconify";
|
||||
import { ArrowBackIosNew, InsertDriveFile } from '@mui/icons-material';
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
|
||||
type Props = {
|
||||
file: any,
|
||||
handleRemoveFileProp: () => void,
|
||||
}
|
||||
|
||||
export default function FormCreateFilesUpload({ file, handleRemoveFileProp }: Props) {
|
||||
return (
|
||||
<Stack direction="row" justifyContent={'space-between'} sx={{ mb: '16px' }}>
|
||||
<Stack direction="row" spacing={1} sx={{color: '#19BBBB'}}>
|
||||
<InsertDriveFile />
|
||||
<Typography variant="body2" gutterBottom>{file.name ? file.name : '-'}</Typography>
|
||||
</Stack>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {handleRemoveFileProp()}}
|
||||
sx={{cursor: 'pointer'}}
|
||||
></Iconify>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Core
|
||||
* ============================================
|
||||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Box, FormControlLabel, Grid, Checkbox, Typography, Card} from '@mui/material';
|
||||
|
||||
/**
|
||||
* Components
|
||||
* ============================================
|
||||
*/
|
||||
// - Global -
|
||||
import Label from '@/components/Label';
|
||||
// - Local -
|
||||
|
||||
/**
|
||||
* Icon, Utils, Types, Functions, theme, hook
|
||||
* ============================================
|
||||
*/
|
||||
import { fDateTimesecond } from '@/utils/formatTime';
|
||||
import { MemberListType } from '../Model/Types';
|
||||
import palette from '@/theme/palette';
|
||||
|
||||
/**
|
||||
* Props
|
||||
* =====================================================
|
||||
*/
|
||||
type Props = {
|
||||
data: MemberListType,
|
||||
ListChoosed: MemberListType[],
|
||||
handleCheckedProp: (checked: boolean, data: MemberListType) => void,
|
||||
};
|
||||
|
||||
export default function FormCreateListChoose({data, ListChoosed, handleCheckedProp}: Props) {
|
||||
const [isChoosed, setIsChoosed] = useState<boolean>(false)
|
||||
|
||||
useEffect(() => {
|
||||
setIsChoosed(false);
|
||||
|
||||
ListChoosed.forEach(list => {
|
||||
if (list.id == data.id) {
|
||||
setIsChoosed(true);
|
||||
}
|
||||
})
|
||||
}, [ListChoosed])
|
||||
|
||||
return (
|
||||
<Grid item xs={12}>
|
||||
<Card sx={{
|
||||
border: '0px solid rgba(0,0,0,0.125)', px: '24px', py: '16px', borderRadius: '12px', display: 'flex', justifyContent: 'space-between',
|
||||
bgcolor: (theme) => {
|
||||
return isChoosed ? palette.light.primary.lighter : palette.light.background.default
|
||||
}
|
||||
}}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', px: '8px'}}>
|
||||
<FormControlLabel
|
||||
label=""
|
||||
control={<Checkbox onChange={(event, checked) => handleCheckedProp(checked, data)} />}
|
||||
checked={isChoosed}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||
{data.name}
|
||||
</Typography>
|
||||
<Typography variant="caption" color={palette.light.grey[500]} sx={{ fontWeight: 600 }}>
|
||||
{data.member_id}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Label variant="ghost" color="default">
|
||||
{fDateTimesecond(new Date())}
|
||||
</Label>
|
||||
</Card>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Core
|
||||
* ============================================
|
||||
*/
|
||||
import { useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Grid } from '@mui/material';
|
||||
|
||||
/**
|
||||
* Components
|
||||
* ============================================
|
||||
*/
|
||||
// - Global -
|
||||
import { FormProvider, RHFTextField } from '@/components/hook-form';
|
||||
// - Local -
|
||||
|
||||
/**
|
||||
* Icon, Utils, Types, Functions
|
||||
* ============================================
|
||||
*/
|
||||
import { Search } from '@mui/icons-material';
|
||||
import { SearchType } from '../Model/Types';
|
||||
|
||||
type Props = {
|
||||
onSubmit: (keyword: string) => void,
|
||||
onEmpty: () => void,
|
||||
};
|
||||
|
||||
const FormCreateSearch = ({ onSubmit, onEmpty }: Props) => {
|
||||
const defaultValuesSearchForm = {
|
||||
keyword: ''
|
||||
};
|
||||
|
||||
const methodsSearchForm = useForm<SearchType>({
|
||||
defaultValues: defaultValuesSearchForm
|
||||
});
|
||||
|
||||
const { handleSubmit, formState: { isDirty } } = methodsSearchForm;
|
||||
|
||||
// search on submit
|
||||
const onSubmitSearch = (data: SearchType ) => {
|
||||
onSubmit(data.keyword);
|
||||
}
|
||||
|
||||
// search on empty
|
||||
useEffect(() => {
|
||||
if (isDirty === false) {
|
||||
onEmpty()
|
||||
}
|
||||
},[isDirty])
|
||||
|
||||
return (
|
||||
<FormProvider methods={methodsSearchForm} onSubmit={handleSubmit(onSubmitSearch)}>
|
||||
<Grid container direction={"row"}>
|
||||
<Grid item xs={12}>
|
||||
<RHFTextField
|
||||
name="keyword"
|
||||
placeholder="Search..."
|
||||
autoComplete='off'
|
||||
fullWidth
|
||||
InputProps={{ startAdornment: <Search /> }}
|
||||
sx={{ input: { paddingLeft: '14px' } }}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormCreateSearch
|
||||
@@ -0,0 +1,456 @@
|
||||
import * as Yup from 'yup';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import React, { useRef, useEffect, useMemo, useState } from 'react';
|
||||
import axios from '../../../utils/axios';
|
||||
import { FormProvider, RHFTextField } from '../../../components/hook-form';
|
||||
|
||||
import { makeFormData } from '@/utils/jsonToFormData';
|
||||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Grid,
|
||||
Stack,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
useTheme,
|
||||
List,
|
||||
ListItem,
|
||||
IconButton,
|
||||
ListItemAvatar,
|
||||
Avatar,
|
||||
ListItemText,
|
||||
Card,
|
||||
InputAdornment,
|
||||
Divider,
|
||||
ButtonBase,
|
||||
Box,
|
||||
} from '@mui/material';
|
||||
import Iconify from '../../../components/Iconify';
|
||||
import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { fCurrency } from '../../../utils/formatNumber';
|
||||
import MemberSelectDialog from '../../../components/dialogs/MemberSelectDialog';
|
||||
import { Add, ArrowBackIosNew, DeleteOutline } from '@mui/icons-material';
|
||||
import { ClaimRequest, Files } from '@/@types/claims';
|
||||
import { fDateTimesecond } from '@/utils/formatTime';
|
||||
|
||||
interface FormValuesProps extends Partial<ClaimRequest> {
|
||||
taxes: boolean;
|
||||
inStock: boolean;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
isEdit: boolean;
|
||||
currentClaim?: ClaimRequest;
|
||||
};
|
||||
|
||||
export default function FormEdit({ isEdit, currentClaim }: Props) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
const EditClaimSchema = Yup.object().shape({
|
||||
organization_id: Yup.string().required('Code Provider is required'),
|
||||
});
|
||||
|
||||
const defaultValues = useMemo(
|
||||
() => ({
|
||||
id: currentClaim?.id || '-',
|
||||
code: currentClaim?.code || '-',
|
||||
member_name: currentClaim?.member?.name || '-',
|
||||
date: currentClaim?.submission_date ? fDateTimesecond(currentClaim?.submission_date) : '-',
|
||||
claim_method: currentClaim?.payment_type || '-',
|
||||
service_type: currentClaim?.service_code || '-',
|
||||
organization_id: currentClaim?.organization?.code || '-',
|
||||
}),
|
||||
[currentClaim]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isEdit && currentClaim) {
|
||||
reset(defaultValues);
|
||||
}
|
||||
if (!isEdit) {
|
||||
reset(defaultValues);
|
||||
}
|
||||
// setFileKondisis(currentClaim?.files_by_type?.claim_diagnosis);
|
||||
// setFileDiagnosas(currentClaim?.files_by_type?.claim_diagnosis);
|
||||
setFileHasilPenunjangCurrent(currentClaim?.files_by_type?.claim_result);
|
||||
}, [isEdit, currentClaim]);
|
||||
|
||||
|
||||
const methods = useForm<FormValuesProps>({
|
||||
resolver: yupResolver(EditClaimSchema),
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
const {
|
||||
reset,
|
||||
watch,
|
||||
control,
|
||||
setValue,
|
||||
getValues,
|
||||
setError,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting },
|
||||
} = methods;
|
||||
|
||||
const values = watch();
|
||||
|
||||
const [isCheckingLimit, setIsCheckingLimit] = useState(false);
|
||||
const [isEligible, setIsEligible] = useState(false);
|
||||
const [memberBenefits, setMemberBenefits] = useState([]);
|
||||
const [diagnosisOption, setDiagnosisOption] = useState([]);
|
||||
const [isMemberDialogOpen, setIsMemberDialogOpen] = useState(false);
|
||||
const [member, setMember] = useState({})
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Files Result Kondisi
|
||||
const fileKondisiInput = useRef<HTMLInputElement>(null);
|
||||
const [fileKondisis, setFileKondisis] = useState<Files>([]);
|
||||
|
||||
const handleKondisiInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileKondisis([...fileKondisis, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeKondisiFiles = (filesState, index) => {
|
||||
setFileKondisis(
|
||||
filesState.filter((file, fileIndex) => {
|
||||
return fileIndex != index;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// Files Result Diagnosa
|
||||
const fileDiagnosaInput = useRef<HTMLInputElement>(null);
|
||||
const [fileDiagnosas, setFileDiagnosas] = useState([]);
|
||||
|
||||
const handleDiagnosaInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileDiagnosas([...fileDiagnosas, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeDiagnosaFiles = (filesState, index) => {
|
||||
setFileDiagnosas(
|
||||
filesState.filter((file, fileIndex) => {
|
||||
return fileIndex != index;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// Files Result Hasil Penunjang
|
||||
const fileHasilPenunjangInput = useRef<HTMLInputElement>(null);
|
||||
const [fileHasilPenunjangs, setFileHasilPenunjangs] = useState([]);
|
||||
const [fileHasilPenunjangsCurrent, setFileHasilPenunjangCurrent] = useState([]);
|
||||
|
||||
const handleResultInputChange = (event) => {
|
||||
if (event.target.files[0]) {
|
||||
setFileHasilPenunjangs([...fileHasilPenunjangs, ...event.target.files]);
|
||||
} else {
|
||||
console.log('NO FILE');
|
||||
}
|
||||
};
|
||||
const removeFiles = (filesState, index) => {
|
||||
setFileHasilPenunjangs(
|
||||
filesState.filter((file, fileIndex) => {
|
||||
return fileIndex != index;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const onSubmit = async (data: FormValuesProps) => {
|
||||
try {
|
||||
// const formData = new FormData();
|
||||
// formData.append('result_files', fileHasilPenunjangs);
|
||||
// formData.append('diagnosa_files', fileDiagnosaInput);
|
||||
// formData.append('kondisi_files', fileKondisiInput);
|
||||
// formData.append('provider_code', data.organization_id);
|
||||
// formData.append('_method', 'PUT');
|
||||
const formData = makeFormData({
|
||||
result_files: fileHasilPenunjangs,
|
||||
diagnosa_files: fileDiagnosas,
|
||||
kondisi_files: fileKondisis,
|
||||
provider_code: data.organization_id,
|
||||
_method: 'PUT'
|
||||
});
|
||||
|
||||
const response = await axios.put(`/claim-requests/${data.id}`, formData);
|
||||
|
||||
reset();
|
||||
enqueueSnackbar('Claim Request Updated Successfully!', { variant: 'success' });
|
||||
navigate('/claim-requests');
|
||||
} catch (error: any) {
|
||||
if (error && error.response.status === 422) {
|
||||
for (const [key, value] of Object.entries(error.response.data.errors)) {
|
||||
// setError(key, { message: value[0] });
|
||||
enqueueSnackbar('Failed Processing Request', { variant: 'error' });
|
||||
}
|
||||
} else {
|
||||
enqueueSnackbar(error.message ?? 'Failed Processing Request', { variant: 'error' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center'}}>
|
||||
<IconButton size='large' color='inherit' onClick={() => navigate(`/claim-requests`)} >
|
||||
<ArrowBackIosNew/>
|
||||
</IconButton>
|
||||
|
||||
<Typography variant="h5" sx={{ marginLeft: '24px' }}>
|
||||
{'Edit Claim Requests'}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<Card sx={{paddingX:2, paddingY:2}}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={5}>
|
||||
<Typography variant="subtitle1">Code*</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={7}>
|
||||
<Typography variant="subtitle1">Name*</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={5}>
|
||||
<RHFTextField name="code" label="Code" disabled/>
|
||||
</Grid>
|
||||
<Grid item xs={7}>
|
||||
<RHFTextField name="member_name" label="Name" disabled/>
|
||||
</Grid>
|
||||
{/* <input type="hidden" name="id"/> */}
|
||||
|
||||
|
||||
<Grid item xs={12}></Grid>
|
||||
|
||||
<Grid item xs={3}>
|
||||
<Typography variant="subtitle1">Date of Submission*</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<Typography variant="subtitle1">Claim Method*</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<Typography variant="subtitle1">Service Type*</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<Typography variant="subtitle1">Code Provider*</Typography>
|
||||
</Grid>
|
||||
|
||||
|
||||
<Grid item xs={3}>
|
||||
<RHFTextField InputProps={{endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<CalendarTodayIcon />
|
||||
</InputAdornment>
|
||||
), }}
|
||||
name="date" label="Date of Submission" disabled/>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<RHFTextField name="claim_method" label="Claim Method" disabled/>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<RHFTextField name="service_type" label="Service Type*" disabled/>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<RHFTextField name="organization_id" label="Code Provider*"/>
|
||||
</Grid>
|
||||
|
||||
|
||||
{/* -------------------------------Upload Dokumen Kondisi------------------------------- */}
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant='h6'> Condition Document</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{fileKondisis &&
|
||||
fileKondisis.map((file, index) => (
|
||||
<Stack sx={{marginTop: 2}} direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: "text.secondary" }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeKondisiFiles(fileKondisis, index);
|
||||
}}
|
||||
></Iconify>
|
||||
</Stack>
|
||||
))}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<ButtonBase sx={{ p: 4, border: '2px dashed #F9FAFB',
|
||||
bgcolor: '#919EAB52',
|
||||
borderRadius: '8px',
|
||||
width: '100%', height: '60px'}} onClick={() => fileKondisiInput.current?.click()}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
placeItems: 'center',
|
||||
gap: 1,
|
||||
placeContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Iconify icon="icon-park-outline:upload-one" fontSize="3em" />
|
||||
<Typography variant="body1" fontWeight="bold">
|
||||
Add File
|
||||
</Typography>
|
||||
</Box>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileKondisiInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleKondisiInputChange}
|
||||
accept="application/pdf"
|
||||
/>
|
||||
</ButtonBase>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
{/* -------------------------------Upload Dokumen Diagnosa------------------------------- */}
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant='h6'> Diagnosis Document</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{fileDiagnosas &&
|
||||
fileDiagnosas.map((file, index) => (
|
||||
<Stack sx={{marginTop: 2}} direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: "text.secondary" }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeDiagnosaFiles(fileDiagnosas, index);
|
||||
}}
|
||||
></Iconify>
|
||||
</Stack>
|
||||
))}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<ButtonBase sx={{ p: 4, border: '2px dashed #F9FAFB',
|
||||
bgcolor: '#919EAB52',
|
||||
borderRadius: '8px',
|
||||
width: '100%', height: '60px'}} onClick={() => fileDiagnosaInput.current?.click()}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
placeItems: 'center',
|
||||
gap: 1,
|
||||
placeContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Iconify icon="icon-park-outline:upload-one" fontSize="3em" />
|
||||
<Typography variant="body1" fontWeight="bold">
|
||||
Add Result
|
||||
</Typography>
|
||||
</Box>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileDiagnosaInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleDiagnosaInputChange}
|
||||
accept="application/pdf"
|
||||
/>
|
||||
</ButtonBase>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
{/* -------------------------------Upload Result Hasil Penunjang------------------------------- */}
|
||||
<React.Fragment>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant='h6'> Supporting Result Document</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{fileHasilPenunjangs &&
|
||||
fileHasilPenunjangs.map((file, index) => (
|
||||
<Stack sx={{marginTop: 2}} direction="row" justifyContent={'space-between'} key={index}>
|
||||
<Typography sx={{ color: "text.secondary" }}>{file.name}</Typography>
|
||||
<Iconify
|
||||
icon="eva:trash-2-outline"
|
||||
color={'darkred'}
|
||||
onClick={() => {
|
||||
removeFiles(fileHasilPenunjangs, index);
|
||||
}}
|
||||
></Iconify>
|
||||
</Stack>
|
||||
))}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<ButtonBase sx={{ p: 4, border: '2px dashed #F9FAFB',
|
||||
bgcolor: '#919EAB52',
|
||||
borderRadius: '8px',
|
||||
width: '100%', height: '60px'}} onClick={() => fileHasilPenunjangInput.current?.click()}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
placeItems: 'center',
|
||||
gap: 1,
|
||||
placeContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Iconify icon="icon-park-outline:upload-one" fontSize="3em" />
|
||||
<Typography variant="body1" fontWeight="bold">
|
||||
Add Result
|
||||
</Typography>
|
||||
</Box>
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
ref={fileHasilPenunjangInput}
|
||||
style={{ display: 'none' }}
|
||||
multiple
|
||||
onChange={handleResultInputChange}
|
||||
accept="application/pdf"
|
||||
/>
|
||||
</ButtonBase>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
|
||||
</Grid>
|
||||
</Card>
|
||||
<Grid container marginTop={3}>
|
||||
<Grid item xs={12} md={12} >
|
||||
<Stack direction="row" alignItems="center" justifyContent="flex-end">
|
||||
<Button
|
||||
sx={{
|
||||
margin: 1
|
||||
}}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
color='inherit'
|
||||
onClick={() => navigate(`/claim-requests`)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<LoadingButton
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="large"
|
||||
loading={isSubmitting}
|
||||
>
|
||||
Update
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</FormProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user