From 1cb3b2d3f059043b393155044b13eeaaaf7e5fbb Mon Sep 17 00:00:00 2001 From: ivan-sim Date: Tue, 23 Apr 2024 16:28:59 +0700 Subject: [PATCH] API APP DOCTOR --- .../Linksehat/Helpers/Doctor/ApiResponse.php | 21 ++ .../Api/Doctor/AuthDoctorController.php | 264 ++++++++++++++++++ .../Api/Doctor/ProfileDoctorController.php | 175 ++++++++++++ .../Http/Middleware/Doctor/Authentication.php | 65 +++++ .../Http/Middleware/Doctor/Authorization.php | 71 +++++ Modules/Linksehat/Routes/api.php | 33 +++ app/Helpers/Helper.php | 10 +- ..._145224_create_person_educations_table.php | 38 +++ ...0705_add_column_to_table_practitioners.php | 33 +++ ...add_column_to_table_practitioner_roles.php | 33 +++ resources/lang/en/Message.php | 2 + resources/lang/en/Validation.php | 6 +- resources/lang/id/Message.php | 2 + resources/lang/id/Validation.php | 6 +- .../views/email/forgot_password.blade.php | 62 ++++ 15 files changed, 811 insertions(+), 10 deletions(-) create mode 100644 Modules/Linksehat/Helpers/Doctor/ApiResponse.php create mode 100644 Modules/Linksehat/Http/Controllers/Api/Doctor/AuthDoctorController.php create mode 100644 Modules/Linksehat/Http/Controllers/Api/Doctor/ProfileDoctorController.php create mode 100644 Modules/Linksehat/Http/Middleware/Doctor/Authentication.php create mode 100644 Modules/Linksehat/Http/Middleware/Doctor/Authorization.php create mode 100644 database/migrations/2024_04_23_145224_create_person_educations_table.php create mode 100644 database/migrations/2024_04_23_160705_add_column_to_table_practitioners.php create mode 100644 database/migrations/2024_04_23_162213_add_column_to_table_practitioner_roles.php create mode 100644 resources/views/email/forgot_password.blade.php diff --git a/Modules/Linksehat/Helpers/Doctor/ApiResponse.php b/Modules/Linksehat/Helpers/Doctor/ApiResponse.php new file mode 100644 index 00000000..56029c67 --- /dev/null +++ b/Modules/Linksehat/Helpers/Doctor/ApiResponse.php @@ -0,0 +1,21 @@ +first(); + } + return response()->json([ + 'meta' => [ + 'status' => $status, + 'code' => $statusCode, + 'message' => $message + ], + 'data' => $data, + ], $statusCode); + } +} diff --git a/Modules/Linksehat/Http/Controllers/Api/Doctor/AuthDoctorController.php b/Modules/Linksehat/Http/Controllers/Api/Doctor/AuthDoctorController.php new file mode 100644 index 00000000..3ba2d663 --- /dev/null +++ b/Modules/Linksehat/Http/Controllers/Api/Doctor/AuthDoctorController.php @@ -0,0 +1,264 @@ + $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']), + ]); + + 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 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); + } + } + + public function logout(Request $request) + { + $request->user()->tokens()->delete(); + + return ApiResponse::apiResponse('Success', [], trans('message.logout'), 200); + } + + public function forgotPassword(Request $request) + { + $data = [ + 'email' => $request->email, + ]; + + $validator = Validator::make($request->all(), [ + 'email' => 'required|email', + ], [ + 'email.required' => trans('validation.required',['attribute' => 'Email']), + 'email.email' => trans('validation.email'), + ]); + + 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); + } + + //send email + // Insert data notifications + $emailTo = $request->email; + $dataNotif = [ + 'user_id' => $user->id, + 'email' => $emailTo, + 'title' => 'Forgot Password', + 'description' => 'Request forgot password from App Doctor', + 'type' => 1, + 'isUnRead' => true, + 'created_by' => auth()->check() ? auth()->user()->id : null, + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), + ]; + $sendNotif = Helper::insertNotification($dataNotif); + //Insert data password reset + $token = mt_rand(100000, 999999); // Menghasilkan angka acak antara 100000 dan 999999 + $p_resets = DB::table('password_resets') + ->insert([ + 'email' => $request->email, + 'token' => $token, + 'created_at' => date('Y-m-d H:i:s'), + ]); + // Send Email after insert notifications + if($sendNotif && $p_resets) + { + //send to alarm + $nameTo = 'User'; + $dataEmail = [ + 'email' => $emailTo, + 'name' => $nameTo, + 'subject' => 'Request Forgot Password from App Doctor Date '. date('Y-m-d H:i:s'), + 'body' => View::make('email/forgot_password', ['token' => $token])->render(), + ]; + Helper::sendEmail($dataEmail); + + $res = DB::table('password_resets') + ->where('email', '=', $request->email) + ->where('token', '=', $token) + ->get(); + + return ApiResponse::apiResponse("Success", $res, trans('message.success'), 200); + } + else + { + return ApiResponse::apiResponse("Internal Server Error", $data, trans('message.server_error'), 500); + } + } + } + + public function verifCode(Request $request) + { + $data = [ + 'email' => $request->email, + 'token' => $request->token, + ]; + + $validator = Validator::make($request->all(), [ + 'email' => 'required|email', + 'token' => 'required|numeric', + ], [ + 'email.required' => trans('validation.required',['attribute' => 'Email']), + 'email.email' => trans('validation.email'), + 'token.required' => trans('validation.required',['attribute' => 'Token']), + ]); + + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); + } + else + { + //Check Time + $check = DB::table('password_resets') + ->where('email', '=', $request->email) + ->where('token', '=', $request->token) + ->select('created_at') + ->first(); + + if($check) + { + $created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp + $now = time(); // Waktu sekarang dalam UNIX timestamp + + // Hitung selisih waktu dalam menit + $diffInMinutes = ($now - $created_at) / 60; + + if ($diffInMinutes > 60) { + return ApiResponse::apiResponse('Not Found', $data, trans('message.token_expired'), 404); + } else { + // Lanjutkan dengan proses pemulihan kata sandi + return ApiResponse::apiResponse("Success", $data, trans('message.success'), 200); + } + } + else + { + return ApiResponse::apiResponse('Not Found', $data, trans('message.not_found'), 404); + } + } + } + + public function resetPassword(Request $request) + { + $data = [ + 'email' => $request->email, + 'token' => $request->token, + 'new_password' => $request->new_password + ]; + + $validator = Validator::make($request->all(), [ + 'email' => 'required|email', + 'token' => 'required|numeric', + 'new_password' => [ + 'required', + 'min:8', + 'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/' + ] + ], [ + 'email.required' => trans('validation.required',['attribute' => 'Email']), + 'email.email' => trans('validation.email'), + 'token.required' => trans('validation.required',['attribute' => 'Token']), + 'new_password.required' => trans('validation.required',['attribute' => 'New Password']), + 'new_password.min' => trans('validation.min',['attribute' => 'New Password']), + 'new_password.regex' => trans('validation.regex',['attribute' => 'New Password']), + ]); + + if ($validator->fails()) + { + return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400); + } + else + { + //Check Time + $check = DB::table('password_resets') + ->where('email', '=', $request->email) + ->where('token', '=', $request->token) + ->select('created_at') + ->first(); + + if($check) + { + $created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp + $now = time(); // Waktu sekarang dalam UNIX timestamp + + // Hitung selisih waktu dalam menit + $diffInMinutes = ($now - $created_at) / 60; + + if ($diffInMinutes > 60) { + return ApiResponse::apiResponse('Not Found', $data, trans('message.token_expired'), 404); + } else { + // Lanjutkan dengan proses pemulihan kata sandi + $user = User::where('email', $request->email)->first(); + if ($user) + { + $newPassword = Hash::make($request->new_password); + $user->password = $newPassword; + $user->save(); + return ApiResponse::apiResponse("Success", $data, trans('message.success'), 200); + } + else + { + return ApiResponse::apiResponse('Not Found', $data, trans('message.token_expired'), 404); + } + } + } + else + { + return ApiResponse::apiResponse('Not Found', $data, trans('message.not_found'), 404); + } + } + } +} diff --git a/Modules/Linksehat/Http/Controllers/Api/Doctor/ProfileDoctorController.php b/Modules/Linksehat/Http/Controllers/Api/Doctor/ProfileDoctorController.php new file mode 100644 index 00000000..e6604fe1 --- /dev/null +++ b/Modules/Linksehat/Http/Controllers/Api/Doctor/ProfileDoctorController.php @@ -0,0 +1,175 @@ + auth()->check() ? auth()->user()->id : null, + ]; + $user_id = auth()->check() ? auth()->user()->id : null; + //Get data Profile + $dataProfile = DB::table('users') + ->join('persons','persons.id', '=', 'users.person_id') + ->leftJoin('person_educations','person_educations.person_id', '=', 'persons.id') + ->leftJoin('practitioners','practitioners.person_id', '=', 'persons.id') + ->leftJoin('practitioner_roles','practitioner_roles.practitioner_id', '=', 'practitioners.id') + ->where('users.id', '=', $user_id) + ->select( + 'persons.name', + DB::raw(' + "Pediatrics" AS specialist + '), + DB::raw(' + "4" AS rating + '), + 'persons.name AS full_name', + 'persons.birth_date as date_of_birth', + 'persons.gender', + 'persons.phone AS mobile_number', + 'persons.email', + 'practitioners.str_number', + 'practitioners.exp_date_str', + 'practitioner_roles.sip_number', + 'practitioner_roles.exp_date_sip' + ) + ->first(); + + //Name + $dataName = [ + 'name' => $dataProfile->name, + 'specialist' => $dataProfile->specialist, + 'rating' => $dataProfile->rating + ]; + $res_data['dataName'] = $dataName; + + // Basic + $dataProfileBasic = [ + 'full_name' => $dataProfile->full_name, + 'date_of_birth' => $dataProfile->date_of_birth ? date('d M Y', strtotime($dataProfile->date_of_birth)) : '', + 'gender' => $dataProfile->gender + ]; + $res_data['dataProfileBasic'] = $dataProfileBasic; + + //Contact + $dataProfileContact = [ + 'mobile_number' => $dataProfile->mobile_number, + 'email' => $dataProfile->email + ]; + $res_data['dataProfileContact'] = $dataProfileContact; + + //Education + $dataEdu = DB::table('users') + ->join('persons','persons.id', '=', 'users.person_id') + ->leftJoin('person_educations','person_educations.person_id', '=', 'persons.id') + ->where('users.id', '=', $user_id) + ->select( + 'person_educations.level_id', + 'person_educations.name', + 'person_educations.start_date', + 'person_educations.end_date', + ) + ->get(); + $dataEducations = []; + foreach($dataEdu as $val) + { + $dataEducations[] = [ + 'level_id' => $val->level_id, + 'name' => $val->name, + 'start_date' => date('d/m/Y', strtotime($val->start_date)), + 'end_date' => date('d/m/Y', strtotime($val->end_date)), + ]; + } + $res_data['dataEducations'] = $dataEducations; + + //Work Experience + $dataWork = DB::table('users') + ->join('persons','persons.id', '=', 'users.person_id') + ->leftJoin('practitioners','practitioners.person_id', '=', 'persons.id') + ->leftJoin('practitioner_roles','practitioner_roles.practitioner_id', '=', 'practitioners.id') + ->leftJoin('organizations','organizations.id', '=', 'practitioner_roles.organization_id') + ->where('users.id', '=', $user_id) + ->select( + 'organizations.name', + 'practitioner_roles.period_start', + 'practitioner_roles.period_end', + ) + ->get(); + $dataWorkExperience = []; + foreach ($dataWork as $val) + { + $dataWorkExperience[] = [ + 'name' => $val->name ? $val->name : '', + 'period' => $this->fWorkExperience($val->period_start, $val->period_end) + ]; + } + $res_data['dataWorkExperience'] = $dataWorkExperience; + + //STR + $dataStr = [ + 'str_number' => $dataProfile->str_number, + 'exp_date_str' => $dataProfile->exp_date_str ? date('d M Y', strtotime($dataProfile->exp_date_str)) : '' + ]; + $res_data['dataStr'] = $dataStr; + + //SIP + $dataSip = [ + 'sip_number' => $dataProfile->sip_number, + 'exp_date_sip' => $dataProfile->exp_date_sip ? date('d M Y', strtotime($dataProfile->exp_date_sip)) : '' + ]; + $res_data['dataSip'] = $dataSip; + + return ApiResponse::apiResponse("Success", $res_data, trans('message.success'), 200); + + } + public function fWorkExperience($start, $end) + { + $startDateString = $start; // Tanggal dan waktu awal + $endDateString = $end ; // Tanggal dan waktu akhir + + // Mengubah string tanggal ke timestamp UNIX + $startTime = strtotime($startDateString); + $endTime = strtotime($endDateString); + + // Menghitung selisih waktu dalam detik + $timeDifference = $endTime - $startTime; + + // Menghitung jumlah tahun, bulan, dan hari dari selisih waktu + $years = floor($timeDifference / (365 * 24 * 60 * 60)); + $months = floor(($timeDifference - ($years * 365 * 24 * 60 * 60)) / (30 * 24 * 60 * 60)); + $days = floor(($timeDifference - ($years * 365 * 24 * 60 * 60) - ($months * 30 * 24 * 60 * 60)) / (24 * 60 * 60)); + + // Formatkan hasilnya + $experience = ''; + if ($years > 0) { + $experience .= $years . ' years '; + } + if ($months > 0) { + $experience .= $months . ' months '; + } + if ($days > 0) { + $experience .= $days . ' days'; + } + + return $experience; + + } +} diff --git a/Modules/Linksehat/Http/Middleware/Doctor/Authentication.php b/Modules/Linksehat/Http/Middleware/Doctor/Authentication.php new file mode 100644 index 00000000..d2c93b97 --- /dev/null +++ b/Modules/Linksehat/Http/Middleware/Doctor/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/Linksehat/Http/Middleware/Doctor/Authorization.php b/Modules/Linksehat/Http/Middleware/Doctor/Authorization.php new file mode 100644 index 00000000..6d29b24f --- /dev/null +++ b/Modules/Linksehat/Http/Middleware/Doctor/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 && $request->isMethod('post')) + { + 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' && $request->isMethod('post')) + { + return ApiResponse::apiResponse('Bad Request', null, trans('Validation.invalid', ['attribute' => 'Content-Type']), 400); + } + return $next($request); + } +} diff --git a/Modules/Linksehat/Routes/api.php b/Modules/Linksehat/Routes/api.php index 29d5b260..eb31555a 100644 --- a/Modules/Linksehat/Routes/api.php +++ b/Modules/Linksehat/Routes/api.php @@ -15,6 +15,10 @@ use Modules\Linksehat\Http\Controllers\Api\SpecialityController; use Modules\Linksehat\Http\Controllers\Api\LinkingController; use Modules\Linksehat\Http\Controllers\Api\HomeController; use Modules\Linksehat\Http\Controllers\Api\LivechatController; +use Modules\Linksehat\Http\Middleware\Doctor\Authentication; +use Modules\Linksehat\Http\Middleware\Doctor\Authorization; +use Modules\Linksehat\Http\Controllers\Api\Doctor\AuthDoctorController; +use Modules\Linksehat\Http\Controllers\Api\Doctor\ProfileDoctorController; /* |-------------------------------------------------------------------------- @@ -108,4 +112,33 @@ Route::prefix('linksehat')->group(function () { Route::post('payment-method-duitku', [DuitkuController::class, 'paymentMethod']); Route::post('callback-duitku', [DuitkuController::class, 'callback']); Route::get('redirect-duitku', [DuitkuController::class, 'redirect']); + + //DOCTOR API + Route::prefix('doctor')->group(function() { + //Version 1.0 + Route::prefix('v1')->group(function() { + Route::middleware(Authentication::class)->group(function () { + Route::controller(AuthDoctorController::class)->group(function () { + Route::post('login', 'login'); + }); + }); + Route::middleware('auth:sanctum')->group(function () { + Route::middleware(Authorization::class)->group(function () { + Route::controller(AuthDoctorController::class)->group(function () { + Route::post('logout', 'logout'); + Route::post('forgot-password', 'forgotPassword'); + }); + Route::controller(ProfileDoctorController::class)->group(function () { + Route::get('get-profile', 'getProfile'); + }); + }); + }); + Route::controller(AuthDoctorController::class)->group(function () { + Route::post('forgot-password', 'forgotPassword'); + Route::post('verif-code', 'verifCode'); + Route::post('resend-code', 'forgotPassword'); + Route::post('reset-password', 'resetPassword'); + }); + }); + }); ;}); diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 6643d50b..acccbfc1 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -391,9 +391,7 @@ class Helper $mail->send(); return true; } catch (\Exception $e) { - dd($e); - return ($mail->ErrorInfo); - return false; + return $mail->ErrorInfo; } } @@ -463,16 +461,16 @@ class Helper $lonFrom = deg2rad($longitudeFrom); $latTo = deg2rad($latitudeTo); $lonTo = deg2rad($longitudeTo); - + // Calculate the change in coordinates $deltaLat = $latTo - $latFrom; $deltaLon = $lonTo - $lonFrom; - + // Apply Haversine formula $a = sin($deltaLat / 2) * sin($deltaLat / 2) + cos($latFrom) * cos($latTo) * sin($deltaLon / 2) * sin($deltaLon / 2); $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); $distance = $earthRadius * $c; - + return $distance; } diff --git a/database/migrations/2024_04_23_145224_create_person_educations_table.php b/database/migrations/2024_04_23_145224_create_person_educations_table.php new file mode 100644 index 00000000..86faea77 --- /dev/null +++ b/database/migrations/2024_04_23_145224_create_person_educations_table.php @@ -0,0 +1,38 @@ +id(); + $table->bigInteger('person_id'); + $table->integer('level_id')->comment('1=SD, 2= SMP, 3=SMA dst.'); + $table->string('name', 255); + $table->dateTime('start_date'); + $table->dateTime('end_date'); + $table->bigInteger('created_by')->nullable(); + $table->bigInteger('updated_by')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('person_educations'); + } +}; diff --git a/database/migrations/2024_04_23_160705_add_column_to_table_practitioners.php b/database/migrations/2024_04_23_160705_add_column_to_table_practitioners.php new file mode 100644 index 00000000..66ea3ce7 --- /dev/null +++ b/database/migrations/2024_04_23_160705_add_column_to_table_practitioners.php @@ -0,0 +1,33 @@ +string('str_number', 255)->after('person_id')->nullable(); + $table->dateTime('exp_date_str')->after('str_number')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('practitioners', function (Blueprint $table) { + // + }); + } +}; diff --git a/database/migrations/2024_04_23_162213_add_column_to_table_practitioner_roles.php b/database/migrations/2024_04_23_162213_add_column_to_table_practitioner_roles.php new file mode 100644 index 00000000..3c4daa2f --- /dev/null +++ b/database/migrations/2024_04_23_162213_add_column_to_table_practitioner_roles.php @@ -0,0 +1,33 @@ +string('sip_number', 255)->after('period_end')->nullable(); + $table->dateTime('exp_date_sip')->after('sip_number')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('practitioner_roles', function (Blueprint $table) { + // + }); + } +}; diff --git a/resources/lang/en/Message.php b/resources/lang/en/Message.php index 7b8a6c6d..f439e71e 100644 --- a/resources/lang/en/Message.php +++ b/resources/lang/en/Message.php @@ -7,4 +7,6 @@ return [ 'password' => 'Password wrong. Please try again.', 'read_notification' => 'Notification has been read.', 'already_exists' => 'Data already exists.', + 'logout' => 'User logged out successfully.', + 'token_expired' => 'Token has expired. Please re-request the token.' ]; diff --git a/resources/lang/en/Validation.php b/resources/lang/en/Validation.php index 8f242065..ba9e9e01 100644 --- a/resources/lang/en/Validation.php +++ b/resources/lang/en/Validation.php @@ -6,5 +6,7 @@ return [ 'max' => [ 'file' => ':attribute max size is :max.', ], - 'email' => 'Invalid email format.' -]; \ No newline at end of file + 'email' => 'Invalid email format.', + 'regex' => 'The :attribute must contain at least one uppercase letter, one lowercase letter, and one numeric digit.', + 'min' => 'The :attribute must be at least 8 characters.' +]; diff --git a/resources/lang/id/Message.php b/resources/lang/id/Message.php index 475a5731..6589d023 100644 --- a/resources/lang/id/Message.php +++ b/resources/lang/id/Message.php @@ -7,4 +7,6 @@ return [ 'password' => 'Password salah. Silakan coba lagi.', 'read_notification' => 'Notifikasi telah dibaca.', 'already_exists' => 'Data sudah ada.', + 'logout' => 'User berhasil logout.', + 'token_expired' => 'Token telah kedaluwarsa. Silakan minta ulang token.' ]; diff --git a/resources/lang/id/Validation.php b/resources/lang/id/Validation.php index 5a8fdb02..a564bf1e 100644 --- a/resources/lang/id/Validation.php +++ b/resources/lang/id/Validation.php @@ -6,5 +6,7 @@ return [ 'max' => [ 'file' => ':attribute tidak boleh melebihi :max.', ], - 'email' => 'Format email salah.' -]; \ No newline at end of file + 'email' => 'Format email salah.', + 'regex' => ':attribute harus berisi setidaknya satu huruf besar, satu huruf kecil, dan satu digit angka.', + 'min' => ':attribute setidaknya harus terdiri dari 8 karakter.' +]; diff --git a/resources/views/email/forgot_password.blade.php b/resources/views/email/forgot_password.blade.php new file mode 100644 index 00000000..9f484c66 --- /dev/null +++ b/resources/views/email/forgot_password.blade.php @@ -0,0 +1,62 @@ + + + + + + + Verification Code + + + + +
+

Verification Code

+
{{$token}}
+

This code is valid for 60 minutes.

+ +
+ + +