diff --git a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php index bea90e0f..db329ea4 100644 --- a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php +++ b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php @@ -29,12 +29,12 @@ class DiagnosisController extends Controller * Display a listing of the resource. * @return Renderable */ - public function index(Request $request) + public function index(Request $request, $diagnosis_template_id) { $diagnosis = Icd::query() ->filter($request->toArray()) - // ->where('deleted_at', '=', NULL) + ->where('icd_template_id', '=', $diagnosis_template_id) ->orderBy('code', 'ASC') ->paginate(15); return $diagnosis; @@ -108,7 +108,7 @@ class DiagnosisController extends Controller })->limit(10)->get(); } - public function import(Request $request) + public function import(Request $request, $id) { $request->validate([ 'file' => 'required|file|mimes:xls,xlsx,csv,txt', @@ -143,14 +143,8 @@ class DiagnosisController extends Controller } else { // Next Row Should be Data $row_data = []; $row_map = [ - 0 => 'code', - 1 => 'parent_code', - 2 => 'reff_exc', - 3 => 'description_en', - 4 => 'description_id', - 5 => 'keywords', - 6 => 'version', - 7 => 'active', + 0 => 'ICD_Code', + 1 => 'Description', ]; foreach ($row->getCells() as $header_index => $cell) { @@ -166,21 +160,15 @@ class DiagnosisController extends Controller try { // Process the Row Data if ( - empty($row_data['code']) && - empty($row_data['parent_code']) && - empty($row_data['reff_exc']) && - empty($row_data['description_en']) && - empty($row_data['description_id']) && - empty($row_data['keywords']) && - empty($row_data['version']) && - empty($row_data['active']) + empty($row_data['ICD_Code']) && + empty($row_data['Description']) ) { continue; } // Save the Row $icdService = new IcdService(); - $icdService->handleIcdRow($row_data); + $icdService->handleIcdRow($row_data, $id); // Write Success Result to File $import->addArrayToRow(array_merge($row_data, [ @@ -242,15 +230,15 @@ class DiagnosisController extends Controller } } - public function generateIcdList(Request $request){ + public function generateIcdList(Request $request, $diagnosis_id){ // Mendapatkan data yang akan diekspor (misalnya, dari database) - $data = Icd::get()->toArray(); + $data = Icd::where('icd_template_id', $diagnosis_id)->get()->toArray(); // Membuat penulis entitas Spout $writer = WriterEntityFactory::createXLSXWriter(); // Membuka penulis untuk menulis ke file - $writer->openToFile(public_path('files/CorporateMembershipList.xlsx')); + $writer->openToFile(public_path('files/TemplateICDList.xlsx')); /** Create a style with the StyleBuilder */ $style = (new StyleBuilder()) ->setFontBold() @@ -266,14 +254,14 @@ class DiagnosisController extends Controller if (!empty($data)) { foreach ($data as $item) { $rowData = [ - $item['rev'], // Rev - $item['version'], // Version + // $item['rev'], // Rev + // $item['version'], // Version $item['code'], // Code - $item['parent_code'], // Parent Code + // $item['parent_code'], // Parent Code $item['name'], // Name - $item['description'], // Description - $item['active'] == 1 ? 'Active' : 'Inactive', // Status - $item['type'], // Type + // $item['description'], // Description + // $item['active'] == 1 ? 'Active' : 'Inactive', // Status + // $item['type'], // Type ]; $row = WriterEntityFactory::createRowFromArray($rowData); @@ -285,11 +273,11 @@ class DiagnosisController extends Controller $writer->close(); // Mengembalikan response untuk mengunduh file - $filePath = public_path('files/CorporateMembershipList.xlsx'); + $filePath = public_path('files/TemplateICDList.xlsx'); return Helper::responseJson([ 'file_name' => "Diagnosis ICD List " . date('Y-m-d h:i:s'), - "file_url" => url('files/CorporateMembershipList.xlsx') + "file_url" => url('files/TemplateICDList.xlsx') ]); } diff --git a/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php b/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php new file mode 100644 index 00000000..01bb72a9 --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/DiagnosisTemplateController.php @@ -0,0 +1,314 @@ +search){ + return IcdTemplate::when($request->search ?? null, function($icd, $search) { + $icd->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('code', 'LIKE', '%'.$search.'%'); + })->paginate(15); + } else { + $diagnosisTemplate = IcdTemplate::query() + // ->filter($request->toArray()) + ->orderBy('code', 'ASC') + ->paginate(15); + return $diagnosisTemplate; + } + + } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function create() + { + return view('internal::create'); + } + + /** + * Store a newly created resource in storage. + * @param Request $request + * @return Renderable + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required' + ]); + + $newDiagnosisTemplate = IcdTemplate::create($request->all()); + + return $newDiagnosisTemplate; + } + + /** + * Show the specified resource. + * @param int $id + * @return Renderable + */ + public function show($id) + { + return view('internal::show'); + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + $IcdTemplate = IcdTemplate::findOrFail($id); + + return $IcdTemplate; + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + $IcdTemplate = IcdTemplate::findOrFail($id); + $request->validate([ + 'name' => 'required' + ]); + $IcdTemplate->fill([ + // 'code' => $request->code, + 'name' => $request->name, + 'description' => $request->description, + 'active' => $request->active, + ])->save(); + + return $IcdTemplate; + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + // + } + + public function search(Request $request) + { + return IcdTemplate::when($request->search ?? null, function($icd, $search) { + $icd->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('code', 'LIKE', '%'.$search.'%'); + })->limit(10)->get(); + } + + public function import(Request $request) + { + $request->validate([ + 'file' => 'required|file|mimes:xls,xlsx,csv,txt', + ]); + $file_name = now()->getPreciseTimestamp(3).'-'.$request->file('file')->getClientOriginalName(); + $file = $request->file('file')->storeAs('temp', $file_name); + + $import = new ImportService(); + $import->read(Storage::path('temp/'.$file_name)); + $import->write(Storage::disk('public')->path('temp/result-'.$file_name), 'xsls'); + + $imported_icd_data = 0; + $failed_icd_data = []; + foreach ($import->sheetsIterator() as $sheetIndex => $sheet) { + $doc_headers_indexes = []; + foreach ($sheet->getRowIterator() as $index => $row) { + if ($index == 1) { // First Row Must be Header + foreach ($row->getCells() as $index => $cell) { + $title = $cell->getValue(); + $title = preg_replace( "/\r|\n/", " ", $title ); + $title = preg_replace('/\xc2\xa0/', " ", $title ); + $title = rtrim($title); + $title = ltrim($title); + $doc_headers_indexes[$index] = $title; + } + + // Write Header to File + $result_headers = array_merge($doc_headers_indexes, ['Ingest Code', 'Ingest Note']); + $import->addArrayToRow($result_headers); + + // TODO Validate if First Row not Header + } else { // Next Row Should be Data + $row_data = []; + $row_map = [ + 0 => 'code', + 1 => 'parent_code', + 2 => 'reff_exc', + 3 => 'description_en', + 4 => 'description_id', + 5 => 'keywords', + 6 => 'version', + 7 => 'active', + ]; + + foreach ($row->getCells() as $header_index => $cell) { + if (isset($row_map[$header_index])) { + $value = $cell->getValue(); + $value = preg_replace( "/\r|\n/", " ", $value ); + $value = preg_replace('/\xc2\xa0/', " ", $value ); + $value = rtrim($value); + $value = ltrim($value); + $row_data[$row_map[$header_index]] = $cell->getValue(); + } + } + + try { // Process the Row Data + if ( + empty($row_data['code']) && + empty($row_data['parent_code']) && + empty($row_data['reff_exc']) && + empty($row_data['description_en']) && + empty($row_data['description_id']) && + empty($row_data['keywords']) && + empty($row_data['version']) && + empty($row_data['active']) + ) { + continue; + } + + // Save the Row + $icdService = new IcdService(); + $icdService->handleIcdRow($row_data); + + // Write Success Result to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 200, + 'Ingest Note' => 'Success', + ]), $sheet->getName()); + $imported_icd_data++; + + } catch (ImportRowException $e) { + // Write Data Validation Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => $e->getCode(), + 'Ingest Note' => $e->getMessage(), + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } catch (\Exception $e) { + throw new \Exception($e); + // Write Server Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 500, + 'Ingest Note' => env('APP_DEBUG') ? $e->getMessage() : 'Server Error', + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } + } + } + + break; // Only Read First Row + } + $import->reader->close(); + Storage::delete('temp/'.$file_name); + $import->writer->close(); + + return [ + 'total_successed_row' => $imported_icd_data, + 'total_failed_row' => count($failed_icd_data), + 'failed_row' => $failed_icd_data, + 'result_file' => [ + 'url' => Storage::disk('public')->url('temp/result-'.$file_name), + 'name' => 'result-'.$file_name, + ] + ]; + } + + public function activation(Request $request, $id) + { + $request->validate([ + 'active' => 'required' + ]); + $Icd = IcdTemplate::findOrFail($id); + $Icd->active = $request->active == '1'; + + if ($Icd->save()) { + return response()->json([ + 'icd' => $Icd, + 'message' => 'Status Updated Successfully' + ]); + } + } + + public function generateIcdList(Request $request){ + // Mendapatkan data yang akan diekspor (misalnya, dari database) + $data = Icd::get()->toArray(); + + // Membuat penulis entitas Spout + $writer = WriterEntityFactory::createXLSXWriter(); + + // Membuka penulis untuk menulis ke file + $writer->openToFile(public_path('files/CorporateMembershipList.xlsx')); + /** Create a style with the StyleBuilder */ + $style = (new StyleBuilder()) + ->setFontBold() + ->build(); + + // Menulis header kolom + $headers_map_to_table_fields = $this->icdService->listing_doc_headers; + $headerRow = WriterEntityFactory::createRowFromArray($headers_map_to_table_fields, $style); + + $writer->addRow($headerRow); + + // Menulis data + if (!empty($data)) { + foreach ($data as $item) { + $rowData = [ + $item['rev'], // Rev + $item['version'], // Version + $item['code'], // Code + $item['parent_code'], // Parent Code + $item['name'], // Name + $item['description'], // Description + $item['active'] == 1 ? 'Active' : 'Inactive', // Status + $item['type'], // Type + ]; + + $row = WriterEntityFactory::createRowFromArray($rowData); + $writer->addRow($row); + } + } + + // Menutup penulis + $writer->close(); + + // Mengembalikan response untuk mengunduh file + $filePath = public_path('files/CorporateMembershipList.xlsx'); + + return Helper::responseJson([ + 'file_name' => "Diagnosis ICD List " . date('Y-m-d h:i:s'), + "file_url" => url('files/CorporateMembershipList.xlsx') + ]); + + } +} diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 435e09ff..9315ddbc 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -15,6 +15,7 @@ use Modules\Internal\Http\Controllers\Api\CorporateMemberController; use Modules\Internal\Http\Controllers\Api\CorporatePlanController; use Modules\Internal\Http\Controllers\Api\CorporateServiceController; use Modules\Internal\Http\Controllers\Api\DiagnosisController; +use Modules\Internal\Http\Controllers\Api\DiagnosisTemplateController; use Modules\Internal\Http\Controllers\Api\DiagnosisExclusionController; use Modules\Internal\Http\Controllers\Api\DistrictController; use Modules\Internal\Http\Controllers\Api\DivisionController; @@ -127,12 +128,22 @@ Route::prefix('internal')->group(function () { // Audittrail Route::get('audittrail/{corporate_id}', [AuditTrailController::class, 'index']); + + Route::get('master/diagnosis-template', [DiagnosisTemplateController::class, 'index']); + Route::get('master/diagnosis-template/search', [DiagnosisTemplateController::class, 'search']); + Route::post('master/diagnosis-template/store', [DiagnosisTemplateController::class, 'store']); + Route::put('master/diagnosis-template/{id}/activation', [DiagnosisTemplateController::class, 'activation']); + Route::get('master/diagnosis-template/{id}/edit', [DiagnosisTemplateController::class, 'edit']); + Route::put('master/diagnosis-template/{id}/update', [DiagnosisTemplateController::class, 'update']); - Route::get('master/diagnosis', [DiagnosisController::class, 'index']); - Route::get('master/diagnosis/search', [DiagnosisController::class, 'search']); - Route::post('master/diagnosis/import', [DiagnosisController::class, 'import']); - Route::get('master/diagnosis/list', [DiagnosisController::class, 'generateIcdList']); - Route::put('master/diagnosis/{id}/activation', [DiagnosisController::class, 'activation']); + Route::get('master/diagnosis/{diagnosis_template_id}', [DiagnosisController::class, 'index']); + Route::get('master/diagnosis/{diagnosis_template_id}/search', [DiagnosisController::class, 'search']); + Route::post('master/diagnosis/{diagnosis_template_id}/import', [DiagnosisController::class, 'import']); + Route::get('master/diagnosis/{diagnosis_template_id}/list', [DiagnosisController::class, 'generateIcdList']); + Route::put('master/diagnosis/{diagnosis_template_id}/activation', [DiagnosisController::class, 'activation']); + + + Route::get('master/drugs', [DrugController::class, 'index']); Route::get('master/formulariums', [FormulariumController::class, 'index']); Route::post('master/formulariums', [FormulariumController::class, 'store']); diff --git a/Modules/Internal/Services/IcdService.php b/Modules/Internal/Services/IcdService.php index c3a22c20..ce668a4b 100644 --- a/Modules/Internal/Services/IcdService.php +++ b/Modules/Internal/Services/IcdService.php @@ -13,27 +13,25 @@ class IcdService { protected function validateDiagnosisExclusionRow($row) { - if (empty($row['code'])) { - throw new ImportRowException(__('code.REQUIRED'), 0, null, $row); - } - if (empty($row['description_en'])) { - throw new ImportRowException(__('name.REQUIRED'), 0, null, $row); + if (empty($row['ICD_Code'])) { + throw new ImportRowException(__('ICD_Code is REQUIRED'), 0, null, $row); } } - public function handleIcdRow($row) + public function handleIcdRow($row, $id) { try { $this->validateDiagnosisExclusionRow($row); $icd = Icd::updateOrCreate([ - 'code' => $row['code'] + 'code' => $row['ICD_Code'] ], [ - "code" => $row['code'], - "parent_code" => $row['parent_code'] ?? null, - "rev" => $row['reff_exc'], - "name" => $row['description_en'], - "version" => $row["version"] ?? null, - "active" => $row["active"] ?? 0 + "code" => $row['ICD_Code'], + "parent_code" => null, + "rev" => '', + "name" => $row['Description'] ?? null, + "version" => null, + "active" => 1, + "icd_template_id" => $id, ]); return true; @@ -43,13 +41,13 @@ class IcdService } public $listing_doc_headers = [ - "Rev", - "Version", + // "Rev", + // "Version", "Code", - "Parent Code", - "Name", + // "Parent Code", + // "Name", "Description", - "Status", - "Type" + // "Status", + // "Type" ]; } diff --git a/app/Models/Icd.php b/app/Models/Icd.php index 69497c4a..981c5a57 100644 --- a/app/Models/Icd.php +++ b/app/Models/Icd.php @@ -21,7 +21,8 @@ class Icd extends Model 'name', 'description', 'parent_code', - 'active' + 'active', + 'icd_template_id' ]; public $appends = [ diff --git a/app/Models/IcdTemplate.php b/app/Models/IcdTemplate.php new file mode 100644 index 00000000..e58c03dc --- /dev/null +++ b/app/Models/IcdTemplate.php @@ -0,0 +1,32 @@ +logAuditTrail($model, 'deleted'); }); + // ICD or exlusion + IcdTemplate::updated(function ($model) { + $this->logAuditTrail($model, 'updated'); + }); + + IcdTemplate::deleted(function ($model) { + $this->logAuditTrail($model, 'deleted'); + }); + } diff --git a/database/migrations/2023_09_19_164907_create_icd_template.php b/database/migrations/2023_09_19_164907_create_icd_template.php new file mode 100644 index 00000000..9174bc8d --- /dev/null +++ b/database/migrations/2023_09_19_164907_create_icd_template.php @@ -0,0 +1,34 @@ +id(); + $table->string('name'); + $table->string('code'); + $table->string('description'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('icd_template'); + } +}; diff --git a/database/migrations/2023_09_20_090317_add_active_to_icd_template.php b/database/migrations/2023_09_20_090317_add_active_to_icd_template.php new file mode 100644 index 00000000..977af55f --- /dev/null +++ b/database/migrations/2023_09_20_090317_add_active_to_icd_template.php @@ -0,0 +1,32 @@ +integer('active'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('icd_template', function (Blueprint $table) { + $table->dropColumn('active'); + }); + } +}; diff --git a/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php b/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php new file mode 100644 index 00000000..603b9104 --- /dev/null +++ b/database/migrations/2023_09_20_152738_add_icd_template_id_to_icd.php @@ -0,0 +1,32 @@ +integer('icd_template_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('icd', function (Blueprint $table) { + $table->dropColumn('icd_template_id'); + }); + } +}; diff --git a/frontend/dashboard/src/@types/corporates.ts b/frontend/dashboard/src/@types/corporates.ts index 45ad95ca..5484f2ce 100644 --- a/frontend/dashboard/src/@types/corporates.ts +++ b/frontend/dashboard/src/@types/corporates.ts @@ -182,3 +182,10 @@ export type CorporateService = { status: string; configurations: any; } + +export type MasterExclusion = { + id?: string | number; + name?: string; + code: string; + description?: string; +} diff --git a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx index f99b2ef4..2629d771 100644 --- a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx @@ -54,7 +54,7 @@ const navConfig = [ // { title: 'Corporate Create', path: '/corporates/create' }, { title: 'Formularium', path: '/master/formularium' }, { title: 'Obat', path: '/master/drugs' }, - { title: 'Diagnosis Library (ICD-X)', path: '/master/diagnosis' }, + { title: 'Master ICD-10 Diagnosis', path: '/master/diagnosis-template' }, { title: 'Hospitals', path: '/hospitals' }, ], }, diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx index 1e6b7361..8b9d8bc1 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx @@ -157,7 +157,12 @@ export default function CustomizedAccordions() { key === 'created_by' || key === 'created_at' || key === 'updated_by' || - key === 'description' + key === 'description'|| + key === 'version'|| + key === 'rev'|| + key === 'active'|| + key === 'parent_code'|| + key === 'id' ) { return null; // Melewati iterasi saat key adalah 'deleted_by' } @@ -196,14 +201,15 @@ export default function CustomizedAccordions() { } const field = key.charAt(0).toUpperCase() + key.slice(1); - - return ( - - {`${field}`} - {`${value}`} - {renderedValue} - - ); + // if (value != renderedValue) { + return ( + + {`${field}`} + {`${value}`} + {renderedValue} + + ); + // } })} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx index 7f4f7381..495f9880 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx @@ -21,11 +21,15 @@ export default function Divisions() { links={[ { name: 'Master', - href: '/master/diagnosis', + href: '/master/diagnosis-template', + }, + { + name: 'Diagnosis Template', + href: '/master/diagnosis-template', }, { name: 'Diagnosis', - href: '/master/diagnosis', + href: '/master/diagnosis-template', }, ]} /> diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx index 6719e31f..ee729f7f 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx @@ -20,7 +20,7 @@ import { enqueueSnackbar } from 'notistack'; export default function List() { const { themeStretch } = useSettings(); - const { corporate_id } = useParams(); + const { diagnosis_template_id } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); @@ -76,7 +76,7 @@ export default function List() { } const handleICDList = async (appliedFilter = null) => { - axios.get('master/diagnosis/list').then((response) => { + axios.get('master/diagnosis/'+ diagnosis_template_id +'/list').then((response) => { const link = document.createElement('a'); link.href = response.data.data.file_url; link.setAttribute('download', response.data.data.file_name); @@ -108,7 +108,7 @@ export default function List() { if (importForm.current?.files.length) { const formData = new FormData(); formData.append("file", importForm.current?.files[0]) - axios.post(`master/diagnosis/import`, formData ) + axios.post(`master/diagnosis/` + diagnosis_template_id + `/import`, formData ) .then(response => { handleCancelImportButton(); loadDataTableData(); @@ -241,48 +241,8 @@ export default function List() { return ( *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - - - {row.type} {row.code} {row.name} - {row.version} - - - {/* */} - - {row.active == 1 && ( - - )} - {row.active != 1 && ( - - )} - {/* */} @@ -290,18 +250,6 @@ export default function List() { - {/* COLLAPSIBLE ROW */} - - - - - - Description : {row.description} - - - - - ); } @@ -329,8 +277,7 @@ export default function List() { const loadDataTableData = async (appliedFilter : any | null = null) => { setDataTableLoading(true); const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); - const response = await axios.get('/master/diagnosis', { params: filter }); - console.log(response.data); + const response = await axios.get('/master/diagnosis/'+diagnosis_template_id, { params: filter }); setDataTableLoading(false); setDataTableData(response.data); @@ -365,12 +312,8 @@ export default function List() { - - Type Code - Name - Version - Status + Description Action diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx index 7e5d53b2..d84e7f80 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx @@ -32,7 +32,7 @@ export default function PlanCreate() { useEffect(() => { if (isEdit) { - axios.get('/corporates/'+corporate_id+'/divisions/'+id+'/edit') + axios.get('/master/diagnosis-template/'+id+'/edit') .then((res) => { setCurrentCorporatePlan(res.data); }) @@ -46,21 +46,17 @@ export default function PlanCreate() { return ( - + ({ name: currentCorporatePlan?.name || '', - code: currentCorporatePlan?.code || '', + description: currentCorporatePlan?.description || '', active: currentCorporatePlan?.active === 1 ? true : false, }), [currentCorporatePlan] @@ -64,12 +63,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop const onSubmit = async (data: any) => { if (!isEdit) { await axios - .post('/corporates/' + corporate_id + '/divisions', data) + .post('/master/diagnosis-template/store', data) .then((res) => { enqueueSnackbar('Division created successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/divisions', { replace: true }); + navigate('/master/diagnosis-template', { replace: true }); }) .catch(({ response }) => { if (response.status === 422) { @@ -84,12 +83,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop }); } else { await axios - .put('/corporates/' + corporate_id + '/divisions/' + currentCorporatePlan?.id , data) + .put('/master/diagnosis-template/' + currentCorporatePlan?.id + '/update', data) .then((res) => { enqueueSnackbar('Division updated successfully', { variant: 'success' }); }) .then((res) => { - navigate('/corporate/' + corporate_id + '/divisions/' , { replace: true }); + navigate('/master/diagnosis-template' , { replace: true }); }) .catch(({ response }) => { enqueueSnackbar('Update Failed : '+ response.data.message, { variant: 'error' }); @@ -106,9 +105,9 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop Division Detail - - + + { isEdit? 'Update' : 'Create' } @@ -117,12 +116,12 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop - + {/* - + */} ); diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx new file mode 100644 index 00000000..c72d8f80 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/History.tsx @@ -0,0 +1,218 @@ +// @mui +import { + Box, + Button, + Card, + Collapse, + Container, + FormControl, + Grid, + IconButton, + InputLabel, + MenuItem, + OutlinedInput, + Paper, + Select, + SelectChangeEvent, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Typography, + Badge, + Stack, +} from '@mui/material'; +import * as React from 'react'; +import { useParams } from 'react-router-dom'; +import { styled } from '@mui/material/styles'; +import ArrowForwardIosSharpIcon from '@mui/icons-material/ArrowForwardIosSharp'; +import MuiAccordion, { AccordionProps } from '@mui/material/Accordion'; +import { useContext, useEffect, useState } from 'react'; +import MuiAccordionSummary, { + AccordionSummaryProps, +} from '@mui/material/AccordionSummary'; +import useSettings from '../../../../hooks/useSettings'; +import axios from '../../../../utils/axios'; +import { ConfiguredCorporateContext } from '@/contexts/ConfiguredCorporateContext'; +import MuiAccordionDetails from '@mui/material/AccordionDetails'; +import HeaderBreadcrumbs from '../../../../components/HeaderBreadcrumbs'; +import { Corporate } from '@/@types/corporates'; +import { fDate, fDateTime } from '@/utils/formatTime'; + +const Accordion = styled((props: AccordionProps) => ( + +))(({ theme }) => ({ + border: `1px solid ${theme.palette.divider}`, + '&:not(:last-child)': { + borderBottom: 0, + }, + '&:before': { + display: 'none', + }, +})); + +const AccordionSummary = styled((props: AccordionSummaryProps) => ( + } + {...props} + /> +))(({ theme }) => ({ + backgroundColor: + theme.palette.mode === 'dark' + ? 'rgba(255, 255, 255, .05)' + : 'rgba(0, 0, 0, .03)', + flexDirection: 'row-reverse', + '& .MuiAccordionSummary-expandIconWrapper.Mui-expanded': { + transform: 'rotate(90deg)', + }, + '& .MuiAccordionSummary-content': { + marginLeft: theme.spacing(1), + }, +})); + +const AccordionDetails = styled(MuiAccordionDetails)(({ theme }) => ({ + padding: theme.spacing(2), + borderTop: '1px solid rgba(0, 0, 0, .125)', +})); + +export default function CustomizedAccordions() { + const [expanded, setExpanded] = React.useState('panel1'); + + const handleChange = + (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => { + setExpanded(newExpanded ? panel : false); + }; + const pageTitle = 'Diagnosis Template Audittrail'; + + const { themeStretch } = useSettings(); + + const { id } = useParams(); + + const [corporate, setCorporate] = useState(); + const [ currentCorporate, setCurrentCorporate ] = useState(); + + const configuredCorporateContext = useContext(ConfiguredCorporateContext); + + useEffect(() => { + setCorporate(configuredCorporateContext.currentCorporate); + const model = 'App\\Models\\IcdTemplate'; + const url = `/audittrail/${id}?model=${model}`; + axios.get(url) + .then((res) => { + setCurrentCorporate(res.data); + }) + .catch((error) => { + console.error('Terjadi kesalahan:', error); + }); + + }, [configuredCorporateContext]); + + return ( +
+ + {currentCorporate?.data.map((item, index) => ( + + + {`Data has ${item.action} by ${item.user_id} on ${fDateTime(item.updated_at)}`} + + + + + Field + Old Value + New Values + + + + {Object.entries(item.old_values).map(([key, value]) => { + let renderedValue; + if (key === 'deleted_by' || + key === 'deleted_at' || + key === 'created_by' || + key === 'created_at' || + key === 'updated_by' || + key === 'description' + ) { + return null; // Melewati iterasi saat key adalah 'deleted_by' + } + switch (key) { + case 'welcome_message': + renderedValue = item.new_values[key].replace(/<[^>]*>/g, ''); + value = value.replace(/<[^>]*>/g, ''); + break; + case 'help_text': + renderedValue = item.new_values[key].replace(/<[^>]*>/g, ''); + value = value.replace(/<[^>]*>/g, ''); + break; + case 'active': + renderedValue = item.new_values[key] == 1 ? 'Active' : 'Inactive'; + value = value == 1 ? 'Active' : 'Inactive'; + break; + case 'created_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'updated_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'updated_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + case 'delete_at': + renderedValue = fDateTime(item.new_values[key]); + value = fDateTime(value); + break; + default: + renderedValue = item.new_values[key]; + break; + } + + const field = key.charAt(0).toUpperCase() + key.slice(1); + if (value == renderedValue) { + return null + } else { + return ( + + {`${field}`} + {`${value}`} + {renderedValue} + + ); + } + })} + + + + + ))} +
+ ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx index ab1cecb2..0afc6518 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx @@ -12,7 +12,7 @@ export default function Divisions() { const { corporate_id } = useParams(); - const pageTitle = 'Diagnosis'; + const pageTitle = 'Diagnosis Template'; return ( @@ -21,11 +21,11 @@ export default function Divisions() { links={[ { name: 'Master', - href: '/master/diagnosis', + href: '/master/diagnosis-template', }, { - name: 'Diagnosis', - href: '/master/diagnosis', + name: 'Diagnosis Template', + href: '/master/diagnosis-template', }, ]} /> diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx index b40379e1..67e30f2f 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx @@ -129,6 +129,7 @@ export default function List() { handleClose(); }) } + return ( @@ -144,9 +145,11 @@ export default function List() { aria-controls={createMenu ? 'basic-menu' : undefined} aria-haspopup="true" aria-expanded={createMenu ? 'true' : undefined} - onClick={handleClick} + > - Import + + Create + - Create Template - {handleGetTemplate('master-icd')}}>Download Template - Download ICD + + + )} - - {( currentImportFileName && - - - - - - - - )} - {( importResult && - - Last Import Result Report : {importResult.result_file?.name ?? "-"} - - )} ); } @@ -203,7 +184,7 @@ export default function List() { const handleActivate = (model: any, status: string) => { axios - .put(`/master/diagnosis/${row.id}/activation`, { + .put(`/master/diagnosis-template/${row.id}/activation`, { // service_code: service.service_code, active: status == 'active', }) @@ -231,65 +212,25 @@ export default function List() { return ( *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - - - {row.type} - {row.code} {row.name} - {row.version} - - - {/* */} - - {row.active == 1 && ( - - )} - {row.active != 1 && ( - - )} - - + {row.description ?? '-'} + {/* */} - + + + + + + + + - - - {/* COLLAPSIBLE ROW */} - - - - - - Description : {row.description} - - - + @@ -319,7 +260,7 @@ export default function List() { const loadDataTableData = async (appliedFilter : any | null = null) => { setDataTableLoading(true); const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); - const response = await axios.get('/master/diagnosis', { params: filter }); + const response = await axios.get('/master/diagnosis-template', { params: filter }); console.log(response.data); setDataTableLoading(false); @@ -355,12 +296,8 @@ export default function List() {
- - Type - Code Name - Version - Status + Description Action @@ -368,7 +305,7 @@ export default function List() { ( - Loading + Loading ) : ( @@ -376,7 +313,7 @@ export default function List() { ( - No Data + No Data ) : ( diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index 29f81fe6..23725491 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -236,12 +236,25 @@ export default function Router() { path: 'master/hospitals/:id/edit', element: , }, + { + path: 'master/diagnosis-template/create', + element: , + }, { path: 'master/diagnosis-template', element: , }, { - path: 'master/diagnosis', + path: 'master/diagnosis-template/:id/diagnosis-template-history', + element: , + }, + { + path: 'master/diagnosis-template/:id/edit', + element: , + }, + + { + path: 'master/diagnosis/:diagnosis_template_id', element: , }, { @@ -423,8 +436,12 @@ const DiagnosisExclusions = Loadable( const CorporateFormularium = Loadable(lazy(() => import('../pages/Corporates/Formularium/Index'))); -const MasterDiagnosis = Loadable(lazy(() => import('../pages/Master/Diagnosis/Index'))); const MasterDiagnosisTemplate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/Index'))); +const MasterDiagnosisTemplateCreate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/CreateUpdate'))); +const MasterDiagnosisTemplateHistories = Loadable( + lazy(() => import('../pages/Master/Diagnosis/Master/History')) +); +const MasterDiagnosis = Loadable(lazy(() => import('../pages/Master/Diagnosis/Index'))); const MasterDiagnosisHistories = Loadable( lazy(() => import('../pages/Master/Diagnosis/History')) ); diff --git a/public/files/CorporateMembershipList.xlsx b/public/files/CorporateMembershipList.xlsx index 0b61774e..a3fd8fdc 100644 Binary files a/public/files/CorporateMembershipList.xlsx and b/public/files/CorporateMembershipList.xlsx differ diff --git a/public/files/CorporatePlan&BenefitImportData.xlsx b/public/files/CorporatePlan&BenefitImportData.xlsx index 04b64569..4c003fd1 100644 Binary files a/public/files/CorporatePlan&BenefitImportData.xlsx and b/public/files/CorporatePlan&BenefitImportData.xlsx differ diff --git a/public/files/Template - ICD.xlsx b/public/files/Template - ICD.xlsx index d3ec396c..90071410 100644 Binary files a/public/files/Template - ICD.xlsx and b/public/files/Template - ICD.xlsx differ diff --git a/public/files/TemplateICDList.xlsx b/public/files/TemplateICDList.xlsx new file mode 100644 index 00000000..fe796c35 Binary files /dev/null and b/public/files/TemplateICDList.xlsx differ