diff --git a/Modules/Internal/Http/Controllers/Api/ClaimController.php b/Modules/Internal/Http/Controllers/Api/ClaimController.php index f120b1d4..7c358d90 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimController.php @@ -21,9 +21,16 @@ use Modules\Internal\Transformers\ClaimEditResource; use Modules\Internal\Transformers\ClaimHistoryCareResource; use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; use Box\Spout\Writer\Common\Creator\WriterEntityFactory; + +use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; +use Box\Spout\Common\Entity\Style\CellAlignment; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\View; +use Modules\Internal\Transformers\RequestLogResource; + +use App\Models\RequestLog; + use PDF; class ClaimController extends Controller @@ -34,41 +41,257 @@ class ClaimController extends Controller */ public function index(Request $request) { - // $serviceCode = 'IP'; - $claims = Claim::with([ - 'member', - 'member.currentCorporate', - 'member.currentCorporate.currentPolicy', - // 'member.currentPlan' => function($memberPlan) use ($serviceCode) { - // $memberPlan->where('plans.service_code', $serviceCode); - // }, - 'member.currentPlan' => function($memberPlan) { - $memberPlan->join('claim_requests', 'claim_requests.service_code', '=', 'plans.service_code'); - }, - 'diagnoses' => function ($diagnosis) { - $diagnosis->where('type', 'primary'); - }, - 'diagnoses.icd', - 'benefit', - 'claimRequest', - 'claimRequest.service', - ]) - ->when($request->search, function ($q, $search) { - $q->where(function ($subQuery) use ($search) { - $subQuery->whereHas('claimRequest', function ($claimRequest) use ($search) { - $claimRequest->where('code', 'LIKE', "%" . $search . "%"); - }) - ->orWhereHas('member', function ($member) use ($search) { - $member->where('name', 'LIKE', "%" . $search . "%"); - }); + $limit = $request->has('per_page') ? $request->input('per_page') : 10; + $results = DB::table('claims') + ->leftJoin('claim_requests', 'claims.claim_request_id','=', 'claim_requests.id') + ->leftJoin('request_logs', 'claim_requests.request_log_id','=', 'request_logs.id') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->when($request->input('search'), function ($query, $search) { + $query->where(function ($query) use ($search) { + $query->orWhere('members.name', 'like', "%" . $search . "%"); }); }) - ->where('status', '!=', 'requested') // Penjagaan agar approve baru masuk ke claim management - ->latest() - ->paginate(10); + ->when($request->has('orderBy'), function ($query) use ($request) { + $orderBy = $request->orderBy; + $direction = $request->order ?? 'asc'; + + $query->orderBy($orderBy, $direction); + }) + ->when($request->input('start_date') , function ($query, $start_date) { + $query->where(function ($query) use ($start_date) { + $query->where('claims.created_at', '>=', $start_date); + }); + }) + ->when($request->input('end_date') , function ($query, $end_date) { + $query->where(function ($query) use ($end_date) { + $query->where('claims.created_at', '<=', $end_date); + }); + }) + ->when($request->input('provider') , function ($query, $provider) { + $query->where(function ($query) use ($provider) { + $query->where('request_logs.organization_id', '=', $provider); + }); + }) + ->select( + 'claims.id', + 'request_logs.id AS id_log', + 'claims.code', + 'members.name', + DB::raw(' + (SELECT members.member_id FROM members WHERE members.id = claims.member_id LIMIT 1) AS member_id + '), + 'claims.created_at', + DB::raw(' + (SELECT plans.code FROM plans WHERE plans.id = claims.plan_id LIMIT 1) AS plan_code + '), + DB::raw(' + (SELECT services.description FROM services WHERE services.code = claim_requests.service_code LIMIT 1) AS service_code + '), + DB::raw(' + (SELECT corporate_policies.code FROM corporate_policies WHERE corporate_policies.id = claim_requests.policy_id LIMIT 1) AS corporate_policies + '), + DB::raw(' + (SELECT organizations.name FROM organizations WHERE organizations.id = request_logs.organization_id LIMIT 1) AS provider + '), + DB::raw(' + (Select SUM(request_log_benefits.amount_approved) as tot_bill FROM request_log_benefits + WHERE request_log_benefits.request_log_id = request_logs.id LIMIT 1) AS tot_bill + '), + 'claims.status', + ) + ->paginate($limit); + - return response()->json($claims); + return response()->json(Helper::paginateResources($results)); + } + + public function exportClaimManagement(Request $request) + { + $start_date = $request->input('start_date') ? $request->input('start_date') : 'all'; + $end_date = $request->input('end_date') ? $request->input('end_date') : 'all'; + $writer = WriterEntityFactory::createXLSXWriter(); + $writer->openToFile(public_path('files/Report-Data-Claim-Management-'.$start_date.'-'.$end_date.'.xlsx')); + $header = [ + 'No', + 'Code', + 'Name', + 'Member ID', + 'Date Submission', + 'Plan ID', + 'Service', + 'Policy Number', + 'Provider', + 'Total Billing', + ]; + $style = (new StyleBuilder()) + ->setFontBold() + // ->setFontSize(15) + // ->setFontColor(Color::BLUE) + // ->setShouldWrapText() + ->setCellAlignment(CellAlignment::LEFT) + // ->setBackgroundColor(Color::YELLOW) + ->build(); + + $headerRow = WriterEntityFactory::createRowFromArray($header, $style); + $writer->addRow($headerRow); + // ============================ + $results = DB::table('claims') + ->leftJoin('claim_requests', 'claims.claim_request_id','=', 'claim_requests.id') + ->leftJoin('request_logs', 'claim_requests.request_log_id','=', 'request_logs.id') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->when($request->input('search'), function ($query, $search) { + $query->where(function ($query) use ($search) { + $query->orWhere('members.name', 'like', "%" . $search . "%"); + }); + }) + ->when($request->has('orderBy'), function ($query) use ($request) { + $orderBy = $request->orderBy; + $direction = $request->order ?? 'asc'; + + $query->orderBy($orderBy, $direction); + }) + ->when($request->input('start_date') , function ($query, $start_date) { + $query->where(function ($query) use ($start_date) { + $query->where('claims.created_at', '>=', $start_date); + }); + }) + ->when($request->input('end_date') , function ($query, $end_date) { + $query->where(function ($query) use ($end_date) { + $query->where('claims.created_at', '<=', $end_date); + }); + }) + ->when($request->input('provider') , function ($query, $provider) { + $query->where(function ($query) use ($provider) { + $query->where('request_logs.organization_id', '=', $provider); + }); + }) + ->select( + 'claims.id', + 'request_logs.id AS id_log', + 'claims.code', + 'members.name', + DB::raw(' + (SELECT members.member_id FROM members WHERE members.id = claims.member_id LIMIT 1) AS member_id + '), + 'claims.created_at', + DB::raw(' + (SELECT plans.code FROM plans WHERE plans.id = claims.plan_id LIMIT 1) AS plan_code + '), + DB::raw(' + (SELECT services.description FROM services WHERE services.code = claim_requests.service_code LIMIT 1) AS service_code + '), + DB::raw(' + (SELECT corporate_policies.code FROM corporate_policies WHERE corporate_policies.id = claim_requests.policy_id LIMIT 1) AS corporate_policies + '), + DB::raw(' + (SELECT organizations.name FROM organizations WHERE organizations.id = request_logs.organization_id LIMIT 1) AS provider + '), + DB::raw(' + (Select SUM(request_log_benefits.amount_approved) as tot_bill FROM request_log_benefits + WHERE request_log_benefits.request_log_id = request_logs.id LIMIT 1) AS tot_bill + '), + 'claims.status', + ) + ->get(); + $no=0; + $gr_total = 0; + foreach($results as $item) + { + $gr_total += $item->tot_bill; + $no++; + $rowData = [ + $no, + $item->code, + $item->name, + $item->member_id, + $item->created_at, + $item->plan_code, + $item->service_code, + $item->corporate_policies, + $item->provider, + $item->tot_bill ? $item->tot_bill : 0 + ]; + $style = (new StyleBuilder()) + //->setFontBold() + // ->setFontSize(15) + // ->setFontColor(Color::BLUE) + // ->setShouldWrapText() + ->setCellAlignment(CellAlignment::LEFT) + // ->setBackgroundColor(Color::YELLOW) + ->build(); + $row = WriterEntityFactory::createRowFromArray($rowData, $style); + $writer->addRow($row); + } + $footer = [ + 'Grand Total', + '', + '', + '', + '', + '', + '', + '', + '', + $gr_total, + ]; + $style = (new StyleBuilder()) + ->setFontBold() + // ->setFontSize(15) + // ->setFontColor(Color::BLUE) + // ->setShouldWrapText() + ->setCellAlignment(CellAlignment::LEFT) + // ->setBackgroundColor(Color::YELLOW) + ->build(); + + $footerRow = WriterEntityFactory::createRowFromArray($footer, $style); + $writer->addRow($footerRow); + + $writer->close(); + + return Helper::responseJson([ + 'file_name' => 'Report-Data-Claim-Management-'. $start_date.'-'.$end_date, + "file_url" => url('files/Report-Data-Claim-Management-'. $start_date.'-'.$end_date.'.xlsx') + ]); + } + public function getProvider(Request $request) + { + $providers = DB::table('organizations') + ->where('organizations.type', '=', 'hospital') + ->where('organizations.status', '=', 'active') + ->select( + 'organizations.id', + 'organizations.name' + ) + ->orderBy('name', 'asc') + ->get(); + + return response()->json($providers); + } + + public function cekStatus($id) + { + $cek = DB::table('claims') + ->where('claims.id', '=', $id) + ->select('claims.status') + ->first(); + + $data['cek'] = $cek; + + $member = DB::table('claims') + ->join('claim_requests', 'claims.claim_request_id','=', 'claim_requests.id') + ->join('request_logs', 'claim_requests.request_log_id','=', 'request_logs.id') + ->join('members', 'request_logs.member_id', '=', 'members.id') + ->where('claims.id', '=', $id) + ->select('claims.code','members.name','claims.created_at', DB::raw(' + (SELECT services.name FROM services WHERE services.code = request_logs.service_code LIMIT 1) AS service_type + '),) + ->first(); + + $data['member'] = $member; + + return response()->json($data); + } /** @@ -334,7 +557,7 @@ class ClaimController extends Controller return Helper::responseJson([], message: "Diagnosis berhasil di update"); } - public function decline($id) + public function decline(Request $request, $id) { //Get claim request id $data_claim_requests = DB::table('claim_requests') @@ -348,7 +571,8 @@ class ClaimController extends Controller ->where('claim_request_id', $id) ->update( [ - 'status' => 'declined' + 'status' => 'declined', + 'reason_decline' => $request->reasonDecline ? $request->reasonDecline : '' ] ); diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index d5f58fda..e29af216 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -235,6 +235,8 @@ Route::prefix('internal')->group(function () { Route::post('claims/{claim_id}/set-final-encounter', [ClaimEncounterController::class, 'setFinalEncounter']); Route::get('claims', [ClaimController::class, 'index']); + Route::get('claims/export-claim-management', [ClaimController::class, 'exportClaimManagement']); + Route::get('claims/get-provider', [ClaimController::class, 'getProvider']); Route::post('claims/{id}/update-items', [ClaimController::class, 'updateItems'])->name('claim.update-items'); Route::post('claims/{id}/update-diagnosis', [ClaimController::class, 'updateDiagnosis'])->name('claim.update-diagnosis'); Route::post('claims/{id}/decline', [ClaimController::class, 'decline'])->name('claim.decline'); @@ -248,6 +250,7 @@ Route::prefix('internal')->group(function () { Route::post('claims', [ClaimController::class, 'store']); Route::get('claims/{id}', [ClaimController::class, 'show']); + Route::get('claims/cek_status/{id}', [ClaimController::class, 'cekStatus']); Route::put('claims/{id}', [ClaimController::class, 'update']); Route::get('claims/{id}/edit', [ClaimController::class, 'edit']); Route::post('check-limit', [ClaimController::class, 'checkLimit']); diff --git a/frontend/dashboard/src/pages/Claims/Detail.tsx b/frontend/dashboard/src/pages/Claims/Detail.tsx index 28cf2c47..98af659a 100644 --- a/frontend/dashboard/src/pages/Claims/Detail.tsx +++ b/frontend/dashboard/src/pages/Claims/Detail.tsx @@ -1,637 +1,102 @@ -import * as Yup from 'yup'; -// mui import { Container, Grid, Stack, Typography, Card, - TextField, - Divider, - ButtonBase, - Box, + TableRow, + Tab, + TableCell, + Collapse, + AccordionSummary, + AccordionDetails, IconButton, - Autocomplete, - FormControl, - InputLabel, - Select, - FormHelperText, - MenuItem } from '@mui/material'; + TextField + } from '@mui/material'; // components -import Page from '../../components/Page'; +import Page from '@/components/Page'; // utils -import useSettings from '../../hooks/useSettings'; +import useSettings from '@/hooks/useSettings'; // react import { useNavigate, useParams, useLocation } from 'react-router-dom'; import { useEffect, useState, useRef, useMemo } from 'react'; -import axios from '../../utils/axios'; +import axios from '@/utils/axios'; // pages -import { format } from 'date-fns'; import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; -import Button from '@mui/material/Button'; -import AddIcon from '@mui/icons-material/Add'; -import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; -import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import FormGroup from '@mui/material/FormGroup'; -import FormControlLabel from '@mui/material/FormControlLabel'; -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 BenefitConfigurationList from './components/BenefitConfigurationList'; -import { map } from 'lodash'; - - -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 { fDateOnly, fDateTimeSuffix } from '@/utils/formatTime'; +import { fDate, fDateTimesecond, fDateTime } from '@/utils/formatTime'; +import { Button } from '@mui/material'; import Label from '@/components/Label'; -import RHFAutocomplete from '../../components/hook-form/RHFAutocompleteV2'; +import { Box } from '@mui/system'; +import { Accordion } from '@mui/material'; +import { Delete, EditOutlined, ExpandMore } from '@mui/icons-material'; +import AddIcon from '@mui/icons-material/Add'; + +import MoreMenu from '@/components/MoreMenu'; +import { MenuItem } from '@mui/material'; +import { fNumber } from '@/utils/formatNumber'; +import palette from '@/theme/palette'; + +import CloseIcon from '@mui/icons-material/Close'; +import { enqueueSnackbar } from 'notistack'; +import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; + + // ---------------------------------------------------------------------- export default function Detail() { const location = useLocation(); const queryParams = new URLSearchParams(location.search); - const code = queryParams.get('code'); const navigate = useNavigate(); const { themeStretch } = useSettings(); - const [customerData, setCustomerData] = useState(null); - const [documentData, setDocumentData] = useState(null); - const [requestDocumentData, setRequestDocumentData] = useState(null); - const [serviceData, setServiceData] = useState(null); - const [serviceBenefitData, setServiceBenefitData] = useState(null); - const [dataDialog, setDataDialog] = useState(null); + const [requestLog, setRequestLog] = useState(); + const [statusClaim, setStatusClaim] = useState(''); + const [dataMember, setDataMember] = useState(''); + const { id } = useParams(); + const {id_claim} = useParams(); useEffect(() => { axios - .get('/claims/detail/'+id) + .get('customer-service/request/'+id) .then((response) => { - setCustomerData(response.data.data.customer_data); - setDocumentData(response.data.data.documents); - setRequestDocumentData(response.data.data.request_documents); - setServiceData(response.data.data.claim_services); - setServiceBenefitData(response.data.data.claim_service_benefits); - setDataDialog(response.data.data.dialog_submits); + setRequestLog(response.data.data) }) .catch((error) => { console.error(error); }); - getService(); + axios + .get('claims/cek_status/'+id_claim) + .then((response) => { + setStatusClaim(response.data.cek.status); + setDataMember(response.data.member); - }, []); - - function toTitleCase(str: string | null) { - return str.replace(/\w\S*/g, function(txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); - } + }) + .catch((error) => { + console.error(error); + }) + }, [id, id_claim]); const style1 = { color: '#919EAB', width: '30%' } + const style3 = { + color: '#919EAB', + width: '35%' + } const style2 = { width: '70%' } const marginBottom1 = { marginBottom: 1, } - - //Request - const [openDialogRequest, setOpenDialogRequest] = useState(false); - const handleCloseDialogRequest = () => { - setOpenDialogRequest(false); + const marginBottom2 = { + marginBottom: 2, } - const [conditionChecked, setConditionChecked] = useState(true); - const [diagnosisChecked, setDiagnosisChecked] = useState(false); - const [supportingResultChecked, setSupportingResultChecked] = useState(false); - - const handleConditionChange = (event) => { - setConditionChecked(event.target.checked); - }; - - const handleDiagnosisChange = (event) => { - setDiagnosisChecked(event.target.checked); - }; - - const handleSupportingResultChange = (event) => { - setSupportingResultChecked(event.target.checked); - }; - - const [noteField, setNoteField] = useState(''); - const [noteFieldError, setNoteFieldError] = useState(''); - const isRequiredFieldsFilled = () => { - return noteField.trim() !== ''; - }; - - const handelRequestDocument = () => { - const dataForm = { - claim_id: id, - condition: conditionChecked, - diagnosis: diagnosisChecked, - result: supportingResultChecked, - note: noteField, - } - axios - .post('/claims/request-documents', dataForm) - .then((response) => { - enqueueSnackbar('Success Request Document', { variant: 'success' }); - setOpenDialogRequest(false); - window.location.reload(); - }) - .catch((error) => { - enqueueSnackbar('Something Went Wrong', { variant: 'error' }); - }) - } - - /*---------------------- Handle History Hospital Care ----------------------------*/ - - interface FormValuesProps extends Partial { - 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(null); // Untuk edit Claim History - - const [carehistory, setCarehistory] = useState(null); - const [isEdit,setEdit] = useState(false); - const [service_code, setServiceType] = useState(); - const handleCloseDialogUpdate = () => { - setOpenDialogRequest(false); - reset() - } - - useEffect( () => { - axios - .get('claims/'+id) - .then((response) => { - setCorporateId(response.data.data.corporate_id) - setCurrentClaimHistoryCare(response.data.data.history_hospital_care) - setServiceType(response.data.data.service_code) - - }) - }, [id]) - - 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, - admission_date: response.data.data.admission_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, - secondary_diagnosis_id: response.data.data.secondary_diagnosis.map((row: any) => ({ - value: { - id: row.id, - name: row.icd.name - } - })) - }); - - 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); - }); - - // 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) - }) - } - - }, [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); - setEdit(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 dataForm = { - status: 1, - claim_id: id - } - axios - .post(`/claims/carehistory/approval`, dataForm) - .then((response) => { - enqueueSnackbar('Claim Approve Successfully!', { variant: 'success' }); - setOpenDialogApproval(false); - window.location.reload(); - }) - .catch((error) => { - enqueueSnackbar('Something Went Wrong', { variant: 'error' }); - }) - - } - - // 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: service_code, - secondary_diagnosis_id: [{ - value: { - name: "", - value: 0 - } - }], - admission_date: isEdit ? carehistory?.admission_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, - }), - [service_code] - ) - - let NewClaimHistoryCareSchema = Yup.object().shape({ - service_code: Yup.string().required('Name is required'), - // admission_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({ - resolver: yupResolver(NewClaimHistoryCareSchema), - defaultValues, - }); - - const { - reset, - watch, - control, - setValue, - getValues, - setError, - handleSubmit, - resetField, - formState: { isSubmitting }, - } = methods; - - const values = watch(); - const valueOfLocation = organization.find((row) => row.organization_id === values.organization_id) - - const {fields, append, remove} = useFieldArray({name: "secondary_diagnosis_id", control}) - - const onSubmit = async (data: FormValuesProps) => { - if (isEdit){ - let newData = { - service_code: data.service_code, - admission_date: data.admission_date ? fDateOnly(data.admission_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, - admission_date: data.admission_date ? fDateOnly(data.admission_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); - window.location.reload(); - // } - - } - - reset(); - } - - function secondaryDiagnosisOption() { - return fields.map((item, index) => { - return ( - - {`#${index+1}`} - - - opt.name} - isOptionEqualToValue={(opt, val) => opt.name === val.name} - label='Comparative Diagnosis (ICD-X)' - /> - - remove(index)}> - - - - - ) - }) - } - - function handleNewHospitalCare() { - setEdit(false); - setOpenHospitalCare(true); - reset(defaultValues); - } - - function handleEditHospitalCare(id: number) { - setClaimHistoryId(id); - setEdit(true); - setOpenHospitalCare(true); - reset(defaultValues); - } - - function handleUpdateHospitalCare(id: number) { - setOpenHospitalCare(false); - setClaimHistoryId(id); - setEdit(false); - setOpenDialogApproval(true); - } - - //Service - const [openDialogService, setOpenDialogService] = useState(false); - const handleCloseDialogService = () => { - setOpenDialogService(false); - } - const handleConditionChangeService = (event) => { - const selectedItem = event.target.value; - - if (valBenefitNames.includes(selectedItem)) { - // Item is already selected, remove it - setValBenefitNames(valBenefitNames.filter(item => item !== selectedItem)); - } else { - // Item is not selected, add it - setValBenefitNames([...valBenefitNames, selectedItem]); - } - }; - - //Data - const [serviceTypeData, setServiceTypeData] = useState(null); - const [benefitNameData, setBenefitNameData] = useState(null); - const [hospitalData, setHospitalData] = useState(null); - //Field - const currentDate = new Date(); - const formattedCurrentDate = format(currentDate, 'dd MMM yyyy'); - //Date Addmissions - const [dateAd, setDateAd] = useState(currentDate); - //Date Discharge - const [dateDis, setDateDis] = useState(currentDate); - //Service Type - const [valServiceType, setValServiceType] = useState(''); - const [valServiceTypeError, setValServiceTypeError] = useState(''); - //Benefit Name - const [valBenefitNames, setValBenefitNames] = useState([]); - const [valBenefitNameError, setValBenefitNameError] = useState(''); - //Hospital - const [valHospital, setValHospital] = useState(''); - const [valHospitalError, setValHospitalError] = useState(''); - //txt name - const [txtName, setTxtName] = useState('Add Service'); - //flag add or edit service - const [flagAddService, setFlagAddService] = useState('add'); - //id claim_services - const [idService, setIdService] = useState(null); - - - const isRequiredFieldsServiceType = () => { - return dateAd !== '' && dateDis !== '' && valServiceType !== '' && valBenefitNames.length > 0 && valHospital !== ''; - }; - - const getService = async () => { - try { - const response = await axios.get('/claims/get-services/' + id); - setServiceTypeData(response.data.data.service_type); - setValServiceType(response.data.data.service_type[0].id); - setBenefitNameData(response.data.data.benefit_name); - setHospitalData(response.data.data.hospital); - await Promise.all([ - setServiceTypeData(response.data.data.service_type), - setBenefitNameData(response.data.data.benefit_name), - setHospitalData(response.data.data.hospital), - ]); - - } catch (error) { - } - } - - - const handleAddService = async () => { - setTxtName('Add Service'); - setFlagAddService('add'); - setOpenDialogService(true); - } - - const handleEditService = async () => { - setDateAd(serviceData.addmission_date); - setDateDis(serviceData.discharge_date); - setIdService(serviceData.id); - - setOpenDialogService(true); - setTxtName('Edit Service'); - setFlagAddService('edit'); - - if (serviceTypeData) { - setValServiceType(serviceData.service_id); - setValHospital(serviceData.hospital_id); - setValBenefitNames(serviceBenefitData.benefit_id); - } - } - - const handelSaveServiceType = () => { - const dateAdd = dateAd ? fPostFormat(dateAd, 'yyyy-MM-dd') : null; - const dateDisc = dateDis ? fPostFormat(dateDis, 'yyyy-MM-dd') : null; - const data = { - flagAddService : flagAddService, - idService: idService, - claim_request_id: id, - dateAdd : dateAdd, - dateDisc : dateDisc, - serviceType : valServiceType, - benefitName : valBenefitNames, - hospital : valHospital - }; - axios - .post('/claims/save-services', data) - .then((response) => { - enqueueSnackbar('Success '+(flagAddService == 'add' ? 'Add' : 'Edit')+' Service', { variant: 'success' }); - handleCloseDialogService(); - window.location.reload(); - }) - .catch((error) => { - enqueueSnackbar('Something Went Wrong', { variant: 'error' }); - }) - } - - const [openDialogSubmit, setOpenDialogSubmit] = useState(false); const handleCloseDialogSubmit = () => { setOpenDialogSubmit(false); } @@ -640,12 +105,17 @@ export default function Detail() { const handleSubmitData = () => { //approve or decline + if(!reasonDecline && approve == 'decline') + { + enqueueSnackbar('Mohon isi alasan', { variant: 'warning' }); + return false; + } axios - .post('claims/'+id+'/'+decline) + .post('claims/'+id_claim+'/'+approve, {reasonDecline:reasonDecline}) .then((response) => { - enqueueSnackbar('Success '+toTitleCase(decline)+' Claim Request', { variant: 'success' }); + enqueueSnackbar('Success '+toTitleCase(approve)+' Claim Request', { variant: 'success' }); setOpenDialogSubmit(false); - window.location.reload(); + // window.location.reload(); }) .catch(({ response }) => { @@ -659,911 +129,590 @@ export default function Detail() { }; - const handelDownloadLog = () => { - axios - .get(`final-log/${id}`, { - responseType: 'blob', - }) - .then((response) => { - window.open(URL.createObjectURL(response.data)); - }) - .catch((response) => { - enqueueSnackbar(response.message, { variant: 'error' }); + function toTitleCase(str: string | null) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); } + const [reasonDecline, setReasonDecline] = useState(''); + + const handleReasonDeclineChange = (event) => { + setReasonDecline(event.target.value); + // Tambahkan logika yang diperlukan di sini + }; + + const [openDialogSubmit, setOpenDialogSubmit] = useState(false); + const [openDialogEditDetail, setDialogDEditDetail] = useState(false); + const [openDialogBenefit, setDialogBenefit] = useState(false); + const [openDialogMedicine, setDialogMedicine] = useState(false); + + // Handel Delete Detail Benefit + const [idBenefitData, setIdBenefitData] = useState(); + const [openDialogDeleteBenefit, setDialogDeleteBenefit] = useState(false) + + const [idMedicineData, setIdMedicineData] = useState(); + const [openDialogDeleteMedicine, setDialogDeleteMedicine] = useState(false) + + const [approve, setApprove] = useState('') + + // Handle Edit Detail Benefit + const [openDialogEditBenefit, setDialogEditBenefit] = useState(false) + const [BenefitConfigurationData, setBenefitConfigurationData] = useState(); + + // Buat total data + const totalAmountIncurred = (requestLog?.benefit_data || []).reduce((accumulator, item) => { + return accumulator + (item.amount_incurred || 0); + }, 0); + const totalAmountApprove = (requestLog?.benefit_data || []).reduce((accumulator, item) => { + return accumulator + (item.amount_approved || 0); + }, 0); + const totalAmountNotApprove = (requestLog?.benefit_data || []).reduce((accumulator, item) => { + return accumulator + (item.amount_not_approved || 0); + }, 0); + const totalExcessPaid = (requestLog?.benefit_data || []).reduce((accumulator, item) => { + return accumulator + (item.excess_paid || 0); + }, 0); + + // Handle Delete File LOG + const [pathFile, setPathFile] = useState('') + const [dialogDeleteFIleLog, setDialogDeleteFileLog] = useState(false) + + // Handle Upload File LOG + const [dialogUploadFileLog, setDialogUploadFileLog] = useState(false) + return ( navigate(-1)} sx={{cursor:'pointer'}}/> - {(customerData && customerData.code ? customerData.code : '')} - {customerData ? ( - - - Status - {(customerData && customerData.status) ? toTitleCase(customerData.status) : ''} - - - Submission Date - {(customerData && customerData.submission_date) ? format(new Date(customerData.submission_date), "d MMM yyyy") : ''} - - - ) : ''} + {(requestLog && requestLog.code ? requestLog.code : '')} - {customerData ? ( + {/* Detail */} - - Summary of Customer Data - - Full Name - {customerData.name} - - - Policy Number - {customerData.payor_id} - - - Member ID - {customerData.member_id} - - - Claim Type - {toTitleCase(customerData.payment_type)} - - - Corporate Name - {toTitleCase(customerData.coporate_name)} - - - - ) : ''} - {documentData ? ( - - - {customerData?.status === 'received' ? ( - - Additional Documents - - - ) : ''} - - {documentData?.map((documentType, index) => ( - - - {documentType.type === 'claim-diagnosis' ? - 'Diagnosis' - : documentType.type === 'claim-kondisi' ? - 'Condition' - : documentType.type === 'claim-result' ? - 'Supporting Result' - : documentType.type === 'claim-invoice' ? - 'Invoice' - : ''} - - - - - {documentType.original_name ? documentType.original_name : '-'} - - - - ))} - - {requestDocumentData && requestDocumentData.length > 0 ? ( - Request Documents - ) : ''} - - {requestDocumentData?.map((documentType, index) => ( - - - - - - {documentType.type === 'claim-diagnosis' ? - 'Diagnosis' - : documentType.type === 'claim-kondisi' ? - 'Condition' - : documentType.type === 'claim-result' ? - 'Supporting Result' - : documentType.type === 'claim-invoice' ? - 'Invoice' - : ''} - - - - ))} - - {/* Dialog Request Documents */} - - - - - Request Document - - - - - - - - - - } - label="Condition Document" - /> - } - label="Diagnosis Document" - /> - } - label="Supporting Result Document" - /> - - - Notes* + + + + + Detail - { - setNoteField(e.target.value); - setNoteFieldError(e.target.value.trim() === '' ? 'This field is required' : ''); - }} - fullWidth - inputProps={{ maxLength: 50 }} - error={!!noteFieldError} - helperText={noteFieldError} - /> - - - - - - - - - - ): ''} - - - - - History of Hospital Care - {customerData?.status === 'received' ? ( - - ) : ''} - - - - {currentClaimHistoryCare?.map((claimHistoryCare, index) => - claimHistoryCare.status === 0 ? ( - {/* Tambahkan key untuk setiap elemen dalam loop */} - - {customerData?.status === 'received' ? ( - - - - handleEditHospitalCare(claimHistoryCare.id)}> - Edit - - handleUpdateHospitalCare(claimHistoryCare.id)}> - Update Status - - - }/> - - ) : ''} - - Admission Date : - { fDate(claimHistoryCare.admission_date)} {/* Perbaikan typo di 'admission_date' */} - - - Discharge Date : - { fDate(claimHistoryCare.discharge_date)} - - - Location : - {toTitleCase(claimHistoryCare.organization?.name)} - - - Doctor : - {toTitleCase(claimHistoryCare.practitioner?.code)} - {claimHistoryCare.person?.name} - - - Status : - {claimHistoryCare.status == 0 ? 'Pending' : 'Approv'} - - - Diagnosis : - #{index+1} {claimHistoryCare.icd?.code} - {claimHistoryCare.icd?.name} - - - - ) : null - )} - - - {/* Dialog for input and update */} - - - - - {isEdit ? 'Update' : 'Add'} History of Hospital Care - - - - - - - - - - - - Service Code - - - - - - - Admission Date* - - - - Discharge Date* - - - {/* Location */} - - Location* - { - 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)} - value={valueOfLocation ?? null} - - renderInput={(params) => ( - - )} - /> - - - {/* Dokter */} - - Doctor* - { - return option.name ?? false - }} - isOptionEqualToValue={(option, value) =>{ - return option.id === value.id - }} - - value={doctor.find(row => row.id == values.practitioner_id) ?? null} - - onChange={handleDoctorChange} - renderInput={(params) => ( - - )} - /> - - - - - Medical Record Number* - - - - Symptoms* - - - - Sign* - - - - Diagnosis* - - - {/* - - {/* Main Diagnosis */} - - { - 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) ?? null} - onChange={handleMainDiagnosisChange} - renderInput={(params) => ( - - )} - /> - - - - {secondaryDiagnosisOption()} - - - - - - - - - {isEdit ? 'Update' : 'Save'} - - - - - - - - - - - - {/* Dialog for approval */} - - - - - Add History of Hospital Care - - - - - - - - - - Are you sure to approve this hospital care ? - - - - - Admission Date - { carehistory ? fDate(carehistory?.admission_date) : '-'} - - - Discharge Date - {carehistory ? fDate(carehistory.discharge_date) : '-'} - - - Location - { carehistory ? carehistory.organization_name : '-'} - - - Doctor - {carehistory ? carehistory.practitioner_name : '-'} - - - Diagnosis - {carehistory ? carehistory?.main_diagnosis_name : '-'} - - - - - - - - - - - - - - - - - - - - - - - - Diagnostic History - - - {currentClaimHistoryCare?.map((claimHistoryCare, index) => - claimHistoryCare.status === 1 ? ( - {/* Tambahkan key untuk setiap elemen dalam loop */} - - - - - - Admission Date : - { fDate(claimHistoryCare.admission_date)} {/* Perbaikan typo di 'admission_date' */} - - - Discharge Date : - { fDate(claimHistoryCare.discharge_date)} - - - Location : - {toTitleCase(claimHistoryCare.organization?.name)} - - - Doctor : - {toTitleCase(claimHistoryCare.practitioner?.code)} - {claimHistoryCare.person?.name} - - - Status : - {claimHistoryCare.status == 0 ? 'Pending' : 'Approv'} - - - Diagnosis : - #{index+1} {claimHistoryCare.icd?.code} - {claimHistoryCare.icd?.name} - - - - ) : null - )} - - - - - - - Diagnosis Summary - - - {currentClaimHistoryCare?.map((claimHistoryCare, index) => - claimHistoryCare.status === 1 ? ( - {/* Tambahkan key untuk setiap elemen dalam loop */} - - - Symtomps : - { claimHistoryCare.symptoms} {/* Perbaikan typo di 'admission_date' */} - - - Sign : - { claimHistoryCare.sign} - - - Main Diagnosis : - {claimHistoryCare.icd?.name} - - - {/* {claimHistoryCare.comparative_diagnosis?.map((comparativeDiagnosis, i) => - ( - - {i == 0 ? 'Comparative Diagnosis :' : ''} - {comparativeDiagnosis.icd?.name} - - ) - )} */} - - {claimHistoryCare.comparative_diagnosis && claimHistoryCare.comparative_diagnosis.length > 0 && ( - claimHistoryCare.comparative_diagnosis.map((comparativeDiagnosis, i) => ( - - - {i === 0 ? 'Comparative Diagnosis :' : ''} - - - {comparativeDiagnosis.icd?.name} - - - )) - )} - - - - - ) : null - )} - - - - - - - Service - {!serviceData && customerData?.status === 'received' ? ( - - ) : ( - - {customerData?.status === 'received' ? ( - - handleEditService()}> - - Edit - - - } - /> - ) : ''} - - )} - - {serviceData ? ( - <> - - Admission Date - {serviceData && serviceData.addmission_date ? fDateTime(serviceData.addmission_date) : ''} - - - Discharge Date - {serviceData && serviceData.discharge_date ? fDateTime(serviceData.discharge_date) : ''} - - - Serice Type - {serviceData && serviceData.name_services ? serviceData.name_services : ''} - - - Benefit Name - {serviceBenefitData && serviceBenefitData.name_benefits ? serviceBenefitData.name_benefits : ''} - - - Hospital - {serviceData && serviceData.name_hospitals ? serviceData.name_hospitals : ''} - - - ): ''} - - {/* Dialog Service */} - - - - - {txtName} - - - - - - - - - - - - Admission Date* - - - { - setDateAd(newValue); - }} - inputFormat="dd MMM yyyy" - renderInput={(params) => } - /> - - - - - Discharge Date* - - - { - setDateDis(newValue); - }} - inputFormat="dd MMM yyyy" - renderInput={(params) => } - /> - - - - - - Service Type* - - - Service Type - - - {valServiceTypeError} - - - - - - Benefit Name* - - - Benefit Name - - - {valBenefitNameError} - - - - - - Hospital* - - - Hospital - - - {valHospitalError} - - - - - - - - - - - - - - - - {/* title */} - - Client Benefit Configuration - - {/* no benefit selected */} - { - false - ? - ( - - Tidak ada benefit yang dipilih - - ) - : - ( - - - - ) - } + {requestLog?.status_final_log != 'requested' ? ( + + + { + setDialogDEditDetail(true) + }}> + + Edit + + + } + /> + ) : null } + + + Provider + {requestLog?.provider} + + + Member ID + {requestLog?.member_id} + + + Policy Number + {requestLog?.policy_number} + + + Name + {requestLog?.name} + + + Date Of Birth + {requestLog?.date_of_birth ? fDate(requestLog?.date_of_birth) : '-'} + + + Marital Status + {requestLog?.marital_status} + + + Submission Date + {requestLog?.submission_date ? fDateTimesecond(requestLog?.submission_date) : '-'} + + + Admission Date + {requestLog?.admission_date ? fDateTimesecond(requestLog?.admission_date) : '-'} + + + + Discharge Date + {requestLog?.discharge_date ? fDateTimesecond(requestLog?.discharge_date) : '-'} + + + + No KTP + {requestLog?.no_identitas ? requestLog?.no_identitas : '-'} + + + Keterangan + {requestLog?.keterangan ? requestLog?.keterangan : '-'} + + + Hak Kamar Pasien + {requestLog?.hak_kamar_pasien ? requestLog?.hak_kamar_pasien : '-'} + + + Penempatan Kamar + {requestLog?.penempatan_kamar ? requestLog?.penempatan_kamar : '-'} + + + Catatan + {requestLog?.catatan ? requestLog?.catatan : '-'} + + + Diagnosis + + {requestLog?.diagnosis?.length > 0 ? ( +
    + {requestLog.diagnosis.map((diagnosisItem, index) => ( +
  • {diagnosisItem.code} - {diagnosisItem.name}
  • + // Replace 'name' with the property you want to display + ))} +
+ ) : ( +

No diagnosis available.

+ )} +
+
+ {/* */}
- - - <> - {(customerData && customerData.status === 'received') ? ( - <> - - - - ) : ( - <> - - - - - - ) } - - {/* Dialog Submits */} - - - - - Confirmation - - - - - - - - {dataDialog ? ( - - Are you sure to {toTitleCase(decline)} this claim ? - - - Code - {dataDialog.code} - - - Name - {dataDialog.name} - - - Date Submission - {fDateTime(dataDialog.submission_date)} - - - Claim Method - Service Type - - - Service Type - - {dataDialog.service_code === 'IP' ? 'Inpatient' : 'Outpatient'} - - - - - ) : ''} - - - - - - - + {/* Service */} + + {/* + */} + + {/* Exclusion */} + + {/* + */} + + + {/* Benefit */} + + + + Benefit + + + + {requestLog?.benefit_data?.map((item, index) => ( + + + + + + + {item.benefit?.description} + + + + + { + setDialogEditBenefit(true) + setIdBenefitData(item.id) + setBenefitConfigurationData(item) + }} + > + + Edit + + { + setIdBenefitData(item.id) + setDialogDeleteBenefit(true) + }} + > + + Delete + + + } /> + + + + + + + + {/* Amount Incurred */} + + + + + Amount Incurred + + + + + {fNumber(item.amount_incurred)} + + + + + + {/* Amount Approved */} + + + + + Amount Approved + + + + + {fNumber(item.amount_approved)} + + + + + + {/* Amount Not Approved */} + + + + + Amount Not Approved + + + + + {fNumber(item.amount_not_approved)} + + + + + + {/* Excess Paid* */} + + + + + Excess Paid* + + + + + {fNumber(item.excess_paid)} + + + + + + {/* Keterangan* */} + + + + + Keterangan* + + + + + {item.keterangan} + + + + + + + + + + + + ))} +
+
+ {requestLog?.benefit_data && requestLog.benefit_data.length > 0 ? ( + + + + + + + Total Benefit + + + + + + + + + + {/* Amount Incurred */} + + + + + Amount Incurred + + + + + {fNumber(totalAmountIncurred)} + + + + + + {/* Amount Approved */} + + + + + Amount Approved + + + + + {fNumber(totalAmountApprove)} + + + + + + {/* Amount Not Approved */} + + + + + Amount Not Approved + + + + + {fNumber(totalAmountNotApprove)} + + + + + + {/* Excess Paid* */} + + + + + Excess Paid + + + + + {fNumber(totalExcessPaid)} + + + + + + + + + + + ) + : ( + null + )} +
+ + {/* PR Buat pindahin ke componen */} + {/* + + */} + +
+ + {/* Medicine */} + + + + Medicine + + + + {requestLog?.medicine.map((item, index) => ( + + {item.medicine} + Rp. {fNumber(item.price)} + { + setIdMedicineData(item.id) + setDialogDeleteMedicine(true) + }}> + + + + + ))} + + + + + + {/* File */} + + + + + Files + + + + + + {requestLog?.files?.map((documentType, index) => ( + + + + {documentType.original_name ? documentType.original_name : '-'} + + + + + + + ))} + + + + + + {statusClaim == 'requested' ? ( + + + + <> +
+ +
+
+ +
+ + +
+ {/* Dialog Submits */} + + + + + Confirmation + + + + + + + + + + Are you sure to {toTitleCase(approve)} this claim ? + + + Code + {dataMember?.code} + + + Name + {dataMember?.name} + + + Date Submission + {dataMember?.created_at ? fDateTime(dataMember?.created_at) : ''} + + + Claim Method + Service Type + + + Service Type + + {dataMember?.service_type} + + + {approve == "decline" ? ( + + + + ): ''} + + + + + + + + +
+
+ ) : null} +
); -} +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/Claims/Index.tsx b/frontend/dashboard/src/pages/Claims/Index.tsx index 5fc6d983..78214d1e 100644 --- a/frontend/dashboard/src/pages/Claims/Index.tsx +++ b/frontend/dashboard/src/pages/Claims/Index.tsx @@ -7,7 +7,7 @@ import List from "./List"; export default function Claims() { - const pageTitle = 'Claim'; + const pageTitle = 'Claim Management'; return ( @@ -16,7 +16,7 @@ export default function Claims() { links={[ { name: 'Dashboard', href: '/dashboard' }, { - name: 'Claim', + name: 'Claim Management', href: '/claims', }, ]} diff --git a/frontend/dashboard/src/pages/Claims/List.tsx b/frontend/dashboard/src/pages/Claims/List.tsx index 5e1d01fd..06791385 100644 --- a/frontend/dashboard/src/pages/Claims/List.tsx +++ b/frontend/dashboard/src/pages/Claims/List.tsx @@ -1,6 +1,7 @@ // @mui import { Box, + Grid, Button, Card, Collapse, @@ -17,12 +18,24 @@ import { ButtonGroup, Tooltip, TableHead, + Checkbox, + InputAdornment, + TableSortLabel, + FormControl } from '@mui/material'; +import { visuallyHidden } from '@mui/utils'; + +import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { fDateOnly } from '@/utils/formatTime'; + +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; import FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; import AssessmentIcon from '@mui/icons-material/Assessment'; // hooks import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; import { Link, Navigate, useNavigate, useSearchParams } from 'react-router-dom'; + +import { LoadingButton } from '@mui/lab'; // components import axios from '../../utils/axios'; import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../@types/paginated-data'; @@ -32,23 +45,146 @@ import EditRoundedIcon from '@mui/icons-material/EditRounded'; import { Chip } from '@mui/material'; import Iconify from '@/components/Iconify'; import { enqueueSnackbar } from 'notistack'; -import { fDate } from '../../utils/formatTime'; +import { fDate, fDateTime } from '../../utils/formatTime'; import { Claims } from '@/@types/claims'; import Label from '@/components/Label'; import { capitalizeFirstLetter } from '@/utils/formatString'; import TableMoreMenu from '@/components/table/TableMoreMenu'; import Edit from '@mui/icons-material/Edit'; import { Download } from '@mui/icons-material'; +import { Add, Search } from '@mui/icons-material'; +import Autocomplete from '@mui/material/Autocomplete'; + +import DownloadIcon from '@mui/icons-material/Download'; + +import UploadIcon from '@mui/icons-material/Upload'; +import CancelIcon from '@mui/icons-material/Cancel'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; + +import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; +import CloseIcon from '@mui/icons-material/Close'; + export default function List() { + const [selectAll, setSelectAll] = useState(false); + const [selectedRows, setSelectedRows] = useState([]); + const [providers, setProviders] = useState(null); + // const [searchText, setSearchText] = useState(''); + const [order, setOrder] = useState('desc'); + const [orderBy, setOrderBy] = useState('created_at'); + const [perPage, setPerPage] = useState(0); + + const handleChange = (event, newValue) => { + // Jika newValue tidak undefined, atur nilai dataProvider + if (newValue !== undefined) { + setDataProvider(newValue.service_code); + } else { + // Jika tidak ada yang dipilih, set dataProvider menjadi string kosong + setDataProvider(null); + } + }; + // Dummy data +const dummyServices = [ + { service_code: '1', name: 'Service 1' }, + { service_code: '2', name: 'Service 2' }, + { service_code: '3', name: 'Service 3' }, + // tambahkan data lain sesuai kebutuhan +]; + + + + const handleSelectAll = () => { + setSelectAll(!selectAll); + if (!selectAll) { + const requestedIds = dataTableData.data + .filter(row => row.status === 'requested') // Memfilter baris dengan status 'requested' + .map(row => row.id); // Mengambil hanya ID dari baris-baris yang memenuhi kondisi + setSelectedRows(requestedIds); + } else { + setSelectedRows([]); + } + }; + + const handleRowSelect = (id) => { + if (selectedRows.includes(id)) { + setSelectedRows(selectedRows.filter(rowId => rowId !== id)); + } else { + setSelectedRows([...selectedRows, id]); + } + }; + const [searchParams, setSearchParams] = useSearchParams(); - const [importResult, setImportResult] = useState(null); + const [startDate, setStartDate] = useState(null); + const [searchText, setSearchText] = useState(''); + const [endDate, setEndDate] = useState(null); const navigate = useNavigate(); + const [dataProvider, setDataProvider] = useState(null); + + useEffect(() => { + if (startDate !== null || endDate !== null || dataProvider !== null + || order !== null || orderBy !== null || perPage !== 0) { + loadDataTableData(); + getProvider(); + } + }, [startDate, endDate, dataProvider, order, orderBy, perPage]); + + const [isLoading, setIsLoading] = useState(false); + const [isLoadingImport, setIsLoadingImport] = useState(false); + const handleExportReport = async () => { + + + const year = startDate?.getFullYear(); + const month = (startDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day = startDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate = year && month && day ? `${year}-${month}-${day}` : ''; + + const year1 = endDate?.getFullYear(); + const month1 = (endDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day1 = endDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate1 = year1 && month1 && day1 ? `${year1}-${month1}-${day1}` : ''; + + + + var filter = Object.fromEntries([...searchParams.entries()]); + setIsLoading(true) + await axios + .get('/claims/export-claim-management',{ + params: { + search: searchText, + start_date: formattedDate ? formattedDate : null, + end_date:formattedDate1, + provider: dataProvider, + order: order, + orderBy: orderBy, + page: perPage, + } + }) + .then((res) => { + enqueueSnackbar('Data berhasil di Export', { + variant: 'success', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }); + setIsLoading(false) + + document.location.href = res.data.data.file_url; + }) + .catch((err) => + enqueueSnackbar('Data Gagal di Export', { + variant: 'error', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }) + + ); + }; + function SearchInput(props: any) { // SEARCH const searchInput = useRef(null); - const [searchText, setSearchText] = useState(''); + + const handleSearchChange = (event: any) => { const newSearchText = event.target.value ?? ''; @@ -73,7 +209,7 @@ export default function List() { useEffect(() => { // Trigger First Search - setSearchText(searchParams.get('search') ?? ''); + // setSearchText(searchParams.get('search') ?? ''); }, []); return ( @@ -126,41 +262,232 @@ export default function List() { ); } + const searchInput = useRef(null); + + + //handle search + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? ''; + setSearchText(newSearchText); + }; + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + loadDataTableData(); + }; + + + + useEffect(() => { + // Trigger First Search + //setSearchText(searchText); + }, []); + + const item = [ + { + id: '', + value: '', + name: 'Semua', + }, + ]; + + const handleClick = () => { + + } + + + // Dummy Default Data const [dataTableIsLoading, setDataTableLoading] = useState(true); const [dataTableData, setDataTableData] = useState( LaravelPaginatedDataDefault ); + + const loadDataTableData = async (appliedFilter: any | null = null) => { setDataTableLoading(true); + const year = startDate?.getFullYear(); + const month = (startDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day = startDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate = year && month && day ? `${year}-${month}-${day}` : ''; + + const year1 = endDate?.getFullYear(); + const month1 = (endDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day1 = endDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate1 = year1 && month1 && day1 ? `${year1}-${month1}-${day1}` : ''; + const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); - const response = await axios.get('/claims', { params: filter }); - // console.log(response.data); + const response = await axios.get('/claims', { + params: { + search: searchText, + start_date: formattedDate ? formattedDate : null, + end_date:formattedDate1, + provider: dataProvider, + order: order, + orderBy: orderBy, + page: perPage, + } + }); + setDataTableLoading(false); setDataTableData(response.data); }; + const getProvider = async () => { + const response = await axios.get('/claims/get-provider'); + setProviders(response.data) + } + const applyFilter = async (searchFilter: { search: string }) => { await loadDataTableData(searchFilter); setSearchParams(searchFilter); }; - + const handlePageChange = (event: ChangeEvent, value: number): void => { - const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]); - loadDataTableData(filter); - setSearchParams(filter); + setPerPage(value); }; - useEffect(() => { - loadDataTableData(); - }, []); + const [openDialogSubmit, setOpenDialogSubmit] = useState(false); + const handleCloseDialogSubmit = () => { + setOpenDialogSubmit(false); + } + + function toTitleCase(str: string | null) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + } + + const [approve, setApprove] = useState(''); + + const [reasonDecline, setReasonDecline] = useState(''); + + const handleReasonDeclineChange = (event) => { + setReasonDecline(event.target.value); + // Tambahkan logika yang diperlukan di sini + }; + + const handleSubmitData = () => { + //approve or decline + if (!reasonDecline && approve == 'decline') { + enqueueSnackbar('Mohon isi alasan', { variant: 'warning' }); + return false; + } + Promise.all(selectedRows.map(send_bulk)) + .then(() => { + enqueueSnackbar('All requests processed successfully', { variant: 'success' }); + setOpenDialogSubmit(false); + setTimeout(() => { + window.location.reload(); + }, 5000); // Reload the page after 5 seconds + }) + .catch((error) => { + enqueueSnackbar(error.response?.data?.message ?? 'Something went wrong!', { variant: 'error' }); + }); + }; + + function send_bulk(id) { + return axios.post(`claims/${id}/${approve}`, { reasonDecline: reasonDecline }); + } + + + // useEffect(() => { + // loadDataTableData(); + // getProvider(); + // }, []); const headStyle = { fontWeight: 'bold', }; + const headCells = [ + { + id: 'code', + align: 'left', + label: 'Code', + isSort: true, + }, + { + id: 'name', + align: 'left', + label: 'Name', + isSort: false, + }, + { + id: 'member_id', + align: 'left', + label: 'Member ID', + isSort: false, + }, + { + id: 'created_at', + align: 'left', + label: 'Date Submission', + isSort: true, + }, + { + id: 'plan_code', + align: 'left', + label: 'Plan ID', + isSort: true, + }, + { + id: 'service_code', + align: 'left', + label: 'Service', + isSort: false, + }, + { + id: 'corporate_policies', + align: 'left', + label: 'Policy Number', + isSort: true, + }, + { + id: 'provider', + align: 'left', + label: 'Provider', + isSort: false, + }, + { + id: 'tot_bill', + align: 'left', + label: 'Total Billing', + isSort: false, + }, + { + id: 'status', + align: 'left', + label: 'Status', + isSort: false, + }, + { + id: 'action', + align: 'left', + label: '', + isSort: false, + }, + ]; + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + const createSortHandler = (property: string) => (event: React.MouseEvent) => { + handleRequestSort(event, property); + }; + const handleRequestSort = async (event: React.MouseEvent, property: string) => { + const isAsc = orders?.orderBy === property && orders?.order === 'asc'; + + orders?.setOrder(isAsc ? 'desc' : 'asc'); + orders?.setOrderBy(property); + }; // Called on every row to map the data to the columns function createData(data: Claims): Claims { return { @@ -171,10 +498,18 @@ export default function List() { { /* ------------------ TABLE ROW ------------------ */ } - function Row(props: { row: ReturnType }) { - const { row } = props; + function Row(props: { row: ReturnType, isSelected: boolean, onSelect: (id: string) => void }) { + const { row, isSelected, onSelect } = props; + // Memperbaiki destrukturisasi props + + const handleRowCheckboxChange = () => { + onSelect(row.id); // Panggil fungsi onSelect dari komponen induk dengan id baris saat checkbox di baris diklik + }; + const [open, setOpen] = React.useState(false); + const test = 1000; + return ( *': { borderBottom: 'unset' } }}> @@ -183,16 +518,22 @@ export default function List() { {open ? : } */} - {row.claim_request?.code} + + {row?.status == 'requested' ? ( + + ):''} + + {row?.code} {/* {row.code} */} - {row.member?.current_plan?.code} - {row.member?.current_corporate?.payor_id} - {row.member?.current_corporate?.code} - {row.member?.current_corporate?.current_policy?.code} - {row.member?.member_id} - {row.benefit_desc} - - + {row?.name} + {row?.member_id} + {row?.created_at ? fDateTime(row?.created_at) : ''} + {row?.plan_code} + {row?.service_code} + {row?.corporate_policies} + {row?.provider} + Rp. {row?.tot_bill?.toLocaleString('id-ID')} + {row.status == 'draft' && ()} {row.status == 'requested' && ()} {row.status == 'received' && ()} @@ -202,18 +543,17 @@ export default function List() { {row.status == 'declined' && ()} - - navigate(`/claims/edit/${row.id}`) }> - - Edit - - navigate('/claims/detail/'+row.id+'') }> - - Detail - - - } /> + + + navigate('/claims/detail/'+row.id_log+'/'+row.id+'') }> + + Detail + + + } /> + + @@ -236,40 +576,77 @@ export default function List() { /* ------------------ END TABLE ROW ------------------ */ } + + function TableContent() { return ( {/* ------------------ TABLE HEADER ------------------ */} - {/* */} - - Code - - - Plan ID - - - Payor ID - - - Corporate ID - - - Policy Number - - - Member ID - - - Benefit Desc - - - Status - - - - + {selectedRows.length > 0 ? ( + <> + + + + {selectedRows.length > 0 ? selectedRows.length : '0'}  Selected + + + + + + + + + + + + + + ) : ( + <> + + + + {headCells && + headCells.map((headCell, index) => ( + + {headCell.isSort ? ( + + {headCell.label} + {orders?.orderBy === headCell.id ? ( + + {orders.order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + ) : ( + headCell.label + )} + + ))} + + + )} + + {/* ------------------ END TABLE HEADER ------------------ */} @@ -278,7 +655,7 @@ export default function List() { {dataTableIsLoading ? ( - + Loading @@ -286,7 +663,7 @@ export default function List() { ) : dataTableData.data.length === 0 ? ( - + No Data @@ -294,7 +671,7 @@ export default function List() { ) : ( {dataTableData.data.map((row) => ( - + ))} )} @@ -305,7 +682,131 @@ export default function List() { return ( - + + +
+ + + { + if (event.key === 'Enter') { + handleSearchSubmit(event); + } + }} + InputProps={{ + startAdornment: ( + + + + ), + placeholder: 'Search Code or Name', + }} + /> + + + + { + + // loadDataTableData(); + setStartDate(value); + }} + renderInput={(params) => } + /> + + + + { + setEndDate(value); + }} + renderInput={(params) => ( + + )} + /> + + + + { + providers && ( + option.name || ''} + value={providers.find((item) => item.id === dataProvider) || null} + onChange={(event, value) => { + if (value) { + setDataProvider(value.id); + } else { + setDataProvider(null); + } + }} + renderInput={(params) => ( + + )} + /> + ) + } + + + + } + sx={{ p: 1.8 }} + // onClick={handleExportReport} + loading={isLoadingImport} + > + + Import + + + + + } + sx={{ p: 1.8 }} + onClick={handleExportReport} + loading={isLoading} + > + + Export + + + + + + +
+
} /> + + + + + Confirmation + + + + + + + + + + Are you sure to {toTitleCase(approve)} this claim ? + {approve == "decline" ? ( + + + + ): ''} + + + + + + +
); } diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index 0859ba78..23c0a50c 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -456,7 +456,7 @@ export default function Router() { element: , }, { - path: 'claims/detail/:id', + path: 'claims/detail/:id/:id_claim', element: , }, { diff --git a/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx b/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx index 914fa652..575a8053 100644 --- a/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx @@ -76,7 +76,7 @@ export default function DialogClaimSubmit({ member, getData, onClose, handleSubm