diff --git a/Modules/HospitalPortal/Helpers/ApiResponse.php b/Modules/HospitalPortal/Helpers/ApiResponse.php new file mode 100644 index 00000000..d24cbca7 --- /dev/null +++ b/Modules/HospitalPortal/Helpers/ApiResponse.php @@ -0,0 +1,21 @@ +first(); + } + return response()->json([ + 'meta' => [ + 'status' => $status, + 'code' => $statusCode, + 'message' => $message + ], + 'data' => $data, + ], $statusCode); + } +} \ No newline at end of file diff --git a/Modules/HospitalPortal/Http/Controllers/Api/AuthController.php b/Modules/HospitalPortal/Http/Controllers/Api/AuthController.php index a9a54aaf..bf221968 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/AuthController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/AuthController.php @@ -12,33 +12,48 @@ use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Mail; use Modules\Internal\Emails\SendVerifyEmail; use Modules\Internal\Events\ForgetPassword; +use Illuminate\Support\Facades\Validator; +use Modules\HospitalPortal\Helpers\ApiResponse; class AuthController extends Controller { public function login(Request $request) { - $request->validate([ + $data = [ + 'email' => $request->email, + 'password' => $request->password + ]; + $validator = Validator::make($request->all(), [ 'email' => 'required|email', 'password' => 'required' + ], [ + 'email.required' => trans('validation.required',['attribute' => 'Email']), + 'email.email' => trans('validation.email'), + 'password.required' => trans('validation.required',['attribute' => 'Password']), ]); - $user = User::query() - ->where('email', $request->email) - ->first(); - - if (!$user) { - return response(['message' => 'User Tidak Ditemukan'], 404); + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); } + else + { + $user = User::where('email', $request->email)->first(); + if (!$user) { + return ApiResponse::apiResponse('Not Found', $data, trans('message.not_found'), 404); + } - if (!Hash::check($request->password, $user->password)) { - return response(['message' => 'Password Salah'], 403); + if (!Hash::check($request->password, $user->password)) { + return ApiResponse::apiResponse('Bad Request', $data, trans('message.password'), 400); + } + + $res_data = [ + 'user' => $user, + 'token' => $user->createToken('app')->plainTextToken + ]; + + return ApiResponse::apiResponse("Success", $res_data, trans('message.success'), 200); } - - return response([ - 'message' => 'Selamat Datang', - 'user' => $user, - 'token' => $user->createToken('app')->plainTextToken - ]); } public function logout(Request $request) diff --git a/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php b/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php index 332bbbeb..1d03ab6c 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/ClaimRequestController.php @@ -108,7 +108,7 @@ class ClaimRequestController extends Controller } } - if ($request->hasFile('result_files')) { + if ($request->hasFile('kondisi_files')) { foreach ($request->result_files as $file) { $pathFile = File::storeFile('claim-kondisi', $newClaimRequest->id, $file); $newClaimRequest->files()->updateOrCreate([ diff --git a/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php b/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php index 7cab7248..de33a43a 100644 --- a/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php +++ b/Modules/HospitalPortal/Http/Controllers/Api/MemberController.php @@ -7,6 +7,8 @@ use App\Models\Member; use Illuminate\Contracts\Support\Renderable; use Illuminate\Http\Request; use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\Validator; +use Modules\HospitalPortal\Helpers\ApiResponse; class MemberController extends Controller { @@ -16,26 +18,37 @@ class MemberController extends Controller */ public function search(Request $request) { - $request->validate([ + $data = [ + 'no_polis' => $request->no_polis, + 'birth_date' => $request->birth_date + ]; + $validator = Validator::make($request->all(), [ 'no_polis' => 'required', 'birth_date' => 'required' + ], [ + 'no_polis.required' => trans('validation.required',['attribute' => 'Member ID']), + 'birth_date.required' => trans('validation.required',['attribute' => 'Birth Date']), ]); - - $member = Member::query() - ->where('member_id', $request->no_polis) - ->where('birth_date', $request->birth_date) - ->with(['person', 'currentCorporate', - // 'currentCorporate.corporateServices' => function ($corporateService) { - // $corporateService->where('status', 'active'); - // }, - // 'currentCorporate.corporateServices.service' - // 'currentPlan.benefits', - // 'currentPlan.corporateBenefit.plan', - 'currentPlan.corporateBenefits.benefit' - ]) - ->firstOrFail(); - - - return Helper::responseJson($member); + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); + } + else + { + $res_data = Member::query() + ->where('member_id', $request->no_polis) + ->where('birth_date', $request->birth_date) + ->with(['person', 'currentCorporate', + // 'currentCorporate.corporateServices' => function ($corporateService) { + // $corporateService->where('status', 'active'); + // }, + // 'currentCorporate.corporateServices.service' + // 'currentPlan.benefits', + // 'currentPlan.corporateBenefit.plan', + 'currentPlan.corporateBenefits.benefit' + ]) + ->firstOrFail(); + return ApiResponse::apiResponse("Success", $res_data, trans('message.success'), 200); + } } } diff --git a/Modules/HospitalPortal/Http/Middleware/Authentication.php b/Modules/HospitalPortal/Http/Middleware/Authentication.php new file mode 100644 index 00000000..a916db9e --- /dev/null +++ b/Modules/HospitalPortal/Http/Middleware/Authentication.php @@ -0,0 +1,65 @@ +header('Accept'); + $contentType = $request->header('Content-Type'); + $locale = $request->header('Accept-Language'); + + // Add language + if(!$locale) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Accept-Language']), 401); + } + if($locale !== 'en-US' && $locale !== 'id-ID') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Accept-Language']), 400); + } + if ($locale === 'en-US') + { + App::setLocale('en'); + } elseif ($locale === 'id-ID') + { + App::setLocale('id'); + } else + { + App::setLocale('en'); + } + + // Validate type accept & content type + if (!$acceptHeader) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Accept']), 401); + } + if (!$contentType) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Content-Type']), 401); + } + if ($acceptHeader !== 'application/json') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Accept']), 400); + } + if($contentType !== 'application/json') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Content-Type']), 400); + } + return $next($request); + } +} diff --git a/Modules/HospitalPortal/Http/Middleware/Authorization.php b/Modules/HospitalPortal/Http/Middleware/Authorization.php new file mode 100644 index 00000000..430258bb --- /dev/null +++ b/Modules/HospitalPortal/Http/Middleware/Authorization.php @@ -0,0 +1,71 @@ +header('Accept'); + $contentType = $request->header('Content-Type'); + $locale = $request->header('Accept-Language'); + $authorization = $request->header('Authorization'); + + // Add language + if(!$locale) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Accept-Language']), 401); + } + if($locale !== 'en-US' && $locale !== 'id-ID') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Accept-Language']), 400); + } + if ($locale === 'en-US') + { + App::setLocale('en'); + } elseif ($locale === 'id-ID') + { + App::setLocale('id'); + } else + { + App::setLocale('en'); + } + + // Validate authorization + if (empty($authorization) || strpos($authorization, 'Bearer ') !== 0) { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Authorization']), 401); + } + + // Validate type accept & content type + if (!$acceptHeader) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Accept']), 401); + } + if (!$contentType) + { + return ApiResponse::apiResponse('Unauthorized', null, trans('validation.required', ['attribute' => 'Content-Type']), 401); + } + if ($acceptHeader !== 'application/json') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Accept']), 400); + } + if($contentType !== 'application/json') + { + return ApiResponse::apiResponse('Bad Request', null, trans('validation.invalid', ['attribute' => 'Content-Type']), 400); + } + return $next($request); + } +} diff --git a/Modules/HospitalPortal/Routes/api.php b/Modules/HospitalPortal/Routes/api.php index b3599848..3ff6dc32 100644 --- a/Modules/HospitalPortal/Routes/api.php +++ b/Modules/HospitalPortal/Routes/api.php @@ -5,6 +5,8 @@ use Modules\HospitalPortal\Http\Controllers\Api\AuthController; use Modules\HospitalPortal\Http\Controllers\Api\ClaimRequestController; use Modules\HospitalPortal\Http\Controllers\Api\MemberController; use Modules\HospitalPortal\Http\Controllers\ClaimController; +use Modules\HospitalPortal\Http\Middleware\Authentication; +use Modules\HospitalPortal\Http\Middleware\Authorization; /* |-------------------------------------------------------------------------- @@ -16,29 +18,39 @@ use Modules\HospitalPortal\Http\Controllers\ClaimController; | is assigned the "api" middleware group. Enjoy building your API! | */ +Route::prefix('v1')->group(function() { + Route::prefix('hospitalportal')->group(function () { -Route::prefix('hospitalportal')->group(function () { - - Route::post('login', [AuthController::class, 'login'])->name('login'); - Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password'); - Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email'); - - - Route::middleware('auth:sanctum')->group(function () { - - Route::post('logout', [AuthController::class, 'logout'])->name('logout'); - Route::get('/user', function (Request $request) { - return $request->user(); + Route::middleware(Authentication::class)->group(function () { + Route::controller(AuthController::class)->group(function () { + Route::post('login', 'login'); + }); }); - Route::put('reset-password', [AuthController::class, 'resetPassword'])->name('resetPassword'); + + //Route::post('forget-password', [AuthController::class, 'forgetPassword'])->name('forget-password'); + //Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email'); - Route::get('claims', [ClaimController::class, 'index']); - Route::post('search-member', [MemberController::class, 'search']); + Route::middleware('auth:sanctum')->group(function () { - Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index'); - 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::post('logout', [AuthController::class, 'logout'])->name('logout'); + Route::get('/user', function (Request $request) { + return $request->user(); + }); + Route::put('reset-password', [AuthController::class, 'resetPassword'])->name('resetPassword'); + + Route::get('claims', [ClaimController::class, 'index']); + + Route::middleware(Authorization::class)->group(function () { + Route::controller(MemberController::class)->group(function () { + Route::post('search-member', 'search'); + }); + }); + + Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index'); + 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'); + }); }); }); diff --git a/Modules/Internal/Http/Controllers/Api/ClaimRequestController.php b/Modules/Internal/Http/Controllers/Api/ClaimRequestController.php index d85e6e9e..5f8f7812 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimRequestController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimRequestController.php @@ -10,6 +10,8 @@ use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Modules\Internal\Transformers\ClaimRequestResource; use Modules\Internal\Transformers\ClaimRequestShowResource; +use App\Models\File; +use App\Models\FilesMcu; class ClaimRequestController extends Controller { @@ -140,4 +142,29 @@ class ClaimRequestController extends Controller return $claimRequest; } + public function filesMcu(Request $request) + { + $request->validate([ + 'id' => 'required', + 'memberid' => 'required' + ]); + if ($request->hasFile('result_files')) { + $pathFile = File::storeFile('claim-result', $request->id, $request->result_files); + $data = [ + 'memberid' => $request->id, + 'original_name' => $request->result_files->getClientOriginalName(), + 'path' => $pathFile, + 'created_by' => auth()->user()->id, + 'updated_by' => auth()->user()->id + ]; + FilesMcu::create($data); + return Helper::responseJson(data: $request->toArray(), message: 'Berhasil tambah file MemberID '.$request->memberid.', silahkan lihat dilaporan'); + } + else + { + return Helper::responseJson(data: $request->toArray(), message: 'Tidak ada file member yang ditambahkan'); + } + + } + } diff --git a/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php b/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php index 4da01d8c..df5368ed 100644 --- a/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php @@ -18,6 +18,8 @@ use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Storage; use Modules\Internal\Services\MemberEnrollmentService; use PDF; +use Illuminate\Support\Facades\DB; +use Illuminate\Database\Eloquent\Builder; class CorporateMemberController extends Controller { @@ -32,11 +34,8 @@ class CorporateMemberController extends Controller public function index(Request $request, $corporate_id) { $members = Member::query() - ->filter($request->all()) - // ->where('corporate_id', $corporate_id) - ->whereHas('employeds', function ($employeds) use ($corporate_id) { - $employeds->where('corporate_id', $corporate_id); - }) + ->joinCorporateEmployees('left') + ->where('corporate_employees.corporate_id', $corporate_id) ->with([ 'employeds', 'currentPolicy', @@ -54,6 +53,14 @@ class CorporateMemberController extends Controller ]); } ]) + ->when($request->input('search'), function (Builder $query, $search) { + $query->where(function (Builder $query) use ($search) { + $query->orWhere('members.member_id', 'like', "%" . $search . "%") + ->orWhere('members.name', 'like', "%" . $search . "%"); + }); + }) + ->select('members.*') + ->selectRaw('(SELECT GROUP_CONCAT(files_mcu.original_name SEPARATOR ", ") AS file_mcu_names from files_mcu WHERE files_mcu.memberid = members.id) AS file_mcu_names') ->paginate() ->appends($request->all()); return Helper::paginateResources(MemberDataTableResource::collection($members)); diff --git a/Modules/Internal/Http/Controllers/ClaimEncounterController.php b/Modules/Internal/Http/Controllers/ClaimEncounterController.php index 9eea7c46..a1f6179b 100644 --- a/Modules/Internal/Http/Controllers/ClaimEncounterController.php +++ b/Modules/Internal/Http/Controllers/ClaimEncounterController.php @@ -263,7 +263,7 @@ class ClaimEncounterController extends Controller } } - public function x`counters($claim_id) + public function xcounters($claim_id) { $claim = Claim::findOrFail($claim_id); $encounters = $claim->encounters()->get(); diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index d13e0f47..716e4b7f 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -158,7 +158,9 @@ Route::prefix('internal')->group(function () { Route::resource('doctors', DoctorController::class); Route::post('generate-log/{member_id}', [CorporateMemberController::class, 'generateLog']); - + Route::controller(ClaimRequestController::class)->group(function(){ + Route::post('files-mcu','filesMcu'); + }); Route::get('claim-requests', [ClaimRequestController::class, 'index'])->name('claim-requests.index'); Route::post('claim-requests/{id}/approve', [ClaimRequestController::class, 'approve'])->name('claim-requests.approve'); Route::get('claim-requests/{id}', [ClaimRequestController::class, 'show'])->name('claim-requests.show'); diff --git a/Modules/Internal/Services/MemberEnrollmentService.php b/Modules/Internal/Services/MemberEnrollmentService.php index c78d516a..c61d1349 100644 --- a/Modules/Internal/Services/MemberEnrollmentService.php +++ b/Modules/Internal/Services/MemberEnrollmentService.php @@ -11,8 +11,13 @@ use App\Models\CorporatePolicy; use App\Models\CorporatePlan; use App\Models\Member; use App\Models\MemberPolicy; +use App\Models\MemberPlan; use App\Models\Person; use App\Models\Plan; +use App\Models\OLDLMS\User; +use App\Models\OLDLMS\UserDetail; +use App\Models\OLDLMS\UserInsurance; +use App\Models\OLDLMS\UserInsuranceDetail; use Box\Spout\Writer\Common\Creator\WriterEntityFactory; use Box\Spout\Common\Entity\Row; use Carbon\Carbon; @@ -565,6 +570,7 @@ class MemberEnrollmentService "policy_in_force" => $row['policy_in_force'] ?? null, "start_no_claim" => $row['start_no_claim'] ?? null, "end_no_claim" => $row['end_no_claim'] ?? null, + "plan_id" => $row['plan_id'] ?? null, "members_effective_date" => $row['member_effective_date'] ?? null, "members_expire_date" => $row['member_expiry_date'] ?? null, @@ -575,14 +581,13 @@ class MemberEnrollmentService "telephone_res" => $row['telephone_res'] ?? null, "telephone_office" => $row['telephone_office'] ?? null, ]; - // $this->validateRow($row); if (!isset($corporate->currentPolicy) || $corporate->currentPolicy->code != $row['policy_number']) { throw new ImportRowException(__('enrollment.POLICY_NUMBER_NOT_MATCH', [ 'policy_id' => $row['policy_number'] ]), 0, null, $row); } - + // validasi member efektif date range date in periode date coroporate $member_effective_date = date("Y-m-d", strtotime($row['member_effective_date'])); $date_terminated = date("Y-m-d", strtotime($row['date_terminated'])); @@ -624,6 +629,7 @@ class MemberEnrollmentService 'start' => $corporate->currentPolicy->start ]), 0, null, $row); } + if ($member_effective_date >= $corporate->currentPolicy->end && ($member_effective_date != $corporate->currentPolicy->end)) { throw new ImportRowException(__('enrollment.LESS_THAN', [ 'date_param' => 'Member Effective Date', @@ -632,6 +638,7 @@ class MemberEnrollmentService 'end' => $corporate->currentPolicy->end ]), 0, null, $row); } + if ($member_effective_date >= $corporate->currentPolicy->end && ($member_effective_date != $corporate->currentPolicy->end)) { throw new ImportRowException(__('enrollment.LESS_THAN', [ 'date_param' => 'Member Effective Date', @@ -648,6 +655,7 @@ class MemberEnrollmentService 'start' => $corporate->currentPolicy->start ]), 0, null, $row); } + if ($members_expire_date >= $corporate->currentPolicy->end && ($members_expire_date != $corporate->currentPolicy->end)) { throw new ImportRowException(__('enrollment.LESS_THAN', [ 'date_param' => 'Member Expired Date', @@ -656,6 +664,7 @@ class MemberEnrollmentService 'end' => $corporate->currentPolicy->end ]), 0, null, $row); } + if ($members_expire_date <= $member_effective_date && ($members_expire_date != $member_effective_date)) { throw new ImportRowException(__('enrollment.MORE_THAN', [ @@ -665,14 +674,14 @@ class MemberEnrollmentService 'start' => $member_effective_date ]), 0, null, $row); } - + if($corporate->code != $row['corporate_id']){ throw new ImportRowException(__('enrollment.CORPORATE_CODE_NOT_MATCH', [ 'corporate_id' => $row['corporate_id'] ]), 0, null, $row); } - + switch ($row['record_mode']) { case "1": // New Member $this->validateRow($row); @@ -790,12 +799,13 @@ class MemberEnrollmentService } break; case "2": // Member Information Update (Without Replacement Card) - $this->validateRow($row); + + // $this->validateRow($row); $member = Member::query() ->where('member_id', $row['member_id']) ->first(); - - // Validate If Exist Member + + // // Validate If Exist Member if (!$member) { throw new ImportRowException(__('enrollment.MEMBER_NOT_FOUND', [ 'member_id' => $row['member_id'], @@ -809,6 +819,102 @@ class MemberEnrollmentService ->with('member') ->first(); + // Pengecekan jika ada perubahan di plan + $plan = Plan::query() + ->where('code', $row['plan_id']) + ->first(); + if ($plan){ + $memberPlan = MemberPlan::query() + ->where('member_id', $member->id) + ->first(); + $memberPlan->plan_id = $plan->id; + $memberPlan->save(); + } + // Update jika ada perubahaan di ASO maka akan teriflek ke LMS juga\ + $userInsuranceLms = UserInsurance::query() + ->where('sNoPolis', $row['member_id']) + ->first(); + if ($userInsuranceLms){ + $userInsuranceLms->sNamaPeserta = $row['name']; + $userInsuranceLms->dStartDate = $row['member_effective_date']; + $userInsuranceLms->dExpireDate = $row['member_expiry_date']; + $nIDUser = $userInsuranceLms->nIDUser; + + UserInsurance::updateOrCreate( + ['nIDUser' => $nIDUser], + [ + 'sNamaPeserta' => $row['name'], + 'dStartDate' => $row['member_effective_date'], + 'dExpireDate' => $row['member_expiry_date'], + 'dTanggalLahir' => $row['date_of_birth'], + // 'nNoKTP' => $row['nric'] ?? , + ] + ); + /* Lihat ID Marital status di table tm_status_pernikahan Linksehat */ + if ($row['relationship_with_principal'] == 'H'){ + $sMartialStatus= 6; + $nIDHubunganKeluarga = 3; + } else if ($row['relationship_with_principal'] == 'W'){ + $sMartialStatus = 7; + $nIDHubunganKeluarga = 4; + } else if ($row['relationship_with_principal'] == 'S'){ + $sMartialStatus = 4; + $nIDHubunganKeluarga = 5; + } else if ($row['relationship_with_principal'] == 'D'){ + $sMartialStatus = 5; + $nIDHubunganKeluarga = 5; + } else { + $sMartialStatus = 0; + $nIDHubunganKeluarga = 0; + } + + + if($row['sex'] == 'M'){ + $nIDJenisKelamin = 1; + } else { + $nIDJenisKelamin = 2; + }; + // $ip_address = $CI->_prepare_ip($CI->input->ip_address()); + $name = explode(" ", $row['name']); + // First name + $first_name = isset($name[0]) ? $name[0] : ''; + // Middle name + $middle_name = isset($name[1]) ? $name[1] : ''; + // Last name + $last_name = ''; + if (count($name) > 2) { + $last_name = implode(" ", array_slice($name, 2)); + } + $userLms = User::updateOrCreate( + [ + 'nID' => $nIDUser // Kondisi untuk mencari data dengan 'nID' yang sesuai dengan $nIDUser + ], + [ + 'sFirstName' => $first_name, + 'sLastName' => $middle_name . ' ' .$last_name, // Ubah ini dengan variabel yang sesuai dengan nama belakang (last name) + 'sPhone' => $row['telephone_mobile'], + 'sEmail' => str_replace(' ', '', $row['email']), + 'nIDHubunganKeluarga' => $nIDHubunganKeluarga !== 0 ? $nIDHubunganKeluarga : null, + 'dUpdateOn' => date('Y-m-d H:i:s'), + ] + ); + + $userLmsDetail = UserDetail::updateOrCreate( + [ + 'nIDUser' => $nIDUser + ], + [ + 'nIDUser' => $nIDUser, + 'dTanggalLahir' => $row['date_of_birth'], + 'dCreateOn' => date('Y-m-d H:i:s'), + 'sMartialStatus' => $sMartialStatus != 0 ? $sMartialStatus : null, + 'nIDJenisKelamin' => $nIDJenisKelamin, + 'sCreateBy' => $nIDUser, + 'sKTP' => $row['nric'] ?? null, + ] + ); + + } if (!$memberPolicy) { throw new ImportRowException(__('enrollment.MEMBER_NOT_EXISTS', [ 'member_id' => $row['member_id'], @@ -829,7 +935,7 @@ class MemberEnrollmentService } $memberPolicy->member->save(); - + $member->save(); // update informasi person $person = Person::query() ->where('id', $member->person_id) diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 704089a7..46888585 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -2,7 +2,9 @@ namespace App\Http\Middleware; +use Closure; use Illuminate\Auth\Middleware\Authenticate as Middleware; +use Illuminate\Support\Facades\Auth; class Authenticate extends Middleware { @@ -18,4 +20,13 @@ class Authenticate extends Middleware return route('login'); } } + + public function handle($request, Closure $next, ...$guards) + { + if (Auth::guard('sanctum')->guest()) { + return response()->json(['error' => 'Bearer Authorization is required'], 401); + } + + return parent::handle($request, $next, ...$guards); + } } diff --git a/app/Models/FilesMcu.php b/app/Models/FilesMcu.php new file mode 100644 index 00000000..f5fab757 --- /dev/null +++ b/app/Models/FilesMcu.php @@ -0,0 +1,14 @@ +increments('id'); + $table->bigInteger('memberid'); + $table->string('original_name', 255); + $table->string('path', 255); + $table->bigInteger('created_by'); + $table->bigInteger('updated_by'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('files_mcu'); + } +}; diff --git a/frontend/dashboard/package.json b/frontend/dashboard/package.json index f7021c75..f844af69 100644 --- a/frontend/dashboard/package.json +++ b/frontend/dashboard/package.json @@ -38,6 +38,7 @@ ] }, "dependencies": { + "@ajoelp/json-to-formdata": "^1.5.0", "@date-io/date-fns": "^2.16.0", "@emotion/cache": "^11.10.5", "@emotion/react": "^11.10.5", diff --git a/frontend/dashboard/src/pages/Corporates/Member/List.tsx b/frontend/dashboard/src/pages/Corporates/Member/List.tsx index ee7051e3..da62e0ef 100644 --- a/frontend/dashboard/src/pages/Corporates/Member/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/Member/List.tsx @@ -28,7 +28,9 @@ import { ButtonGroup, Grid, Tooltip, + Divider, } from '@mui/material'; +import Iconify from '@/components/Iconify'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import AddIcon from '@mui/icons-material/Add'; @@ -49,8 +51,34 @@ import { enqueueSnackbar } from 'notistack'; import { LoadingButton } from '@mui/lab'; import DialogLog from './sections/DialogLog'; import HistoryIcon from '@mui/icons-material/History'; +import { makeFormData } from '@/utils/jsonToFormData'; -export default function CorporatePlanList() { +export default function CorporatePlanList({handleSubmitSuccess}) { + // Files MCU + const fileMcuInput = useRef(null); + const [fileMcus, setFileMcus] = useState([]); + + const handleMcuInputChange = (id, member_id) => (event) => { + if (event.target.files[0]) { + const updatedFiles = Array.from(event.target.files).map((file) => ({ + file, + id + })); + setFileMcus((prevFileMcus) => { + const newFileMcus = [...prevFileMcus, ...updatedFiles]; + submitRequest(id, newFileMcus, member_id); + return newFileMcus; + }); + } else { + console.log('Tidak ada file'); + } + }; + const removeMcuFiles = (id, index) => { + setFileMcus((filesState) => + filesState.filter((file, fileIndex) => fileIndex !== index || file.id !== id) + ); + }; + const [submitLoading, setSubmitLoading] = useState(false); const { themeStretch } = useSettings(); const { corporate_id } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); @@ -149,6 +177,47 @@ export default function CorporatePlanList() { ); } + function submitRequest(id, newFileMcus, member_id) { + setSubmitLoading(true); + if (newFileMcus && newFileMcus.length > 0) { + const fileWithId = newFileMcus.find((file) => file.id === id); + if (fileWithId) { + const formData = makeFormData({ + id: id, + memberid: member_id, + result_files: fileWithId.file, + }); + axios + .post('/files-mcu', formData) + .then((response) => { + const responseData = response?.data; + if(responseData) + { + setTimeout(() => { + loadDataTableData(); + }, 2000); + enqueueSnackbar(responseData.message ?? 'Berhasil tambah file MemberID '+member_id+', silahkan lihat dilaporan', { variant: 'success' }); + handleSubmitSuccess(); + } + + }) + .catch(({ response }) => { + const responseData = response?.data; + if(responseData) + { + enqueueSnackbar(responseData.message ?? 'Something Went Wrong', { variant: 'error' }); + } + }) + .then(() => { + setSubmitLoading(false); + }); + + } else { + console.log(`File dengan ID ${id} tidak ditemukan`); + } + } + } + // End Files MCU function ImportForm(props: any) { // IMPORT @@ -178,9 +247,7 @@ export default function CorporatePlanList() { const handleMemberList = async (appliedFilter = null) => { axios.get('corporates/' + corporate_id + '/members/list').then((response) => { - console.log(response); const link = document.createElement('a'); - console.log(response.data.data.file_name); link.href = response.data.data.file_url; link.setAttribute('download', response.data.data.file_name); document.body.appendChild(link); @@ -577,21 +644,81 @@ export default function CorporatePlanList() { + File History + + + + + {row.file_mcu_names + ? row.file_mcu_names.split(',').map((fileName, index) => ( +
{fileName}
+ )) + : '-'} +
+
+
+
- - } - // sx={{ p: 1.8 }} - // onClick={() => {handleDownloadLog(row)}} - onClick={() => { - setDialogLogOpen(true); - }} - loading={loadingLog} - > - Download LOG - + + + } + // sx={{ p: 1.8 }} + // onClick={() => {handleDownloadLog(row)}} + onClick={() => { + setDialogLogOpen(true); + }} + loading={loadingLog} + > + Download LOG + + + {/* -------------------------------Upload Dokumen MCU------------------------------- */} + + {/*} + spacing={1} + sx={{ marginY: 2}} + > + {fileMcus && + fileMcus + .filter((datas) => datas.id === row.id) + .map((datas, index) => ( + + {datas.file.name} + { + removeMcuFiles(datas.id, index); + }} + sx={{ cursor: 'pointer' }} + > + + ))} + */} + { + handleMcuInputChange(row.id, row.member_id)(event); + }} + accept="application/pdf" + /> + { + fileMcuInput.current.click(); + }} + > + + Add Result + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/hospital-portal/public/icons/ic_flag_id.svg b/frontend/hospital-portal/public/icons/ic_flag_id.svg new file mode 100644 index 00000000..1d4e5d5b --- /dev/null +++ b/frontend/hospital-portal/public/icons/ic_flag_id.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/frontend/hospital-portal/public/image/en-US.json b/frontend/hospital-portal/public/image/en-US.json new file mode 100644 index 00000000..baef7538 --- /dev/null +++ b/frontend/hospital-portal/public/image/en-US.json @@ -0,0 +1,15 @@ +{ + "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/ic_flag_en.svg b/frontend/hospital-portal/public/image/ic_flag_en.svg new file mode 100644 index 00000000..55e243b2 --- /dev/null +++ b/frontend/hospital-portal/public/image/ic_flag_en.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/hospital-portal/public/image/ic_flag_id.svg b/frontend/hospital-portal/public/image/ic_flag_id.svg new file mode 100644 index 00000000..1d4e5d5b --- /dev/null +++ b/frontend/hospital-portal/public/image/ic_flag_id.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/frontend/hospital-portal/public/image/id-ID.json b/frontend/hospital-portal/public/image/id-ID.json new file mode 100644 index 00000000..41db3e54 --- /dev/null +++ b/frontend/hospital-portal/public/image/id-ID.json @@ -0,0 +1,15 @@ +{ + "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 new file mode 100644 index 00000000..baef7538 --- /dev/null +++ b/frontend/hospital-portal/public/lang/en-US.json @@ -0,0 +1,15 @@ +{ + "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/lang/id-ID.json b/frontend/hospital-portal/public/lang/id-ID.json new file mode 100644 index 00000000..41db3e54 --- /dev/null +++ b/frontend/hospital-portal/public/lang/id-ID.json @@ -0,0 +1,15 @@ +{ + "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/logo/ic_flag_id.svg b/frontend/hospital-portal/public/logo/ic_flag_id.svg new file mode 100644 index 00000000..1d4e5d5b --- /dev/null +++ b/frontend/hospital-portal/public/logo/ic_flag_id.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/frontend/hospital-portal/src/LocalizationUtil.ts b/frontend/hospital-portal/src/LocalizationUtil.ts new file mode 100644 index 00000000..0ab70238 --- /dev/null +++ b/frontend/hospital-portal/src/LocalizationUtil.ts @@ -0,0 +1,7 @@ +const getLocalizedData = async (locale) => { + const response = await fetch(`../public/image/${locale}.json`); // Mengambil file lokal berdasarkan bahasa yang dipilih + const data = await response.json(); + return data; +}; + +export default getLocalizedData; \ No newline at end of file diff --git a/frontend/hospital-portal/src/components/Logo.tsx b/frontend/hospital-portal/src/components/Logo.tsx index de8e5831..03637b80 100644 --- a/frontend/hospital-portal/src/components/Logo.tsx +++ b/frontend/hospital-portal/src/components/Logo.tsx @@ -17,7 +17,7 @@ export default function Logo({ disabledLink = false, sx }: Props) { const logo = ( - LinkSehat + LinkSehat ); diff --git a/frontend/hospital-portal/src/contexts/LanguageContext.tsx b/frontend/hospital-portal/src/contexts/LanguageContext.tsx new file mode 100644 index 00000000..b8cce590 --- /dev/null +++ b/frontend/hospital-portal/src/contexts/LanguageContext.tsx @@ -0,0 +1,38 @@ +import React, { createContext, useState, useEffect, useRef } from 'react'; +import getLocalizedData from '../LocalizationUtil'; +export const LanguageContext = createContext(); + +export const LanguageProvider = ({ children }) => { + const [currentLocale, setCurrentLocale] = useState(localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID'); + const [localeData, setLocaleData] = useState('id'); + const cancelToken = useRef(null); + + useEffect(() => { + const fetchData = async () => { + const token = { cancelled: false }; + cancelToken.current = token; + + try { + const data = await getLocalizedData(currentLocale); + if (!cancelToken.current.cancelled) { + setLocaleData(data); + } + } catch (error) { + console.error('Error fetching localized data:', error); + // Tangani kesalahan jika diperlukan + } + }; + + fetchData(); + + return () => { + cancelToken.current.cancelled = true; + }; + }, [currentLocale]); + + return ( + + {children} + + ); +}; diff --git a/frontend/hospital-portal/src/contexts/LaravelAuthContext.tsx b/frontend/hospital-portal/src/contexts/LaravelAuthContext.tsx index 08c3eef8..c4ad4438 100644 --- a/frontend/hospital-portal/src/contexts/LaravelAuthContext.tsx +++ b/frontend/hospital-portal/src/contexts/LaravelAuthContext.tsx @@ -122,10 +122,18 @@ function AuthProvider({ children }: AuthProviderProps) { initialize(); }, []); + const headers = { + headers: { + 'Accept': 'application/json', + 'Content-Type' : 'application/json', + 'Accept-Language': (localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID'), + }, + }; + const login = async (email: string, password: string) => axios - .post('/login', { email, password }) + .post('/login', { email, password }, headers) .then((response) => { - const { user, token } = response.data; + const { user, token } = response.data.data; setSession(token); dispatch({ diff --git a/frontend/hospital-portal/src/index.tsx b/frontend/hospital-portal/src/index.tsx index ee6d44e7..52ea5b45 100644 --- a/frontend/hospital-portal/src/index.tsx +++ b/frontend/hospital-portal/src/index.tsx @@ -12,6 +12,7 @@ import { HelmetProvider } from 'react-helmet-async'; // contexts import { SettingsProvider } from './contexts/SettingsContext'; import { CollapseDrawerProvider } from './contexts/CollapseDrawerContext'; +import { LanguageProvider } from './contexts/LanguageContext'; // import App from './App'; @@ -23,7 +24,9 @@ ReactDOM.render( - + + + diff --git a/frontend/hospital-portal/src/layouts/dashboard/header/LanguagePopover.tsx b/frontend/hospital-portal/src/layouts/dashboard/header/LanguagePopover.tsx index 7b78ee18..f5bc67e3 100644 --- a/frontend/hospital-portal/src/layouts/dashboard/header/LanguagePopover.tsx +++ b/frontend/hospital-portal/src/layouts/dashboard/header/LanguagePopover.tsx @@ -1,28 +1,24 @@ -import { useState } from 'react'; +import React, { useState, useContext } from 'react'; // @mui -import { MenuItem, Stack } from '@mui/material'; +import { ButtonBase, Box, Typography, MenuItem, Stack } from '@mui/material'; // components import Image from '@/components/Image'; import MenuPopover from '@/components/MenuPopover'; import { IconButtonAnimate } from '@/components/animate'; +import { LanguageContext } from '@/contexts/LanguageContext'; // ---------------------------------------------------------------------- const LANGS = [ + { + label: 'Bahasa Indonesia', + value: 'id-ID', + icon: '/image/ic_flag_id.svg', + }, { label: 'English', - value: 'en', - icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_en.svg', - }, - { - label: 'German', - value: 'de', - icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_de.svg', - }, - { - label: 'French', - value: 'fr', - icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_fr.svg', + value: 'en-US', + icon: '/image/ic_flag_en.svg', }, ]; @@ -39,18 +35,50 @@ export default function LanguagePopover() { setOpen(null); }; + const { setCurrentLocale } = useContext(LanguageContext); + const handleChangeLanguage = (language) => { + localStorage.setItem('currentLocale', language); + setCurrentLocale(language); + }; + return ( <> - - {LANGS[0].label} - + + + + { + + + + + + Language + + + ( { + handleClose(); + handleChangeLanguage(option.value); + }} > {option.label} + {option.label} + ))} diff --git a/frontend/hospital-portal/src/layouts/dashboard/header/index.tsx b/frontend/hospital-portal/src/layouts/dashboard/header/index.tsx index 156125b4..a79e2f3f 100644 --- a/frontend/hospital-portal/src/layouts/dashboard/header/index.tsx +++ b/frontend/hospital-portal/src/layouts/dashboard/header/index.tsx @@ -93,8 +93,8 @@ export default function DashboardHeader({ - - + {/* + */} diff --git a/frontend/hospital-portal/src/pages/Dashboard.tsx b/frontend/hospital-portal/src/pages/Dashboard.tsx index c394df27..aa5ae9b3 100644 --- a/frontend/hospital-portal/src/pages/Dashboard.tsx +++ b/frontend/hospital-portal/src/pages/Dashboard.tsx @@ -20,12 +20,12 @@ import DialogDetailClaim from '@/components/dialogs/DialogDetailClaim'; // 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' }, -// ]; +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' }, +]; // ---------------------------------------------------------------------- @@ -66,7 +66,7 @@ export default function Dashboard() { const [policyData, setPolicyData] = useState(defaultPolicyData); // TODO Remove This - const [itemList, setItemList] = useState([]); + //const [itemList, setItemList] = useState([]); function handleDataLoaded(dataTable) { let dummyData = []; dataTable.map(function(data) { @@ -79,7 +79,7 @@ export default function Dashboard() { } }) - setItemList(dummyData); + //setItemList(dummyData); } return ( diff --git a/frontend/hospital-portal/src/pages/auth/Login.tsx b/frontend/hospital-portal/src/pages/auth/Login.tsx index 4ab4f315..9f4369f9 100644 --- a/frontend/hospital-portal/src/pages/auth/Login.tsx +++ b/frontend/hospital-portal/src/pages/auth/Login.tsx @@ -1,3 +1,4 @@ +import React, { useContext, useRef, useState, useEffect } from 'react'; import { capitalCase } from "change-case"; import { Link as RouterLink } from "react-router-dom"; // @mui @@ -23,6 +24,7 @@ import Logo from "@/components/Logo"; import Image from "@/components/Image"; // sections import { LoginForm } from "@/sections/auth/login"; +import { LanguageContext } from '@/contexts/LanguageContext'; // ---------------------------------------------------------------------- @@ -70,6 +72,7 @@ const ContentStyle = styled("div")(({ theme }) => ({ // ---------------------------------------------------------------------- export default function Login() { + const { localeData } = useContext(LanguageContext); const { method } = useAuth(); const smUp = useResponsive("up", "sm"); @@ -80,7 +83,7 @@ export default function Login() { - + {/* {smUp && ( Has problem with your account? {""} @@ -97,7 +100,7 @@ export default function Login() { Contact Us - )} + )}*/} {/* {mdUp && ( @@ -121,16 +124,17 @@ export default function Login() { alignItems="center" sx={{ mb: 5 }} > + - Sign in to LinkSehat + {localeData.txtLogin1} - - Enter your details below. + + {localeData.txtLogin2} - @@ -141,12 +145,12 @@ export default function Login() { sx={{ width: 32, height: 32 }} /> - + */} - {false && !smUp && ( + {/*{false && !smUp && ( - )} + )}*/} diff --git a/frontend/hospital-portal/src/sections/auth/login/LoginForm.tsx b/frontend/hospital-portal/src/sections/auth/login/LoginForm.tsx index 42ddfac4..b19f8aa3 100644 --- a/frontend/hospital-portal/src/sections/auth/login/LoginForm.tsx +++ b/frontend/hospital-portal/src/sections/auth/login/LoginForm.tsx @@ -1,5 +1,5 @@ import * as Yup from 'yup'; -import { useState } from 'react'; +import React, { useContext, useRef, useState, useEffect } from 'react'; import { Link as RouterLink, useNavigate } from 'react-router-dom'; // form import { useForm } from 'react-hook-form'; @@ -15,6 +15,7 @@ import useIsMountedRef from '@/hooks/useIsMountedRef'; // components import Iconify from '@/components/Iconify'; import { FormProvider, RHFTextField, RHFCheckbox } from '@/components/hook-form'; +import { LanguageContext } from '@/contexts/LanguageContext'; // ---------------------------------------------------------------------- @@ -26,6 +27,7 @@ type FormValuesProps = { }; export default function LoginForm() { + const { localeData } = useContext(LanguageContext); const { login } = useAuth(); const navigate = useNavigate(); @@ -34,8 +36,8 @@ export default function LoginForm() { const [showPassword, setShowPassword] = useState(false); const LoginSchema = Yup.object().shape({ - email: Yup.string().email('Email must be a valid email address').required('Email is required'), - password: Yup.string().required('Password is required'), + email: Yup.string().email('Format email tidak valid').required('Email harus diisi'), + password: Yup.string().required('Password harus diisi'), }); const defaultValues = { @@ -75,10 +77,10 @@ export default function LoginForm() { return ( - Email : admin@linksehat.dev & Password : password - {!!errors.afterSubmit && {errors.afterSubmit.message}} + {localeData.infoLogin} + {!!errors.afterSubmit && {errors.afterSubmit.data.meta.message}} - + ), }} + required /> - + {/* Forgot password? - + */} Login diff --git a/frontend/hospital-portal/src/sections/dashboard/CardSearchMember.tsx b/frontend/hospital-portal/src/sections/dashboard/CardSearchMember.tsx index 7a7f7211..5d13683e 100644 --- a/frontend/hospital-portal/src/sections/dashboard/CardSearchMember.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/CardSearchMember.tsx @@ -13,7 +13,7 @@ import { } from '@mui/material'; import { ChevronRight } from '@mui/icons-material'; // React -import React, { useState } from 'react'; +import React, { useContext, useState } from 'react'; import { LoadingButton } from '@mui/lab'; import Iconify from '@/components/Iconify'; import { DatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers'; @@ -25,6 +25,7 @@ import MuiDialog from '@/components/MuiDialog'; import axios from '@/utils/axios'; import { useSnackbar } from 'notistack'; import DialogMember from './DialogMember'; +import { LanguageContext } from '@/contexts/LanguageContext'; // ---------------------------------------------------------------------- @@ -46,29 +47,32 @@ const ItemNotificationStyle = styled(Card)(({ theme }) => ({ // ---------------------------------------------------------------------- export default function CardSearchMember(handleSubmitSuccess) { + const { localeData } = useContext(LanguageContext); const {enqueueSnackbar} = useSnackbar(); const [noPolis, setNoPolis] = useState('AW001-01'); - const [tanggalLahir, setTanggalLahir] = useState('1991-01-10'); + const [birthDate, setBirthDate] = useState('1991-01-10'); const [loadingBenefit, setLoadingBenefit] = useState(false); const [loadingClaim, setLoadingClaim] = useState(false); const [openDialogBenefit, setOpenDialogBenefit] = useState(false); const [openDialogClaim, setOpenDialogClaim] = useState(false); const [currentMember, setCurrentMember] = useState(null); + const [nameMember, setNameMember] = useState(''); function handleSearchMember() { setLoadingBenefit(true) axios.post('/search-member', { no_polis: noPolis, - birth_date: tanggalLahir ? fPostFormat(tanggalLahir, 'yyyy-MM-dd') : null + birth_date: birthDate ? fPostFormat(birthDate, 'yyyy-MM-dd') : null }) .then((response) => { setOpenDialogBenefit(true) setCurrentMember(response.data.data) + setNameMember(response.data.data.name); }) .catch(({response}) => { - enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.message : 'Opps, Something went Wrong!'), {variant : "error"}) + enqueueSnackbar(response.data.errors ? response.data.errors[0] : (response.data ? response.data.meta.message : 'Opps, Something went Wrong!'), {variant : "error"}) }) .then(() => { setLoadingBenefit(false) @@ -90,23 +94,23 @@ export default function CardSearchMember(handleSubmitSuccess) { component="span" sx={{ display: 'flex', alignItems: 'center' }} > - Pengajuan Jaminan + {localeData.txtCardSearchMember1} - { + { setNoPolis(event.target.value) - }}> + }} required> { setTanggalLahir( (newValue)); }} inputFormat="dd-MM-yyyy" - renderInput={(params) => } + renderInput={(params) => } /> @@ -124,7 +128,7 @@ export default function CardSearchMember(handleSubmitSuccess) { }} > - Cari Member + {localeData.txtCardSearchMember2} {/* */} {setOpenDialogBenefit(false); handleSubmitSuccess()})} diff --git a/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx b/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx index 12646730..b2192dcb 100644 --- a/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx +++ b/frontend/hospital-portal/src/sections/dashboard/DialogMember.tsx @@ -4,20 +4,22 @@ import { LoadingButton, TabPanel } from "@mui/lab"; import { Button, Card, Divider, Grid, LinearProgress, linearProgressClasses, Typography } from "@mui/material"; import { Tab, Tabs } from "@mui/material"; import { Box, Stack } from "@mui/material"; -import { useEffect, useState } from "react"; +import React, { useEffect, useState, useContext } from "react"; import { fCurrency } from '@/utils/formatNumber'; import { fPostFormat } from '@/utils/formatTime'; import { Avatar } from '@mui/material'; import Iconify from '@/components/Iconify'; import FormRequestClaim from './FormRequestClaim'; +import { LanguageContext } from '@/contexts/LanguageContext'; export default function DialogMember(member, handleSubmitSuccess) { + const { localeData } = useContext(LanguageContext); const [currentTab, setCurrentTab] = useState('request') // ---------------------------------------------------------------------- useEffect(() => { - setCurrentTab('benefit') + setCurrentTab('detail') }, [member]) function handleChangeTab(event: React.SyntheticEvent, newValue: string) { @@ -67,13 +69,93 @@ export default function DialogMember(member, handleSubmitSuccess) { onChange={handleChangeTab} aria-label="wrapped label tabs example" > - - + + + + + + + + + + Mapping ID + + + : {1 ?? '-'} + + + Policy Number + + + : {1 ?? '-'} + + + NRIC + + + : {1 ?? '-'} + + + + NIK + + + : {1 ?? '-'} + + + Email + + + : {1 ?? '-'} + + + + + + + Birth Date + + + : {1 ?? '-'} + + + Gender + + + : {1 ?? '-'} + + + Marital Status + + + : {1 ?? '-'} + + + Language + + + : {1 ?? '-'} + + + Race + + + : {1 ?? '-'} + + + Relationship + + + : {1 ?? '-'} + + + + + + + { member && member?.current_plan?.corporate_benefits?.map((corporateBenefit, index) => {return ( diff --git a/frontend/hospital-portal/src/utils/token.ts b/frontend/hospital-portal/src/utils/token.ts index db33ff36..ec74def0 100644 --- a/frontend/hospital-portal/src/utils/token.ts +++ b/frontend/hospital-portal/src/utils/token.ts @@ -29,12 +29,18 @@ const setSession = (accessToken: string | null) => { if (accessToken) { localStorage.setItem('accessToken', accessToken); axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`; + axios.defaults.headers.common['Accept-Language'] = (localStorage.getItem('currentLocale') ? localStorage.getItem('currentLocale') : 'id-ID'); + axios.defaults.headers.common['Accept'] = 'application/json'; + axios.defaults.headers.common['Content-Type'] = 'application/json'; // This function below will handle when token is expired // const { exp } = jwtDecode(accessToken); // handleTokenExpired(exp); } else { localStorage.removeItem('accessToken'); delete axios.defaults.headers.common.Authorization; + delete axios.defaults.headers.common['Accept-Language']; + delete axios.defaults.headers.common['Accept']; + delete axios.defaults.headers.common['Content-Type']; } }; diff --git a/frontend/hospital-portal/vite.config.ts b/frontend/hospital-portal/vite.config.ts index e417f3e9..ec18a01f 100644 --- a/frontend/hospital-portal/vite.config.ts +++ b/frontend/hospital-portal/vite.config.ts @@ -10,6 +10,14 @@ export default defineConfig({ // comment this out if that isn't relevant for your project build: { outDir: 'build', + chunkSizeWarningLimit: 100, + rollupOptions: { + onwarn(warning, warn) { + if (warning.code === 'MODULE_LEVEL_DIRECTIVE') { + return + } + warn(warning) + }} }, plugins: [ react(), diff --git a/resources/lang/en/Message.php b/resources/lang/en/Message.php new file mode 100644 index 00000000..b94896ea --- /dev/null +++ b/resources/lang/en/Message.php @@ -0,0 +1,8 @@ + 'Request has been successfully processed.', + 'server_error' => 'Internal server error.', + 'not_found' => 'Data not found', + 'password' => 'Password wrong. Please try again.' +]; diff --git a/resources/lang/en/Validation.php b/resources/lang/en/Validation.php new file mode 100644 index 00000000..c5c2b448 --- /dev/null +++ b/resources/lang/en/Validation.php @@ -0,0 +1,8 @@ + 'The :attribute field is required.', + 'invalid' => 'The :attribute field is invalid.', + 'max' => ':attribute cannot exceed :length characters.', + 'email' => 'Invalid email format.' +]; \ No newline at end of file diff --git a/resources/lang/id/Message.php b/resources/lang/id/Message.php new file mode 100644 index 00000000..18c0f99f --- /dev/null +++ b/resources/lang/id/Message.php @@ -0,0 +1,8 @@ + 'Request berhasil dilakukan.', + 'server_error' => 'Internal server error.', + 'not_found' => 'Data tidak ditemukan.', + 'password' => 'Password salah. Silakan coba lagi.' +]; diff --git a/resources/lang/id/Validation.php b/resources/lang/id/Validation.php new file mode 100644 index 00000000..2b2ffa07 --- /dev/null +++ b/resources/lang/id/Validation.php @@ -0,0 +1,8 @@ + 'Kolom :attribute harus diisi.', + 'invalid' => 'Kolom :attribute tidak valid.', + 'max' => ':attribute tidak boleh melebihi :length karakter.', + 'email' => 'Format email salah.' +]; \ No newline at end of file