From 7809e8828fc15a1a077746e2ed4af61c4e8267f0 Mon Sep 17 00:00:00 2001 From: Tb Fajri Date: Fri, 9 Feb 2024 14:33:47 +0700 Subject: [PATCH 1/2] update name hasil penunjang --- .../src/pages/AlarmCenter/ServiceMonitoring.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/client-portal/src/pages/AlarmCenter/ServiceMonitoring.tsx b/frontend/client-portal/src/pages/AlarmCenter/ServiceMonitoring.tsx index fb1d915a..64ac0451 100644 --- a/frontend/client-portal/src/pages/AlarmCenter/ServiceMonitoring.tsx +++ b/frontend/client-portal/src/pages/AlarmCenter/ServiceMonitoring.tsx @@ -481,7 +481,7 @@ export default function ServiceMonitoring() { {loading ? ( ) : ( - 'Files Document' + 'Files Documentation' )} @@ -866,7 +866,7 @@ export default function ServiceMonitoring() { - + @@ -1104,7 +1104,7 @@ export default function ServiceMonitoring() { - File Document : + File Documentation : From 2dad40048667e251f2e73f6d4c862967619b8717 Mon Sep 17 00:00:00 2001 From: Tb Fajri Date: Fri, 9 Feb 2024 16:58:03 +0700 Subject: [PATCH 2/2] add fitur delete dan upload ulang file di FINAL log --- .../AlarmCenter/DataServiceMonitoring.php | 12 +- .../Controllers/Api/RequestLogController.php | 73 ++-- Modules/Internal/Routes/api.php | 2 + app/Models/File.php | 1 + app/Models/RequestLog.php | 2 +- ...52415_add_column_reason_to_files_table.php | 32 ++ .../Components/DetailMonitoringForm.tsx | 4 +- .../CustomerService/Components/CardFile.tsx | 52 ++- .../Components/DialogDeleteFileLog.tsx | 144 ++++++++ .../Components/DialogUploadFileFinalLog.tsx | 322 ++++++++++++++++++ .../pages/CustomerService/FinalLog/Detail.tsx | 80 +++-- 11 files changed, 650 insertions(+), 74 deletions(-) create mode 100644 database/migrations/2024_02_09_152415_add_column_reason_to_files_table.php create mode 100644 frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteFileLog.tsx create mode 100644 frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogUploadFileFinalLog.tsx diff --git a/Modules/Client/Transformers/AlarmCenter/DataServiceMonitoring.php b/Modules/Client/Transformers/AlarmCenter/DataServiceMonitoring.php index 639040f8..175b48b7 100644 --- a/Modules/Client/Transformers/AlarmCenter/DataServiceMonitoring.php +++ b/Modules/Client/Transformers/AlarmCenter/DataServiceMonitoring.php @@ -118,7 +118,11 @@ class DataServiceMonitoring extends JsonResource ->map(function ($requestLogDailyMonitoring) { $arr_document = []; $document = DB::table('files') - ->where(['fileable_type' => 'App\Models\LaboratoriumResult', 'fileable_id' => $requestLogDailyMonitoring->id]) + ->where([ + 'fileable_type' => 'App\Models\LaboratoriumResult', + 'fileable_id' => $requestLogDailyMonitoring->id, + 'deleted_at' => null + ]) ->whereIn('type', ['medical-action-letter', 'confirmation-medical-letter']) ->get(); if ($document){ @@ -173,7 +177,11 @@ class DataServiceMonitoring extends JsonResource ->map(function ($requestLogDailyMonitoring) { $arr_document = []; $document = DB::table('files') - ->where(['fileable_type' => 'App\Models\LaboratoriumResult', 'fileable_id' => $requestLogDailyMonitoring->id]) + ->where([ + 'fileable_type' => 'App\Models\LaboratoriumResult', + 'fileable_id' => $requestLogDailyMonitoring->id, + 'deleted_at' => null + ]) ->whereIn('type', ['laboratorium-result']) ->get(); if ($document){ diff --git a/Modules/Internal/Http/Controllers/Api/RequestLogController.php b/Modules/Internal/Http/Controllers/Api/RequestLogController.php index 42228fc7..167edf7f 100644 --- a/Modules/Internal/Http/Controllers/Api/RequestLogController.php +++ b/Modules/Internal/Http/Controllers/Api/RequestLogController.php @@ -861,17 +861,15 @@ class RequestLogController extends Controller return self::$code_prefix . $sparator. $data['source'] . $sparator. $data['provideCode'] . $sparator. $data['date'] . $sparator . $data['policy'] . $sparator. $data['member_code'] . $sparator. str_pad($next_number, 5, '0', STR_PAD_LEFT); } - public function requestFiles(Request $request, $claim_id) + public function requestFiles(Request $request, $id) { - - if ($request->hasFile('fileDiagnosis')) { - foreach ($request->fileDiagnosis as $file) { - $pathFile = File::storeFile('claim-diagnosis', $claim_id, $file); - File::updateOrCreate([ - 'fileable_type'=>'App\Models\RequestLog', - 'fileable_id' => $claim_id, - 'type' => 'claim-diagnosis', - 'name' => File::getFileName('claim-diagnosis', $claim_id, $file), + $requestLog = RequestLog::findOrFail($id); + if ($request->hasFile('result_files')) { + foreach ($request->result_files as $file) { + $pathFile = File::storeFile('final-log-result', $id, $file); + $requestLog->files()->updateOrCreate([ + 'type' => 'final-log-result', + 'name' => File::getFileName('final-log-result', $id, $file), 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), 'path' => $pathFile, @@ -881,14 +879,12 @@ class RequestLogController extends Controller } } - if ($request->hasFile('fileKondisis')) { - foreach ($request->fileKondisis as $file) { - $pathFile = File::storeFile('claim-kondisi', $claim_id, $file); - File::updateOrCreate([ - 'fileable_type'=>'App\Models\RequestLog', - 'fileable_id' => $claim_id, - 'type' => 'claim-kondisi', - 'name' => File::getFileName('claim-kondisi', $claim_id, $file), + if ($request->hasFile('diagnosa_files')) { + foreach ($request->diagnosa_files as $file) { + $pathFile = File::storeFile('final-log-diagnosis', $id, $file); + $requestLog->files()->updateOrCreate([ + 'type' => 'final-log-diagnosis', + 'name' => File::getFileName('final-log-diagnosis', $id, $file), 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), 'path' => $pathFile, @@ -898,23 +894,44 @@ class RequestLogController extends Controller } } - if ($request->hasFile('fileResults')) { - foreach ($request->fileResults as $file) { - $pathFile = File::storeFile('claim-result', $claim_id, $file); - File::updateOrCreate([ - 'fileable_type'=>'App\Models\RequestLog', - 'fileable_id' => $claim_id, - 'type' => 'claim-result', - 'name' => File::getFileName('claim-result', $claim_id, $file), + if ($request->hasFile('kondisi_files')) { + foreach ($request->kondisi_files as $file) { + $pathFile = File::storeFile('final-log-kondisi', $id, $file); + $requestLog->files()->updateOrCreate([ + 'type' => 'final-log-kondisi', + 'name' => File::getFileName('final-log-kondisi', $id, $file), 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), - 'path' => $pathFile, + 'path' => $pathFile, 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, ]); } } - return Helper::responseJson(data: $request->toArray(), message: 'Invoice Success Uploaded'); + return Helper::responseJson(data: $request->toArray(), message: 'File Success Uploaded'); + } + + public function deleteFiles(Request $request, $id) + { + // Path file yang akan dihapus + $path = 'public/' . $request->path; + + // Menghapus file dari penyimpanan + if (Storage::exists($path)) { + Storage::delete($path); + + // Update entri file dari basis data + File::where('path', $request->path)->update([ + 'deleted_at' => Carbon::now(), // Gunakan Carbon untuk mendapatkan tanggal dan waktu saat ini + 'deleted_by' => auth()->user()->id, + 'reason' => $request->reason + ]); + // Mengembalikan respons JSON sukses + return Helper::responseJson(data: $request->toArray(), message: 'File successfully deleted'); + } + + // Jika file tidak ditemukan di penyimpanan, kirim respons JSON gagal + return Helper::responseJson(data: $request->toArray(), message: 'File deletion failed'); } } diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index b3f9aa67..560bae58 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -267,6 +267,8 @@ Route::prefix('internal')->group(function () { Route::get('customer-service/request/{id}/download', [RequestLogController::class, 'generateRequestLog']); Route::post('customer-service/request/import', [RequestLogController::class, 'importRequestLog']); Route::get('customer-service/request/data', [RequestLogController::class, 'generateDataRequestLogExcel']); + Route::post('customer-service/request/{id}/add_file', [RequestLogController::class, 'requestFiles']); + Route::post('customer-service/request/{id}/delete_file', [RequestLogController::class, 'deleteFiles']); Route::post('customer-service/request/final-log', [RequestLogController::class, 'updateFinalLog']); diff --git a/app/Models/File.php b/app/Models/File.php index 627dc1a4..45beb3e6 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -21,6 +21,7 @@ class File extends Model 'path', 'created_by', 'updated_by', + 'reason' ]; protected $hidden = [ diff --git a/app/Models/RequestLog.php b/app/Models/RequestLog.php index 8f7f9a20..ea538202 100644 --- a/app/Models/RequestLog.php +++ b/app/Models/RequestLog.php @@ -220,7 +220,7 @@ class RequestLog extends Model public function files() { - return $this->morphMany(File::class, 'fileable'); + return $this->morphMany(File::class, 'fileable')->whereNull('deleted_at'); } public function claimResults() diff --git a/database/migrations/2024_02_09_152415_add_column_reason_to_files_table.php b/database/migrations/2024_02_09_152415_add_column_reason_to_files_table.php new file mode 100644 index 00000000..e605da26 --- /dev/null +++ b/database/migrations/2024_02_09_152415_add_column_reason_to_files_table.php @@ -0,0 +1,32 @@ +string('reason')->after('deleted_at')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('files', function (Blueprint $table) { + $table->dropColumn('reason'); + }); + } +}; diff --git a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DetailMonitoringForm.tsx b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DetailMonitoringForm.tsx index 8d0d13a2..9a5e5c52 100644 --- a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DetailMonitoringForm.tsx +++ b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DetailMonitoringForm.tsx @@ -553,7 +553,7 @@ export default function DetailMonitoringList() { - Laboratorium Result + Pemeriksaan Penunjang @@ -598,7 +598,7 @@ export default function DetailMonitoringList() { - Laboratorium Result + Pemeriksaan Penunjang diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx index ee0c70b3..c3cdfffd 100644 --- a/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx @@ -1,7 +1,10 @@ -import { Card, Typography } from "@mui/material"; +import { Card, IconButton, Typography } from "@mui/material"; import { Stack } from '@mui/material'; import { DetailFinalLogType } from "../FinalLog/Model/Types"; import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import { Button } from "@mui/material"; +import AddIcon from '@mui/icons-material/Add'; +import { Delete } from "@mui/icons-material"; type CardDetail = { @@ -26,25 +29,40 @@ const marginBottom2 = { export default function CardFile({requestLog} : CardDetail ) { return ( - + - Files - {requestLog?.files?.map((documentType, index) => ( - - - - {documentType.original_name ? documentType.original_name : '-'} - - + Files + + + + + + {requestLog?.files?.map((documentType, index) => ( + + + + {documentType.original_name ? documentType.original_name : '-'} + - ))} - - + + {}} aria-label="delete" size="small" sx={{ marginLeft: 'auto' }}> + + + + + ))} + + + ) } \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteFileLog.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteFileLog.tsx new file mode 100644 index 00000000..a4e48c1b --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteFileLog.tsx @@ -0,0 +1,144 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Autocomplete, Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; +import { TextField } from "@mui/material"; + + +type DialogDeleteType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + id: number|undefined; + path: string; +} + +export default function DialogDeleteFileLog({id, path, setOpenDialog, openDialog,onSubmit} : DialogDeleteType ) { + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom2 = { + marginBottom: 2, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + resetForm(); + } + + const [isReasonSelected, setIsReasonSelected] = useState(false); + + const reasons = [ + { value: 'agreement', label: 'Agreement changed' }, + { value: 'endorsement', label: 'Endorsement' }, + { value: 'renewal', label: 'Renewal' }, + { value: 'wrong_setting', label: 'Wrong Setting' }, + // Add more options as needed + ]; + const [formData, setFormData] = useState({ + path: path, + reason: null + }); + + const resetForm = () => { + setFormData({ + reason: null, + path: path + }); + }; + + useEffect(() => { + // Update formData setiap kali approve berubah + setFormData(prevData => ({ + ...prevData, + path: path || '', + })); + }, [path]); + + const handleChange = (field, value) => { + setFormData((prevData) => ({ + ...prevData, + [field]: value, + })); + if (field === 'reason') { + setIsReasonSelected(!!value); + } + + }; + + const handleSubmit = () => { + if (isReasonSelected && formData.reason !== '') { + console.log(formData) + axios + .post(`customer-service/request/${id}/delete_file`, formData) + .then((response) => { + enqueueSnackbar('File LOG has Deleted', { variant: 'success' }); + setOpenDialog(false); + window.location.reload() + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } else { + setIsReasonSelected(false); + alert('Silakan pilih alasan sebelum menghapus data.'); + } + + } + + + const getContent = () => ( + + Are you sure to delete this file Final LOG ? + + + + Reason* + option.label} + fullWidth + value={reasons.find((r) => r.value === formData.reason) || null} // Use find to match the default value + onChange={(e, newValue) => handleChange('reason', newValue?.value)} + renderInput={(params) => ( + + )} + /> + + + + + + + + + ); + + + return ( + + ); +} diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogUploadFileFinalLog.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogUploadFileFinalLog.tsx new file mode 100644 index 00000000..af4d1728 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogUploadFileFinalLog.tsx @@ -0,0 +1,322 @@ +import { styled } from '@mui/material/styles'; +import Iconify from '@/components/Iconify'; +import { fCurrency } from '@/utils/formatNumber'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Button, Divider, LinearProgress, linearProgressClasses, ButtonBase, Box } from '@mui/material'; +import { Card } from '@mui/material'; +import { Stack, Typography } from '@mui/material'; +import { fPostFormat } from '@/utils/formatTime'; +import axios from '@/utils/axios'; +import { enqueueSnackbar } from 'notistack'; +import { useRef, useState, useContext, useEffect } from 'react'; +import { makeFormData } from '@/utils/jsonToFormData'; +import { format } from 'date-fns'; +// import { LanguageContext } from '@/contexts/LanguageContext'; +import { DatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers'; +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; +import TextField from '@mui/material/TextField'; +import MuiDialog from '@/components/MuiDialog'; + +type DialogUploadType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + id: number|undefined; +} +export default function DialogUploadFileFinalLog({ id, openDialog, setOpenDialog }: DialogUploadType) { + // ---------------------------------------------------------------------- + // Files Diagnosa + + const fileDiagnosaInput = useRef(null); + const [fileDiagnosas, setFileDiagnosas] = useState([]); + + const handleDiagnosaInputChange = (event:any) => { + if (event.target.files[0]) { + setFileDiagnosas([...fileDiagnosas, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeDiagnosaFiles = (filesState:any, index:any) => { + setFileDiagnosas( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // ---------------------------------------------------------------------- + // Files Result Kondisi + + const fileKondisiInput = useRef(null); + const [fileKondisis, setFileKondisis] = useState([]); + + const handleKondisiInputChange = (event:any) => { + if (event.target.files[0]) { + setFileKondisis([...fileKondisis, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeKondisiFiles = (filesState:any, index:any) => { + setFileKondisis( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // ---------------------------------------------------------------------- + // Files Result Hasil Penunjang + + const fileHasilPenunjangInput = useRef(null); + const [fileHasilPenunjangs, setFileHasilPenunjangs] = useState([]); + + const handleResultInputChange = (event:any) => { + if (event.target.files[0]) { + setFileHasilPenunjangs([...fileHasilPenunjangs, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeFiles = (filesState:any, index:any) => { + setFileHasilPenunjangs( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // -------------------------------------------------------------- + // Submit Form + const [submitLoading, setSubmitLoading] = useState(false); + function submitRequestFinalLog() { + setSubmitLoading(true); + const formData = makeFormData({ + request_logs_id: id, + result_files: fileHasilPenunjangs, + diagnosa_files: fileDiagnosas, + kondisi_files: fileKondisis, + }); + axios + .post(`/customer-service/request/${id}/add_file`, formData) + .then((response) => { + enqueueSnackbar('Berhasil membuat data', { variant: 'success' }); + setOpenDialog(false); + window.location.reload() + }) + .catch(({ response }) => { + enqueueSnackbar('Something Went Wrong', { variant: 'error' }); + }) + .then(() => { + setSubmitLoading(false); + }); + } + + const getContent = () => ( + + } + spacing={4} + sx={{ marginY: 2, marginBottom: 6 }} + > + {/* -------------------------------Upload Dokumen Kondisi------------------------------- */} + + + File Kondisi + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileKondisis && + fileKondisis.map((file:any, index:any) => ( + + {file.name} + { + removeKondisiFiles(fileKondisis, index); + }} + > + + ))} + + fileKondisiInput.current?.click()}> + + + + Upload + + + + + + + {/* -------------------------------Upload Dokumen Diagnosa------------------------------- */} + + + File Diagnosa + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileDiagnosas && + fileDiagnosas.map((file:any, index:any) => ( + + {file.name} + { + removeDiagnosaFiles(fileDiagnosas, index); + }} + > + + ))} + {/* + Nama File .pdf + + */} + + {/* { JSON.stringify(filesResult) } */} + fileDiagnosaInput.current?.click()}> + + + + Upload + + + + + + + {/* -------------------------------Upload Dokumen Hasil Penunjang------------------------------- */} + + + File Hasil Penunjang + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileHasilPenunjangs && + fileHasilPenunjangs.map((file:any, index:any) => ( + + {file.name} + { + removeFiles(fileHasilPenunjangs, index); + }} + > + + ))} + {/* + Nama File .pdf + + */} + + {/* { JSON.stringify(filesResult) } */} + fileHasilPenunjangInput.current?.click()}> + + + + Upload + + + + + + + { + submitRequestFinalLog(); + }} + loading={submitLoading} + > + Upload File + + + ) + return ( + + ); +} diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx index 48044d83..1231aa24 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx @@ -55,6 +55,8 @@ import palette from '@/theme/palette'; import CardMedicine from '../Components/CardMedicine'; import CardFile from '../Components/CardFile'; import DialogEditFinalLOG from './Components/DialogEditFinalLOG'; +import DialogDeleteFileLog from './Components/DialogDeleteFileLog'; +import DialogUploadFileFinalLog from './Components/DialogUploadFileFinalLog'; // ---------------------------------------------------------------------- @@ -131,6 +133,12 @@ export default function Detail() { 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 ( @@ -260,27 +268,6 @@ export default function Detail() { */} - {/* Hospital Care */} - {/* - - - History of Hospital Care - - - - - - */} - {/* Benefit */} @@ -595,9 +582,54 @@ export default function Detail() { {/* File */} - + + + + Files + + + + + + {requestLog?.files?.map((documentType, index) => ( + + + + {documentType.original_name ? documentType.original_name : '-'} + + + + { + setDialogDeleteFileLog(true) + setPathFile(documentType.path) + }} aria-label="delete" size="small" sx={{ marginLeft: 'auto' }}> + + + + + ))} + + + + + {requestLog?.status_final_log == 'requested' ? (