diff --git a/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php b/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php index e70991c4..54d56720 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php @@ -18,6 +18,7 @@ use Modules\HospitalPortal\Transformers\ClaimRequestShowResource; use PDF; use Illuminate\Support\Facades\DB; use Modules\HospitalPortal\Helpers\ApiResponse; +use Illuminate\Support\Facades\Validator; class ClaimRequestController extends Controller { @@ -63,90 +64,93 @@ class ClaimRequestController extends Controller */ public function store(Request $request) { - $request->validate([ + $data = [ + 'request_logs_id' => $request->request_logs_id, + 'member_id' => $request->member_id, + 'service_code' => $request->service_code + ]; + $validator = Validator::make($request->all(), [ + 'request_logs_id' => 'required', 'member_id' => 'required', 'service_code' => 'required' + ], [ + 'request_logs_id.required' => trans('Validation.required',['attribute' => 'Request Log ID']), + 'member_id.required' => trans('Validation.required',['attribute' => 'Member ID']), + 'service_code.required' => trans('Validation.required',['attribute' => 'Service Code']) ]); - $code = $this->getNextCode(); - $member = Member::find($request->member_id); - $newClaimRequest = ClaimRequestService::storeClaimRequest( - row: [], - code: $code, - member: $member, - paymentType: 'reimbursement', - serviceCode: $request->service_code - ); - - ClaimRequested::dispatch($newClaimRequest); - - // Log History - $newClaimRequest->histories()->create([ - 'title' => 'New Claim Requested', - 'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})", - 'type' => 'info', - 'system_origin' => 'hospital-portal' - ]); - - // Claim Log - DB::table('claim_logs') - ->insert([ - 'claim_request_id' => $newClaimRequest->id, - 'status' => 'requested', - 'date' => date('Y-m-d H:i:s'), - 'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})", - 'system_origin' => 'hospital-portal', - 'created_by' => auth()->user()->id, - 'created_at' => date('Y-m-d H:i:s'), - 'updated_at'=> date('Y-m-d H:i:s'), - ]); - - - if ($request->hasFile('result_files')) { - foreach ($request->result_files as $file) { - $pathFile = File::storeFile('claim-result', $newClaimRequest->id, $file); - $newClaimRequest->files()->updateOrCreate([ - 'type' => 'claim-result', - 'name' => File::getFileName('claim-result', $newClaimRequest->id, $file), - 'original_name' => $file->getClientOriginalName(), - 'extension' => $file->getClientOriginalExtension(), - 'path' => $pathFile, - 'created_by' => auth()->user()->id, - 'updated_by' => auth()->user()->id, - ]); - } + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); } - - if ($request->hasFile('diagnosa_files')) { - foreach ($request->diagnosa_files as $file) { - $pathFile = File::storeFile('claim-diagnosis', $newClaimRequest->id, $file); - $newClaimRequest->files()->updateOrCreate([ - 'type' => 'claim-diagnosis', - 'name' => File::getFileName('claim-diagnosis', $newClaimRequest->id, $file), - 'original_name' => $file->getClientOriginalName(), - 'extension' => $file->getClientOriginalExtension(), - 'path' => $pathFile, - 'created_by' => auth()->user()->id, - 'updated_by' => auth()->user()->id, - ]); + else + { + $check_claim_requests = DB::table('claim_requests') + ->where('claim_requests.request_log_id', '=', $request->request_logs_id) + ->first(); + if(!$check_claim_requests) + { + try { + DB::beginTransaction(); + $code = $this->getNextCode(); + $member = Member::find($request->member_id); + $newClaimRequest = ClaimRequestService::storeClaimRequest( + row: [], + code: $code, + member: $member, + paymentType: 'reimbursement', + serviceCode: $request->service_code, + requestLogID: $request->request_logs_id, + ); + // Log History + $newClaimRequest->histories()->create([ + 'title' => 'New Claim Requested', + 'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})", + 'type' => 'info', + 'system_origin' => 'hospital-portal' + ]); + + // Claim Log + DB::table('claim_logs') + ->insert([ + 'claim_request_id' => $newClaimRequest->id, + 'status' => 'requested', + 'date' => date('Y-m-d H:i:s'), + 'description' => "Claim Requested for Member : {$member->member_id} - ({$member->full_name})", + 'system_origin' => 'hospital-portal', + 'created_by' => auth()->user()->id, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at'=> date('Y-m-d H:i:s'), + ]); + + + if ($request->hasFile('additional_files')) { + foreach ($request->additional_files as $file) { + $pathFile = File::storeFile('additional-files', $newClaimRequest->id, $file); + $newClaimRequest->files()->updateOrCreate([ + 'type' => 'additional-files', + 'name' => File::getFileName('additional-files', $newClaimRequest->id, $file), + 'original_name' => $file->getClientOriginalName(), + 'extension' => $file->getClientOriginalExtension(), + 'path' => $pathFile, + 'created_by' => auth()->user()->id, + 'updated_by' => auth()->user()->id, + ]); + } + } + DB::commit(); + return ApiResponse::apiResponse('Success', $data, trans('Message.success'), 200); + } + catch (\Exception $e) { + DB::rollback(); + return ApiResponse::apiResponse("Error", $data, $e->getMessage(), 500); + } } - } - - if ($request->hasFile('kondisi_files')) { - foreach ($request->kondisi_files as $file) { - $pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file); - $newClaimRequest->files()->updateOrCreate([ - 'type' => 'claim-kondisi', - 'name' => File::getFileName('claim-kondisi', $newClaimRequest->id, $file), - 'original_name' => $file->getClientOriginalName(), - 'extension' => $file->getClientOriginalExtension(), - 'path' => $pathFile, - 'created_by' => auth()->user()->id, - 'updated_by' => auth()->user()->id, - ]); + else + { + return ApiResponse::apiResponse("Error", $data, trans('Message.already_exists'), 409); } + } - - return ApiResponse::apiResponse("Success", [], trans('message.success'), 200); } /** @@ -253,12 +257,13 @@ class ClaimRequestController extends Controller ->leftJoin('corporate_divisions', 'corporate_employees.division_id', '=', 'corporate_divisions.id') ->when($request->input('search'), function ($query, $search) { $query->where(function ($query) use ($search) { - $query->orWhere('claim_requests.code', 'like', "%" . $search . "%") + $query->orWhere('claim_requests.code', 'like', "%" . ($search == 'outpatient' || $search == 'Outpatient' ? 'OP' : 'IP') . "%") ->orWhere('members.member_id', 'like', "%" . $search . "%") ->orWhere('members.name', 'like', "%" . $search . "%") ->orWhere('corporate_divisions.name', 'like', "%" . $search . "%") ->orWhere('claim_requests.status', 'like', "%" . $search . "%") - ->orWhere('claim_requests.submission_date', 'like', "%" . $search . "%"); + ->orWhere('claim_requests.submission_date', 'like', "%" . $search . "%") + ->orWhere('claims.status', 'like', "%" . $search . "%"); }); }) ->when($request->has('orderBy'), function ($query) use ($request) { @@ -296,7 +301,12 @@ class ClaimRequestController extends Controller }); }) - ->select('members.id', 'claim_requests.code','members.member_id', 'members.name as full_name', 'corporate_divisions.name AS division_name', + ->select( + 'members.id', + 'claim_requests.code', + 'members.member_id', + 'members.name as full_name', + 'corporate_divisions.name AS division_name', DB::raw(' CASE WHEN claim_requests.status = "requested" THEN "requested" @@ -308,7 +318,16 @@ class ClaimRequestController extends Controller ELSE "" END AS status '), - 'claim_requests.id AS claim_request_id', 'claim_requests.submission_date') + 'claim_requests.id AS claim_request_id', + 'claim_requests.submission_date', + DB::raw(' + CASE + WHEN service_code = "OP" THEN "Outpatient" + WHEN service_code = "IP" THEN "Inpatient" + ELSE "" + END AS service_type + ') + ) ->paginate($limit); return response()->json(Helper::paginateResources($results)); } diff --git a/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php b/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php index 7d5dbdcc..4a69d876 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php @@ -94,6 +94,8 @@ class MemberController extends Controller $res_data['groupServices'] = $groupServices; + $res_data['type'] = $request->type; + return ApiResponse::apiResponse("Success", $res_data, trans('Message.success'), 200); } diff --git a/Modules/HospitalPortal/Http/Controllers/Api/RequestLogController.php b/Modules/HospitalPortal/Http/Controllers/Api/RequestLogController.php index 377c50a0..a3d8ea35 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/RequestLogController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/RequestLogController.php @@ -8,6 +8,8 @@ use Illuminate\Support\Facades\Validator; use Modules\HospitalPortal\Helpers\ApiResponse; use Illuminate\Support\Facades\DB; use Modules\Internal\Http\Controllers\Api\RequestLogController as primeCenterRequestLog; +use App\Helpers\Helper; +use App\Models\File; class RequestLogController extends Controller { @@ -48,4 +50,235 @@ class RequestLogController extends Controller } } } + + public function getRequestLog(Request $request) + { + + $limit = $request->has('per_page') ? $request->input('per_page') : 10; + + $results = DB::table('request_logs') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->when($request->input('search'), function ($query, $search) { + $query->where(function ($query) use ($search) { + $query->orWhere('request_logs.code', 'like', "%" . $search . "%") + ->orWhere('members.name', 'like', "%" . $search . "%") + ->orWhere('request_logs.submission_date', 'like', "%" . $search . "%"); + }); + }) + ->when($request->has('orderBy'), function ($query) use ($request) { + $orderBy = $request->orderBy; + $direction = $request->order ?? 'asc'; + + $query->orderBy($orderBy, $direction); + }) + ->when($request->input('start_date') && !$request->input('end_date'), function ($query, $start_date) { + $query->where(function ($query) use ($start_date) { + $query->where('request_logs.submission_date', '<', $start_date); + }); + }) + ->when($request->input('status'), function ($query, $status) { + $query->where(function ($query) use ($status) { + + if ($status === 'requested') { + $query->where('request_logs.status', '=', 'requested'); + } + + if ($status === 'reviewed') { + $query->where('request_logs.status', '=', 'approved'); + } + + if ($status === 'approved') { + $query->where('request_logs.status', '=', 'approved'); + } + + if ($status === 'declined') { + $query->where('request_logs.status', '=', 'declined'); + } + + }); + }) + ->select( + 'request_logs.id', + 'request_logs.final_log', + 'request_logs.code', + 'members.name as full_name', + 'members.member_id as no_polis', + 'members.birth_date', + DB::raw(' + CASE + WHEN request_logs.status = "requested" THEN "requested" + WHEN request_logs.status = "approved" THEN "approved" + WHEN request_logs.status = "declined" THEN "declined" + WHEN request_logs.status = "reviewed" THEN "reviewed" + ELSE "" + END AS status + '), + 'request_logs.submission_date') + ->paginate($limit); + return response()->json(Helper::paginateResources($results)); + } + + public function getFinalLog(Request $request) + { + + $limit = $request->has('per_page') ? $request->input('per_page') : 10; + + $results = DB::table('request_logs') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->when($request->input('search'), function ($query, $search) { + $query->where(function ($query) use ($search) { + $query->orWhere('request_logs.code', 'like', "%" . $search . "%") + ->orWhere('members.name', 'like', "%" . $search . "%") + ->orWhere('request_logs.submission_date', 'like', "%" . $search . "%") + ->orWhere('request_logs.service_code', 'like', "%" . ($search == 'outpatient' || $search == 'Outpatient' ? 'OP' : 'IP') . "%"); + }); + }) + ->when($request->has('orderBy'), function ($query) use ($request) { + $orderBy = $request->orderBy; + $direction = $request->order ?? 'asc'; + + $query->orderBy($orderBy, $direction); + }) + ->when($request->input('start_date') && !$request->input('end_date'), function ($query, $start_date) { + $query->where(function ($query) use ($start_date) { + $query->where('request_logs.submission_date', '<', $start_date); + }); + }) + ->when($request->input('status'), function ($query, $status) { + $query->where(function ($query) use ($status) { + + if ($status === 'requested') { + $query->where('request_logs.status_final_log', '=', 'requested'); + } + + if ($status === 'reviewed') { + $query->where('request_logs.status_final_log', '=', 'approved'); + } + + if ($status === 'approved') { + $query->where('request_logs.status_final_log', '=', 'approved'); + } + + if ($status === 'declined') { + $query->where('request_logs.status_final_log', '=', 'declined'); + } + + }); + }) + ->where('request_logs.final_log', '=', 1) + ->select( + 'request_logs.id', + 'request_logs.final_log', + 'request_logs.code', + 'members.name as full_name', + 'members.member_id as no_polis', + 'members.id AS member_id', + 'request_logs.service_code', + 'members.birth_date', + DB::raw(' + CASE + WHEN request_logs.status_final_log = "requested" THEN "requested" + WHEN request_logs.status_final_log = "approved" THEN "approved" + WHEN request_logs.status_final_log = "declined" THEN "declined" + WHEN request_logs.status_final_log = "reviewed" THEN "reviewed" + ELSE "" + END AS status + '), + 'request_logs.submission_date', + DB::raw(' + CASE + WHEN service_code = "OP" THEN "Outpatient" + WHEN service_code = "IP" THEN "Inpatient" + ELSE "" + END AS service_type + '), + DB::raw(' + (Select request_log_id FROM claim_requests WHERE claim_requests.request_log_id = request_logs.id LIMIT 1) AS check_claim + ') + ) + ->paginate($limit); + return response()->json(Helper::paginateResources($results)); + } + + public function requestFinalLog(Request $request) + { + $data = [ + 'request_logs_id' => $request->request_logs_id + ]; + $validator = Validator::make($request->all(), [ + 'request_logs_id' => 'required' + ], [ + 'request_logs_id.required' => trans('Validation.required',['attribute' => 'Request Logs ID']) + ]); + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); + } + else + { + try { + DB::beginTransaction(); + DB::table('request_logs') + ->where('request_logs.id', '=', $request->request_logs_id) + ->update([ + 'status_final_log' => 'requested', + 'final_log' => 1 + ]); + if ($request->hasFile('result_files')) { + foreach ($request->result_files as $file) { + $pathFile = File::storeFile('final-log-result', $request->request_logs_id, $file); + File::updateOrCreate([ + 'fileable_type' => 'App\Models\RequestLog', + 'fileable_id' => $request->request_logs_id, + 'type' => 'final-log-result', + 'name' => File::getFileName('final-log-result', $request->request_logs_id, $file), + 'original_name' => $file->getClientOriginalName(), + 'extension' => $file->getClientOriginalExtension(), + 'path' => $pathFile, + 'created_by' => auth()->user()->id, + 'updated_by' => auth()->user()->id, + ]); + } + } + if ($request->hasFile('diagnosa_files')) { + foreach ($request->diagnosa_files as $file) { + $pathFile = File::storeFile('final-log-diagnosis', $request->request_logs_id, $file); + File::updateOrCreate([ + 'fileable_type' => 'App\Models\RequestLog', + 'fileable_id' => $request->request_logs_id, + 'type' => 'final-log-diagnosis', + 'name' => File::getFileName('final-log-diagnosis', $request->request_logs_id, $file), + 'original_name' => $file->getClientOriginalName(), + 'extension' => $file->getClientOriginalExtension(), + 'path' => $pathFile, + 'created_by' => auth()->user()->id, + 'updated_by' => auth()->user()->id, + ]); + } + } + if ($request->hasFile('kondisi_files')) { + foreach ($request->kondisi_files as $file) { + $pathFile = File::storeFile('final-log-kondisi', $request->request_logs_id, $file); + File::updateOrCreate([ + 'fileable_type' => 'App\Models\RequestLog', + 'fileable_id' => $request->request_logs_id, + 'type' => 'final-log-kondisi', + 'name' => File::getFileName('final-log-kondisi', $request->request_logs_id, $file), + 'original_name' => $file->getClientOriginalName(), + 'extension' => $file->getClientOriginalExtension(), + 'path' => $pathFile, + 'created_by' => auth()->user()->id, + 'updated_by' => auth()->user()->id, + ]); + } + } + DB::commit(); + return ApiResponse::apiResponse('Success', $data, trans('Message.success'), 200); + } + catch (\Exception $e) { + DB::rollback(); + return ApiResponse::apiResponse("Error", $data, $e->getMessage(), 500); + } + } + } } diff --git a/Modules/HospitalPortal/Routes/api.php b/Modules/HospitalPortal/Routes/api.php index bde509b5..fabf81c9 100644 --- a/Modules/HospitalPortal/Routes/api.php +++ b/Modules/HospitalPortal/Routes/api.php @@ -51,6 +51,9 @@ Route::prefix('v1')->group(function() { // Request LOG Route::controller(RequestLogController::class)->group(function () { Route::post('request-log', 'requestLog'); + Route::get('get-request-log', 'getRequestLog'); + Route::get('get-final-log', 'getFinalLog'); + Route::post('request-final-log', 'requestFinalLog'); }); //Notification Route::controller(NotificationController::class)->group(function() { @@ -60,8 +63,16 @@ Route::prefix('v1')->group(function() { Route::post('set-read-notification', 'setReadNotification'); }); }); + // Request Final LOG + Route::controller(RequestLogController::class)->group(function () { + Route::post('request-final-log', 'requestFinalLog'); + }); + // Claim Submit + Route::controller(ClaimRequestController::class)->group(function () { + Route::post('claim-requests', 'store'); + }); Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index'); - Route::post('claim-requests', [ClaimRequestController::class, 'store'])->name('claim-requests.store'); + // Route::post('claim-requests', [ClaimRequestController::class, 'store'])->name('claim-requests.store'); Route::get('claim-requests/{claim_request_id}/log', [ClaimRequestController::class, 'generateLog'])->name('claim-requests.generate-log'); Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show'); Route::get('get-claim-requests', [ClaimRequestController::class, 'get_claim_requests'])->name('claim-requests.get_claim_requests'); diff --git a/Modules/Internal/Http/Controllers/Api/ClaimController.php b/Modules/Internal/Http/Controllers/Api/ClaimController.php index 2d79fc2f..5b84078c 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimController.php @@ -34,7 +34,7 @@ class ClaimController extends Controller */ public function index(Request $request) { - $serviceCode = 'IP'; + // $serviceCode = 'IP'; $claims = Claim::with([ 'member', 'member.currentCorporate', diff --git a/Modules/Internal/Http/Controllers/Api/DailyMonitoringController.php b/Modules/Internal/Http/Controllers/Api/DailyMonitoringController.php index 3bb34c82..09347128 100644 --- a/Modules/Internal/Http/Controllers/Api/DailyMonitoringController.php +++ b/Modules/Internal/Http/Controllers/Api/DailyMonitoringController.php @@ -35,12 +35,15 @@ class DailyMonitoringController extends Controller */ public function GetMemberList() { - $memberList = DB::table('claims') - ->leftJoin('members', 'claims.member_id', '=', 'members.id') - ->leftJoin('member_plans', 'members.id', '=', 'member_plans.id') - ->select('members.member_id','members.name','member_plans.start AS startdate','member_plans.end AS enddate') - ->groupBy('claims.member_id') - ->orderBy('claims.created_at', 'desc') + $memberList = DB::table('request_logs') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->leftJoin('member_plans', 'request_logs.member_id', '=', 'member_plans.member_id') + ->leftJoin('organizations', 'organizations.id', '=', 'request_logs.organization_id') + ->select('members.member_id','members.name','member_plans.start AS startdate','member_plans.end AS enddate', 'request_logs.submission_date as addmision_date', 'organizations.name as provider' ) + ->where('request_logs.service_code', 'IP') + ->where('request_logs.status_final_log', 'approved') + ->groupBy('request_logs.member_id') + ->orderBy('request_logs.created_at', 'desc') ->get(); return response()->json([ @@ -62,15 +65,14 @@ class DailyMonitoringController extends Controller ->where('member_id', $member_id) ->first(); - $claimList = DB::table('claims') - ->leftJoin('claim_requests', 'claims.claim_request_id', '=', 'claim_requests.id') - ->leftJoin('claim_history_cares', 'claims.id', '=', 'claim_history_cares.claim_id') - ->leftJoin('services', 'claim_requests.service_code', '=', 'services.code') - ->leftJoin('members', 'claims.member_id', '=', 'members.id') - ->select('claims.id AS claim_id','claim_history_cares.admission_date','claim_history_cares.discharge_date','claim_requests.code AS claim_code','services.name AS service_type','claims.status AS claim_status','members.member_id',) - ->where("claims.member_id", "=", $memberDetail->id) - ->where("claim_requests.claim_id", "!=",null) - ->orderBy("claims.created_at", "desc") + $claimList = DB::table('request_logs') + ->leftJoin('services', 'services.code', '=', 'request_logs.service_code') + ->leftJoin('members', 'members.id', '=', 'request_logs.member_id') + ->select('request_logs.id','request_logs.submission_date AS admission_date','request_logs.discharge_date','request_logs.code','services.name as service_name','request_logs.status','members.name',) + ->where('request_logs.service_code', 'IP') + ->where('request_logs.status_final_log', 'approved') + ->where("request_logs.member_id", "=", $memberDetail->id) + ->orderBy("request_logs.created_at", "desc") ->get(); return response()->json([ diff --git a/Modules/Internal/Http/Controllers/Api/RequestLogBenefitController.php b/Modules/Internal/Http/Controllers/Api/RequestLogBenefitController.php new file mode 100644 index 00000000..97788e6f --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/RequestLogBenefitController.php @@ -0,0 +1,141 @@ + 'Kolom :attribute wajib diisi.', + 'numeric' => 'Kolom :attribute harus berupa angka.', + ]; + + $validator = Validator::make($request->all(), [ + 'benefit_data' => 'required|array', + 'benefit_data.*' => 'required', + ], $customMessages); + + if ($validator->fails()) { + return Helper::responseJson([],'error', 400, $validator->errors()); + } else { + $benefitData = $request->benefit_data; + + if (count($benefitData)>0){ + // BeginTransaction + DB::beginTransaction(); + foreach($benefitData as $key => $value){ + $data = [ + 'request_log_id' => $value['request_log_id'], + 'benefit_id' => $value['benefit_id'], + 'amount_incurred' => $value['amount_incurred'], + 'amount_approved' => $value['amount_approved'], + 'amount_not_approved' => $value['amount_not_approved'], + 'excess_paid' => $value['excess_paid'], + 'keterangan' => $value['keterangan'], + + ]; + // Insert Data + try { + RequestLogBenefit::create($data); + } catch (\Throwable $th) { + DB::rollBack(); + return Helper::responseJson(status: 'failed', statusCode: 500, message: $th->getMessage()); + } + } + DB::commit(); + return Helper::responseJson(status: 'success', statusCode: 201, message: 'success', data: $request->toArray()); + }; + + } + + + $requestLogBenefit = RequestLogBenefit::insert($data); + return $requestLogBenefit; + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + return view('internal::edit'); + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + $requestLogBenefit = requestLogBenefit::findOrFail($id); + $requestLogBenefit->amount_approved = $request->amount_approved; + $requestLogBenefit->amount_incurred = $request->amount_incurred; + $requestLogBenefit->amount_not_approved = $request->amount_not_approved; + $requestLogBenefit->excess_paid = $request->excess_paid; + $requestLogBenefit->keterangan = $request->keterangan; + + $requestLogBenefit->save(); + + return response()->json([ + 'error' => false, + 'message' => 'Update succses', + 'data' => $requestLogBenefit], + 200); + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + $requestLogBenefit = RequestLogBenefit::findOrFail($id); + $requestLogBenefit->delete(); + } + +} diff --git a/Modules/Internal/Http/Controllers/Api/RequestLogController.php b/Modules/Internal/Http/Controllers/Api/RequestLogController.php index 23a99492..ba8e088f 100644 --- a/Modules/Internal/Http/Controllers/Api/RequestLogController.php +++ b/Modules/Internal/Http/Controllers/Api/RequestLogController.php @@ -57,8 +57,11 @@ class RequestLogController extends Controller ->when(empty($request->orderBy), function ($q) { $q->orderBy('created_at', 'desc'); }) - ->when($request->status, function($q, $status) { - $q->where('status', $status); + ->when($request->final_log, function($q, $final_log) { + $q->where('final_log', $final_log); + }) + ->when($request->service_code, function($q, $service_code) { + $q->where('service_code', $service_code); }) // ->where('status', $request->status) ->with(['member', 'files', 'service', 'member.currentPolicy']) @@ -165,6 +168,9 @@ class RequestLogController extends Controller }, 'files', 'member', + 'member.currentPlan' => function($memberPlan) { + $memberPlan->join('request_logs', 'request_logs.service_code', '=', 'plans.service_code'); + }, 'claim', 'organization', ]); @@ -293,9 +299,21 @@ class RequestLogController extends Controller ]); } - public function updateFinalLog(Request $request, $id) + /** + * Submit Request LOG to Final LOG + */ + public function updateFinalLog(Request $request) { + $id = $request->id; $requestLog = RequestLog::findOrFail($id); + $status = $request->status ?? 'requested'; + + + // Update Request LOG untuk lanjut ke Final LOG + $requestLog->final_log = 1; + $requestLog->status_final_log = $status; + $requestLog->save(); + if ($request->hasFile('result_files')) { foreach ($request->result_files as $file) { @@ -335,7 +353,7 @@ class RequestLogController extends Controller 'name' => File::getFileName('final-log-kondisi', $id, $file), 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), - 'path' => $pathFile, + 'path' => $pathFile, 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, ]); @@ -345,7 +363,7 @@ class RequestLogController extends Controller return response()->json([ 'error' => false, 'message' => 'Update succses', - 'data' => $updateClaimRequest], + 'data' => $requestLog], 200); } diff --git a/Modules/Internal/Http/Controllers/Api/RequestLogMedicineController.php b/Modules/Internal/Http/Controllers/Api/RequestLogMedicineController.php new file mode 100644 index 00000000..d9aaeb59 --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/RequestLogMedicineController.php @@ -0,0 +1,136 @@ + 'Kolom :attribute wajib diisi.', + 'numeric' => 'Kolom :attribute harus berupa angka.', + ]; + + $validator = Validator::make($request->all(), [ + 'medicine' => 'required|array', + 'medicine.*' => 'required', + ], $customMessages); + + if ($validator->fails()) { + return Helper::responseJson([],'error', 400, $validator->errors()); + } else { + $medicine = $request->medicine; + + if (count($medicine)>0){ + // BeginTransaction + DB::beginTransaction(); + foreach($medicine as $key => $value){ + $data = [ + 'request_log_id' => $value['request_log_id'], + 'medicine' => $value['medicine_name'], + 'price' => $value['medicine_price'], + ]; + // Insert Data + try { + RequestLogMedicine::create($data); + } catch (\Throwable $th) { + DB::rollBack(); + return Helper::responseJson(status: 'failed', statusCode: 500, message: $th->getMessage()); + } + } + DB::commit(); + return Helper::responseJson(status: 'success', statusCode: 201, message: 'success', data: $request->toArray()); + }; + + } + + + $requestLogMedicine = RequestLogMedicine::insert($data); + return $requestLogMedicine; + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + return view('internal::edit'); + } + + /** + * Update the specified resource in storage. + * @param Request $request + * @param int $id + * @return Renderable + */ + public function update(Request $request, $id) + { + $requestLogBenefit = requestLogBenefit::findOrFail($id); + $requestLogBenefit->amount_approved = $request->amount_approved; + $requestLogBenefit->amount_incurred = $request->amount_incurred; + $requestLogBenefit->amount_not_approved = $request->amount_not_approved; + $requestLogBenefit->excess_paid = $request->excess_paid; + $requestLogBenefit->keterangan = $request->keterangan; + + $requestLogBenefit->save(); + + return response()->json([ + 'error' => false, + 'message' => 'Update succses', + 'data' => $requestLogBenefit], + 200); + } + + /** + * Remove the specified resource from storage. + * @param int $id + * @return Renderable + */ + public function destroy($id) + { + $RequestLogMedicine = RequestLogMedicine::findOrFail($id); + $RequestLogMedicine->delete(); + } + +} diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 1977019a..c97454bd 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -7,8 +7,10 @@ use Modules\Internal\Http\Controllers\Api\AppointmentController; use Modules\Internal\Http\Controllers\Api\BenefitController; use Modules\Internal\Http\Controllers\Api\CityController; use Modules\Internal\Http\Controllers\Api\ClaimController; -use Modules\Internal\Http\Controllers\Api\RequestLogController; use Modules\Internal\Http\Controllers\Api\ClaimRequestController; +use Modules\Internal\Http\Controllers\Api\RequestLogController; +use Modules\Internal\Http\Controllers\Api\RequestLogBenefitController; +use Modules\Internal\Http\Controllers\Api\RequestLogMedicineController; use Modules\Internal\Http\Controllers\Api\CorporateBenefitController; use Modules\Internal\Http\Controllers\Api\CorporateController; use Modules\Internal\Http\Controllers\Api\CorporateFormulariumController; @@ -251,12 +253,23 @@ Route::prefix('internal')->group(function () { Route::get('customer-service/request', [RequestLogController::class, 'index']); Route::post('customer-service/request', [RequestLogController::class, 'createNew']); Route::put('customer-service/request/{id}', [RequestLogController::class, 'update']); + Route::get('customer-service/request/{id}', [RequestLogController::class, 'show']); Route::get('customer-service/request/{id}/download', [RequestLogController::class, 'generateRequestLog']); Route::post('customer-service/request/import', [RequestLogController::class, 'importRequestLog']); Route::get('customer-service/request/data', [RequestLogController::class, 'generateDataRequestLogExcel']); - - + Route::post('customer-service/request/final-log', [RequestLogController::class, 'updateFinalLog']); + + // insert benefit + Route::post('customer-service/request/insert-benefit', [RequestLogBenefitController::class, 'store']); + Route::delete('customer-service/request/benefit_data/{id}', [RequestLogBenefitController::class, 'destroy']); + Route::put('customer-service/request/benefit_data/{id}', [RequestLogBenefitController::class, 'update']); + + // insert medicine + Route::post('customer-service/request/medicine-data', [RequestLogMedicineController::class, 'store']); + Route::delete('customer-service/request/medicine-data/{id}', [RequestLogMedicineController::class, 'destroy']); + Route::put('customer-service/request/medicine-data/{id}', [RequestLogMedicineController::class, 'update']); + Route::get('search-organizations', [OrganizationController::class, 'searchOrganization']); Route::get('search-specialities', [SpecialityController::class, 'searchSpeciality']); Route::resource('organizations', OrganizationController::class); diff --git a/Modules/Internal/Transformers/RequestLogResource.php b/Modules/Internal/Transformers/RequestLogResource.php index bb900cfd..06b43fa2 100644 --- a/Modules/Internal/Transformers/RequestLogResource.php +++ b/Modules/Internal/Transformers/RequestLogResource.php @@ -23,8 +23,9 @@ class RequestLogResource extends JsonResource 'id' => $this->id, 'code' => $this->code, 'submission_date' => $this->submission_date, - 'member' => $this->member, + 'member_name' => $this->member->name, 'status' => $this->status ?? 'unknown', + 'status_final_log' => $this->status_final_log ?? 'unknown', 'service_name' => $this->service ? $this->service->name : '', 'payment_type' => $this->payment_type, 'payment_type_name' => $this->payment_type_name, diff --git a/Modules/Internal/Transformers/RequestLogShowResource.php b/Modules/Internal/Transformers/RequestLogShowResource.php new file mode 100644 index 00000000..480eb3f1 --- /dev/null +++ b/Modules/Internal/Transformers/RequestLogShowResource.php @@ -0,0 +1,93 @@ +where('plan_id', $corporateId)->get()->toArray(); + $benefitDetailLog = RequestLogBenefit::with('benefit')->where('request_log_id', $requestLog['id'])->get()->toArray(); + $medicineDetailLog = RequestLogMedicine::where('request_log_id', $requestLog['id'])->get()->toArray(); + $benefitData = []; + if (count($benefit)){ + foreach($benefit as $data){ + array_push($benefitData, $data['benefit']); + } + } + + // Medicine + $medicineData = []; + if (count($medicineDetailLog)){ + foreach($medicineDetailLog as $data){ + array_push($medicineData, $data); + } + } + // Service Rule + $corporateService = CorporateService::query() + ->where('corporate_id', $corporateId) + ->where('service_code', $requestLog['service_code']) + ->with(['configs']) + ->first(); + $config = []; + if ($corporateService) { + $config = $corporateService->configs->pluck('value', 'name')->toArray(); + } + + // Exclusion Service or diagnosis + $exclusions = Exclusion::query() + ->where('corporate_id', $corporateId) + ->where('type', 'diagnosis') + ->with(['exclusionable', 'rules']) + ->get()->toArray(); + + $data = [ + 'id' => $requestLog['id'], + 'code' => $requestLog['code'], + 'member_id' => $requestLog['member']['member_id'], + 'policy_number' => $requestLog['member']['current_policy']['code'], + 'name' => $requestLog['member']['name'], + 'date_of_birth' => $requestLog['member']['birth_date'], + 'gender' => $requestLog['member']['gender'], + 'marital_status' => Helper::maritalNormalization($requestLog['member']['marital_status']), + 'member_type' => Helper::memberType($requestLog['member']['record_type']), + 'principal_id' => $requestLog['member']['principal_id'] ? $requestLog['member']['principal_id'] : '-', + 'principal_name' => $requestLog['member']['principal_id'] ? Helper::principalName($requestLog['member']['principal_id']) : '-', + 'relation_with_principal' => Helper::relationWithPrincipal($requestLog['member']['relation_with_principal']), + 'submission_date' => $requestLog['submission_date'], + 'service_type' => Helper::serviceName($requestLog['service_code']), + 'claim_method' => $requestLog['payment_type'], + 'status' => $requestLog['status'], + 'status_final_log' => $requestLog['status_final_log'], + 'benefit' => $benefitData, + 'benefit_data' => $benefitDetailLog, + 'config_service' => $config, + 'exclusion' => $exclusions, + 'medicine' => $medicineData, + 'files' => $requestLog['files'], + + + ]; + + return $data; + } +} diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 59629850..5ce5c9a4 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -8,24 +8,39 @@ use Illuminate\Http\JsonResponse; use Symfony\Component\HttpFoundation\Response; use PHPMailer\PHPMailer\PHPMailer; use Illuminate\Support\Facades\DB; +use App\Models\Member; +use App\Models\Service; class Helper { public static function genderNormalization($anyGenderCode) { if ($anyGenderCode == 'M') { - return 'male'; + return 'Male'; } else if ($anyGenderCode == 'F') { - return 'female'; + return 'Female'; } else if ($anyGenderCode == 'O') { - return 'others'; + return 'Others'; } else if ($anyGenderCode == 'U') { - return 'unknown'; + return 'Unknown'; } else { return null; } } + public static function maritalNormalization($code) + { + if ($code == 'M') { + return 'Married'; + } else if ($code == 'D') { + return 'Divorced'; + } else if ($code == 'S') { + return 'Single'; + } else { + return '-'; + } + } + public static function genderPerson($anyGenderCode) { if ($anyGenderCode == 'M') { @@ -41,6 +56,44 @@ class Helper } } + public static function memberType($code){ + if ($code == 'P') { + return 'Principal'; + } else if ($code == 'D') { + return 'Dependent'; + } else { + '-'; + } + } + + public static function relationWithPrincipal($code){ + if ($code == 'H') { + return 'Husbund'; + } + else if ($code == 'W') { + return 'Wife'; + } + else if ($code == 'S') { + return 'Son'; + } + else if ($code == 'D') { + return 'Daughter'; + } + else { + '-'; + } + } + + public static function principalName($code){ + $principalName = Member::where('member_id', $code)->get()->first(); + return $principalName->name; + } + + public static function serviceName($code){ + $serviceName = Service::where('code', $code)->get()->first(); + return $serviceName->name; + } + public static function paginateResources($resource) { return [ diff --git a/app/Models/ClaimRequest.php b/app/Models/ClaimRequest.php index c6f2c68b..6622efc4 100644 --- a/app/Models/ClaimRequest.php +++ b/app/Models/ClaimRequest.php @@ -27,7 +27,8 @@ class ClaimRequest extends Model 'status', 'claim_id', 'organization_id', - 'code' + 'code', + 'request_log_id' ]; protected $hidden = [ diff --git a/app/Models/File.php b/app/Models/File.php index f172de82..627dc1a4 100644 --- a/app/Models/File.php +++ b/app/Models/File.php @@ -19,6 +19,8 @@ class File extends Model 'original_name', 'extension', 'path', + 'created_by', + 'updated_by', ]; protected $hidden = [ @@ -44,7 +46,11 @@ class File extends Model 'claim-diagnosis' => 'claim/', 'claim-kondisi' => 'claim/', 'claim-invoice' => 'claim/', + 'final-log-result' => 'final-log/', + 'final-log-diagnosis' => 'final-log/', + 'final-log-kondisi' => 'final-log/', 'docs' => 'docs/', + 'additional-files' => 'additional-files/', ]; public function fileable() @@ -54,7 +60,7 @@ class File extends Model public static function getDirectory($type) { - return self::$file_directories[$type] ?? 'any'; + return self::$file_directories[$type] ?? 'any/'; } public static function getFileName($type, $id) diff --git a/app/Models/OrganizationUser.php b/app/Models/OrganizationUser.php new file mode 100644 index 00000000..21f98751 --- /dev/null +++ b/app/Models/OrganizationUser.php @@ -0,0 +1,20 @@ +hasOne(Organization::class, 'id', 'organization_id'); + } +} diff --git a/app/Models/RequestLog.php b/app/Models/RequestLog.php index 827cd846..8f93fd52 100644 --- a/app/Models/RequestLog.php +++ b/app/Models/RequestLog.php @@ -24,7 +24,9 @@ class RequestLog extends Model 'payment_type', 'service_code', 'policy_id', + 'final_log', 'status', + 'status_final_log', 'source', 'claim_id', 'organization_id', diff --git a/app/Models/RequestLogBenefit.php b/app/Models/RequestLogBenefit.php new file mode 100644 index 00000000..331227f1 --- /dev/null +++ b/app/Models/RequestLogBenefit.php @@ -0,0 +1,27 @@ +belongsTo(Benefit::class, 'benefit_id', 'id'); + } +} diff --git a/app/Models/RequestLogMedicine.php b/app/Models/RequestLogMedicine.php new file mode 100644 index 00000000..2cd1cec8 --- /dev/null +++ b/app/Models/RequestLogMedicine.php @@ -0,0 +1,30 @@ +belongsTo(Benefit::class, 'benefit_id', 'id'); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index d4090eca..22b1bee4 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -105,4 +105,9 @@ class User extends Authenticatable { return $this->morphMany(NotificationToken::class, 'notifiabletoken'); } + + public function getOrganization() + { + return $this->hasOne(OrganizationUser::class, 'user_id'); + } } diff --git a/app/Services/ClaimRequestService.php b/app/Services/ClaimRequestService.php index b03cabc9..71626fc4 100644 --- a/app/Services/ClaimRequestService.php +++ b/app/Services/ClaimRequestService.php @@ -20,7 +20,7 @@ use Str; class ClaimRequestService{ - public static function storeClaimRequest($row = null, $code, $member, $paymentType, $serviceCode, $submissionDate = null, $status = 'requested', $organization_code = null) + public static function storeClaimRequest($row = null, $code, $member, $paymentType, $serviceCode, $requestLogID, $submissionDate = null, $status = 'requested', $organization_code = null) { // try { $organization = False; @@ -38,6 +38,7 @@ class ClaimRequestService{ $claimRequestData = [ 'code' => $code, + 'request_log_id' => $requestLogID, 'member_id' => $member->id, 'submission_date' => $submissionDate ?? now(), 'status' => $status, diff --git a/app/Services/RequestLogService.php b/app/Services/RequestLogService.php index 76d124cb..5a5a5c64 100644 --- a/app/Services/RequestLogService.php +++ b/app/Services/RequestLogService.php @@ -154,12 +154,16 @@ class RequestLogService{ } // Update Request LOG Status & Link with Claim - $requestLog->update([ - 'status' => $row['status'] - ]); - $requestLog->save(); + DB::beginTransaction(); + $requestLog->update([ + 'status' => $row['status'] + ]); + $requestLog->save(); + DB::commit(); return $requestLog; } catch (\Exception $e) { + DB::rollBack(); + throw $e; } } diff --git a/database/migrations/2023_11_07_124118_add_columns_corporate_id_to_users_table.php b/database/migrations/2023_11_07_124118_add_columns_corporate_id_to_users_table.php new file mode 100644 index 00000000..78f562be --- /dev/null +++ b/database/migrations/2023_11_07_124118_add_columns_corporate_id_to_users_table.php @@ -0,0 +1,32 @@ +integer('corporate_id')->default(0)->after('phone'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('corporate_id'); + }); + } +}; diff --git a/database/migrations/2023_11_30_092154_add_columns_to_request_logs.php b/database/migrations/2023_11_30_092154_add_columns_to_request_logs.php new file mode 100644 index 00000000..94df90fd --- /dev/null +++ b/database/migrations/2023_11_30_092154_add_columns_to_request_logs.php @@ -0,0 +1,35 @@ +integer('final_log') + ->default(0) + ->after('status') + ->comment('untuk flag request masuk ke final, jika 0 masih request dan 1 itu sudah masuk ke finallog'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('request_logs', function (Blueprint $table) { + $table->dropColumn('final_log'); + }); + } +}; diff --git a/database/migrations/2023_11_30_101523_add_columns_to_request_logs.php b/database/migrations/2023_11_30_101523_add_columns_to_request_logs.php new file mode 100644 index 00000000..ded8a874 --- /dev/null +++ b/database/migrations/2023_11_30_101523_add_columns_to_request_logs.php @@ -0,0 +1,32 @@ +string('status_final_log')->after('status')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('request_logs', function (Blueprint $table) { + $table->dropColumn('status_final_log'); + }); + } +}; diff --git a/database/migrations/2023_12_09_090301_create_organization_user.php b/database/migrations/2023_12_09_090301_create_organization_user.php new file mode 100644 index 00000000..320d9227 --- /dev/null +++ b/database/migrations/2023_12_09_090301_create_organization_user.php @@ -0,0 +1,34 @@ +id(); + $table->foreignId('user_id'); + $table->foreignId('organization_id'); + $table->integer('status')->nullable()->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('organization_user'); + } +}; diff --git a/database/migrations/2023_12_11_100126_create_request_log_benefits_table.php b/database/migrations/2023_12_11_100126_create_request_log_benefits_table.php new file mode 100644 index 00000000..070b64d9 --- /dev/null +++ b/database/migrations/2023_12_11_100126_create_request_log_benefits_table.php @@ -0,0 +1,38 @@ +id(); + $table->timestamps(); + $table->foreignId('request_log_id'); + $table->foreignId('benefit_id'); + $table->integer('amount_incurred'); + $table->integer('amount_approved'); + $table->integer('amount_not_approved'); + $table->integer('excess_paid'); + $table->string('keterangan'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('request_log_benefits'); + } +}; diff --git a/database/migrations/2023_12_13_091954_create_request_log_medicines_table.php b/database/migrations/2023_12_13_091954_create_request_log_medicines_table.php new file mode 100644 index 00000000..3013006a --- /dev/null +++ b/database/migrations/2023_12_13_091954_create_request_log_medicines_table.php @@ -0,0 +1,34 @@ +id(); + $table->timestamps(); + $table->foreignId('request_log_id'); + $table->integer('price'); + $table->string('medicine'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('request_log_medicines'); + } +}; diff --git a/database/migrations/2023_12_15_153059_add_columns_to_request_logs.php b/database/migrations/2023_12_15_153059_add_columns_to_request_logs.php new file mode 100644 index 00000000..81bb25c6 --- /dev/null +++ b/database/migrations/2023_12_15_153059_add_columns_to_request_logs.php @@ -0,0 +1,32 @@ +dateTime('discharge_date')->after('submission_date')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('request_logs', function (Blueprint $table) { + $table->dropColumn('discharge_date'); + }); + } +}; diff --git a/database/migrations/2023_10_27_111432_create_claim_daily_monitoring_table.php b/database/migrations/2023_12_15_154820_create_request_log_daily_monitoring_table.php similarity index 66% rename from database/migrations/2023_10_27_111432_create_claim_daily_monitoring_table.php rename to database/migrations/2023_12_15_154820_create_request_log_daily_monitoring_table.php index 61713605..f09cf94e 100644 --- a/database/migrations/2023_10_27_111432_create_claim_daily_monitoring_table.php +++ b/database/migrations/2023_12_15_154820_create_request_log_daily_monitoring_table.php @@ -13,9 +13,10 @@ return new class extends Migration */ public function up() { - Schema::create('claim_daily_monitoring', function (Blueprint $table) { - $table->bigIncrements('id'); - $table->integer('claim_id'); + Schema::create('request_log_daily_monitorings', function (Blueprint $table) { + $table->id(); + $table->foreignId('request_log_id'); + $table->timestamps(); $table->text('subject'); $table->decimal('body_temperature', 11, 2); $table->decimal('respiration_rate', 11, 2); @@ -23,7 +24,9 @@ return new class extends Migration $table->decimal('diastole', 11, 2); $table->text('analysis'); $table->text('complaints'); - $table->timestamps(); + $table->dateTime('lab_date')->nullable(); + $table->string('provider')->nullable(); + $table->string('examination')->nullable(); }); } @@ -34,6 +37,6 @@ return new class extends Migration */ public function down() { - Schema::dropIfExists('claim_daily_monitoring'); + Schema::dropIfExists('request_log_daily_monitorings'); } }; diff --git a/frontend/dashboard/src/@types/claims.ts b/frontend/dashboard/src/@types/claims.ts index 15c068bc..61e098cc 100644 --- a/frontend/dashboard/src/@types/claims.ts +++ b/frontend/dashboard/src/@types/claims.ts @@ -61,7 +61,7 @@ export type ClaimHistoryCare = { id: number; claim_id: number; service_code: string; - admision_date: string; + admission_date: string; discharge_date: string; main_diagnosis_id: number; main_diagnosis_name: string; diff --git a/frontend/dashboard/src/@types/member.ts b/frontend/dashboard/src/@types/member.ts index bd2edf24..45bfc833 100644 --- a/frontend/dashboard/src/@types/member.ts +++ b/frontend/dashboard/src/@types/member.ts @@ -22,4 +22,5 @@ export type Member = { active: string, current_plans: Plan, current_corporate: Corporate, + full_name: string, }; diff --git a/frontend/dashboard/src/components/MuiDialog.tsx b/frontend/dashboard/src/components/MuiDialog.tsx index 54ee1110..c9b57835 100644 --- a/frontend/dashboard/src/components/MuiDialog.tsx +++ b/frontend/dashboard/src/components/MuiDialog.tsx @@ -1,4 +1,4 @@ -import { Dialog, DialogTitle, DialogContent, Stack, Typography, IconButton } from '@mui/material'; +import { Dialog, DialogTitle, DialogContent, Stack, Typography, IconButton, DialogActions } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; import { ReactElement } from 'react'; import Iconify from './Iconify'; @@ -13,12 +13,13 @@ type MuiDialogProps = { openDialog: boolean; setOpenDialog: Function; content?: ReactElement; + action?: ReactElement|null; maxWidth?: string; }; // ---------------------------------------------------------------------- -const MuiDialog = ({ title, openDialog, setOpenDialog, content, maxWidth }: MuiDialogProps) => { +const MuiDialog = ({ title, openDialog, setOpenDialog, content, action, maxWidth }: MuiDialogProps) => { const handleClose = () => { setOpenDialog(false); }; @@ -46,9 +47,15 @@ const MuiDialog = ({ title, openDialog, setOpenDialog, content, maxWidth }: MuiD + {content ? content : 'Testing Content Dialog'} + + {action ? ( + {action} + ) : ''} + ); }; diff --git a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx index 3ca34a56..0827cd38 100644 --- a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx @@ -77,6 +77,7 @@ const navConfig = [ children: [ { title: 'Daily Monitoring', path: '/case_management/daily_monitoring' }, { title: 'Laboratorium Result', path: '/case_management/laboratorium_result' }, + { title: 'Inpatient Monitoring', path: '/case_management/inpatient_monitoring' }, ], }, { @@ -84,7 +85,7 @@ const navConfig = [ children: [ { title: 'Request', path: '/custormer-service/request' }, // { title: 'Membership', path: '/cs-membership' }, - { title: 'Final LOG', path: '/custormer-service/final-request' }, + { title: 'Final LOG', path: '/custormer-service/final-log' }, ], }, { diff --git a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/ClaimListRow.tsx b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/ClaimListRow.tsx index d89c0ef7..67e46a89 100644 --- a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/ClaimListRow.tsx +++ b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/ClaimListRow.tsx @@ -37,7 +37,7 @@ export default function ClaimListRow ({ ...props }: Props) { td': { borderBottom: '1' } }}> - {props.row.admission_date == "0000-00-00 00:00:00" ? + {props.row.admission_date == null? ('-') : ( @@ -50,7 +50,7 @@ export default function ClaimListRow ({ ...props }: Props) { )} - {props.row.discharge_date == "0000-00-00 00:00:00" ? + {props.row.discharge_date == null ? ('-') : ( @@ -62,9 +62,29 @@ export default function ClaimListRow ({ ...props }: Props) { )} - {props.row.claim_code} - {props.row.service_type} - {props.row.claim_status} + {props.row.code} + {props.row.service_name} + + {props.row.discharge_date == null ? + ( + + ) : + ( + + ) + } + + e.stopPropagation()}> Name Start Date End Date + Admission Date + Provider diff --git a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DailyMonitoringListRow.tsx b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DailyMonitoringListRow.tsx index 40dc5395..2b6df13b 100644 --- a/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DailyMonitoringListRow.tsx +++ b/frontend/dashboard/src/pages/CaseManagement/DailyMonitoring/Components/DailyMonitoringListRow.tsx @@ -53,6 +53,15 @@ export default function DailyMonitoringListRow ({ ...props }: Props) { {fDate(props.row.enddate)} + + + + {props.row.provider} e.stopPropagation()}> + + + + {/* */} + + {/* */} + + ); +} diff --git a/frontend/dashboard/src/pages/CaseManagement/InpatientMonitoring/List.tsx b/frontend/dashboard/src/pages/CaseManagement/InpatientMonitoring/List.tsx new file mode 100644 index 00000000..f734db68 --- /dev/null +++ b/frontend/dashboard/src/pages/CaseManagement/InpatientMonitoring/List.tsx @@ -0,0 +1,582 @@ +// @mui +import { + Box, + Button, + Card, + Collapse, + IconButton, + MenuItem, + Table, + TableBody, + TableCell, + TableRow, + TextField, + Typography, + Stack, + Menu, + ButtonGroup, + Link, + Chip, + TableHead, + Grid, +} 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 FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; +import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; +// hooks +import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; +import useSettings from '@/hooks/useSettings'; +// components +import axios from '../../../utils/axios'; +import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../../@types/paginated-data'; +import DataTable from '../../../components/LaravelTable'; +import { fCurrency } from '../../../utils/formatNumber'; +import EditRoundedIcon from '@mui/icons-material/EditRounded'; +import { LoadingButton } from '@mui/lab'; +import { enqueueSnackbar } from 'notistack'; +import { Divider } from '@mui/material'; +import Iconify from '@/components/Iconify'; +import DialogDetailClaim from '@/components/dialogs/DialogDetailClaim'; +import { fDateTimesecond } from '@/utils/formatTime'; +import { capitalizeFirstLetter } from '@/utils/formatString'; +import Label from '@/components/Label'; +import TableMoreMenu from '@/components/table/TableMoreMenu'; +import { Import } from '@/@types/claims'; + +import { FinalLogType } from '../../CustomerService/FinalLog/Model/Types'; +// import LoadingButton from '@/theme/overrides/LoadingButton'; + +export default function List() { + const { themeColorPresets } = useSettings(); + const [searchParams, setSearchParams] = useSearchParams(); + const [importResult, setImportResult] = useState(null); + + const navigate = useNavigate() + + 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({ search: searchText }); // Trigger to Parent + }; + + useEffect(() => { + // Trigger First Search + setSearchText(searchParams.get('search') ?? ''); + }, []); + + 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 [importLoading, setImportLoading] = useState(false); + + 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 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]); + + setImportLoading(true); + axios + .post(`claim-requests/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'); + setImportLoading(false); + }) + .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 = (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(); + }) + } + + const handleGetData = (type :string) => { + axios.get(`corporates/${corporate_id}/data-plan-benefit`) + .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 && ( + + + + + Import + {handleGetTemplate('claim-request')}}>Download Template + {handleGetData('data-plan-benefit')}}>Download Claim Request + + {/* */} + + )} + + {currentImportFileName && ( + + + + + + + } + sx={{ p: 1.8 }} + onClick={handleUpload} + loading={importLoading} + > + Upload + + + )} + {importResult && ( + + + Last Import Result Report :{' '} + + {importResult.result_file?.name ?? '-'} + + + + )} +
+ ); + } + + // Dummy Default Data + const [dataTableIsLoading, setDataTableLoading] = useState(true); + const [dataTableData, setDataTableData] = useState( + LaravelPaginatedDataDefault + ); + + const loadDataTableData = async (appliedFilter: any | null = null) => { + setDataTableLoading(true); + const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); + const response = await axios.get('/customer-service/request?final_log=1&service_code=IP', { params: filter }); + // console.log(response.data); + setDataTableLoading(false); + + setDataTableData(response.data); + }; + + const applyFilter = async (searchFilter: { search: string }) => { + await loadDataTableData(searchFilter); + setSearchParams(searchFilter); + }; + + const handlePageChange = (event: ChangeEvent, value: number): void => { + const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]); + loadDataTableData(filter); + setSearchParams(filter); + }; + + const handleApprove = (claimRequest) => { + axios + .post(`claim-requests/${claimRequest.id}/approve`) + .then((response) => { + enqueueSnackbar('Success Approve', { variant: 'success' }); + loadDataTableData(); + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + }; + + useEffect(() => { + loadDataTableData(); + }, []); + + const headStyle = { + fontWeight: 'bold', + }; + + // Called on every row to map the data to the columns + function createData(data: FinalLogType) { + return { + ...data, + }; + } + + { + /* ------------------ TABLE ROW ------------------ */ + } + function Row(props: { row: ReturnType }) { + const { row } = props; + const [open, setOpen] = React.useState(false); + const [loadingApprove, setLoadingApprove] = React.useState(false); + + return ( + + *': { borderBottom: 'unset' } }}> + {/* + setOpen(!open)}> + {open ? : } + + */ } + {/* + { + // handleShowClaim(row); + // }} + > + {row.id} + + */} + {row.code} + {row.member_name} + + {row.service_name} + {row.payment_type_name} + + { row.status_final_log == "requested" ? + () : + row.status_final_log == "declined" ? + () + : + () + } + + + + {/* navigate(`/claim-requests/edit/${row.id}`)}> + + Edit + */} + navigate ('/custormer-service/final-log/detail/'+row.id+'')}> + + Detail + + + } /> + + {/* + + { + handleShowClaim(row); + }} + > + + + */} + + {/* COLLAPSIBLE ROW */} + + + + + } + spacing={1} + sx={{ marginY: 2 }} + > + + Berkas Hasil Penunjang + {/* {row.files_by_type?.claim_kondisi && + row.files_by_type?.claim_kondisi.map((file, index) => ( + + -{' '} + + {file.name} + + + ))} */} + + {row.files_by_type?.claim_kondisi && ( + <> + - Kondisi + {row.files_by_type?.claim_kondisi.map((file, index) => ( + + + + {file.name} + + + ))} + + )} + + {row.files_by_type?.claim_diagnosis && ( + <> + - Diagnosa + {row.files_by_type?.claim_diagnosis.map((file, index) => ( + + + + {file.name} + + + ))} + + )} + + {row.files_by_type?.claim_result && ( + <> + - Hasil + {row.files_by_type?.claim_result.map((file, index) => ( + + + + {file.name} + + + ))} + + )} + {(!row.files_by_type?.claim_result && !row.files_by_type?.claim_diagnosis && !row.files_by_type?.claim_kondisi)&& Tidak ada berkas} + + + + + + + + ); + } + { + /* ------------------ END TABLE ROW ------------------ */ + } + + function TableContent() { + return ( + + {/* ------------------ TABLE HEADER ------------------ */} + + + {/* */} + {/* + ID Request LOG + */} + + Code + + + Name + + + Date of Submission + + + Service Type + + + Claim Method + + + Status + + + + + {/* ------------------ END TABLE HEADER ------------------ */} + + {/* ------------------ TABLE ROW ------------------ */} + {dataTableIsLoading ? ( + + + + Loading + + + + ) : dataTableData.data.length === 0 ? ( + + + + No Data + + + + ) : ( + + {dataTableData.data.map((row) => ( + + ))} + + )} + {/* ------------------ END TABLE ROW ------------------ */} +
+ ); + } + + // --------------------------------------------------------- + // Dialog Detail Claim Request + const [openDialogDetailClaim, setOpenDialogDetailClaim] = useState(false); + const [loadingClaimDetail, setLoadingClaimDetail] = useState(true); + const [currentClaim, setCurrentClaim] = useState(null); + + function handleShowClaim(claimRequest) { + setLoadingClaimDetail(true); + setOpenDialogDetailClaim(true); + + axios + .get(`/claim-requests/${claimRequest.id}`) + .then(({ data }) => { + setCurrentClaim(data.data); + setLoadingClaimDetail(false); + }) + .catch((err) => { + enqueueSnackbar(err.message, { variant: 'error' }); + }); + } + + function handleDownloadLog() {} + + return ( + + + + + + + } + /> + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Corporates/DiagnosisExclusion/List.tsx b/frontend/dashboard/src/pages/Corporates/DiagnosisExclusion/List.tsx index 0bb45008..8f6b4c03 100644 --- a/frontend/dashboard/src/pages/Corporates/DiagnosisExclusion/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/DiagnosisExclusion/List.tsx @@ -687,7 +687,7 @@ export default function List(props: any) { - Play : + Plan : diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardBenefit.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardBenefit.tsx new file mode 100644 index 00000000..65addbfe --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardBenefit.tsx @@ -0,0 +1,214 @@ +import { Card, Grid, MenuItem, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { BenefitData, DetailFinalLogType } from "../FinalLog/Model/Types"; +import { useEffect, useState, useRef, useMemo } from 'react'; +import { Box } from "@mui/material"; + + +import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import Label from '@/components/Label'; + +import AddIcon from '@mui/icons-material/Add'; +import { Button } from "@mui/material"; +import MoreMenu from "@/components/MoreMenu"; +import { Delete, EditOutlined } from "@mui/icons-material"; +import { fNumber } from "@/utils/formatNumber"; +import palette from "@/theme/palette"; +import DialogBenefit from "../FinalLog/Components/DialogBenefit"; +import DialogEditBenefit from "../FinalLog/Components/DialogEditBenefit"; +import DialogDelete from "../FinalLog/Components/DialogDelete"; + + + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom1 = { + marginBottom: 1, +} +const marginBottom2 = { + marginBottom: 2, +} + +const [openDialogBenefit, setDialogBenefit] = useState(false); +// Handle Edit Detail Benefit +const [openDialogEditBenefit, setDialogEditBenefit] = useState(false) +const [BenefitConfigurationData, setBenefitConfigurationData] = useState(); + +// Handel Delete Detail Benefit +const [idBenefitData, setIdBenefitData] = useState(); +const [openDialogDeleteBenefit, setDialogDeleteBenefit] = useState(false) + + +export default function CardBenefit({requestLog} : CardDetail ) { + return ( + + + Benefit + + + + {requestLog?.benefit_data?.map((item, index) => ( + + + + + + + {item.benefit?.description} + + + + + { + setDialogEditBenefit(true) + setIdBenefitData(item.id) + setBenefitConfigurationData(item) + }} + > + + Edit + + { + setIdBenefitData(item.id) + setDialogDeleteBenefit(true) + }} + > + + Delete + + + } /> + + + + + + + + {/* Amount Incurred */} + + + + + Amount Incurred + + + + + {fNumber(item.amount_incurred)} + + + + + + {/* Amount Approved */} + + + + + Amount Approved + + + + + {fNumber(item.amount_approved)} + + + + + + {/* Amount Not Approved */} + + + + + Amount Not Approved + + + + + {fNumber(item.amount_not_approved)} + + + + + + {/* Excess Paid* */} + + + + + Excess Paid* + + + + + {fNumber(item.excess_paid)} + + + + + + {/* Keterangan* */} + + + + + Keterangan* + + + + + {item.keterangan} + + + + + + + + + + + + ))} + + {/* Dialog Edit */} + + + + {/* Dialog Delete */} + + + + ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardDetail.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardDetail.tsx new file mode 100644 index 00000000..39db8867 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardDetail.tsx @@ -0,0 +1,57 @@ +import { Card, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { DetailFinalLogType } from "../FinalLog/Model/Types"; +import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; + + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom1 = { + marginBottom: 1, +} +const marginBottom2 = { + marginBottom: 2, +} + + +export default function CardDetail({requestLog} : CardDetail ) { + return ( + + Detail + + Member ID + {requestLog?.member_id} + + + Policy Number + {requestLog?.policy_number} + + + Name + {requestLog?.name} + + + Date Of Birth + {requestLog?.date_of_birth ? fDate(requestLog?.date_of_birth) : '-'} + + + Marital Status + {requestLog?.marital_status} + + + Submission Date + {requestLog?.submission_date ? fDateTimesecond(requestLog?.submission_date) : '-'} + + + ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardExclusion.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardExclusion.tsx new file mode 100644 index 00000000..4369074d --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardExclusion.tsx @@ -0,0 +1,117 @@ +import { Accordion, AccordionDetails, AccordionSummary, Card, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { DetailFinalLogType } from "../FinalLog/Model/Types"; +import { toTitleCase } from "@/utils/formatTime"; +import Label from '@/components/Label'; +import { ExpandMore } from "@mui/icons-material"; + + + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom2 = { + marginBottom: 2, +} + + +export default function CardExclusion({requestLog} : CardDetail ) { + return ( + + Exclusion + {requestLog?.exclusion?.length > 0 ? requestLog?.exclusion.map((r, index) => ( + + } + aria-controls='panelia-content' + id='panel1a-header' + > + {r.exclusionable.code} + {r.exclusionable.name} + + + + MSC + + {r.rules.length > 0 && r?.rules?.map((text, i) => { + return text.name === 'msc' ? + text.values.split(',').map((text2, j) => { + let labelMSC: string = text2; + switch (labelMSC) { + case 'm': + labelMSC = 'Member'; + break; + case 'c': + labelMSC = 'Child'; + break; + case 's': + labelMSC = 'Spouse'; + break; + default: + labelMSC = 'Member'; + } + return ( + + ); + }) + : null; + })} + + + + Gender + + {r.rules.length > 0 && r?.rules?.map((text, i) => { + return text.name === 'gender' ? + text.values.split(',').map((text2, j) => { + let labelGender: string = toTitleCase(text2); + return ( + + ); + }) + : null; + })} + + + + Min Age + + {r.rules.length > 0 && r?.rules?.map((text, i) => { + return text.name === 'min_age' ? + {text.values} : null + })} + + + + Max Age + + {r.rules.length > 0 && r?.rules?.map((text, i) => { + return text.name === 'max_age' ? + {text.values} : null + })} + + + + Plan + + {r.rules.length > 0 && r?.rules?.map((text, i) => { + return text.name === 'plan' ? + {text.values} : null + })} + + + + + )) : null} + + ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx new file mode 100644 index 00000000..9cb6efb4 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardFile.tsx @@ -0,0 +1,50 @@ +import { Card, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { DetailFinalLogType } from "../FinalLog/Model/Types"; +import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; + + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom1 = { + marginBottom: 1, +} +const marginBottom2 = { + marginBottom: 2, +} + + +export default function CardFile({requestLog} : CardDetail ) { + return ( + + + + Files History + {requestLog?.files?.map((documentType, index) => ( + + + + {documentType.original_name ? documentType.original_name : '-'} + + + + ))} + + + + ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardMedicine.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardMedicine.tsx new file mode 100644 index 00000000..4054024c --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardMedicine.tsx @@ -0,0 +1,65 @@ +import { Card, Grid, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { DetailFinalLogType } from "../FinalLog/Model/Types"; +import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import DialogMedicine from "../FinalLog/Components/DialogMedicine"; +import { fNumber } from "@/utils/formatNumber"; +import { Button } from '@mui/material'; +import AddIcon from '@mui/icons-material/Add'; +import { useState } from "react"; + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom1 = { + marginBottom: 1, +} +const marginBottom2 = { + marginBottom: 2, +} + +const [openDialogMedicine, setDialogMedicine] = useState(false); + + +export default function CardMedicine({requestLog} : CardDetail ) { + return ( + + + Medicine + + + + {requestLog?.medicine.map((item, index) => ( + + {item.medicine} + Rp. {fNumber(item.price)} + + ))} + + {/* */} + + ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Components/CardService.tsx b/frontend/dashboard/src/pages/CustomerService/Components/CardService.tsx new file mode 100644 index 00000000..0ef1a11e --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Components/CardService.tsx @@ -0,0 +1,105 @@ +import { Card, Typography } from "@mui/material"; +import { Stack } from '@mui/material'; +import { DetailFinalLogType } from "../FinalLog/Model/Types"; +import { fDate, fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import Label from '@/components/Label'; + + + +type CardDetail = { + requestLog: DetailFinalLogType|undefined; + isFinalLog: boolean +} + +const style1 = { + color: '#919EAB', + width: '30%' +} +const style2 = { + width: '70%' +} +const marginBottom1 = { + marginBottom: 1, +} +const marginBottom2 = { + marginBottom: 2, +} + + +export default function CardService({requestLog, isFinalLog = true} : CardDetail ) { + return ( + + Service + + Service Type + {requestLog?.service_type} + + + Claim Method + {toTitleCase(requestLog?.claim_method ?? '-')} + + {/* + Benefit + +
    + {requestLog?.benefit.length > 0 ? requestLog?.benefit.map((r, index) => ( +
  • {r.code } - {r.description}
  • + )) :
  • -
  • } +
+
+
*/} + {/* General Practitioner */} + + General Practitioner + External Doctor : + {requestLog?.config_service?.gp_external_doctor_online == '1' ? () : '-'} + {requestLog?.config_service?.gp_external_doctor_offline == '1' ? () : '-'} + + + + + Internal Doctor : + {requestLog?.config_service?.gp_internal_doctor_online == '1' ? () : '-'} + {requestLog?.config_service?.gp_internal_doctor_offline == '1' ? () : '-'} + + + + {/* Specialist Practitioner */} + + Specialist Practitioner + External Doctor : + {requestLog?.config_service?.sp_external_doctor_online == '1' ? () : '-'} + {requestLog?.config_service?.sp_external_doctor_offline == '1' ? () : '-'} + + + + + Internal Doctor : + {requestLog?.config_service?.gp_internal_doctor_online == '1' ? () : '-'} + {requestLog?.config_service?.gp_internal_doctor_offline == '1' ? () : '-'} + + + + {/* Medicine */} + + Medicine + +
    + {requestLog?.config_service?.vitamins == '1' ? (
  • Suplemen
  • ) : (
  • -
  • )} + {requestLog?.config_service?.delivery_fee == '1' ? (
  • Delivery Fee
  • ) : (
  • -
  • )} +
+
+
+ + Admin Fee + + {requestLog?.config_service?.general_practitioner_fee == '1' ? () : '-'} + {requestLog?.config_service?.specialist_practitioner_fee == '1' ? () : '-'} + + + + +
+ ) + +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogBenefit.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogBenefit.tsx new file mode 100644 index 00000000..353b61c8 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogBenefit.tsx @@ -0,0 +1,343 @@ +import * as Yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; + +import MuiDialog from "@/components/MuiDialog"; +import { Checkbox, Typography, FormControl, Card, Grid, DialogActions } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { BenefitConfigurationListType } from "../Model/Types"; +import { InputLabel, Select, FormHelperText } from "@mui/material"; +import FormGroup from '@mui/material/FormGroup'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Button from '@mui/material/Button'; +import { fNumber } from "@/utils/formatNumber"; +import palette from "@/theme/palette"; +import { Box } from "@mui/material"; +import { FormProvider, RHFTextField } from "@/components/hook-form"; +import RHFTextFieldMoney from '@/components/hook-form/v2/RHFTextFieldMoney'; + +import { useFieldArray, useForm } from 'react-hook-form'; +import { LoadingButton } from '@mui/lab'; +import { postAddBenefit } from '../Model/Functions'; +import { useNavigate } from 'react-router'; +import { description } from '@/_mock/text'; + + +type DialogConfirmationType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + requestLog: DetailFinalLogType|undefined; +} + +type BenefitSelected = { + id: number, + description: string, + benefit_id: number, +} + + + +export default function DialogBenefit({requestLog, setOpenDialog, openDialog } : DialogConfirmationType ) { + + // Add Benefit + const [addBenefit, setAddBenefit] = useState(false) + const navigate = useNavigate() + //Benefit Name + const [valBenefitNames, setValBenefitNames] = useState([]); + const [valBenefitNameError, setValBenefitNameError] = useState(''); + const benefitNameData = requestLog?.benefit; + const [benefitSelected, setBenefitSelected] = useState([]); + + const handleConditionChangeService = (event) => { + const selectedItem = event.target.value; + + if (valBenefitNames.includes(selectedItem)) { + // Item is already selected, remove it + setValBenefitNames(valBenefitNames.filter(item => item !== selectedItem)); + } else { + // Item is not selected, add it + setValBenefitNames([...valBenefitNames, selectedItem]); + } + }; + + useEffect(() => { + const datax: any[] = [] + + valBenefitNames.map((data) => { + benefitNameData?.map((row) => { + if(row.id == data) { + datax.push(row) + } + }) + }) + + // for data information + let temp = datax.map((item, indx) => { + return { + benefit_id: item.id, + description: item.description, + request_log_id: requestLog?.id, + amount_incurred: 0, + amount_approved: 0, + amount_not_approved: 0, + excess_paid: 0, + keterangan: '', + } + }) + + reset({benefit_data: temp}) + + setBenefitSelected(datax) + + }, [valBenefitNames]) + + const handleCloseDialogBenefit = () => { + // setOpenDialog(false); + setAddBenefit(false) + setBenefitSelected([]) + setValBenefitNames([]) + } + + const handleAddDialogBenefit = () => { + setAddBenefit(true) + } + + const defaultValues: BenefitConfigurationListType = { + request_log_id: requestLog?.id, + benefit_name: '', + amount_incurred: 0, + amount_approved: 0, + amount_not_approved: 0, + excess_paid: 0, + }; + + const validationSchema = Yup.object().shape({ + benefit_data: Yup.array().of( + Yup.object().shape({ + amount_incurred : Yup.number().typeError('').required(''), + amount_approved : Yup.number().typeError('').required(''), + amount_not_approved : Yup.number().typeError('').required(''), + excess_paid : Yup.number().typeError('').required(''), + }) + ) + }) + + const methods = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }); + + const {fields, append, remove} = useFieldArray({name: 'benefit_data',control: methods.control}) + + const { handleSubmit, reset, watch, setValue, formState: { isDirty, isSubmitting, errors } } = methods; + // Submit Form + // ===================================== + const submitHandler = async (data: BenefitConfigurationListType) => { + + const response = await postAddBenefit(data); + + if (response == true) { + reset(); + // navigate('custormer-service/final-log/detail/'+requestLog?.id); + window.location.reload() + } + } + + const getContent = () => !addBenefit ? ( + + + + Benefit Name* + + + Benefit Name + + + {valBenefitNameError} + + + + + ) : + + ( + + + {/* */} + {fields?.map((item, index) => + ( + + + + + {item.description} + + + + + + + + Amount Incurred* + + + + + + + + + + + + + Amount Approved* + + + + append({amount_approved: ''}) } + id='amount_approved' + key={item.id} + name={`benefit_data.${index}.amount_approved`} + placeholder='Amount Approved' + required + /> + + + + + + + + + Amount Not Approved* + + + + append({amount_not_approved: ''}) } + id='amount_not_approved' + key={item.id} + name={`benefit_data.${index}.amount_not_approved`} + placeholder='Amount Not Approved' + required + /> + + + + + + + + + Excess Paid* + + + + append({excess_paid: ''}) } + id='excess_paid' + key={item.id} + name={`benefit_data.${index}.excess_paid`} + placeholder='Excess Paid' + required + /> + + + + + + + + + Keterangan* + + + + append({keterangan: ''}) } + id='keterangan' + key={item.id} + name={`benefit_data.${index}.keterangan`} + placeholder='Keterangan' + required + /> + + + + + + ))} + + + {/* */} + + + + + Save + + + + + + + ); + + const getAction = () => !addBenefit ? ( + + + + + ) : null; + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogConfirmation.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogConfirmation.tsx new file mode 100644 index 00000000..061739d0 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogConfirmation.tsx @@ -0,0 +1,110 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; + + +type DialogConfirmationType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + approve: string; + requestLog: DetailFinalLogType|undefined; +} + +export default function DialogConfirmation({requestLog, setOpenDialog, openDialog, approve, onSubmit} : DialogConfirmationType ) { + + const navigate = useNavigate(); + const handleSubmit = () => { + const formData = { + status : approve, + id: requestLog?.id + } + axios + .post(`customer-service/request/final-log`, formData) + .then((response) => { + enqueueSnackbar('Verification Final LOG Success', { variant: 'success' }); + setOpenDialog(false); + navigate('/custormer-service/final-log') + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + } + + const getContent = () => ( + + Are you sure to {approve == 'approved' ? 'approve' : 'deciline'} this final log ? + + + + Member ID + {requestLog?.member_id} + + + Policy Number + {requestLog?.policy_number} + + + Name + {requestLog?.name} + + + Submission Date + {requestLog?.submission_date ? fDateTimesecond(requestLog?.submission_date) : '-'} + + + Claim Method + {requestLog?.claim_method ? toTitleCase(requestLog?.claim_method) : '-'} + + + Service Type + {requestLog?.service_type} + + + + + + + {approve == 'approved' ? ( + + ) : ( + + ) } + + + + ); + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDelete.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDelete.tsx new file mode 100644 index 00000000..59669585 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDelete.tsx @@ -0,0 +1,120 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; + + +type DialogDeleteType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + id: number|undefined; +} + +export default function DialogDelete({id, setOpenDialog, openDialog,onSubmit} : DialogDeleteType ) { + const handleSubmit = () => { + axios + .delete(`customer-service/request/benefit_data/${id}`) + .then((response) => { + enqueueSnackbar('Benefit Data has Deleted', { variant: 'success' }); + setOpenDialog(false); + window.location.reload() + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + } + + const getContent = () => ( + + Are you sure to delete this detail benefit ? + + + + + + ); + + + return ( + + ); +} + +export function DialogDeleteMedicine({id, setOpenDialog, openDialog,onSubmit} : DialogDeleteType ) { + const handleSubmit = () => { + axios + .delete(`customer-service/request/medicine-data/${id}`) + .then((response) => { + enqueueSnackbar('Benefit Data has Deleted', { variant: 'success' }); + setOpenDialog(false); + window.location.reload() + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + } + + const getContent = () => ( + + Are you sure to delete this detail medicine ? + + + + + + ); + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteMedicine.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteMedicine.tsx new file mode 100644 index 00000000..bd98ba42 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogDeleteMedicine.tsx @@ -0,0 +1,69 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; + + +type DialogDeleteType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + id: number|undefined; +} + +export default function DialogDeleteMedicine({id, setOpenDialog, openDialog,onSubmit} : DialogDeleteType ) { + const handleSubmit = () => { + axios + .delete(`customer-service/request/medicine-data/${id}`) + .then((response) => { + enqueueSnackbar('Benefit Data has Deleted', { variant: 'success' }); + setOpenDialog(false); + window.location.reload() + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + } + + const getContent = () => ( + + Are you sure to delete this detail medicine ? + + + + + + ); + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogEditBenefit.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogEditBenefit.tsx new file mode 100644 index 00000000..57063b87 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogEditBenefit.tsx @@ -0,0 +1,220 @@ +import * as Yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; + +import MuiDialog from "@/components/MuiDialog"; +import { Box, Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; +import { BenefitConfigurationListType } from "../Model/Types"; +import { postEditBenefit } from "../Model/Functions"; +import { useForm } from 'react-hook-form'; +import { FormProvider, RHFTextField } from "@/components/hook-form"; +import RHFTextFieldMoney from "@/components/hook-form/v2/RHFTextFieldMoney"; +import { LoadingButton } from "@mui/lab"; + + +type DialogDeleteType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + data: BenefitConfigurationListType|undefined; + id: number|undefined; +} + +export default function DialogEditBenefit({id, data, setOpenDialog, openDialog,onSubmit} : DialogDeleteType ) { + const handleCloseDialog = () => { + setOpenDialog(false); + } + + // setup form + // ==================================== + const defaultValues: BenefitConfigurationListType = { + request_log_id: 0, + benefit_name: '', + amount_incurred: 0, + amount_approved: 0, + amount_not_approved: 0, + excess_paid: 0, + keterangan: '-', + description: '-' + }; + + const validationSchema = Yup.object().shape({ + amount_incurred : Yup.string().typeError('').required(''), + amount_approved : Yup.string().typeError('').required(''), + amount_not_approved : Yup.string().typeError('').required(''), + excess_paid : Yup.string().typeError('').required(''), + }); + + const methods = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }); + + const { handleSubmit, reset, watch, setValue, formState: { isDirty, isSubmitting, errors } } = methods; + + // Submit Form + // ===================================== + const submitHandler = async (data: BenefitConfigurationListType) => { + + const response = await postEditBenefit(id, data); + + if (response == true) { + reset(); + // navigate('custormer-service/final-log/detail/'+requestLog?.id); + window.location.reload() + } + } + + // Set Value Form + // ===================================== + useEffect(() => { + setValue('amount_incurred', data?.amount_incurred) + setValue('amount_approved', data?.amount_approved) + setValue('amount_not_approved', data?.amount_not_approved) + setValue('excess_paid', data?.excess_paid) + setValue('keterangan', data?.keterangan) + }, [data]) + + const getContent = () => ( + + + {/* */} + + + + + {data?.benefit?.description} + + + + + + + + Amount Incurred* + + + + + + + + + + + + + Amount Approved* + + + + append({amount_approved: ''}) } + id='amount_approved' + key={id} + name={`amount_approved`} + placeholder='Amount Approved' + required + /> + + + + + + + + + Amount Not Approved* + + + + append({amount_not_approved: ''}) } + id='amount_not_approved' + key={id} + name={`amount_not_approved`} + placeholder='Amount Not Approved' + required + /> + + + + + + + + + Excess Paid* + + + + append({excess_paid: ''}) } + id='excess_paid' + key={id} + name={`excess_paid`} + placeholder='Excess Paid' + required + /> + + + + + + + + + Keterangan* + + + + append({keterangan: ''}) } + id='keterangan' + key={id} + name={`keterangan`} + placeholder='Keterangan' + required + /> + + + + + + {/* */} + + + + + Save + + + + + + ); + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogHospitalCare.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogHospitalCare.tsx new file mode 100644 index 00000000..c2467a21 --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogHospitalCare.tsx @@ -0,0 +1,155 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Button, Autocomplete, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import { useFieldArray, useForm } from 'react-hook-form'; +import { FormProvider, RHFDatepicker, RHFSelect, RHFTextField } from '@/components/hook-form'; + +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; +import { LoadingButton } from '@mui/lab'; +import AddIcon from '@mui/icons-material/Add'; + + + + +type DialogConfirmationType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + requestLog: DetailFinalLogType|undefined; +} + +export default function DialogHospitalCare({requestLog, setOpenDialog, openDialog } : DialogConfirmationType ) { + + interface FormValuesProps extends Partial { + taxes: boolean; + inStock: boolean; + } + + const onSubmit = async (data: DetailFinalLogType) => { + + reset(); + } + + const methods = useForm(); + const { + reset, + watch, + control, + setValue, + getValues, + setError, + handleSubmit, + resetField, + formState: { isSubmitting }, + } = methods; + + const {fields, append, remove} = useFieldArray({name: "secondary_diagnosis_id", control}) + + const getContent = () => ( + + + + {/* Location */} + + Location* + + + + {/* Dokter */} + + Doctor* + + + + + Medical Record Number* + + + + + Symptoms* + + + + + Sign* + + + + + Diagnosis* + + + + {/* + + + + + + + + + Examination and Result* + + + + {/* + + + + + + + + + + + Invoice* + + + + + + + + + + Save + + + + + ); + + + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogMedicine.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogMedicine.tsx new file mode 100644 index 00000000..0b9d01ed --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Components/DialogMedicine.tsx @@ -0,0 +1,171 @@ +import * as Yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; + +import MuiDialog from "@/components/MuiDialog"; +import { Button, Autocomplete, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { DetailFinalLogType } from "../Model/Types"; +import { MedicineType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import { useFieldArray, useForm } from 'react-hook-form'; +import { FormProvider, RHFDatepicker, RHFSelect, RHFTextField } from '@/components/hook-form'; + +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; +import { LoadingButton } from '@mui/lab'; +import AddIcon from '@mui/icons-material/Add'; +import RemoveIcon from '@mui/icons-material/Remove'; +import RHFTextFieldMoney from "@/components/hook-form/v2/RHFTextFieldMoney"; +import { IconButton } from '@mui/material'; +import { postAddMedince } from '../Model/Functions'; + +type DialogConfirmationType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + requestLog: DetailFinalLogType|undefined; +} + +export default function DialogMedicine({requestLog, setOpenDialog, openDialog } : DialogConfirmationType ) { + const handleCloseDialogMedicine = () => { + setOpenDialog(false); + } + + const requestID = requestLog?.id + + const defaultValues: MedicineType = { + medicine : [{ + id: 0, + medicine_name: '', + medicine_price: 0, + request_log_id: requestID, + medicine: '', // input to database + price: 0, // input to database + }], + }; + + const validationSchema = Yup.object().shape({ + medicine: Yup.array().of( + Yup.object().shape({ + medicine_name : Yup.string().typeError('').required(''), + medicine_price : Yup.number().typeError('').required(''), + request_log_id : Yup.number().typeError('').required(''), + }) + ) + }) + + const methods = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }); + + const {fields, append, remove} = useFieldArray({name: 'medicine',control: methods.control}) + + useEffect(() => { + let temp = fields.map((item, i) => { + return { + medicine_name: 'test', + medicine_price: 0, + request_log_id: 3, + } + }) + + reset({medicine: temp}) + }, []) + + + + const { handleSubmit, reset, watch, setValue, formState: { isDirty, isSubmitting, errors } } = methods; + // Submit Form + // ===================================== + const submitHandler = async (data: MedicineType) => { + const response = await postAddMedince(data); + + if (response == true) { + reset(); + // navigate('custormer-service/final-log/detail/'+requestLog?.id); + window.location.reload() + } + } + + const getContent = () => ( + + + + {/* Medicine */} + + + Medicine* + + + + + {fields.map((field, index) => ( + + + + + + + + { + index != (fields.length-1) ? + ( + + remove(index)}> + + + + ) : null + } + + + ))} + + + + + + + + Add + + + + + + ); + + const getAction = () => null; + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx index 39aa66ab..480fd05a 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx @@ -1,305 +1,430 @@ -// mui -import { Container, Grid, Stack, Typography, Card, TextField, Divider, ButtonBase, Box, IconButton } from '@mui/material'; +import { + Container, + Grid, + Stack, + Typography, + Card, + Dialog, + TableRow, + Tab, + TableCell, + Collapse, + AccordionSummary, + AccordionDetails, + IconButton, + } from '@mui/material'; // components -import Page from '../../components/Page'; +import Page from '../../../components/Page'; // utils -import useSettings from '../../hooks/useSettings'; +import useSettings from '../../../hooks/useSettings'; // react import { useNavigate, useParams, useLocation } from 'react-router-dom'; -import { useEffect, useState, useRef } from 'react'; -import axios from '../../utils/axios'; +import { useEffect, useState, useRef, useMemo } from 'react'; +import axios from '../../../utils/axios'; // pages -import DetailTimeline from '../../pages/ClaimRequests/DetailTimeline'; -import DetailStepper from '../../pages/ClaimRequests/DetailStepper'; -import { format } from 'date-fns'; import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; -import Button from '@mui/material/Button'; +import { DetailFinalLogType } from './Model/Types'; +import { fDate, fDateTimesecond } from '@/utils/formatTime'; +import { Button } from '@mui/material'; +import DialogConfirmation from '../FinalLog/Components/DialogConfirmation'; +import Label from '@/components/Label'; +import { Box } from '@mui/system'; +import { Accordion } from '@mui/material'; +import { Delete, EditOutlined, ExpandMore } from '@mui/icons-material'; +import {BenefitData } from '../FinalLog/Model/Types' import AddIcon from '@mui/icons-material/Add'; -import RemoveIcon from '@mui/icons-material/Remove'; -import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; -import Iconify from '@/components/Iconify'; -import { fPostFormat } from '@/utils/formatTime'; -import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; -import DownloadIcon from '@mui/icons-material/Download'; -import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { fDateTimesecond } from '@/utils/formatTime'; -import { makeFormData } from '@/utils/jsonToFormData'; -import { enqueueSnackbar } from 'notistack'; +// Import Card Detail Final LOG +import CardDetail from '../Components/CardDetail'; +import CardService from '../Components/CardService'; +import CardExclusion from '../Components/CardExclusion'; +import CardBenefit from '../Components/CardBenefit'; + +// Import Dialog +import DialogHospitalCare from './Components/DialogHospitalCare'; +import DialogBenefit from './Components/DialogBenefit'; +import DialogMedicine from './Components/DialogMedicine'; +import DialogDelete from './Components/DialogDelete'; +import DialogEditBenefit from './Components/DialogEditBenefit'; +import { DialogDeleteMedicine } from './Components/DialogDelete'; + +import MoreMenu from '@/components/MoreMenu'; +import { MenuItem } from '@mui/material'; +import { fNumber } from '@/utils/formatNumber'; +import palette from '@/theme/palette'; +import CardMedicine from '../Components/CardMedicine'; +import CardFile from '../Components/CardFile'; + // ---------------------------------------------------------------------- export default function Detail() { const location = useLocation(); const queryParams = new URLSearchParams(location.search); - const code = queryParams.get('code'); const navigate = useNavigate(); const { themeStretch } = useSettings(); - const [data, setData] = useState(); - const [dataDialog, setDataDialog] = useState(); - const [document, setDocument] = useState(null); + const [requestLog, setRequestLog] = useState(); + const { id } = useParams(); useEffect(() => { axios - .get('/claim-requests/detail/'+id) + .get('customer-service/request/'+id) .then((response) => { - setData(response.data); - setDataDialog(response.data.data.dialog_submits); - setDocument(response.data.data.documents); - + setRequestLog(response.data.data) }) .catch((error) => { console.error(error); - }); - - }, []); - - const [isInvoiceVisible, setInvoiceVisibility] = useState(false); - - const handleInvoice = () => { - setInvoiceVisibility(!isInvoiceVisible); - } - const currentDate = new Date(); - const formattedCurrentDate = format(currentDate, 'dd MMM yyyy'); - const [dateInvoice, setDateInvoice] = useState(currentDate); - - const fileInvoiceInput = useRef(null); - const [fileInvoices, setFileInvoices] = useState([]); - - const handleInvoiceInputChange = (event) => { - if (event.target.files[0]) { - setFileInvoices([...fileInvoices, ...event.target.files]); - } else { - console.log('NO FILE'); - } - }; - const removeInvoiceFiles = (filesState, index) => { - setFileInvoices( - filesState.filter((file, fileIndex) => { - return fileIndex != index; }) - ); - }; - const date = dateInvoice ? fPostFormat(dateInvoice, 'yyyy-MM-dd') : null; + }, [id]); + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + const marginBottom2 = { + marginBottom: 2, + } const [openDialogSubmit, setOpenDialogSubmit] = useState(false); - const handleCloseDialogSubmit = () => { - setOpenDialogSubmit(false); - } - const handleSubmitData = () => { - // if(fileInvoices.length > 0) - // { - //submit data - axios - .post('claim-requests/'+id+'/approve') - .then((response) => { - enqueueSnackbar('Success Submit Claim Request', { variant: 'success' }); - setOpenDialogSubmit(false); - }) - .catch(({ response }) => { - enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); - }); - //Upload file invoices - const formData = makeFormData({ - date:date, - invoice_files: fileInvoices, - }); - axios - .post('claim-requests/'+id+'/invoice-files', formData) - .then((response) => { - enqueueSnackbar(response.data.message ?? 'Success upload invoice', { variant: 'success' }); - }) - .catch(({ response }) => { - enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' }); - }); - // } - // else - // { - // enqueueSnackbar('Please upload file invoice, before submit', { variant: 'warning' }); - // } + const [openDialogHospital, setDialogHospital] = useState(false); + const [openDialogBenefit, setDialogBenefit] = useState(false); + const [openDialogMedicine, setDialogMedicine] = useState(false); - setTimeout(() => - { - window.location.reload(); - }, 5000); + // Handel Delete Detail Benefit + const [idBenefitData, setIdBenefitData] = useState(); + const [openDialogDeleteBenefit, setDialogDeleteBenefit] = useState(false) - }; - - const check_invoice = document?.find((dataInvoice) => dataInvoice.type === 'claim-invoice'); + const [approve, setApprove] = useState('') + // Handle Edit Detail Benefit + const [openDialogEditBenefit, setDialogEditBenefit] = useState(false) + const [BenefitConfigurationData, setBenefitConfigurationData] = useState(); return ( navigate(-1)} sx={{cursor:'pointer'}}/> - {(data && data.data) ? data.data.status.code : ''} - {data ? ( - - Submission Date - {(data && data.data) ? format(new Date(data.data.status.submission_date), "d MMM yyyy") : ''} + {(requestLog && requestLog.code ? requestLog.code : '')} - ) : ''} - - {data ? ( + {/* Detail */} - + + - - - Format Claim - - + + {/* Service */} + + + + + + {/* Exclusion */} + + + - {check_invoice ? ( - - - Request Claim - - - - ) : ''} - - - - - { - setDateInvoice(newValue); - }} - inputFormat="dd MMM yyyy" - renderInput={(params) => } - /> - - } - spacing={1} - sx={{ marginY: 2 }} - > - {fileInvoices && - fileInvoices.map((file, index) => ( - - - - {file.name ? file.name : '-'} - - { - removeInvoiceFiles(fileInvoices, index); - }} - sx={{cursor: 'pointer'}} - > - - ))} - - fileInvoiceInput.current?.click()}> - - - - Upload Invoice - - - - + {/* Hospital Care */} + {/* + + + History of Hospital Care + - + + + */} + + {/* Benefit */} - - - - - {dataDialog && dataDialog.status === 'requested' ? ( - <> - - - - ) : ''} - {/* Dialog Submits */} - - - - - Confirmation - - - - - - - - {dataDialog ? ( - - Are you sure to submit this claim ? - - - Code - {dataDialog.code} - - - Name - {dataDialog.name} - - - Date Submission - {fDateTimesecond(dataDialog.submission_date)} - - - Claim Method - Service Type - - - Service Type - - {dataDialog.service_code === 'IP' ? 'Inpatient' : 'Outpatient'} + + + Benefit + + + + {requestLog?.benefit_data?.map((item, index) => ( + + + + + + + {item.benefit?.description} - - - - ) : ''} - - - - - - + + + + { + setDialogEditBenefit(true) + setIdBenefitData(item.id) + setBenefitConfigurationData(item) + }} + > + + Edit + + { + setIdBenefitData(item.id) + setDialogDeleteBenefit(true) + }} + > + + Delete + + + } /> + + + + + + + + {/* Amount Incurred */} + + + + + Amount Incurred + + + + + {fNumber(item.amount_incurred)} + + + + + + {/* Amount Approved */} + + + + + Amount Approved + + + + + {fNumber(item.amount_approved)} + + + + + + {/* Amount Not Approved */} + + + + + Amount Not Approved + + + + + {fNumber(item.amount_not_approved)} + + + + + + {/* Excess Paid* */} + + + + + Excess Paid* + + + + + {fNumber(item.excess_paid)} + + + + + + {/* Keterangan* */} + + + + + Keterangan* + + + + + {item.keterangan} + + + + + + + + + +
+ + ))} + + + + + {/* PR Buat pindahin ke componen */} + {/* + + */} + + + {/* Dialog Edit */} + + + + {/* Dialog Delete */} + + + + {/* Medicine */} + + + + Medicine + + + + {requestLog?.medicine.map((item, index) => ( + + {item.medicine} + Rp. {fNumber(item.price)} + { + setIdBenefitData(item.id) + setDialogDeleteBenefit(true) + }}> + + + + + ))} + + + + + + + {/* File */} + + + + + {requestLog?.status_final_log == 'requested' ? ( + + + <> +
+ +
+
+ +
+ +
+ ) : null} + - ) : ''} ); diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/List.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/List.tsx index ece99d47..fe591df7 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/List.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/List.tsx @@ -48,6 +48,8 @@ import { capitalizeFirstLetter } from '@/utils/formatString'; import Label from '@/components/Label'; import TableMoreMenu from '@/components/table/TableMoreMenu'; import { Import } from '@/@types/claims'; + +import { FinalLogType } from '../FinalLog/Model/Types'; // import LoadingButton from '@/theme/overrides/LoadingButton'; export default function List() { @@ -217,7 +219,7 @@ export default function List() { {handleGetTemplate('claim-request')}}>Download Template {handleGetData('data-plan-benefit')}}>Download Claim Request - + */}
)} @@ -281,7 +283,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('/customer-service/request?status=approved', { params: filter }); + const response = await axios.get('/customer-service/request?final_log=1&service_code=OP', { params: filter }); // console.log(response.data); setDataTableLoading(false); @@ -320,7 +322,7 @@ export default function List() { }; // Called on every row to map the data to the columns - function createData(data: any): any { + function createData(data: FinalLogType) { return { ...data, }; @@ -342,7 +344,7 @@ export default function List() { {open ? : }
*/ } - + {/* { // handleShowClaim(row); @@ -350,26 +352,29 @@ export default function List() { > {row.id} - - {row.member?.code} + */} + {row.code} {row.member?.full_name} {row.service_name} {row.payment_type_name} - { row.status == "requested" ? - () : - () - } + { row.status_final_log == "requested" ? + () : + row.status_final_log == "declined" ? + () + : + () + } - navigate(`/claim-requests/edit/${row.id}`)}> + {/* navigate(`/claim-requests/edit/${row.id}`)}> Edit - - navigate ('/claim-requests/detail/'+row.id+'')}> + */} + navigate ('/custormer-service/final-log/detail/'+row.id+'')}> Detail @@ -471,9 +476,9 @@ export default function List() { {/* */} - + {/* ID Request LOG - + */} Code diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Functions.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Functions.tsx index da72ff60..753fca55 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Functions.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Functions.tsx @@ -1,6 +1,7 @@ import axios from '@/utils/axios'; import { enqueueSnackbar } from 'notistack'; -import { MemberListType } from './Types'; +import { MedicineType, MemberListType } from './Types'; +import { BenefitConfigurationListType } from './Types'; import { makeFormData } from '@/utils/jsonToFormData'; /** @@ -77,3 +78,113 @@ export const addClaimRequest = async ( data: MemberListType[] ): Promise => { + const response = await axios.post(`customer-service/request/insert-benefit`, { + ...data + }) + .then((res) =>{ + enqueueSnackbar(res.data.message, { + variant: 'success', + }); + + return true; + }) + .catch((res) => { + if (res.response.status == 400) { + let arr_message = res.response.data.message; + + // for (const key in arr_message) { + enqueueSnackbar(arr_message, { + variant: 'warning', + }); + // } + } + else { + enqueueSnackbar("server error !", { + variant: 'error', + }); + } + + return false; + }); + + return response; +} + +/** + * Edit Benefit + */ +export const postEditBenefit = async (id:number|undefined, data: BenefitConfigurationListType):Promise => { + const response = await axios.put(`customer-service/request/benefit_data/${id}`, { + ...data + }) + .then((res) =>{ + enqueueSnackbar(res.data.message, { + variant: 'success', + }); + + return true; + }) + .catch((res) => { + if (res.response.status == 400) { + let arr_message = res.response.data.message; + + // for (const key in arr_message) { + enqueueSnackbar(arr_message, { + variant: 'warning', + }); + // } + } + else { + enqueueSnackbar("server error !", { + variant: 'error', + }); + } + + return false; + }); + + return response; +} + +/** + * Add Medicine + */ + +export const postAddMedince = async (data: MedicineType):Promise => { + const response = await axios.post(`customer-service/request/medicine-data`, { + ...data + }) + .then((res) =>{ + enqueueSnackbar(res.data.message, { + variant: 'success', + }); + + return true; + }) + .catch((res) => { + if (res.response.status == 400) { + let arr_message = res.response.data.message; + + // for (const key in arr_message) { + enqueueSnackbar(arr_message, { + variant: 'warning', + }); + // } + } + else { + enqueueSnackbar("server error !", { + variant: 'error', + }); + } + + return false; + }); + + return response; +} diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Types.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Types.tsx index 81b7da49..ad56d099 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Types.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Model/Types.tsx @@ -1,3 +1,5 @@ +import { Member } from "@/@types/member" + /** * Search Type */ @@ -8,18 +10,130 @@ export type SearchType = { /** * Member List */ -export type MemberListType = { - id : string, - member_id : string, - name : string, - service_type : ServiceType[], - patien_type? : string, - file_kondisi? : any[], - file_diagnosa? : any[], - file_penunjang? : any[], +export type FinalLogType = { + id : number, + code : string, + member : Member, + member_name : string, + submission_date : string, + service_name : string, + payment_type_name : string, + status_final_log : string, + status : string, + files_by_type : files_by_type, } -export type ServiceType = { - code : string - name : string + +export type DetailFinalLogType = { + id : number, + code : string, + member_id : string, + policy_number : string, + name : string|any, + date_of_birth : string, + gender : string, + marital_status : string, + submission_date : string, + service_type : string, + claim_method : string, + status : string, + status_final_log : string, + benefit : Benefit[], + benefit_data : BenefitData[], + config_service : ConfigService, + exclusion : Exclusion[], + medicine : Medicine[], + files : file[], } + +export type BenefitData = { + amount_incurred : number, + amount_approved : number, + amount_not_approved : number, + excess_paid : number, + keterangan : string, + benefit : Benefit, + request_log_id : number, + benefit_name : string, + description : string, + id : number, +} + +export type BenefitConfigurationListType = { + request_log_id: number|undefined, + benefit_name: string, + benefit: { + description: string + }, + amount_incurred: number, + amount_approved: number, + amount_not_approved: number, + excess_paid: number, + keterangan: string, + description: string, +} + +export type Benefit = { + id: number, + code: string, + description: string +} + +export type files_by_type = { + claim_diagnosis : file[], + claim_kondisi : file[], + claim_result : file[], +} + +export type file = { + original_name: string, + name: string, + path: string, + url: string, +} + +export type ConfigService = { + gp_external_doctor_online: string, + gp_external_doctor_offline: string, + gp_internal_doctor_online: string, + gp_internal_doctor_offline: string, + sp_external_doctor_online: string, + sp_external_doctor_offline: string, + sp_internal_doctor_online: string, + sp_internal_doctor_offline: string, + vitamins: string, + delivery_fee: string, + general_practitioner_fee: string, + specialist_practitioner_fee: string +} + +export type Exclusion = { + exclusionable: { + code: string, + name: string + }, + rules: Rule[] +} + +export type Rule = { + id: number, + exclusion_id: number, + name: string, + values: string, + +} + +export type MedicineType = { + medicine: Medicine[], +} + +export type Medicine = { + id: number, + medicine_name: string, + medicine_price: number, + medicine: string, + price: number, + request_log_id: number|undefined, +} + + diff --git a/frontend/dashboard/src/pages/CustomerService/Request/Components/DialogConfirmation.tsx b/frontend/dashboard/src/pages/CustomerService/Request/Components/DialogConfirmation.tsx new file mode 100644 index 00000000..fe3a734b --- /dev/null +++ b/frontend/dashboard/src/pages/CustomerService/Request/Components/DialogConfirmation.tsx @@ -0,0 +1,109 @@ +import MuiDialog from "@/components/MuiDialog"; +import { Button, Card, Checkbox, DialogActions, Grid, Typography } from "@mui/material"; +import { Paper } from "@mui/material"; +import { Stack } from '@mui/material'; +import React, { useState } from 'react'; +import { DetailRequestLogType } from "../Model/Types"; +import { fDateTimesecond, toTitleCase } from "@/utils/formatTime"; +import axios from "@/utils/axios"; +import { enqueueSnackbar } from "notistack"; +import { useNavigate } from "react-router"; + + +type DialogConfirmationType = { + openDialog: boolean; + setOpenDialog: any; + onSubmit?: void; + approve: string; + requestLog: DetailRequestLogType|undefined; +} + +export default function DialogConfirmation({requestLog, setOpenDialog, openDialog, approve, onSubmit} : DialogConfirmationType ) { + + const navigate = useNavigate(); + const handleSubmit = () => { + const formData = { + status : approve + } + axios + .put(`customer-service/request/${requestLog?.id}`, formData) + .then((response) => { + enqueueSnackbar('Verification Request LOG Success', { variant: 'success' }); + setOpenDialog(false); + navigate('/custormer-service/request') + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } + + const handleCloseDialog = () => { + setOpenDialog(false); + } + + const getContent = () => ( + + Are you sure to {approve == 'approved' ? 'approve' : 'deciline'} this request ? + + + + Member ID + {requestLog?.member_id} + + + Policy Number + {requestLog?.policy_number} + + + Name + {requestLog?.name} + + + Submission Date + {requestLog?.submission_date ? fDateTimesecond(requestLog?.submission_date) : '-'} + + + Claim Method + {requestLog?.claim_method ? toTitleCase(requestLog?.claim_method) : '-'} + + + Service Type + {requestLog?.service_type} + + + + + + + {approve == 'approved' ? ( + + ) : ( + + ) } + + + + ); + + + return ( + + ); +} \ No newline at end of file diff --git a/frontend/dashboard/src/pages/CustomerService/Request/Detail.tsx b/frontend/dashboard/src/pages/CustomerService/Request/Detail.tsx index 77f9e59e..db8cc17d 100644 --- a/frontend/dashboard/src/pages/CustomerService/Request/Detail.tsx +++ b/frontend/dashboard/src/pages/CustomerService/Request/Detail.tsx @@ -1,305 +1,174 @@ -// mui -import { Container, Grid, Stack, Typography, Card, TextField, Divider, ButtonBase, Box, IconButton } from '@mui/material'; +import { + Container, + Grid, + Stack, + Typography, + Card, + Dialog, + } from '@mui/material'; // components import Page from '../../../components/Page'; // utils import useSettings from '../../../hooks/useSettings'; // react import { useNavigate, useParams, useLocation } from 'react-router-dom'; -import { useEffect, useState, useRef } from 'react'; +import { useEffect, useState, useRef, useMemo } from 'react'; import axios from '../../../utils/axios'; // pages -import DetailTimeline from '../../../pages/ClaimRequests/DetailTimeline'; -import DetailStepper from '../../../pages/ClaimRequests/DetailStepper'; -import { format } from 'date-fns'; import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; -import Button from '@mui/material/Button'; -import AddIcon from '@mui/icons-material/Add'; -import RemoveIcon from '@mui/icons-material/Remove'; -import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; -import Iconify from '@/components/Iconify'; -import { fPostFormat } from '@/utils/formatTime'; -import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; -import DownloadIcon from '@mui/icons-material/Download'; -import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { fDateTimesecond } from '@/utils/formatTime'; -import { makeFormData } from '@/utils/jsonToFormData'; - -import { enqueueSnackbar } from 'notistack'; +import { DetailRequestLogType } from './Model/Types'; +import { fDate, fDateTimesecond } from '@/utils/formatTime'; +import { Button } from '@mui/material'; +import DialogConfirmation from './Components/DialogConfirmation'; // ---------------------------------------------------------------------- export default function Detail() { const location = useLocation(); const queryParams = new URLSearchParams(location.search); - const code = queryParams.get('code'); const navigate = useNavigate(); const { themeStretch } = useSettings(); - const [data, setData] = useState(); - const [dataDialog, setDataDialog] = useState(); - const [document, setDocument] = useState(null); + const [requestLog, setRequestLog] = useState(); + const { id } = useParams(); useEffect(() => { axios - .get('/claim-requests/detail/'+id) + .get('customer-service/request/'+id) .then((response) => { - setData(response.data); - setDataDialog(response.data.data.dialog_submits); - setDocument(response.data.data.documents); - + setRequestLog(response.data.data) }) .catch((error) => { console.error(error); - }); - - }, []); - - const [isInvoiceVisible, setInvoiceVisibility] = useState(false); - - const handleInvoice = () => { - setInvoiceVisibility(!isInvoiceVisible); - } - const currentDate = new Date(); - const formattedCurrentDate = format(currentDate, 'dd MMM yyyy'); - const [dateInvoice, setDateInvoice] = useState(currentDate); - - const fileInvoiceInput = useRef(null); - const [fileInvoices, setFileInvoices] = useState([]); - - const handleInvoiceInputChange = (event) => { - if (event.target.files[0]) { - setFileInvoices([...fileInvoices, ...event.target.files]); - } else { - console.log('NO FILE'); - } - }; - const removeInvoiceFiles = (filesState, index) => { - setFileInvoices( - filesState.filter((file, fileIndex) => { - return fileIndex != index; }) - ); - }; - const date = dateInvoice ? fPostFormat(dateInvoice, 'yyyy-MM-dd') : null; + }, [id]); + + function toTitleCase(str: string | null) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + } + + const style1 = { + color: '#919EAB', + width: '30%' + } + const style2 = { + width: '70%' + } + const marginBottom1 = { + marginBottom: 1, + } const [openDialogSubmit, setOpenDialogSubmit] = useState(false); const handleCloseDialogSubmit = () => { setOpenDialogSubmit(false); } - const handleSubmitData = () => { - // if(fileInvoices.length > 0) - // { - //submit data - axios - .post('claim-requests/'+id+'/approve') - .then((response) => { - enqueueSnackbar('Success Submit Claim Request', { variant: 'success' }); - setOpenDialogSubmit(false); - }) - .catch(({ response }) => { - enqueueSnackbar(response.data.message ?? 'Something went wrong!', { variant: 'error' }); - }); - //Upload file invoices - const formData = makeFormData({ - date:date, - invoice_files: fileInvoices, - }); - axios - .post('claim-requests/'+id+'/invoice-files', formData) - .then((response) => { - enqueueSnackbar(response.data.message ?? 'Success upload invoice', { variant: 'success' }); - }) - .catch(({ response }) => { - enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' }); - }); - // } - // else - // { - // enqueueSnackbar('Please upload file invoice, before submit', { variant: 'warning' }); - // } - setTimeout(() => - { - window.location.reload(); - }, 5000); - - }; - - const check_invoice = document?.find((dataInvoice) => dataInvoice.type === 'claim-invoice'); + const [approve, setApprove] = useState('') return ( navigate(-1)} sx={{cursor:'pointer'}}/> - {(data && data.data) ? data.data.status.code : ''} - {data ? ( - - Submission Date - {(data && data.data) ? format(new Date(data.data.status.submission_date), "d MMM yyyy") : ''} + {(requestLog && requestLog.code ? requestLog.code : '')} - ) : ''} - - {data ? ( - - - - - Format Claim - - - - {check_invoice ? ( - - - Request Claim - + + Detail + + Member ID + {requestLog?.member_id} - - ) : ''} - - - - - { - setDateInvoice(newValue); - }} - inputFormat="dd MMM yyyy" - renderInput={(params) => } - /> - - } - spacing={1} - sx={{ marginY: 2 }} - > - {fileInvoices && - fileInvoices.map((file, index) => ( - - - - {file.name ? file.name : '-'} - - { - removeInvoiceFiles(fileInvoices, index); - }} - sx={{cursor: 'pointer'}} - > - - ))} - - fileInvoiceInput.current?.click()}> - - - - Upload Invoice - - - - + + Policy Number + {requestLog?.policy_number} + + + Name + {requestLog?.name} + + + Date Of Birth + {requestLog?.date_of_birth ? fDate(requestLog?.date_of_birth) : '-'} + + + Marital Status + {requestLog?.marital_status} + + + Submission Date + {requestLog?.submission_date ? fDateTimesecond(requestLog?.submission_date) : '-'} - - + + + Service + + Service Type + {requestLog?.service_type} + + + Claim Method + {toTitleCase(requestLog?.claim_method ?? '-')} + + {/* + Benefit + +
    + {requestLog?.benefit.length > 0 ? requestLog?.benefit.map((r, index) => ( +
  • {r.code } - {r.description}
  • + )) :
  • -
  • } +
+
+
*/} +
- - - {dataDialog && dataDialog.status === 'requested' ? ( - <> - - - - ) : ''} - {/* Dialog Submits */} - - - - - Confirmation - - - - - - - - {dataDialog ? ( - - Are you sure to submit this claim ? - - - Code - {dataDialog.code} - - - Name - {dataDialog.name} - - - Date Submission - {fDateTimesecond(dataDialog.submission_date)} - - - Claim Method - Service Type - - - Service Type - - {dataDialog.service_code === 'IP' ? 'Inpatient' : 'Outpatient'} - - - - - ) : ''} - - - - - - + {requestLog?.status == 'requested' ? ( + + + <> +
+ +
+
+ +
+ +
+ ) : null} +
- ) : ''}
); diff --git a/frontend/dashboard/src/pages/CustomerService/Request/List.tsx b/frontend/dashboard/src/pages/CustomerService/Request/List.tsx index 4e9927a1..1a2b3179 100644 --- a/frontend/dashboard/src/pages/CustomerService/Request/List.tsx +++ b/frontend/dashboard/src/pages/CustomerService/Request/List.tsx @@ -51,6 +51,8 @@ import { capitalizeFirstLetter } from '@/utils/formatString'; import Label from '@/components/Label'; import TableMoreMenu from '@/components/table/TableMoreMenu'; import { Import } from '@/@types/claims'; + +import { RequestLogType } from '../Request/Model/Types'; // import SvgIconStyle from '@/components/SvgIconStyle'; import SvgIconStyle from '../../../components/SvgIconStyle'; // import LoadingButton from '@/theme/overrides/LoadingButton'; @@ -323,7 +325,7 @@ export default function List() { }; // Called on every row to map the data to the columns - function createData(data: any): any { + function createData(data: RequestLogType): any { return { ...data, }; @@ -345,7 +347,7 @@ export default function List() { {open ? : }
*/ } - + {/* { // handleShowClaim(row); @@ -353,9 +355,9 @@ export default function List() { > {row.id} - + */} {row.code} - {row.member?.full_name} + {row.member_name} {row.service_name} {row.payment_type_name} @@ -371,19 +373,11 @@ export default function List() { - navigate ('/claim-requests/detail/'+row.id+'')}> + navigate ('/custormer-service/request/detail/'+row.id+'')}> Detail - navigate ('/claim-requests/detail/'+row.id+'')}> - - {/* credit: plus icon from https://heroicons.com/ */} - - - - - Konfirmasi - + } /> @@ -482,9 +476,9 @@ export default function List() { {/* */} - + {/* ID Request LOG - + */} Code diff --git a/frontend/dashboard/src/pages/CustomerService/Request/Model/Types.tsx b/frontend/dashboard/src/pages/CustomerService/Request/Model/Types.tsx index 81b7da49..0091c213 100644 --- a/frontend/dashboard/src/pages/CustomerService/Request/Model/Types.tsx +++ b/frontend/dashboard/src/pages/CustomerService/Request/Model/Types.tsx @@ -1,3 +1,5 @@ +import { Member } from "@/@types/member" + /** * Search Type */ @@ -8,18 +10,48 @@ export type SearchType = { /** * Member List */ -export type MemberListType = { - id : string, - member_id : string, - name : string, - service_type : ServiceType[], - patien_type? : string, - file_kondisi? : any[], - file_diagnosa? : any[], - file_penunjang? : any[], +export type RequestLogType = { + id : number, + code : string, + member : Member, + submission_date : string, + service_name : string, + payment_type_name : string, + status_final_log : string, + status : string, + files_by_type : files_by_type, } -export type ServiceType = { - code : string - name : string +export type files_by_type = { + claim_diagnosis : file[], + claim_kondisi : file[], + claim_result : file[], } + +export type file = { + name: string, + url: string, +} + +export type DetailRequestLogType = { + id : number, + code : string, + member_id : string, + policy_number : string, + name : string, + date_of_birth : string, + gender : string, + marital_status : string, + submission_date : string, + service_type : string, + claim_method : string, + status : string, + benefit : Benefit[], +} + +export type Benefit = { + code: string, + description: string +} + + diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index fd49827c..3d0a249c 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -252,6 +252,10 @@ export default function Router() { path: 'laboratorium_result/:member_id/claims/:claim_code/list_lab_result', element: }, + { + path: 'inpatient_monitoring', // Inpatient Monitoring + element: + }, ] }, { @@ -475,9 +479,17 @@ export default function Router() { element: , }, { - path: 'custormer-service/final-request', + path: 'custormer-service/request/detail/:id', + element: , + }, + { + path: 'custormer-service/final-log', element: , }, + { + path: 'custormer-service/final-log/detail/:id', + element: , + }, ], }, // { @@ -594,6 +606,8 @@ const LaboratoriumResult = Loadable(lazy(() => import('../pages/CaseManage const LaboratoriumResultClaims = Loadable(lazy(() => import('../pages/CaseManagement/LaboratoriumResult/Claim'))) const DetailLabResultForm = Loadable(lazy(() => import('../pages/CaseManagement/LaboratoriumResult/Components/DetailLabResultForm'))) const DetailLabResultList = Loadable(lazy(() => import('../pages/CaseManagement/LaboratoriumResult/Components/DetailLabResultList'))) +// Inpatient Monitoring +const InpatientMonitoring = Loadable(lazy(() => import('../pages/CaseManagement/InpatientMonitoring/Index'))) /** @@ -601,7 +615,13 @@ const DetailLabResultList = Loadable(lazy(() => import('../pages/CaseManage */ // Request const RequestLog = Loadable(lazy(() => import('../pages/CustomerService/Request/Index'))) +const RequestLogDetail = Loadable(lazy(() => import('../pages/CustomerService/Request/Detail'))) +// Final LOG const FinalLog = Loadable(lazy(() => import('../pages/CustomerService/FinalLog/Index'))) +const FinalLogDetail = Loadable(lazy(() => import('../pages/CustomerService/FinalLog/Detail'))) + + + const MasterDiagnosisTemplate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/Index'))); const MasterDiagnosisTemplateCreate = Loadable(lazy(() => import('../pages/Master/Diagnosis/Master/CreateUpdate'))); diff --git a/frontend/dashboard/src/utils/formatTime.ts b/frontend/dashboard/src/utils/formatTime.ts index 33f90e55..2bca0113 100644 --- a/frontend/dashboard/src/utils/formatTime.ts +++ b/frontend/dashboard/src/utils/formatTime.ts @@ -35,3 +35,9 @@ export function fPostFormat(date: Date | string | number) { export function fDateOnly(date: Date | string | number) { return format(new Date(date), 'yyyy-MM-dd'); } + +export function toTitleCase(str: string | null) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); +} diff --git a/frontend/hospital-portal/public/image/en-US.json b/frontend/hospital-portal/public/image/en-US.json deleted file mode 100644 index baef7538..00000000 --- a/frontend/hospital-portal/public/image/en-US.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "greeting": "Hello", - "buttonText": "Click Me", - "infoLogin": "Enter the registered account", - "txtLogin1" : "Sign in to Hospital Portal", - "txtLogin2" : "Enter your details below", - "txtCardSearchMember1" : "Guarantee Submission", - "txtCardSearchMember2" : "Find Member", - "txtCardSearchMember3" : "Date Birth", - "txtCardSearchMember4" : "Member ID", - "txtCardSearchMember5" : "Member", - "txtDialogMember1" : "Benefit Summary", - "txtDialogMember2" : "Request LOG", - "txtDialogMember3" : "Member Detail" -} diff --git a/frontend/hospital-portal/public/image/id-ID.json b/frontend/hospital-portal/public/image/id-ID.json deleted file mode 100644 index 41db3e54..00000000 --- a/frontend/hospital-portal/public/image/id-ID.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "greeting": "Halo", - "buttonText": "Klik Saya", - "infoLogin": "Masukan akun yang telah terdaftar", - "txtLogin1" : "Masuk ke Hospital Portal", - "txtLogin2" : "Masukkan detail Anda di bawah ini", - "txtCardSearchMember1" : "Pengajuan Jaminan", - "txtCardSearchMember2" : "Cari Anggota", - "txtCardSearchMember3" : "Tanggal Lahir", - "txtCardSearchMember4" : "Member ID", - "txtCardSearchMember5" : "Member", - "txtDialogMember1" : "Ringkasan Manfaat", - "txtDialogMember2" : "Request LOG", - "txtDialogMember3" : "Detail Member" -} diff --git a/frontend/hospital-portal/public/lang/en-US.json b/frontend/hospital-portal/public/lang/en-US.json index d150075b..c8060371 100644 --- a/frontend/hospital-portal/public/lang/en-US.json +++ b/frontend/hospital-portal/public/lang/en-US.json @@ -6,7 +6,7 @@ "txtLogin2" : "Enter your details below", "txtCardSearchMember1" : "Membership Query", "txtCardSearchMember2" : "Search Member", - "txtCardSearchMember3" : "Date Birth", + "txtCardSearchMember3" : "Date of Birth", "txtCardSearchMember4" : "Member ID", "txtCardSearchMember5" : "Member", "txtDialogMember1" : "Services", @@ -18,5 +18,21 @@ "txtGender" : "Gender", "txtMaritalStatus" : "Marital Status", "txtLanguage" : "Language", - "txtRelationship" : "Relationship" + "txtRelationship" : "Relationship", + "txtRequestDate" : "Request Date", + "txtMemberID" : "Member ID", + "txtClaimCode" : "Claim Code", + "txtRequestCode" : "Request Code", + "txtName" : "Name", + "txtStatus" : "Status", + "txtSearch" : "Search Name or Member ID...", + "txtAll" : "All", + "txtSubmissionDate" : "Submission Date", + "txtDataNotFound" : "Data Not Found", + "txtConditionDocument" : "Condition Document", + "txtDiagnosisDokument" : "Diagnosis Dokument", + "txtSupportingResultDocument" : "Supporting Result Document", + "txtAddResult" : "Add Result", + "txtServiceType" : "Service Type", + "txtAdditionalDocuments" : "Additional Documents" } diff --git a/frontend/hospital-portal/public/lang/id-ID.json b/frontend/hospital-portal/public/lang/id-ID.json index 4354359e..5ca6e767 100644 --- a/frontend/hospital-portal/public/lang/id-ID.json +++ b/frontend/hospital-portal/public/lang/id-ID.json @@ -18,5 +18,21 @@ "txtGender" : "Jenis Kelamin", "txtMaritalStatus" : "Status Perkawinan", "txtLanguage" : "Bahasa", - "txtRelationship" : "Hubungan" + "txtRelationship" : "Hubungan", + "txtRequestDate" : "Tanggal Permintaan", + "txtMemberID" : "ID Anggota", + "txtClaimCode" : "Kode Klaim", + "txtRequestCode" : "Kode Pengajuan", + "txtName" : "Nama", + "txtStatus" : "Status", + "txtSearch" : "Cari Nama atau ID Anggota...", + "txtAll" : "Semua", + "txtSubmissionDate" : "Tanggal Pengajuan", + "txtDataNotFound" : "Data Tidak Ditemukan", + "txtConditionDocument" : "Dokumen Kondisi", + "txtDiagnosisDokument" : "Dokumen Diagnosa", + "txtSupportingResultDocument" : "Dokumen Hasil Pendukung", + "txtAddResult" : "Tambah Hasil", + "txtServiceType" : "Tipe Layanan", + "txtAdditionalDocuments" : "Dokumen Tambahan" } diff --git a/frontend/hospital-portal/src/components/Table.tsx b/frontend/hospital-portal/src/components/Table.tsx index 172bb0a7..a60bc862 100644 --- a/frontend/hospital-portal/src/components/Table.tsx +++ b/frontend/hospital-portal/src/components/Table.tsx @@ -42,6 +42,8 @@ import { Download, Search as SearchIcon, Upload } from '@mui/icons-material'; import { DivisionDataProps, Order, PaginationTableProps, TableListProps } from '../@types/table'; import { InputAdornment } from '@mui/material'; import GetAppIcon from '@mui/icons-material/GetApp'; +import { LanguageContext } from '@/contexts/LanguageContext'; + /* --------------------------------- styled --------------------------------- */ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({ height: 10, @@ -83,6 +85,8 @@ export default function Table({ ]); params.setAppliedParams(parameters); }; + + const { localeData }: any = useContext(LanguageContext); /* -------------------------------------------------------------------------- */ /* -------------------------- enchanced table head -------------------------- */ @@ -219,7 +223,7 @@ export default function Table({ ), }} - placeholder="Search Name or Member ID... " + placeholder={localeData.txtSearch} /> @@ -239,7 +243,7 @@ export default function Table({ ), }} - placeholder="Search Name or Member ID... " + placeholder={localeData.txtSearch} /> @@ -299,7 +303,7 @@ export default function Table({ label="Status" onChange={filterStatus.config.handleStatusChange} > - All + {localeData.txtAll} {filterStatus.config.filterData.map((row: StatusDataProps, index) => ( {row.name} @@ -336,7 +340,7 @@ export default function Table({ {/* End Table Header */} {/* Table Body */} - {loadings.isLoading && rows.length >= 1 ? ( + {loadings.isLoading ? ( Loading . . . @@ -358,7 +362,7 @@ export default function Table({ ) : ( - No Data Found + {localeData.txtDataNotFound} )} diff --git a/frontend/hospital-portal/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/hospital-portal/src/layouts/dashboard/navbar/NavConfig.tsx index 2e1efd95..33d562e3 100644 --- a/frontend/hospital-portal/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/hospital-portal/src/layouts/dashboard/navbar/NavConfig.tsx @@ -12,7 +12,7 @@ const ICONS = { ecommerce: getIcon('ic_ecommerce'), analytics: getIcon('ic_analytics'), dashboard: getIcon('ic_dashboard'), - hospital: getIcon('ic_banking'), + ic_booking: getIcon('ic_booking'), }; const navConfig = [ @@ -21,6 +21,9 @@ const navConfig = [ { items: [{ title: 'Dashboard', path: '/dashboard', icon: ICONS.dashboard }], }, + { + items: [{ title: 'Claim', path: '/claim', icon: ICONS.ic_booking }], + }, // Membership // ---------------------------------------------------------------------- diff --git a/frontend/hospital-portal/src/layouts/dashboard/navbar/NavbarDocs.tsx b/frontend/hospital-portal/src/layouts/dashboard/navbar/NavbarDocs.tsx index a12453a1..5ede566c 100644 --- a/frontend/hospital-portal/src/layouts/dashboard/navbar/NavbarDocs.tsx +++ b/frontend/hospital-portal/src/layouts/dashboard/navbar/NavbarDocs.tsx @@ -25,7 +25,7 @@ export default function NavbarDocs() { - Hak Cipta © 2023 - 2024 Link Sehat + Hak Cipta © 2023 - 2024 Link Medis Sehat ); diff --git a/frontend/hospital-portal/src/pages/Claim.tsx b/frontend/hospital-portal/src/pages/Claim.tsx new file mode 100644 index 00000000..d06a81a5 --- /dev/null +++ b/frontend/hospital-portal/src/pages/Claim.tsx @@ -0,0 +1,119 @@ +// @mui +import { Typography, Container, Grid, Card } from '@mui/material'; +// hooks +import useSettings from '@/hooks/useSettings'; +// components +import Page from '@/components/Page'; +// theme +import CardNotification from '@/sections/dashboard/CardNotification'; +import CardSearchMember from '@/sections/dashboard/CardSearchMember' +import { useContext, useEffect, useState } from 'react'; +import axios from '@/utils/axios'; +import { Stack } from '@mui/system'; +import { Input } from '@mui/material'; +//sections +import TableList from '@/sections/claim/TableList'; +import { fDate } from '@/utils/formatTime'; +import DialogDetailClaim from '@/components/dialogs/DialogDetailClaim'; +import HeaderBreadcrumbs from "@/components/HeaderBreadcrumbs"; + +// ---------------------------------------------------------------------- + +// const [notifications, setNotifications] = useState([]) + +const itemList = [ + { info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '08:00 WIB' }, + { info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '09:00 WIB' }, + { info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '10:00 WIB' }, + { info: 'Mohon lengkapi dokumen Mahen sadarsa', date: 'Selasa, 20 April 22', time: '11:00 WIB' }, +]; + +// ---------------------------------------------------------------------- + +/* ---------------------------------- types --------------------------------- */ + +type PolicyProps = { + myLimit: { + balance: number; + total: number; + percentage: number; + }; + lockLimit: { + balance: number; + percentage: number; + }; +}; + +/* -------------------------------------------------------------------------- */ + +/* ------------------------------ default data ------------------------------ */ +const defaultPolicyData = { + myLimit: { + balance: 0, + total: 0, + percentage: 0, + }, + lockLimit: { + balance: 0, + percentage: 0, + }, +}; +/* -------------------------------------------------------------------------- */ + +export default function Claim() { + const { themeStretch } = useSettings(); + + // const [tableData, setTableData] = useState([]); + const [policyData, setPolicyData] = useState(defaultPolicyData); + + // TODO Remove This + //const [itemList, setItemList] = useState([]); + function handleDataLoaded(dataTable:any) { + let dummyData = []; + dataTable.map(function(data:any) { + if (data.status == 'approved') { + dummyData.push({ + info: `LOG Approved for member ${data.member.full_name}`, + date: fDate(data.created_at, "dd MMMM"), + time: fDate(data.created_at, "HH:mm") + }) + } + }) + + //setItemList(dummyData); + } + + return ( + + + + {/* + + */} + {/* + + */} + + + + + + + + + + + ); +} diff --git a/frontend/hospital-portal/src/routes/index.tsx b/frontend/hospital-portal/src/routes/index.tsx index 4815a322..b3006919 100644 --- a/frontend/hospital-portal/src/routes/index.tsx +++ b/frontend/hospital-portal/src/routes/index.tsx @@ -82,6 +82,27 @@ export default function Router() { }, ], }, + { + path: '/', + element: ( + + + + + + ), + children: [ + { element: , index: true }, + { + path: 'claim', + element: , + }, + { + path: '/detail/:id', + element: , + }, + ], + }, { path: '*', @@ -101,6 +122,7 @@ const ForgetPassword = Loadable(lazy(() => import('@/pages/auth/ForgetPassword') // Dashboard const Dashboard = Loadable(lazy(() => import('@/pages/Dashboard'))); +const Claim = Loadable(lazy(() => import('@/pages/Claim'))); const NotFound = Loadable(lazy(() => import('@/pages/Page404'))); const DetailClaimReport = Loadable(lazy(()=> import('@/sections/dashboard/Detail'))); diff --git a/frontend/hospital-portal/src/sections/claim/TableList.tsx b/frontend/hospital-portal/src/sections/claim/TableList.tsx new file mode 100644 index 00000000..513ea292 --- /dev/null +++ b/frontend/hospital-portal/src/sections/claim/TableList.tsx @@ -0,0 +1,365 @@ +/* ---------------------------------- @mui ---------------------------------- */ +import { Stack, Button, MenuItem, SelectChangeEvent, Tab, Tabs, Card, Box } from '@mui/material'; +/* ---------------------------------- axios --------------------------------- */ +// import axios from 'axios'; +import axios from '../../utils/axios'; +import { styled } from '@mui/material/styles'; +/* ---------------------------------- react --------------------------------- */ +import { useContext, useEffect, useState } from 'react'; + +/* -------------------------------- component ------------------------------- */ +import Iconify from '../../components/Iconify'; +import TableComponent from '../../components/Table'; +/* ---------------------------------- theme --------------------------------- */ +import palette from '../../theme/palette'; +//import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import { HeadCell, Order, PaginationTableProps } from '../../@types/table'; +import { useSearchParams, useNavigate } from 'react-router-dom'; +import { fDate, fDateSuffix } from '../../utils/formatTime'; +import Typography from '@mui/material/Typography'; +import { format } from 'date-fns'; +import TableMoreMenu from '../../components/table/TableMoreMenu'; +import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; +import HistoryIcon from '@mui/icons-material/History'; +import SearchIcon from '@mui/icons-material/Search'; +import Label from '../../components/Label'; +import { enqueueSnackbar } from 'notistack'; +import { LoadingButton, TabPanel } from "@mui/lab"; +import { LanguageContext } from '@/contexts/LanguageContext'; +import MuiDialog from '@/components/MuiDialog'; +import DialogMember from '@/sections/dashboard/DialogMember'; +import DialogClaimSubmit from '@/sections/dashboard/DialogClaimSubmit'; +import { fPostFormat } from '@/utils/formatTime'; + +export default function TableList() { + const navigate = useNavigate(); + const { localeData }: any = useContext(LanguageContext); + + const [data, setData] = useState([]); + + // Download LOG + async function handleDownloadLog(claimRequest:any) { + return axios + .get(`claim-requests/${claimRequest}/log`, { + responseType: 'blob', + }) + .then((response) => { + window.open(URL.createObjectURL(response.data)); + // setLoadingLog(false); + }) + // .then((blobFile) => { + // new File([blobFile], 'asdads.pdf', { type: blobFile.type }) + // setLoadingLog(false); + // }) + .catch((response) => { + console.log(response); + enqueueSnackbar(response.message, { variant: 'error' }); + // setLoadingLog(false); + }); + } + + /* -------------------------------------------------------------------------- */ + /* setting up for the table */ + /* -------------------------------------------------------------------------- */ + const [isLoading, setIsLoading] = useState(true); + + const loadings = { + isLoading: isLoading, + setIsLoading: setIsLoading, + }; + + /* ------------------------------ handle params ----------------------------- */ + const [searchParams, setSearchParams] = useSearchParams(); + const [appliedParams, setAppliedParams] = useState({}); + + const params = { + searchParams: searchParams, + setSearchParams: setSearchParams, + appliedParams: appliedParams, + setAppliedParams: setAppliedParams, + }; + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle order ------------------------------ */ + const [order, setOrder] = useState('desc'); + const [orderBy, setOrderBy] = useState('submission_date'); + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + /* -------------------------------------------------------------------------- */ + + /* ---------------------------- handle pagination --------------------------- */ + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + + const [paginationTable, setPaginationTable] = useState({ + current_page: 0, + from: 0, + last_page: 0, + links: [], + path: '', + per_page: 0, + to: 0, + total: 0, + }); + + const paginations = { + page: page, + setPage: setPage, + rowsPerPage: rowsPerPage, + setRowsPerPage: setRowsPerPage, + paginationTable: paginationTable, + setPaginationTable: setPaginationTable, + }; + + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle search ----------------------------- */ + const [searchText, setSearchText] = useState(''); + + const handleSearchSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (searchText === '') { + searchParams.delete('search'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); + setAppliedParams(params); + } + }; + + const searchs = { + useSearchs: true, + searchText: searchText, + setSearchText: setSearchText, + handleSearchSubmit: handleSearchSubmit, + }; + + /* ------------------------------ handle filter ----------------------------- */ + const [statusValue, setStatusValue] = useState('all'); + const [filterData, setStatusData] = useState([]); + + // handle status + const handleStatusChanges = (event: SelectChangeEvent) => { + setStatusValue(event.target.value as string); + + if (event.target.value === 'all') { + searchParams.delete('status'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([ + ...searchParams.entries(), + ['status', event.target.value as string], + ]); + setAppliedParams(params); + } + }; + + const filterStatus = { + useFilter: true, + config: { + label: 'Status', + statusValue: statusValue, + filterData: filterData, + handleStatusChange: handleStatusChanges, + }, + }; + + // handle start date + const [startDateValue, setStartDateValue] = useState(''); + + const handleStartDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newStartDateValue = event.currentTarget.elements['date-input'].value; + setStartDateValue(newStartDateValue); + if (newStartDateValue === '') { + searchParams.delete('start_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['start_date', newStartDateValue]]); + setAppliedParams(params); + } + }; + + const filterStartDate = { + useFilter: true, + startDate: startDateValue, + setStartDate: setStartDateValue, + handleStartDateChange: handleStartDateChanges, + }; + + // handle end date + const [endDateValue, setEndDateValue] = useState(''); + + const handleEndDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newEndDateValue = event.currentTarget.elements['date-input'].value; + setEndDateValue(newEndDateValue); + if (newEndDateValue === '') { + searchParams.delete('end_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['end_date', newEndDateValue]]); + setAppliedParams(params); + } + }; + + const filterEndDate = { + useFilter: true, + endDate: endDateValue, + setEndDate: setEndDateValue, + handleEndDateChange: handleEndDateChanges, + }; + + /* -------------------------------- headCell Claim -------------------------------- */ + const headCells: HeadCell[] = [ + { + id: 'code', + align: 'left', + label: localeData.txtRequestCode, + isSort: true, + }, + { + id: 'full_name', + align: 'left', + label: localeData.txtName, + isSort: true, + }, + { + id: 'submission_date', + align: 'center', + label: localeData.txtSubmissionDate, + isSort: true, + }, + { + id: 'service_type', + align: 'center', + label: localeData.txtServiceType, + isSort: true, + }, + { + id: 'status', + align: 'center', + label: localeData.txtStatus, + isSort: true, + }, + { + id: 'action', + align: 'right', + label: '', + isSort: false, + }, + ]; + + + useEffect(() => { + getData(); + }, [appliedParams, searchParams, order, orderBy, setSearchParams]); + + function getData() + { + (async () => { + setIsLoading(true); + + await new Promise((resolve) => setTimeout(resolve, 250)); + + const parameters = + Object.keys(appliedParams).length !== 0 + ? appliedParams + : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); + + const response = await axios.get(`/get-claim-requests`, { + params: { ...parameters, type: 'final-log' }, + }); + setData( + response.data.data.map((obj: any) => ({ + ...obj, + status: + obj.status === 'requested' ? ( + + ) : obj.status === 'approved' ? ( + + ) : obj.status === 'declined' ? ( + + ) : obj.status === 'reviewed' ? ( + + ) : ( + + ), + submission_date: + + , + action: + + + + View + + + } /> + })) + ); + + setPaginationTable(response.data); + setRowsPerPage(response.data.per_page); + + if (searchParams.get('page')) { + //@ts-ignore + const currentPage = parseInt(searchParams.get('page')) - 1; + + paginationTable.current_page = currentPage; + setPage(currentPage); + } + + const status:any = [ + {"id": "requested", "name": "Request" }, + {"id": "reviewed", "name": "Review" }, + {"id": "approved", "name": "Approval" }, + {"id": "declined", "name": "Decline" }, + ]; + setStatusData(status) + + setIsLoading(false); + })(); + } + + + return ( + <> + + + ); +} \ No newline at end of file diff --git a/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx b/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx new file mode 100644 index 00000000..914fa652 --- /dev/null +++ b/frontend/hospital-portal/src/sections/dashboard/DialogClaimSubmit.tsx @@ -0,0 +1,164 @@ +import { styled } from '@mui/material/styles'; +import Iconify from '@/components/Iconify'; +import { fCurrency } from '@/utils/formatNumber'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Button, Divider, LinearProgress, linearProgressClasses, ButtonBase, Box } from '@mui/material'; +import { Card } from '@mui/material'; +import { Stack, Typography } from '@mui/material'; +import { fPostFormat } from '@/utils/formatTime'; +import axios from '@/utils/axios'; +import { enqueueSnackbar } from 'notistack'; +import { useRef, useState, useContext } from 'react'; +import { makeFormData } from '@/utils/jsonToFormData'; +import { format } from 'date-fns'; +import { LanguageContext } from '@/contexts/LanguageContext'; + +export default function DialogClaimSubmit({ member, getData, onClose, handleSubmitSuccess }: any) { + const { localeData }: any = useContext(LanguageContext); + + // ---------------------------------------------------------------------- + // Files Result Tambahan + + const fileAdditionalInput = useRef(null); + const [fileAdditionals, setFileAdditionals] = useState([]); + + const handleKondisiInputChange = (event:any) => { + if (event.target.files[0]) { + setFileAdditionals([...fileAdditionals, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeKondisiFiles = (filesState:any, index:any) => { + setFileAdditionals( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // -------------------------------------------------------------- + // Submit Form + + const [submitLoading, setSubmitLoading] = useState(false); + function submitRequestClaim() { + setSubmitLoading(true); + const formData = makeFormData({ + request_logs_id: member.id, + service_code: member.service_code, + member_id: member.member_id, + additional_files: fileAdditionals + }); + axios + .post('/claim-requests', formData) + .then((response) => { + enqueueSnackbar(response.data.meta.message ?? 'Berhasil membuat data', { variant: 'success' }); + handleSubmitSuccess(); + onClose({ someData: 'example data' }, getData); + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.meta.message ?? 'Something Went Wrong', { variant: 'error' }); + }) + .then(() => { + setSubmitLoading(false); + }); + } + + return ( + + + + {localeData.txtDialogMember5} + + {format(member?.submission_date ? new Date(member.submission_date) : new Date(), "d MMM yyyy")} + + + + + + + {member?.full_name ?? ''} + {member?.no_polis ?? ''} + + + + + } + spacing={4} + sx={{ marginY: 2, marginBottom: 6 }} + > + {/* -------------------------------Upload Dokumen Tambahan------------------------------- */} + + + {localeData.txtAdditionalDocuments} + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileAdditionals && + fileAdditionals.map((file:any, index:any) => ( + + {file.name} + { + removeKondisiFiles(fileAdditionals, index); + }} + > + + ))} + + fileAdditionalInput.current?.click()}> + + + + {localeData.txtAddResult} + + + + + + + + { + submitRequestClaim(); + }} + loading={submitLoading} + > + Submit Claim + + + ); +} diff --git a/frontend/hospital-portal/src/sections/dashboard/DialogFinalLog.tsx b/frontend/hospital-portal/src/sections/dashboard/DialogFinalLog.tsx new file mode 100644 index 00000000..3326616e --- /dev/null +++ b/frontend/hospital-portal/src/sections/dashboard/DialogFinalLog.tsx @@ -0,0 +1,328 @@ +import { styled } from '@mui/material/styles'; +import Iconify from '@/components/Iconify'; +import { fCurrency } from '@/utils/formatNumber'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Button, Divider, LinearProgress, linearProgressClasses, ButtonBase, Box } from '@mui/material'; +import { Card } from '@mui/material'; +import { Stack, Typography } from '@mui/material'; +import { fPostFormat } from '@/utils/formatTime'; +import axios from '@/utils/axios'; +import { enqueueSnackbar } from 'notistack'; +import { useRef, useState, useContext } from 'react'; +import { makeFormData } from '@/utils/jsonToFormData'; +import { format } from 'date-fns'; +import { LanguageContext } from '@/contexts/LanguageContext'; + +export default function DialogFinalLog({ member, getData, onClose, handleSubmitSuccess }: any) { + const { localeData }: any = useContext(LanguageContext); + + // ---------------------------------------------------------------------- + // Files Diagnosa + + const fileDiagnosaInput = useRef(null); + const [fileDiagnosas, setFileDiagnosas] = useState([]); + + const handleDiagnosaInputChange = (event:any) => { + if (event.target.files[0]) { + setFileDiagnosas([...fileDiagnosas, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeDiagnosaFiles = (filesState:any, index:any) => { + setFileDiagnosas( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // ---------------------------------------------------------------------- + // Files Result Kondisi + + const fileKondisiInput = useRef(null); + const [fileKondisis, setFileKondisis] = useState([]); + + const handleKondisiInputChange = (event:any) => { + if (event.target.files[0]) { + setFileKondisis([...fileKondisis, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeKondisiFiles = (filesState:any, index:any) => { + setFileKondisis( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // ---------------------------------------------------------------------- + // Files Result Hasil Penunjang + + const fileHasilPenunjangInput = useRef(null); + const [fileHasilPenunjangs, setFileHasilPenunjangs] = useState([]); + + const handleResultInputChange = (event:any) => { + if (event.target.files[0]) { + setFileHasilPenunjangs([...fileHasilPenunjangs, ...event.target.files]); + } else { + console.log('NO FILE'); + } + }; + const removeFiles = (filesState:any, index:any) => { + setFileHasilPenunjangs( + filesState.filter((file:any, fileIndex:any) => { + return fileIndex != index; + }) + ); + }; + + // -------------------------------------------------------------- + // Submit Form + + const [submitLoading, setSubmitLoading] = useState(false); + function submitRequestFinalLog() { + setSubmitLoading(true); + const formData = makeFormData({ + request_logs_id: member.id, + result_files: fileHasilPenunjangs, + diagnosa_files: fileDiagnosas, + kondisi_files: fileKondisis + }); + axios + .post('/request-final-log', formData) + .then((response) => { + enqueueSnackbar(response.data.meta.message ?? 'Berhasil membuat data', { variant: 'success' }); + handleSubmitSuccess(); + onClose({ someData: 'example data' }, getData); + }) + .catch(({ response }) => { + enqueueSnackbar(response.data.meta.message ?? 'Something Went Wrong', { variant: 'error' }); + }) + .then(() => { + setSubmitLoading(false); + }); + } + + return ( + + + + {localeData.txtDialogMember5} + + {format(member?.submission_date ? new Date(member.submission_date) : new Date(), "d MMM yyyy")} + + + + + + + {member?.full_name ?? ''} + {member?.no_polis ?? ''} + + + + + } + spacing={4} + sx={{ marginY: 2, marginBottom: 6 }} + > + {/* -------------------------------Upload Dokumen Kondisi------------------------------- */} + + + {localeData.txtConditionDocument} + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileKondisis && + fileKondisis.map((file:any, index:any) => ( + + {file.name} + { + removeKondisiFiles(fileKondisis, index); + }} + > + + ))} + + fileKondisiInput.current?.click()}> + + + + {localeData.txtAddResult} + + + + + + + {/* -------------------------------Upload Dokumen Diagnosa------------------------------- */} + + + {localeData.txtDiagnosisDokument} + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileDiagnosas && + fileDiagnosas.map((file:any, index:any) => ( + + {file.name} + { + removeDiagnosaFiles(fileDiagnosas, index); + }} + > + + ))} + {/* + Nama File .pdf + + */} + + {/* { JSON.stringify(filesResult) } */} + fileDiagnosaInput.current?.click()}> + + + + {localeData.txtAddResult} + + + + + + + {/* -------------------------------Upload Dokumen Hasil Penunjang------------------------------- */} + + + {localeData.txtSupportingResultDocument} + + {/* Hasil Lab, */} + } + spacing={1} + sx={{ marginY: 2 }} + > + {fileHasilPenunjangs && + fileHasilPenunjangs.map((file:any, index:any) => ( + + {file.name} + { + removeFiles(fileHasilPenunjangs, index); + }} + > + + ))} + {/* + Nama File .pdf + + */} + + {/* { JSON.stringify(filesResult) } */} + fileHasilPenunjangInput.current?.click()}> + + + + {localeData.txtAddResult} + + + + + + + + { + submitRequestFinalLog(); + }} + loading={submitLoading} + > + Request Final LOG + + + ); +} diff --git a/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx b/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx index 3aa254f1..0c95dec6 100644 --- a/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx @@ -33,7 +33,7 @@ import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; export default function DialogMember(member:any, handleSubmitSuccess:() => void) { const { localeData }: any = useContext(LanguageContext); - const [currentTab, setCurrentTab] = useState('request') + const [currentTab, setCurrentTab] = useState('request'); // ---------------------------------------------------------------------- @@ -97,7 +97,9 @@ export default function DialogMember(member:any, handleSubmitSuccess:() => void) > - + {member?.type !== 'view' ? ( + + ) : ''} diff --git a/frontend/hospital-portal/src/sections/dashboard/TableList.tsx b/frontend/hospital-portal/src/sections/dashboard/TableList.tsx index fa14ad4d..b1575b08 100644 --- a/frontend/hospital-portal/src/sections/dashboard/TableList.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/TableList.tsx @@ -1,8 +1,9 @@ /* ---------------------------------- @mui ---------------------------------- */ -import { Stack, Button, MenuItem, SelectChangeEvent } from '@mui/material'; +import { Stack, Button, MenuItem, SelectChangeEvent, Tab, Tabs, Card, Box } from '@mui/material'; /* ---------------------------------- axios --------------------------------- */ // import axios from 'axios'; import axios from '../../utils/axios'; +import { styled } from '@mui/material/styles'; /* ---------------------------------- react --------------------------------- */ import { useContext, useEffect, useState } from 'react'; @@ -23,9 +24,26 @@ import HistoryIcon from '@mui/icons-material/History'; import SearchIcon from '@mui/icons-material/Search'; import Label from '../../components/Label'; import { enqueueSnackbar } from 'notistack'; +import { LoadingButton, TabPanel } from "@mui/lab"; +import { LanguageContext } from '@/contexts/LanguageContext'; +import MuiDialog from '@/components/MuiDialog'; +import DialogMember from './DialogMember'; +import DialogFinalLog from './DialogFinalLog'; +import { fPostFormat } from '@/utils/formatTime'; +import TableListFinalLog from './TableListFinalLog'; -export default function TableList2() { +export default function TableList() { const navigate = useNavigate(); + const { localeData }: any = useContext(LanguageContext); + const [currentTab, setCurrentTab] = useState('request_log'); + + useEffect(() => { + setCurrentTab('request_log') +}, []) + +function handleChangeTab(event: React.SyntheticEvent, newValue: string) { + setCurrentTab(newValue) +} //const { corporateValue } = useContext(UserCurrentCorporateContext); //const { corporateValue } = useContext(null); @@ -33,7 +51,7 @@ export default function TableList2() { const [data, setData] = useState([]); // Download LOG - async function handleDownloadLog(claimRequest) { + async function handleDownloadLog(claimRequest:any) { return axios .get(`claim-requests/${claimRequest}/log`, { responseType: 'blob', @@ -215,36 +233,30 @@ export default function TableList2() { handleEndDateChange: handleEndDateChanges, }; - /* -------------------------------- headCell -------------------------------- */ + /* -------------------------------- headCell Request LOG -------------------------------- */ const headCells: HeadCell[] = [ - { - id: 'submission_date', - align: 'center', - label: 'Request Date', - isSort: true, - }, - { - id: 'member_id', - align: 'left', - label: 'Member ID', - isSort: true, - }, { id: 'code', align: 'left', - label: 'Claim Code', + label: localeData.txtRequestCode, isSort: true, }, { id: 'full_name', align: 'left', - label: 'Name', + label: localeData.txtName, + isSort: true, + }, + { + id: 'submission_date', + align: 'center', + label: localeData.txtSubmissionDate, isSort: true, }, { id: 'status', align: 'center', - label: 'Status', + label: localeData.txtStatus, isSort: true, }, { @@ -254,8 +266,47 @@ export default function TableList2() { isSort: false, }, ]; + + + function handleSearchMember(noPolis:any, birthDate:any) { + setLoadingClaim(false) + axios.post('/search-member', { + no_polis: noPolis, + birth_date: birthDate ? fPostFormat(birthDate, 'yyyy-MM-dd') : null, + type: 'view' + }) + .then((response) => { + setOpenDialogBenefit(true) + setCurrentMember(response.data.data) + setNameMember(response.data.data.members.name); + }) + .catch(({response}) => { + enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.meta.message : 'Opps, Something went Wrong!'), {variant : "error"}) + }) + .then(() => { + }); + } + + + + function handleRequestFinalLog(id:any, full_name:any, no_polis:any, submission_date:any) + { + setOpenDialogFinalLog(true); + const datas_view = { + 'id' : id, + 'full_name' : full_name, + 'no_polis' : no_polis, + 'submission_date' : submission_date + }; + setDataViewFinalDialog(datas_view); + } useEffect(() => { + getData(); + }, [appliedParams, searchParams, order, orderBy, setSearchParams]); + + function getData() + { (async () => { setIsLoading(true); @@ -266,10 +317,9 @@ export default function TableList2() { ? appliedParams : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); - const response = await axios.get(`/get-claim-requests`, { - params: { ...parameters, type: 'claim-request' }, + const response = await axios.get(`/get-request-log`, { + params: { ...parameters, type: 'request-log' }, }); - setData( response.data.data.map((obj: any) => ({ ...obj, @@ -303,14 +353,22 @@ export default function TableList2() { action: - navigate ('/detail/'+obj.claim_request_id)}> + handleSearchMember(obj.no_polis, obj.birth_date) }> View + {obj.status === 'approved' ? ( handleDownloadLog(obj.claim_request_id)}> Download LOG + ):''} + {obj.final_log === 0 ? ( + handleRequestFinalLog(obj.id, obj.full_name, obj.no_polis, obj.submission_date) }> + + Request Final LOG + + ):''} } /> })) @@ -327,32 +385,116 @@ export default function TableList2() { setPage(currentPage); } - const status = [ + const status:any = [ {"id": "requested", "name": "Request" }, {"id": "reviewed", "name": "Review" }, {"id": "approved", "name": "Approval" }, {"id": "declined", "name": "Decline" }, - ] + ]; setStatusData(status) setIsLoading(false); })(); - }, [appliedParams, searchParams, order, orderBy, setSearchParams]); + } + + const RootNotificationStyle = styled(Card)(({ theme }) => ({ + boxShadow: 'none', + padding: '1rem 0.5rem', + color: 'black', + borderRadius: 0, + backgroundColor: theme.palette.grey[200], + // maxHeight: '240px', + })); + + function TabPanel(props:any) { + const { children, value, index, ...other } = props; + return ( + + ); + } + + // const [noPolis, setNoPolis] = useState('AW001-01'); + //const [birthDate, setBirthDate] = useState('1991-01-10'); + const [loadingBenefit, setLoadingBenefit] = useState(false); + const [loadingClaim, setLoadingClaim] = useState(false); + const [openDialogBenefit, setOpenDialogBenefit] = useState(false); + const [openDialogFinalLog, setOpenDialogFinalLog] = useState(false); + const [openDialogClaim, setOpenDialogClaim] = useState(false); + const [currentMember, setCurrentMember] = useState(null); + const [nameMember, setNameMember] = useState(''); + const [setIsRequestFinalLog, isRequestFinalLog] = useState(false); + const [dataViewFinalDialog, setDataViewFinalDialog] = useState(null); return ( - - - + + + + + + + + + + + + + + setOpenDialogBenefit(false)) + } + maxWidth="sm" + /> + + { + console.log('Data returned:', data); + getData(); + setOpenDialogFinalLog(false); + }} + handleSubmitSuccess={() => { + }} + /> + } + maxWidth="sm" + /> + ); } diff --git a/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx b/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx new file mode 100644 index 00000000..06dc44d8 --- /dev/null +++ b/frontend/hospital-portal/src/sections/dashboard/TableListFinalLog.tsx @@ -0,0 +1,441 @@ +/* ---------------------------------- @mui ---------------------------------- */ +import { Stack, Button, MenuItem, SelectChangeEvent, Tab, Tabs, Card, Box } from '@mui/material'; +/* ---------------------------------- axios --------------------------------- */ +// import axios from 'axios'; +import axios from '../../utils/axios'; +import { styled } from '@mui/material/styles'; +/* ---------------------------------- react --------------------------------- */ +import { useContext, useEffect, useState } from 'react'; + +/* -------------------------------- component ------------------------------- */ +import Iconify from '../../components/Iconify'; +import TableComponent from '../../components/Table'; +/* ---------------------------------- theme --------------------------------- */ +import palette from '../../theme/palette'; +//import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import { HeadCell, Order, PaginationTableProps } from '../../@types/table'; +import { useSearchParams, useNavigate } from 'react-router-dom'; +import { fDate, fDateSuffix } from '../../utils/formatTime'; +import Typography from '@mui/material/Typography'; +import { format } from 'date-fns'; +import TableMoreMenu from '../../components/table/TableMoreMenu'; +import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; +import HistoryIcon from '@mui/icons-material/History'; +import SearchIcon from '@mui/icons-material/Search'; +import Label from '../../components/Label'; +import { enqueueSnackbar } from 'notistack'; +import { LoadingButton, TabPanel } from "@mui/lab"; +import { LanguageContext } from '@/contexts/LanguageContext'; +import MuiDialog from '@/components/MuiDialog'; +import DialogMember from './DialogMember'; +import DialogClaimSubmit from './DialogClaimSubmit'; +import { fPostFormat } from '@/utils/formatTime'; + +export default function TableListFinalLog() { + const navigate = useNavigate(); + const { localeData }: any = useContext(LanguageContext); + + const [data, setData] = useState([]); + + // Download LOG + async function handleDownloadLog(claimRequest:any) { + return axios + .get(`claim-requests/${claimRequest}/log`, { + responseType: 'blob', + }) + .then((response) => { + window.open(URL.createObjectURL(response.data)); + // setLoadingLog(false); + }) + // .then((blobFile) => { + // new File([blobFile], 'asdads.pdf', { type: blobFile.type }) + // setLoadingLog(false); + // }) + .catch((response) => { + console.log(response); + enqueueSnackbar(response.message, { variant: 'error' }); + // setLoadingLog(false); + }); + } + + /* -------------------------------------------------------------------------- */ + /* setting up for the table */ + /* -------------------------------------------------------------------------- */ + const [isLoading, setIsLoading] = useState(true); + + const loadings = { + isLoading: isLoading, + setIsLoading: setIsLoading, + }; + + /* ------------------------------ handle params ----------------------------- */ + const [searchParams, setSearchParams] = useSearchParams(); + const [appliedParams, setAppliedParams] = useState({}); + + const params = { + searchParams: searchParams, + setSearchParams: setSearchParams, + appliedParams: appliedParams, + setAppliedParams: setAppliedParams, + }; + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle order ------------------------------ */ + const [order, setOrder] = useState('desc'); + const [orderBy, setOrderBy] = useState('submission_date'); + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + /* -------------------------------------------------------------------------- */ + + /* ---------------------------- handle pagination --------------------------- */ + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + + const [paginationTable, setPaginationTable] = useState({ + current_page: 0, + from: 0, + last_page: 0, + links: [], + path: '', + per_page: 0, + to: 0, + total: 0, + }); + + const paginations = { + page: page, + setPage: setPage, + rowsPerPage: rowsPerPage, + setRowsPerPage: setRowsPerPage, + paginationTable: paginationTable, + setPaginationTable: setPaginationTable, + }; + + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle search ----------------------------- */ + const [searchText, setSearchText] = useState(''); + + const handleSearchSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (searchText === '') { + searchParams.delete('search'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); + setAppliedParams(params); + } + }; + + const searchs = { + useSearchs: true, + searchText: searchText, + setSearchText: setSearchText, + handleSearchSubmit: handleSearchSubmit, + }; + + /* ------------------------------ handle filter ----------------------------- */ + const [statusValue, setStatusValue] = useState('all'); + const [filterData, setStatusData] = useState([]); + + // handle status + const handleStatusChanges = (event: SelectChangeEvent) => { + setStatusValue(event.target.value as string); + + if (event.target.value === 'all') { + searchParams.delete('status'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([ + ...searchParams.entries(), + ['status', event.target.value as string], + ]); + setAppliedParams(params); + } + }; + + const filterStatus = { + useFilter: true, + config: { + label: 'Status', + statusValue: statusValue, + filterData: filterData, + handleStatusChange: handleStatusChanges, + }, + }; + + // handle start date + const [startDateValue, setStartDateValue] = useState(''); + + const handleStartDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newStartDateValue = event.currentTarget.elements['date-input'].value; + setStartDateValue(newStartDateValue); + if (newStartDateValue === '') { + searchParams.delete('start_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['start_date', newStartDateValue]]); + setAppliedParams(params); + } + }; + + const filterStartDate = { + useFilter: true, + startDate: startDateValue, + setStartDate: setStartDateValue, + handleStartDateChange: handleStartDateChanges, + }; + + // handle end date + const [endDateValue, setEndDateValue] = useState(''); + + const handleEndDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newEndDateValue = event.currentTarget.elements['date-input'].value; + setEndDateValue(newEndDateValue); + if (newEndDateValue === '') { + searchParams.delete('end_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['end_date', newEndDateValue]]); + setAppliedParams(params); + } + }; + + const filterEndDate = { + useFilter: true, + endDate: endDateValue, + setEndDate: setEndDateValue, + handleEndDateChange: handleEndDateChanges, + }; + + /* -------------------------------- headCell Final LOG -------------------------------- */ + const headCells: HeadCell[] = [ + { + id: 'code', + align: 'left', + label: localeData.txtRequestCode, + isSort: true, + }, + { + id: 'full_name', + align: 'left', + label: localeData.txtName, + isSort: true, + }, + { + id: 'submission_date', + align: 'center', + label: localeData.txtSubmissionDate, + isSort: true, + }, + { + id: 'service_type', + align: 'center', + label: localeData.txtServiceType, + isSort: true, + }, + { + id: 'status', + align: 'center', + label: localeData.txtStatus, + isSort: true, + }, + { + id: 'action', + align: 'right', + label: '', + isSort: false, + }, + ]; + function handleSearchMember(noPolis:any, birthDate:any) { + setLoadingClaim(false) + axios.post('/search-member', { + no_polis: noPolis, + birth_date: birthDate ? fPostFormat(birthDate, 'yyyy-MM-dd') : null, + type: 'view' + }) + .then((response) => { + setOpenDialogBenefit(true) + setCurrentMember(response.data.data) + setNameMember(response.data.data.members.name); + }) + .catch(({response}) => { + enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.meta.message : 'Opps, Something went Wrong!'), {variant : "error"}) + }) + .then(() => { + }); + } + const [openDialogClaimSubmit, setOpenDialogClaimSubmit] = useState(false); + const [dataViewClaimSubmit, setDataViewClaimSubmit] = useState(null); + function handleRequestClaimSubmit(member_id:any, service_code:any, id:any, full_name:any, no_polis:any, submission_date:any) + { + setOpenDialogClaimSubmit(true); + const datas_view = { + 'member_id' : member_id, + 'service_code' : service_code, + 'id' : id, + 'full_name' : full_name, + 'no_polis' : no_polis, + 'submission_date' : submission_date + }; + setDataViewClaimSubmit(datas_view); + } + + useEffect(() => { + getData(); + }, [appliedParams, searchParams, order, orderBy, setSearchParams]); + + function getData() + { + (async () => { + setIsLoading(true); + + await new Promise((resolve) => setTimeout(resolve, 250)); + + const parameters = + Object.keys(appliedParams).length !== 0 + ? appliedParams + : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); + + const response = await axios.get(`/get-final-log`, { + params: { ...parameters, type: 'final-log' }, + }); + setData( + response.data.data.map((obj: any) => ({ + ...obj, + status: + obj.status === 'requested' ? ( + + ) : obj.status === 'approved' ? ( + + ) : obj.status === 'declined' ? ( + + ) : obj.status === 'reviewed' ? ( + + ) : ( + + ), + submission_date: + + , + action: + + handleSearchMember(obj.no_polis, obj.birth_date) }> + + View + + {obj.status === 'approved' ? ( + handleDownloadLog(obj.claim_request_id)}> + + Download LOG + + ):''} + {!obj.check_claim ? ( + handleRequestClaimSubmit(obj.member_id, obj.service_code, obj.id, obj.full_name, obj.no_polis, obj.submission_date) }> + + Submit Claim + + ):''} + + } /> + })) + ); + + setPaginationTable(response.data); + setRowsPerPage(response.data.per_page); + + if (searchParams.get('page')) { + //@ts-ignore + const currentPage = parseInt(searchParams.get('page')) - 1; + + paginationTable.current_page = currentPage; + setPage(currentPage); + } + + const status:any = [ + {"id": "requested", "name": "Request" }, + {"id": "reviewed", "name": "Review" }, + {"id": "approved", "name": "Approval" }, + {"id": "declined", "name": "Decline" }, + ]; + setStatusData(status) + + setIsLoading(false); + })(); + } + + const [loadingClaim, setLoadingClaim] = useState(false); + const [openDialogBenefit, setOpenDialogBenefit] = useState(false); + const [currentMember, setCurrentMember] = useState(null); + const [nameMember, setNameMember] = useState(''); + + return ( + <> + + setOpenDialogBenefit(false)) + } + maxWidth="sm" + /> + { + console.log('Data returned:', data); + getData(); + setOpenDialogClaimSubmit(false); + }} + handleSubmitSuccess={() => { + }} + /> + } + maxWidth="sm" + /> + + ); +} \ No newline at end of file diff --git a/frontend/hospital-portal/src/sections/dashboard/TableListReqLog.tsx b/frontend/hospital-portal/src/sections/dashboard/TableListReqLog.tsx new file mode 100644 index 00000000..1e5b224f --- /dev/null +++ b/frontend/hospital-portal/src/sections/dashboard/TableListReqLog.tsx @@ -0,0 +1,425 @@ +/* ---------------------------------- @mui ---------------------------------- */ +import { Stack, Button, MenuItem, SelectChangeEvent, Tab, Tabs, Card, Box } from '@mui/material'; +/* ---------------------------------- axios --------------------------------- */ +// import axios from 'axios'; +import axios from '../../utils/axios'; +import { styled } from '@mui/material/styles'; +/* ---------------------------------- react --------------------------------- */ +import { useContext, useEffect, useState } from 'react'; + +/* -------------------------------- component ------------------------------- */ +import Iconify from '../../components/Iconify'; +import TableComponent from '../../components/Table'; +/* ---------------------------------- theme --------------------------------- */ +import palette from '../../theme/palette'; +//import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; +import { HeadCell, Order, PaginationTableProps } from '../../@types/table'; +import { useSearchParams, useNavigate } from 'react-router-dom'; +import { fDate, fDateSuffix } from '../../utils/formatTime'; +import Typography from '@mui/material/Typography'; +import { format } from 'date-fns'; +import TableMoreMenu from '../../components/table/TableMoreMenu'; +import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'; +import HistoryIcon from '@mui/icons-material/History'; +import SearchIcon from '@mui/icons-material/Search'; +import Label from '../../components/Label'; +import { enqueueSnackbar } from 'notistack'; +import { LoadingButton, TabPanel } from "@mui/lab"; +import { LanguageContext } from '@/contexts/LanguageContext'; + +export default function TableList() { + const navigate = useNavigate(); + const { localeData }: any = useContext(LanguageContext); + const [currentTab, setCurrentTab] = useState('request_log'); + + useEffect(() => { + setCurrentTab('request_log') +}, []) + +function handleChangeTab(event: React.SyntheticEvent, newValue: string) { + setCurrentTab(newValue) +} + + //const { corporateValue } = useContext(UserCurrentCorporateContext); + //const { corporateValue } = useContext(null); + + const [data, setData] = useState([]); + + // Download LOG + async function handleDownloadLog(claimRequest) { + return axios + .get(`claim-requests/${claimRequest}/log`, { + responseType: 'blob', + }) + .then((response) => { + window.open(URL.createObjectURL(response.data)); + // setLoadingLog(false); + }) + // .then((blobFile) => { + // new File([blobFile], 'asdads.pdf', { type: blobFile.type }) + // setLoadingLog(false); + // }) + .catch((response) => { + console.log(response); + enqueueSnackbar(response.message, { variant: 'error' }); + // setLoadingLog(false); + }); + } + + /* -------------------------------------------------------------------------- */ + /* setting up for the table */ + /* -------------------------------------------------------------------------- */ + const [isLoading, setIsLoading] = useState(true); + + const loadings = { + isLoading: isLoading, + setIsLoading: setIsLoading, + }; + + /* ------------------------------ handle params ----------------------------- */ + const [searchParams, setSearchParams] = useSearchParams(); + const [appliedParams, setAppliedParams] = useState({}); + + const params = { + searchParams: searchParams, + setSearchParams: setSearchParams, + appliedParams: appliedParams, + setAppliedParams: setAppliedParams, + }; + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle order ------------------------------ */ + const [order, setOrder] = useState('desc'); + const [orderBy, setOrderBy] = useState('submission_date'); + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + /* -------------------------------------------------------------------------- */ + + /* ---------------------------- handle pagination --------------------------- */ + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + + const [paginationTable, setPaginationTable] = useState({ + current_page: 0, + from: 0, + last_page: 0, + links: [], + path: '', + per_page: 0, + to: 0, + total: 0, + }); + + const paginations = { + page: page, + setPage: setPage, + rowsPerPage: rowsPerPage, + setRowsPerPage: setRowsPerPage, + paginationTable: paginationTable, + setPaginationTable: setPaginationTable, + }; + + /* -------------------------------------------------------------------------- */ + + /* ------------------------------ handle search ----------------------------- */ + const [searchText, setSearchText] = useState(''); + + const handleSearchSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (searchText === '') { + searchParams.delete('search'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['search', searchText]]); + setAppliedParams(params); + } + }; + + const searchs = { + useSearchs: true, + searchText: searchText, + setSearchText: setSearchText, + handleSearchSubmit: handleSearchSubmit, + }; + + /* ------------------------------ handle filter ----------------------------- */ + const [statusValue, setStatusValue] = useState('all'); + const [filterData, setStatusData] = useState([]); + + // handle status + const handleStatusChanges = (event: SelectChangeEvent) => { + setStatusValue(event.target.value as string); + + if (event.target.value === 'all') { + searchParams.delete('status'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([ + ...searchParams.entries(), + ['status', event.target.value as string], + ]); + setAppliedParams(params); + } + }; + + const filterStatus = { + useFilter: true, + config: { + label: 'Status', + statusValue: statusValue, + filterData: filterData, + handleStatusChange: handleStatusChanges, + }, + }; + + // handle start date + const [startDateValue, setStartDateValue] = useState(''); + + const handleStartDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newStartDateValue = event.currentTarget.elements['date-input'].value; + setStartDateValue(newStartDateValue); + if (newStartDateValue === '') { + searchParams.delete('start_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['start_date', newStartDateValue]]); + setAppliedParams(params); + } + }; + + const filterStartDate = { + useFilter: true, + startDate: startDateValue, + setStartDate: setStartDateValue, + handleStartDateChange: handleStartDateChanges, + }; + + // handle end date + const [endDateValue, setEndDateValue] = useState(''); + + const handleEndDateChanges = async (event: React.FormEvent) => { + event.preventDefault(); + const newEndDateValue = event.currentTarget.elements['date-input'].value; + setEndDateValue(newEndDateValue); + if (newEndDateValue === '') { + searchParams.delete('end_date'); + const params = Object.fromEntries([...searchParams.entries()]); + setAppliedParams(params); + } else { + const params = Object.fromEntries([...searchParams.entries(), ['end_date', newEndDateValue]]); + setAppliedParams(params); + } + }; + + const filterEndDate = { + useFilter: true, + endDate: endDateValue, + setEndDate: setEndDateValue, + handleEndDateChange: handleEndDateChanges, + }; + + /* -------------------------------- headCell -------------------------------- */ + const headCells: HeadCell[] = [ + { + id: 'submission_date', + align: 'center', + label: localeData.txtRequestDate, + isSort: true, + }, + { + id: 'member_id', + align: 'left', + label: localeData.txtMemberID, + isSort: true, + }, + { + id: 'code', + align: 'left', + label: localeData.txtClaimCode, + isSort: true, + }, + { + id: 'full_name', + align: 'left', + label: localeData.txtName, + isSort: true, + }, + { + id: 'status', + align: 'center', + label: localeData.txtStatus, + isSort: true, + }, + { + id: 'action', + align: 'right', + label: '', + isSort: false, + }, + ]; + + useEffect(() => { + (async () => { + setIsLoading(true); + + await new Promise((resolve) => setTimeout(resolve, 250)); + + const parameters = + Object.keys(appliedParams).length !== 0 + ? appliedParams + : Object.fromEntries([...searchParams.entries(), ['order', order], ['orderBy', orderBy]]); + + const response = await axios.get(`/get-claim-requests`, { + params: { ...parameters, type: 'claim-request' }, + }); + + setData( + response.data.data.map((obj: any) => ({ + ...obj, + status: + obj.status === 'requested' ? ( + + ) : obj.status === 'approved' ? ( + + ) : obj.status === 'declined' ? ( + + ) : obj.status === 'reviewed' ? ( + + ) : ( + + ), + submission_date: + + , + action: + + navigate ('/detail/'+obj.claim_request_id)}> + + View + + handleDownloadLog(obj.claim_request_id)}> + + Download LOG + + + } /> + })) + ); + + setPaginationTable(response.data); + setRowsPerPage(response.data.per_page); + + if (searchParams.get('page')) { + //@ts-ignore + const currentPage = parseInt(searchParams.get('page')) - 1; + + paginationTable.current_page = currentPage; + setPage(currentPage); + } + + const status = [ + {"id": "requested", "name": "Request" }, + {"id": "reviewed", "name": "Review" }, + {"id": "approved", "name": "Approval" }, + {"id": "declined", "name": "Decline" }, + ] + setStatusData(status) + + setIsLoading(false); + })(); + }, [appliedParams, searchParams, order, orderBy, setSearchParams]); + + const RootNotificationStyle = styled(Card)(({ theme }) => ({ + boxShadow: 'none', + padding: '1rem 0.5rem', + color: 'black', + borderRadius: 0, + backgroundColor: theme.palette.grey[200], + // maxHeight: '240px', + })); + + function TabPanel(props:any) { + const { children, value, index, ...other } = props; + return ( + + ); + } + + return ( + + + + + + + + + + + + + + + ); +} diff --git a/resources/lang/en/Message.php b/resources/lang/en/Message.php index 0cd2443f..d0167b2b 100644 --- a/resources/lang/en/Message.php +++ b/resources/lang/en/Message.php @@ -6,4 +6,5 @@ return [ 'not_found' => 'Data not found', 'password' => 'Password wrong. Please try again.', 'read_notification' => 'Notification has been read.', + 'already_exists' => 'Data already exists.', ]; diff --git a/resources/lang/id/Message.php b/resources/lang/id/Message.php index 61ed1c80..475a5731 100644 --- a/resources/lang/id/Message.php +++ b/resources/lang/id/Message.php @@ -6,4 +6,5 @@ return [ 'not_found' => 'Data tidak ditemukan.', 'password' => 'Password salah. Silakan coba lagi.', 'read_notification' => 'Notifikasi telah dibaca.', + 'already_exists' => 'Data sudah ada.', ]; diff --git a/resources/views/pdf/guaranted_leter.blade.php b/resources/views/pdf/guaranted_leter.blade.php index 324614f5..8738d901 100644 --- a/resources/views/pdf/guaranted_leter.blade.php +++ b/resources/views/pdf/guaranted_leter.blade.php @@ -123,8 +123,8 @@
Date of Admission
- @if (isset($claimRequest)) -
{{ !empty($claimRequest->submission_date) ? \Carbon\Carbon::parse($claimRequest->submission_date)->format('d/m/Y') : now()->format('d/m/Y') }}
+ @if (isset($requestLog)) +
{{ !empty($requestLog->submission_date) ? \Carbon\Carbon::parse($requestLog->submission_date)->format('d/m/Y') : now()->format('d/m/Y') }}
@else
{{ $dateOfAdmission->format('d/m/Y') }}
@endif @@ -140,7 +140,7 @@ - + @@ -148,18 +148,34 @@ --}} + @if ($member->currentPlan) + @foreach ($member->currentPlan->corporateBenefits as $corporateBenefit) + + + + + + @endforeach + @endif +
Detail BenefitLimit
Medical Check Up As Charged
{{ @$corporateBenefit->benefit->description ?? '' }}
+ - @foreach ($member->currentPlan->corporateBenefits as $corporateBenefit) - - - {{ @$corporateBenefit->benefit->description ?? '' }} - @if($corporateBenefit->limit_amount == 999999999) - As Charged - @else - IDR {{ number_format($corporateBenefit->limit_amount, 0, ',', '.') ?? '' }} - @endif - - @endforeach +
+ + + + + + + @if ($member->currentPlan) + @foreach ($member->currentPlan->corporateBenefits as $corporateBenefit) + + + + + + @endforeach + @endif
Term on Condition
{{ @$corporateBenefit->benefit->description ?? '' }}