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/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/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/frontend/hospital-portal/.env.development b/frontend/hospital-portal/.env.development
index 1256ddfc..5be659fc 100644
--- a/frontend/hospital-portal/.env.development
+++ b/frontend/hospital-portal/.env.development
@@ -1,4 +1,4 @@
REACT_APP_HOST_API_URL="http://localhost:8000"
-VITE_API_URL="http://localhost:8000/api/hospitalportal"
+VITE_API_URL="http://localhost:8000/api/v1/hospitalportal"
diff --git a/frontend/hospital-portal/public/icons/ic_flag_en.svg b/frontend/hospital-portal/public/icons/ic_flag_en.svg
new file mode 100644
index 00000000..55e243b2
--- /dev/null
+++ b/frontend/hospital-portal/public/icons/ic_flag_en.svg
@@ -0,0 +1,18 @@
+
\ 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/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/src/LocalizationUtil.ts b/frontend/hospital-portal/src/LocalizationUtil.ts
new file mode 100644
index 00000000..c7fa3520
--- /dev/null
+++ b/frontend/hospital-portal/src/LocalizationUtil.ts
@@ -0,0 +1,7 @@
+const getLocalizedData = async (locale) => {
+ const response = await fetch(`../public/lang/${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/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..a5e14ad6 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: '/icons/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: '/icons/ic_flag_en.svg',
},
];
@@ -39,18 +35,34 @@ export default function LanguagePopover() {
setOpen(null);
};
+ const { setCurrentLocale } = useContext(LanguageContext);
+ const handleChangeLanguage = (language) => {
+ localStorage.setItem('currentLocale', language);
+ setCurrentLocale(language);
+ };
+
return (
<>
-
-
-
+
+
+
+
+
+
+
+
+
+ Language
+
+
+
(
))}
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..ab771023 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) {
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/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