diff --git a/Modules/Internal/Http/Controllers/Api/DrugController.php b/Modules/Internal/Http/Controllers/Api/DrugController.php index 2a25a575..97c7bd63 100644 --- a/Modules/Internal/Http/Controllers/Api/DrugController.php +++ b/Modules/Internal/Http/Controllers/Api/DrugController.php @@ -145,7 +145,7 @@ class DrugController extends Controller } $response = [ - 'message' => 'File uploaded and data saved to database!', + 'message' => 'File uploaded and data saved to database', 'data' => [ 'total_success_row' => $importedRows, 'total_failed_row' => count($failedRows), diff --git a/Modules/Internal/Http/Controllers/Api/HospitalController.php b/Modules/Internal/Http/Controllers/Api/HospitalController.php index 63a716f7..9d2be239 100644 --- a/Modules/Internal/Http/Controllers/Api/HospitalController.php +++ b/Modules/Internal/Http/Controllers/Api/HospitalController.php @@ -8,6 +8,8 @@ use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Illuminate\Validation\Rule; use Illuminate\Support\Facades\DB; +use App\Helpers\Helper; +use Maatwebsite\Excel\Facades\Excel; class HospitalController extends Controller { @@ -150,4 +152,93 @@ class HospitalController extends Controller { // } + public function downloadTemplate() + { + return Helper::responseJson([ + 'file_name' => "Template - Hospitals.xlsx", + "file_url" => url('files/Template - Hospitals.xlsx') + ]); + } + + public function import(Request $request, $corporate_id) + { + if ($request->hasFile('file')) { + $file = $request->file('file'); + $data = Excel::toArray([], $file); + + $processedData = $this->processCategoryNames($data); + + $importedRows = 0; + $failedRows = []; + + foreach ($processedData as $row) { + $q = DB::table('organizations') + ->where('code', '=', $row['code']) + ->where('type', '=', 'hospital') + ->where('status', '=', 'active') + ->select('id', 'code', 'name') + ->limit(1) + ->first(); + try { + CorporateHospital::create( + [ + 'corporate_id' => $corporate_id, + 'code' => $q->code, + 'name' => $q->name, + 'organization_id' => $q->id, + 'description' => $request->description ? $request->description : null, + ] + ); + $importedRows++; + } catch (\Exception $e) { + $failedRows[] = $row; + } + } + + $response = [ + 'message' => 'File uploaded and data saved to database', + 'data' => [ + 'total_success_row' => $importedRows, + 'total_failed_row' => count($failedRows), + 'failed_rows' => $failedRows, + ], + ]; + + return response()->json($response); + } + + return response()->json(['error' => 'No file uploaded.']); + } + + private function processCategoryNames($data) + { + $header = []; + $row = []; + for ($i = 1; $i < count($data[0]); $i++) { + $row[] = $data[0][$i]; + $header[] = $data[0][0]; + } + + $filed = []; + foreach ($header[0] as $value) + { + $modelColumn = strtolower(preg_replace('/\s+/', '_', trim($value))); + $modelColumn = str_replace(['*', ' '], '', $modelColumn); + if($modelColumn) + { + $filed[] = $modelColumn; + } + } + + $result = []; + foreach ($row as $subarray) { + $trimmedSubarray = []; + for ($i = 0; $i < count($filed); $i++) { + $trimmedSubarray[$filed[$i]] = $subarray[$i] ? $subarray[$i] : null; + } + + $result[] = $trimmedSubarray; + } + return $result; + } } diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 00b9477a..dfc68def 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -109,6 +109,8 @@ Route::prefix('internal')->group(function () { Route::get('corporates/{corporate_id}/hospitals/data', [HospitalController::class, 'dataHospital']); Route::post('corporates/{corporate_id}/hospitals/save', [HospitalController::class, 'store']); Route::put('corporates/{corporate_id}/hospitals/{id}/edit', [HospitalController::class, 'update']); + Route::get('corporates/hospitals/download-template', [HospitalController::class, 'downloadTemplate']); + Route::post('corporates/{corporate_id}/hospitals/import', [HospitalController::class, 'import']); Route::get('corporates/{corporate_id}/members', [CorporateMemberController::class, 'index']); diff --git a/frontend/dashboard/src/pages/Corporates/Hospital/List.tsx b/frontend/dashboard/src/pages/Corporates/Hospital/List.tsx index 4f6b1ffb..081c2c4b 100644 --- a/frontend/dashboard/src/pages/Corporates/Hospital/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/Hospital/List.tsx @@ -20,6 +20,8 @@ import { InputLabel, Select, FormHelperText, + Menu, + ButtonGroup } from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; // hooks @@ -39,6 +41,10 @@ import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material import CloseIcon from '@mui/icons-material/Close'; import { enqueueSnackbar } from 'notistack'; import Label from '../../../components/Label'; +import DownloadIcon from '@mui/icons-material/Download'; +import { LoadingButton } from '@mui/lab'; +import CancelIcon from '@mui/icons-material/Cancel'; +import UploadIcon from '@mui/icons-material/Upload'; export default function HospitalList() { const { corporate_id } = useParams(); @@ -267,22 +273,182 @@ export default function HospitalList() { } // End dialog for update status devisions + const [anchorEl, setAnchorEl] = React.useState(null); + const createMenu = Boolean(anchorEl); + const importHospital = useRef(null); + const [currentImportFileName, setCurrentImportFileName] = useState(null); + const [importLoading, setImportLoading] = useState(false); + const [importResult, setImportResult] = useState(null); + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + const handleImportButton = () => { + if (importHospital?.current) { + handleClose(); + importHospital.current ? importHospital.current.click() : console.log('No File selected'); + } else { + alert('No file selected'); + } + }; + const handleCancelImportButton = () => { + if(importHospital.current) + { + importHospital.current.value = ''; + importHospital.current.dispatchEvent(new Event('change', { bubbles: true })); + } +}; + const handleImportChange = (event: any) => { + if (event.target.files[0]) { + setCurrentImportFileName(event.target.files[0].name); + } else { + setCurrentImportFileName(null); + } + }; + const handleUpload = () => { + if(importHospital.current && importHospital.current.files) + { + if (importHospital.current?.files.length) { + const formData = new FormData(); + formData.append('file', importHospital.current?.files[0]); + setImportLoading(true); + axios + .post('corporates/'+corporate_id+'/hospitals/import', formData) + .then((response) => { + handleCancelImportButton(); + loadDataTableData(); + setImportResult(response.data); + setImportLoading(false); + enqueueSnackbar('Success Import Hospitals', { variant: 'success' }); + }) + .catch((response) => { + enqueueSnackbar( + 'Looks like something went wrong. Please check your data and try again. ' + + response.message, + { variant: 'error' } + ); + setImportLoading(false); + }); + } else { + enqueueSnackbar('No File Selected', { variant: 'warning' }); + } + } +}; + const handleGetTemplate = () => { + axios.get('corporates/hospitals/download-template').then((response) => { + const link = document.createElement('a'); + link.href = response.data.data.file_url; + link.setAttribute('download', response.data.data.file_name); + document.body.appendChild(link); + link.click(); + handleClose(); + }); + + +}; + return ( - - - - + + {!currentImportFileName && ( + + + + + + Create + + + Import + + { + handleGetTemplate(); + }} + > + Download Template + + {/* + Download ICD + */} + + + )} + {currentImportFileName && ( + + + + + + + } + sx={{ p: 1.8 }} + onClick={handleUpload} + loading={importLoading} + > + Upload + + + )} + {importResult && ( + + + Last Import Result :{' '} + + {importResult.data.total_success_row ?? 0} + {' '} + Row Processed,{' '} + + {importResult.data.total_failed_row} + {' '} + Failed + {importResult.data.failed_rows.map((row, index) => ( + [Code={row.code ? row.code : 'Required'},Name={row.name ? row.name : 'Required'}] + ))} + + + )} {/* The Main Table */} diff --git a/frontend/dashboard/src/pages/Master/Drug/List.tsx b/frontend/dashboard/src/pages/Master/Drug/List.tsx index f3110b19..00afbecc 100644 --- a/frontend/dashboard/src/pages/Master/Drug/List.tsx +++ b/frontend/dashboard/src/pages/Master/Drug/List.tsx @@ -98,7 +98,7 @@ import { // Create Button Menu const [anchorEl, setAnchorEl] = React.useState(null); const createMenu = Boolean(anchorEl); - const importPlan = useRef(null); + const importDrug = useRef(null); const [currentImportFileName, setCurrentImportFileName] = useState(null); const [importLoading, setImportLoading] = useState(false); @@ -111,19 +111,19 @@ import { }; const handleImportButton = () => { - if (importPlan?.current) { + if (importDrug?.current) { handleClose(); - importPlan.current ? importPlan.current.click() : console.log('No File selected'); + importDrug.current ? importDrug.current.click() : console.log('No File selected'); } else { alert('No file selected'); } }; const handleCancelImportButton = () => { - if(importPlan.current) + if(importDrug.current) { - importPlan.current.value = ''; - importPlan.current.dispatchEvent(new Event('change', { bubbles: true })); + importDrug.current.value = ''; + importDrug.current.dispatchEvent(new Event('change', { bubbles: true })); } }; @@ -136,11 +136,11 @@ import { }; const handleUpload = () => { - if(importPlan.current && importPlan.current.files) + if(importDrug.current && importDrug.current.files) { - if (importPlan.current?.files.length) { + if (importDrug.current?.files.length) { const formData = new FormData(); - formData.append('file', importPlan.current?.files[0]); + formData.append('file', importDrug.current?.files[0]); setImportLoading(true); axios .post(`master/drugs/import`, formData) @@ -181,7 +181,7 @@ import {