diff --git a/Modules/Internal/Http/Controllers/Api/AuditTrailController.php b/Modules/Internal/Http/Controllers/Api/AuditTrailController.php index dd5ca4e4..dd73e6b1 100644 --- a/Modules/Internal/Http/Controllers/Api/AuditTrailController.php +++ b/Modules/Internal/Http/Controllers/Api/AuditTrailController.php @@ -19,7 +19,7 @@ class AuditTrailController extends Controller { $audittrails = AuditTrail::query() ->where('model', '=', $request->model) ->where('model_id', '=', $id) - // ->latest() + ->latest() ->paginate(1000); return response()->json(Helper::paginateResources(AuditTrailResource::collection($audittrails))); } diff --git a/Modules/Internal/Http/Controllers/Api/CorporateController.php b/Modules/Internal/Http/Controllers/Api/CorporateController.php index 9b8bf00d..0ea5cb51 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporateController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateController.php @@ -524,7 +524,13 @@ class CorporateController extends Controller 'file_name' => "Corporate Exclusion Import.xlsx", "file_url" => url('files/Corporate Exclusion Import.xlsx') ]); - break; + break; + case 'master-icd': + return Helper::responseJson([ + 'file_name' => "Template - ICD.xlsx", + "file_url" => url('files/Template - ICD.xlsx') + ]); + break; default: return Helper::responseJson([], 'error', 404); break; diff --git a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php index f42a6b49..8ad0cec7 100644 --- a/Modules/Internal/Http/Controllers/Api/DiagnosisController.php +++ b/Modules/Internal/Http/Controllers/Api/DiagnosisController.php @@ -3,20 +3,40 @@ namespace Modules\Internal\Http\Controllers\Api; use App\Models\Icd; +use App\Services\ImportService; +use App\Helpers\Helper; use Illuminate\Contracts\Support\Renderable; + +use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; +use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; +use Box\Spout\Common\Entity\Style\CellAlignment; +use Box\Spout\Common\Entity\Style\Color; +use Box\Spout\Writer\Common\Creator\WriterEntityFactory; +use Box\Spout\Common\Entity\Row; + use Illuminate\Http\Request; use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\Storage; +use Modules\Internal\Services\IcdService; class DiagnosisController extends Controller { + public function __construct(IcdService $icdService) + { + $this->icdService = $icdService; + } /** * Display a listing of the resource. * @return Renderable */ public function index(Request $request) { - $diagnosis = Icd::withTrashed()->filter($request->toArray())->paginate(); - + + $diagnosis = Icd::query() + ->filter($request->toArray()) + // ->where('deleted_at', '=', NULL) + ->orderBy('code', 'ASC') + ->paginate(15); return $diagnosis; } @@ -87,4 +107,189 @@ class DiagnosisController extends Controller ->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', + ]; + + 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, $diagnosis_id) + { + $request->validate([ + 'active' => 'required' + ]); + + $Icd = Icd::findOrFail($diagnosis_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 d55c5f42..84325536 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -125,6 +125,9 @@ Route::prefix('internal')->group(function () { 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/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 new file mode 100644 index 00000000..c3a22c20 --- /dev/null +++ b/Modules/Internal/Services/IcdService.php @@ -0,0 +1,55 @@ +validateDiagnosisExclusionRow($row); + $icd = Icd::updateOrCreate([ + 'code' => $row['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 + ]); + + return true; + } catch (\Exception $e) { + throw $e; + } + } + + public $listing_doc_headers = [ + "Rev", + "Version", + "Code", + "Parent Code", + "Name", + "Description", + "Status", + "Type" + ]; +} diff --git a/app/Models/Icd.php b/app/Models/Icd.php index 9dfa57ff..69497c4a 100644 --- a/app/Models/Icd.php +++ b/app/Models/Icd.php @@ -6,6 +6,7 @@ use App\Traits\Blameable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Altek\Accountant\Contracts\Recordable; class Icd extends Model { @@ -20,11 +21,12 @@ class Icd extends Model 'name', 'description', 'parent_code', + 'active' ]; public $appends = [ 'type', - 'active' + // 'active' ]; protected $hidden = [ @@ -41,10 +43,10 @@ class Icd extends Model return 'ICD-'.$this->rev; } - public function getActiveAttribute() - { - return empty($this->deleted_at); - } + // public function getActiveAttribute() + // { + // return empty($this->deleted_at); + // } public function subCategories() { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index d56e97c2..c0da828f 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,6 +11,7 @@ use App\Models\CorporateService; use App\Models\CorporatePlan; use App\Models\CorporateBenefit; use App\Models\Member; +use App\Models\Icd; use App\Models\AuditTrail; use Illuminate\Support\Facades\Auth; use Str; @@ -94,6 +95,15 @@ class AppServiceProvider extends ServiceProvider $this->logAuditTrail($model, 'deleted'); }); + // ICD or exlusion + Icd::updated(function ($model) { + $this->logAuditTrail($model, 'updated'); + }); + + Icd::deleted(function ($model) { + $this->logAuditTrail($model, 'deleted'); + }); + } diff --git a/database/migrations/2023_09_18_154540_add_active_to_icd.php b/database/migrations/2023_09_18_154540_add_active_to_icd.php new file mode 100644 index 00000000..22257349 --- /dev/null +++ b/database/migrations/2023_09_18_154540_add_active_to_icd.php @@ -0,0 +1,32 @@ +integer('active'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('icd', function (Blueprint $table) { + $table->dropColumn('active'); + }); + } +}; diff --git a/frontend/client-portal/src/@types/diagnosis.ts b/frontend/client-portal/src/@types/diagnosis.ts index a33734b5..f6d674ce 100644 --- a/frontend/client-portal/src/@types/diagnosis.ts +++ b/frontend/client-portal/src/@types/diagnosis.ts @@ -2,6 +2,7 @@ export type Icd = { id: number; type: string; rev: string; + active: number; version?: string; code: string; name: string; diff --git a/frontend/dashboard/src/pages/Corporates/Division/CreateUpdate.tsx b/frontend/dashboard/src/pages/Corporates/Division/CreateUpdate.tsx index d4ad3ea9..31ed9c23 100644 --- a/frontend/dashboard/src/pages/Corporates/Division/CreateUpdate.tsx +++ b/frontend/dashboard/src/pages/Corporates/Division/CreateUpdate.tsx @@ -3,18 +3,29 @@ import { useNavigate, useParams } from "react-router-dom"; import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs"; import Page from "../../../components/Page"; import useSettings from "../../../hooks/useSettings"; -import { useEffect, useMemo, useState } from 'react'; +import {useContext, useEffect, useMemo, useState } from 'react'; import axios from '../../../utils/axios'; import { useSnackbar } from 'notistack'; import CorporatePlanForm from './Form'; import { CorporatePlan } from '../../../@types/corporates'; +import { Corporate } from "@/@types/corporates"; +import { ConfiguredCorporateContext } from "@/contexts/ConfiguredCorporateContext"; export default function PlanCreate() { const { themeStretch } = useSettings(); const { corporate_id, id } = useParams(); + const [corporate, setCorporate] = useState(); + const configuredCorporateContext = useContext(ConfiguredCorporateContext); + + useEffect(() => { + setCorporate(configuredCorporateContext.currentCorporate); + }, [configuredCorporateContext]) + const [ currentCorporatePlan, setCurrentCorporatePlan ] = useState(); + + const navigate = useNavigate(); const isEdit = !!id; @@ -44,16 +55,16 @@ export default function PlanCreate() { href: '/corporates', }, { - name: 'Corporate Name', - href: '/corporates/'+corporate_id, + name: corporate?.name ?? '-', + href: '/corporate/'+corporate_id, }, { name: 'Division', - href: '/corporates/'+corporate_id+'/divisions', + href: '/corporate/'+corporate_id+'/divisions', }, { name: !isEdit ? 'Create' : 'Edit', - href: '/corporates/'+corporate_id+'/divisions/'+id, + href: '/corporate/'+corporate_id+'/divisions/'+id, }, ]} /> diff --git a/frontend/dashboard/src/pages/Corporates/Division/Index.tsx b/frontend/dashboard/src/pages/Corporates/Division/Index.tsx index 84aa6e6e..43361b05 100644 --- a/frontend/dashboard/src/pages/Corporates/Division/Index.tsx +++ b/frontend/dashboard/src/pages/Corporates/Division/Index.tsx @@ -32,7 +32,7 @@ export default function Divisions() { links={[ { name: 'Corporates', - href: '/corporates', + href: '/corporate', }, { name: corporate?.name ?? '-', diff --git a/frontend/dashboard/src/pages/Corporates/Index.tsx b/frontend/dashboard/src/pages/Corporates/Index.tsx index 580600c5..5253961b 100644 --- a/frontend/dashboard/src/pages/Corporates/Index.tsx +++ b/frontend/dashboard/src/pages/Corporates/Index.tsx @@ -386,8 +386,8 @@ export default function Corporates() { - : {fDate(row.current_policy?.start)}- - {fDate(row.current_policy?.end)} + {/* : {fDate(row.current_policy?.start)}- */} + {/* {fDate(row.current_policy?.end)} */} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx new file mode 100644 index 00000000..1e6b7361 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/History.tsx @@ -0,0 +1,215 @@ +// @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 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\\Icd'; + 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); + + 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 4da33ed2..7f4f7381 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Index.tsx @@ -21,7 +21,7 @@ export default function Divisions() { links={[ { name: 'Master', - href: '/master', + href: '/master/diagnosis', }, { name: 'Diagnosis', diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/List-master.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/List-master.tsx new file mode 100644 index 00000000..70127b94 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/List-master.tsx @@ -0,0 +1,397 @@ +// @mui +import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup, Pagination } from '@mui/material'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import AddIcon from '@mui/icons-material/Add'; +import UploadIcon from '@mui/icons-material/Upload'; +import CancelIcon from '@mui/icons-material/Cancel'; +import HistoryIcon from '@mui/icons-material/History'; +// hooks +import { Link, NavLink as RouterLink } from 'react-router-dom'; +import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; +import useSettings from '../../../hooks/useSettings'; +import { useParams, useSearchParams } from 'react-router-dom'; +// components +import axios from '../../../utils/axios'; +import { LaravelPaginatedData } from '../../../@types/paginated-data'; +import { Icd } from '../../../@types/diagnosis'; +import BasePagination from '../../../components/BasePagination'; +import { enqueueSnackbar } from 'notistack'; + +export default function List() { + const { themeStretch } = useSettings(); + const { corporate_id } = useParams(); + const [searchParams, setSearchParams] = useSearchParams(); + const [importResult, setImportResult] = useState(null); + + function SearchInput(props: any) { + // SEARCH + const searchInput = useRef(null); + const [searchText, setSearchText] = useState(""); + + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? '' + setSearchText(newSearchText); + } + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + props.onSearch(searchText); // Trigger to Parent + } + + useEffect(() => { // Trigger First Search + setSearchText(searchParams.get('search') ?? ''); + }, [searchParams]) + + return ( +
+ + + ); + } + + function ImportForm(props: any) { + // IMPORT + // Create Button Menu + const [anchorEl, setAnchorEl] = React.useState(null); + const createMenu = Boolean(anchorEl); + const importForm = useRef(null) + const [currentImportFileName, setCurrentImportFileName] = useState(null) + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleImportButton = () => { + if (importForm?.current) { + handleClose(); + importForm.current ? importForm.current.click() : console.log('No File selected'); + } else { + alert('No file selected') + } + } + + const handleICDList = async (appliedFilter = null) => { + axios.get('master/diagnosis/list').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(); + }); + } + + const handleCancelImportButton = () => { + importForm.current.value = ""; + importForm.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 (importForm.current?.files.length) { + const formData = new FormData(); + formData.append("file", importForm.current?.files[0]) + axios.post(`master/diagnosis/import`, formData ) + .then(response => { + handleCancelImportButton(); + loadDataTableData(); + setImportResult(response.data) + // alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows'); + }) + .catch(response => { + enqueueSnackbar('Looks like something went wrong. Please check your data and try again. ' + response.message, { variant: 'error' }) + }) + } else { + enqueueSnackbar('No File Selected', { variant: 'warning' }) + } + } + + const handleGetTemplate = (type :string) => { + axios.get('corporates/import-document-example/' + type) + .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 && + + {/*

kjasndkjandskjasndkjansdkjansd

*/} + + + Create Template + {handleGetTemplate('master-icd')}}>Download Template + Download ICD + +
+ )} + + {( currentImportFileName && + + + + + + + + )} + {( importResult && + + Last Import Result Report : {importResult.result_file?.name ?? "-"} + + )} +
+ ); + } + + // Called on every row to map the data to the columns + function createData( icd: Icd ): Icd { + return { + ...icd, + } + } + + // Generate the every row of the table + function Row(props: { row: ReturnType }) { + const { row } = props; + const [open, setOpen] = React.useState(false); + + const handleActivate = (model: any, status: string) => { + axios + .put(`/master/diagnosis/${row.id}/activation`, { + // service_code: service.service_code, + active: status == 'active', + }) + .then((res) => { + setDataTableData({ + ...dataTableData, + data: dataTableData.data.map((model) => { + let updatedModel = model; + if (row.id == model.id) { + updatedModel.active = res.data.icd.active; + } + return updatedModel; + }), + }); + }) + .catch((error) => { + // console.log('asdasd', error.response.data.message) + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + }; + + return ( + + *': { borderBottom: 'unset' } }}> + + setOpen(!open)} + > + {open ? : } + + + {row.type} + {row.code} + {row.name} + {row.version} + + + {/* */} + + {row.active == 1 && ( + + )} + {row.active != 1 && ( + + )} + + + {/* */} + + + + + + {/* COLLAPSIBLE ROW */} + + + + + + Description : {row.description} + + + + + + + ); + } + + // Dummy Default Data + const [dataTableIsLoading, setDataTableLoading] = useState(true); + const [dataTableLastRequest, setDataTableLastRequest] = useState(0); + const [dataTableResponseState, setDataTableResponseState] = useState('idle'); + const [dataTableData, setDataTableData] = useState({ + current_page: 1, + data: [], + path: "", + first_page_url: "", + last_page: 1, + last_page_url: "", + next_page_url: "", + prev_page_url: "", + per_page: 10, + from: 0, + to: 0, + total: 0 + }); + const [dataTablePage, setDataTablePage] = useState(5); + + 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); + setDataTableLoading(false); + + setDataTableData(response.data); + } + + const headStyle = { + fontWeight: 'bold', + }; + + const applyFilter = async (searchFilter: string) => { + await loadDataTableData({ "search" : searchFilter }); + setSearchParams({ "search" : searchFilter }); + } + + const handlePageChange = (event : ChangeEvent, value: number) => { + const filter = Object.fromEntries([...searchParams.entries(), ["page", value]]); + loadDataTableData(filter); + setSearchParams(filter); + } + + useEffect(() => { + loadDataTableData(); + }, []) + + return ( + + + + + {/* The Main Table */} + + + + + + Type + Code + Name + Version + Status + Action + + + {dataTableIsLoading ? + ( + + + Loading + + + ) : ( + dataTableData.data.length == 0 ? + ( + + + No Data + + + ) : ( + + {dataTableData.data.map(row => ( + + ))} + + ) + )} +
+
+ + +
+
+ ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx index ef1aad24..6719e31f 100644 --- a/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx +++ b/frontend/dashboard/src/pages/Master/Diagnosis/List.tsx @@ -5,7 +5,9 @@ import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import AddIcon from '@mui/icons-material/Add'; import UploadIcon from '@mui/icons-material/Upload'; import CancelIcon from '@mui/icons-material/Cancel'; +import HistoryIcon from '@mui/icons-material/History'; // hooks +import { Link, NavLink as RouterLink } from 'react-router-dom'; import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; import useSettings from '../../../hooks/useSettings'; import { useParams, useSearchParams } from 'react-router-dom'; @@ -73,6 +75,22 @@ export default function List() { } } + const handleICDList = async (appliedFilter = null) => { + axios.get('master/diagnosis/list').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(); + enqueueSnackbar('Download Success', { variant: 'succes' }) + }) + .catch(response => { + enqueueSnackbar('Looks like something went wrong. Please check your data and try again. ' + response.message, { variant: 'error' }) + }) + ; + } + const handleCancelImportButton = () => { importForm.current.value = ""; importForm.current.dispatchEvent(new Event("change", { bubbles: true })); @@ -90,12 +108,13 @@ export default function List() { if (importForm.current?.files.length) { const formData = new FormData(); formData.append("file", importForm.current?.files[0]) - axios.post(`corporates/${corporate_id}/import-plan-benefit`, formData ) + axios.post(`master/diagnosis/import`, formData ) .then(response => { handleCancelImportButton(); loadDataTableData(); setImportResult(response.data) // alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows'); + enqueueSnackbar('Succesfully import data '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows', { variant: 'success' }) }) .catch(response => { enqueueSnackbar('Looks like something went wrong. Please check your data and try again. ' + response.message, { variant: 'error' }) @@ -104,6 +123,19 @@ export default function List() { enqueueSnackbar('No File Selected', { variant: 'warning' }) } } + + const handleGetTemplate = (type :string) => { + axios.get('corporates/import-document-example/' + type) + .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 (
@@ -132,7 +164,8 @@ export default function List() { }} > Import - Download Template + {handleGetTemplate('master-icd')}}>Download Template + Download ICD )} @@ -174,6 +207,37 @@ export default function List() { const { row } = props; const [open, setOpen] = React.useState(false); + const handleActivate = (model: any, status: string) => { + axios + .put(`/master/diagnosis/${row.id}/activation`, { + // service_code: service.service_code, + active: status == 'active', + }) + .then((res) => { + setDataTableData({ + ...dataTableData, + data: dataTableData.data.map((model) => { + let updatedModel = model; + if (row.id == model.id) { + updatedModel.active = res.data.icd.active; + } + return updatedModel; + }), + }); + enqueueSnackbar( + 'Updated Successfully!', + { variant: 'success' } + ); + }) + .catch((error) => { + // console.log('asdasd', error.response.data.message) + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + }; + return ( *': { borderBottom: 'unset' } }}> @@ -190,9 +254,41 @@ export default function List() { {row.code} {row.name} {row.version} + - - + {/* */} + + {row.active == 1 && ( + + )} + {row.active != 1 && ( + + )} + + + {/* */} + + + + {/* COLLAPSIBLE ROW */} @@ -234,7 +330,7 @@ export default function List() { setDataTableLoading(true); const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); const response = await axios.get('/master/diagnosis', { params: filter }); - // console.log(response.data); + console.log(response.data); setDataTableLoading(false); setDataTableData(response.data); diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx new file mode 100644 index 00000000..7e5d53b2 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/CreateUpdate.tsx @@ -0,0 +1,75 @@ + +import { useNavigate, useParams } from "react-router-dom"; +import HeaderBreadcrumbs from "../../../../components/HeaderBreadcrumbs"; +import Page from "../../../../components/Page"; +import useSettings from "../../../../hooks/useSettings"; +import {useContext, useEffect, useMemo, useState } from 'react'; +import axios from '../../../../utils/axios'; +import { useSnackbar } from 'notistack'; +import CorporatePlanForm from './Form'; +import { CorporatePlan } from '../../../../@types/corporates'; +import { Corporate } from "@/@types/corporates"; +import { ConfiguredCorporateContext } from "@/contexts/ConfiguredCorporateContext"; + + + +export default function PlanCreate() { + const { themeStretch } = useSettings(); + const { corporate_id, id } = useParams(); + const [corporate, setCorporate] = useState(); + const configuredCorporateContext = useContext(ConfiguredCorporateContext); + + useEffect(() => { + setCorporate(configuredCorporateContext.currentCorporate); + }, [configuredCorporateContext]) + + const [ currentCorporatePlan, setCurrentCorporatePlan ] = useState(); + + + const navigate = useNavigate(); + + const isEdit = !!id; + + useEffect(() => { + if (isEdit) { + axios.get('/corporates/'+corporate_id+'/divisions/'+id+'/edit') + .then((res) => { + setCurrentCorporatePlan(res.data); + }) + .catch((err) => { + if (err.response.status === 404) { + navigate('/404'); + } + }) + } + }, [corporate_id, id]); + + + return ( + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Form.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Form.tsx new file mode 100644 index 00000000..99663c77 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Form.tsx @@ -0,0 +1,129 @@ +import * as Yup from 'yup'; +import { LoadingButton } from "@mui/lab"; +import { Card, Grid, Stack, Typography } from "@mui/material"; +import { CorporatePlan } from "../../../../@types/corporates"; +import { FormProvider, RHFSwitch, RHFTextField } from "../../../../components/hook-form"; +import { useEffect, useMemo } from 'react'; +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { useSnackbar } from 'notistack'; +import { useNavigate, useParams } from 'react-router-dom'; +import axios from '../../../../utils/axios'; + +type Props = { + isEdit: boolean; + currentCorporatePlan?: CorporatePlan; +}; + +export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Props) { + + const { enqueueSnackbar } = useSnackbar(); + const navigate = useNavigate(); + const { corporate_id } = useParams(); + + const NewCorporatePlanSchema = Yup.object().shape({ + name: Yup.string().required('Name is required'), + code: Yup.string().required('Corporate Code is required'), + }); + + const defaultValues = useMemo( + () => ({ + name: currentCorporatePlan?.name || '', + code: currentCorporatePlan?.code || '', + active: currentCorporatePlan?.active === 1 ? true : false, + }), + [currentCorporatePlan] + ); + + useEffect(() => { + if (isEdit && currentCorporatePlan) { + reset(defaultValues); + } + if (!isEdit) { + reset(defaultValues); + } + }, [isEdit, currentCorporatePlan]); + + const methods = useForm({ + resolver: yupResolver(NewCorporatePlanSchema), + defaultValues, + }); + + const { + reset, + watch, + control, + setValue, + getValues, + setError, + handleSubmit, + formState: { isSubmitting }, + } = methods; + + + const onSubmit = async (data: any) => { + if (!isEdit) { + await axios + .post('/corporates/' + corporate_id + '/divisions', data) + .then((res) => { + enqueueSnackbar('Division created successfully', { variant: 'success' }); + }) + .then((res) => { + navigate('/corporate/' + corporate_id + '/divisions', { replace: true }); + }) + .catch(({ response }) => { + if (response.status === 422) { + for (const [key, value] of Object.entries(response.data.errors)) { + setError(key, { message: value[0] }); + enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' }); + } + } + else { + enqueueSnackbar('Create Failed : '+ response.data.message, { variant: 'error' }); + } + }); + } else { + await axios + .put('/corporates/' + corporate_id + '/divisions/' + currentCorporatePlan?.id , data) + .then((res) => { + enqueueSnackbar('Division updated successfully', { variant: 'success' }); + }) + .then((res) => { + navigate('/corporate/' + corporate_id + '/divisions/' , { replace: true }); + }) + .catch(({ response }) => { + enqueueSnackbar('Update Failed : '+ response.data.message, { variant: 'error' }); + }); + } + }; + + return ( + + + + + + + Division Detail + + + + + + + { isEdit? 'Update' : 'Create' } + + + + + + + + + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx new file mode 100644 index 00000000..ab1cecb2 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/Index.tsx @@ -0,0 +1,38 @@ +import { Card, Grid } from "@mui/material"; +import { useParams } from "react-router-dom"; +import HeaderBreadcrumbs from "../../../../components/HeaderBreadcrumbs"; +import Page from "../../../../components/Page"; +import useSettings from "../../../../hooks/useSettings"; +import List from "./List"; + + + +export default function Divisions() { + const { themeStretch } = useSettings(); + + const { corporate_id } = useParams(); + + const pageTitle = 'Diagnosis'; + return ( + + + + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx new file mode 100644 index 00000000..b40379e1 --- /dev/null +++ b/frontend/dashboard/src/pages/Master/Diagnosis/Master/List.tsx @@ -0,0 +1,397 @@ +// @mui +import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup, Pagination } from '@mui/material'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import AddIcon from '@mui/icons-material/Add'; +import UploadIcon from '@mui/icons-material/Upload'; +import CancelIcon from '@mui/icons-material/Cancel'; +import HistoryIcon from '@mui/icons-material/History'; +// hooks +import { Link, NavLink as RouterLink } from 'react-router-dom'; +import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; +import useSettings from '../../../../hooks/useSettings'; +import { useParams, useSearchParams } from 'react-router-dom'; +// components +import axios from '../../../../utils/axios'; +import { LaravelPaginatedData } from '../../../../@types/paginated-data'; +import { Icd } from '../../../../@types/diagnosis'; +import BasePagination from '../../../../components/BasePagination'; +import { enqueueSnackbar } from 'notistack'; + +export default function List() { + const { themeStretch } = useSettings(); + const { corporate_id } = useParams(); + const [searchParams, setSearchParams] = useSearchParams(); + const [importResult, setImportResult] = useState(null); + + function SearchInput(props: any) { + // SEARCH + const searchInput = useRef(null); + const [searchText, setSearchText] = useState(""); + + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? '' + setSearchText(newSearchText); + } + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + props.onSearch(searchText); // Trigger to Parent + } + + useEffect(() => { // Trigger First Search + setSearchText(searchParams.get('search') ?? ''); + }, [searchParams]) + + return ( +
+ + + ); + } + + function ImportForm(props: any) { + // IMPORT + // Create Button Menu + const [anchorEl, setAnchorEl] = React.useState(null); + const createMenu = Boolean(anchorEl); + const importForm = useRef(null) + const [currentImportFileName, setCurrentImportFileName] = useState(null) + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleImportButton = () => { + if (importForm?.current) { + handleClose(); + importForm.current ? importForm.current.click() : console.log('No File selected'); + } else { + alert('No file selected') + } + } + + const handleICDList = async (appliedFilter = null) => { + axios.get('master/diagnosis/list').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(); + }); + } + + const handleCancelImportButton = () => { + importForm.current.value = ""; + importForm.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 (importForm.current?.files.length) { + const formData = new FormData(); + formData.append("file", importForm.current?.files[0]) + axios.post(`master/diagnosis/import`, formData ) + .then(response => { + handleCancelImportButton(); + loadDataTableData(); + setImportResult(response.data) + // alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows'); + }) + .catch(response => { + enqueueSnackbar('Looks like something went wrong. Please check your data and try again. ' + response.message, { variant: 'error' }) + }) + } else { + enqueueSnackbar('No File Selected', { variant: 'warning' }) + } + } + + const handleGetTemplate = (type :string) => { + axios.get('corporates/import-document-example/' + type) + .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 && + + {/*

kjasndkjandskjasndkjansdkjansd

*/} + + + Create Template + {handleGetTemplate('master-icd')}}>Download Template + Download ICD + +
+ )} + + {( currentImportFileName && + + + + + + + + )} + {( importResult && + + Last Import Result Report : {importResult.result_file?.name ?? "-"} + + )} +
+ ); + } + + // Called on every row to map the data to the columns + function createData( icd: Icd ): Icd { + return { + ...icd, + } + } + + // Generate the every row of the table + function Row(props: { row: ReturnType }) { + const { row } = props; + const [open, setOpen] = React.useState(false); + + const handleActivate = (model: any, status: string) => { + axios + .put(`/master/diagnosis/${row.id}/activation`, { + // service_code: service.service_code, + active: status == 'active', + }) + .then((res) => { + setDataTableData({ + ...dataTableData, + data: dataTableData.data.map((model) => { + let updatedModel = model; + if (row.id == model.id) { + updatedModel.active = res.data.icd.active; + } + return updatedModel; + }), + }); + }) + .catch((error) => { + // console.log('asdasd', error.response.data.message) + enqueueSnackbar( + error.response.data.message ?? error.message ?? 'Failed Processing Request', + { variant: 'error' } + ); + }); + }; + + return ( + + *': { borderBottom: 'unset' } }}> + + setOpen(!open)} + > + {open ? : } + + + {row.type} + {row.code} + {row.name} + {row.version} + + + {/* */} + + {row.active == 1 && ( + + )} + {row.active != 1 && ( + + )} + + + {/* */} + + + + + + {/* COLLAPSIBLE ROW */} + + + + + + Description : {row.description} + + + + + + + ); + } + + // Dummy Default Data + const [dataTableIsLoading, setDataTableLoading] = useState(true); + const [dataTableLastRequest, setDataTableLastRequest] = useState(0); + const [dataTableResponseState, setDataTableResponseState] = useState('idle'); + const [dataTableData, setDataTableData] = useState({ + current_page: 1, + data: [], + path: "", + first_page_url: "", + last_page: 1, + last_page_url: "", + next_page_url: "", + prev_page_url: "", + per_page: 10, + from: 0, + to: 0, + total: 0 + }); + const [dataTablePage, setDataTablePage] = useState(5); + + 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); + setDataTableLoading(false); + + setDataTableData(response.data); + } + + const headStyle = { + fontWeight: 'bold', + }; + + const applyFilter = async (searchFilter: string) => { + await loadDataTableData({ "search" : searchFilter }); + setSearchParams({ "search" : searchFilter }); + } + + const handlePageChange = (event : ChangeEvent, value: number) => { + const filter = Object.fromEntries([...searchParams.entries(), ["page", value]]); + loadDataTableData(filter); + setSearchParams(filter); + } + + useEffect(() => { + loadDataTableData(); + }, []) + + return ( + + + + + {/* The Main Table */} + + + + + + Type + Code + Name + Version + Status + Action + + + {dataTableIsLoading ? + ( + + + Loading + + + ) : ( + dataTableData.data.length == 0 ? + ( + + + No Data + + + ) : ( + + {dataTableData.data.map(row => ( + + ))} + + ) + )} +
+
+ + +
+
+ ); +} diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index 455291c5..29f81fe6 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -236,10 +236,18 @@ export default function Router() { path: 'master/hospitals/:id/edit', element: , }, + { + path: 'master/diagnosis-template', + element: , + }, { path: 'master/diagnosis', element: , }, + { + path: 'master/diagnosis/:id/diagnosis-history', + element: , + }, { path: 'master/drugs', @@ -412,9 +420,14 @@ const DiagnosisExclusions = Loadable( lazy(() => import('../pages/Corporates/DiagnosisExclusion/Index')) ); + 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 MasterDiagnosisHistories = Loadable( + lazy(() => import('../pages/Master/Diagnosis/History')) +); const MasterDoctors = Loadable(lazy(() => import('../pages/Master/Doctors/Index'))); const MasterDoctorsCreate = Loadable(lazy(() => import('../pages/Master/Doctors/Create'))); const MasterHospitals = Loadable(lazy(() => import('../pages/Master/Hospitals/Index'))); diff --git a/public/files/CorporateMembershipList.xlsx b/public/files/CorporateMembershipList.xlsx index 4094bd78..062ac1cc 100644 Binary files a/public/files/CorporateMembershipList.xlsx and b/public/files/CorporateMembershipList.xlsx differ diff --git a/public/files/Template - ICD.xlsx b/public/files/Template - ICD.xlsx new file mode 100644 index 00000000..d3ec396c Binary files /dev/null and b/public/files/Template - ICD.xlsx differ