language login
This commit is contained in:
parent
9c8ebdfabe
commit
d21b26a5d2
|
|
@ -5,10 +5,9 @@ namespace App\Http\Controllers\Auth;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Repositories\Member\Auth\MemberAuthRepository;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class LoginWaController extends Controller
|
||||
{
|
||||
|
|
@ -36,13 +35,23 @@ class LoginWaController extends Controller
|
|||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => __('otp.invalid_phone'),
|
||||
'errors' => $validator->errors()
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$identity = $request->identity;
|
||||
|
||||
|
||||
// check first if user exists
|
||||
$user = $this->memberAuthRepository->check(['phone' => $identity]);
|
||||
if (! $user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => __('otp.user_not_found'),
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Use MemberAuthRepository to generate OTP
|
||||
$otp = $this->memberAuthRepository->waOtp(['phone' => $identity]);
|
||||
|
||||
|
|
@ -53,14 +62,14 @@ class LoginWaController extends Controller
|
|||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => __('otp.sent'),
|
||||
'redirect' => route('login-phone.otp.view', ['identity' => $identity])
|
||||
'redirect' => route('login-phone.otp.view', ['identity' => $identity]),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error("OTP generation failed: " . $e->getMessage());
|
||||
|
||||
Log::error('OTP generation failed: '.$e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => __('otp.generate_failed')
|
||||
'message' => __('otp.generate_failed'),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +77,7 @@ class LoginWaController extends Controller
|
|||
public function otpView($identity)
|
||||
{
|
||||
return view('account.otp', [
|
||||
'identity' => $identity
|
||||
'identity' => $identity,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -92,25 +101,23 @@ class LoginWaController extends Controller
|
|||
// Use MemberAuthRepository to verify OTP
|
||||
$result = $this->memberAuthRepository->waOtpConfirm([
|
||||
'phone' => $identity,
|
||||
'otp' => $otp
|
||||
'otp' => $otp,
|
||||
]);
|
||||
|
||||
// TODO: Authenticate user or create new user
|
||||
// For now, we'll just redirect to dashboard
|
||||
// In production, you would:
|
||||
// 1. Find or create user by phone number
|
||||
// 2. Log them in
|
||||
// 3. Redirect to intended page
|
||||
$check = $this->memberAuthRepository->check(['phone' => $identity]);
|
||||
|
||||
|
||||
// Auth::guard('web')->attempt(['id' => $check->id]);
|
||||
|
||||
return redirect()->route('home')->with('success', __('otp.login_success'));
|
||||
|
||||
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
return back()
|
||||
->withErrors(['otp' => $e->getMessage()])
|
||||
->withInput();
|
||||
} catch (\Exception $e) {
|
||||
Log::error("OTP verification failed: " . $e->getMessage());
|
||||
|
||||
Log::error('OTP verification failed: '.$e->getMessage());
|
||||
|
||||
return back()
|
||||
->withErrors(['otp' => __('otp.verification_failed')])
|
||||
->withInput();
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ class MemberAuthRepository
|
|||
$this->voucherRepository = $voucherRepository;
|
||||
}
|
||||
|
||||
public function check($request)
|
||||
public function check($data)
|
||||
{
|
||||
$phone = $request->phone;
|
||||
$email = $request->email;
|
||||
$phone = $data['phone'] ?? null;
|
||||
$email = $data['email'] ?? null;
|
||||
|
||||
if ($email) {
|
||||
return $this->findUserByEmail($email);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'categories' => 'Categories',
|
||||
'account' => 'Account',
|
||||
'wishlist' => 'Wishlist',
|
||||
];
|
||||
|
|
@ -23,6 +23,7 @@ return [
|
|||
'resend_in' => 'Resend in',
|
||||
'need_help' => 'Need help?',
|
||||
'invalid_phone' => 'Please enter a valid phone number',
|
||||
'user_not_found' => 'User not found with this phone number',
|
||||
'sent' => 'OTP sent successfully',
|
||||
'expired' => 'OTP has expired',
|
||||
'max_attempts' => 'Maximum attempts reached. Please request a new OTP',
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ return [
|
|||
'facebook' => 'Facebook',
|
||||
'apple' => 'Apple',
|
||||
'need_help' => 'Need help?',
|
||||
'rights_reserved' => '© All rights reserved. Made by :company',
|
||||
'company_name' => 'Coderthemes',
|
||||
'rights_reserved' => '© All rights reserved. Made by <span class="animate-underline"><a class="animate-target text-dark-emphasis text-decoration-none" href="/" rel="noreferrer" target="_blank">:company</a></span>',
|
||||
|
||||
'sending' => 'Sending...',
|
||||
'error' => 'An error occurred. Please try again.',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ return [
|
|||
'apple' => 'Apple',
|
||||
'need_help' => 'Need help?',
|
||||
'rights_reserved' => '© All rights reserved. Made by :company',
|
||||
'company_name' => 'Coderthemes',
|
||||
|
||||
// Benefits section
|
||||
'benefits_title' => 'Why create an account?',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'categories' => 'Kategori',
|
||||
'account' => 'Akun',
|
||||
'wishlist' => 'Daftar Keinginan',
|
||||
];
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| OTP Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during OTP authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
|
||||
'title' => 'Verifikasi Telepon Anda',
|
||||
'description' => 'Kami mengirim kode 6 digit ke :phone',
|
||||
'enter_code' => 'Masukkan kode verifikasi',
|
||||
'invalid_code' => 'Masukkan kode 6 digit yang valid',
|
||||
'verify' => 'Verifikasi',
|
||||
'back_to_login' => 'Kembali ke login',
|
||||
'resend_code' => 'Kirim ulang kode',
|
||||
'resend_in' => 'Kirim ulang dalam',
|
||||
'need_help' => 'Butuh bantuan?',
|
||||
'invalid_phone' => 'Masukkan nomor telepon yang valid',
|
||||
'user_not_found' => 'Pengguna tidak ditemukan dengan nomor telepon ini',
|
||||
'sent' => 'OTP berhasil dikirim',
|
||||
'expired' => 'OTP telah kadaluarsa',
|
||||
'max_attempts' => 'Maksimal percobaan tercapai. Silakan minta OTP baru',
|
||||
'invalid' => 'Kode OTP tidak valid',
|
||||
'login_success' => 'Login berhasil',
|
||||
'resend_failed' => 'Gagal mengirim ulang OTP. Silakan coba lagi',
|
||||
'generate_failed' => 'Gagal membuat OTP. Silakan coba lagi',
|
||||
'verification_failed' => 'Verifikasi OTP gagal. Silakan coba lagi',
|
||||
|
||||
];
|
||||
|
|
@ -31,7 +31,7 @@ return [
|
|||
'facebook' => 'Facebook',
|
||||
'apple' => 'Apple',
|
||||
'need_help' => 'Butuh bantuan?',
|
||||
'rights_reserved' => ' Semua hak dilindungi. Dibuat oleh :company',
|
||||
'rights_reserved' => '© Semua hak dilindungi. Dibuat oleh :company',
|
||||
'company_name' => 'Coderthemes',
|
||||
'rights_reserved' => '© Semua hak dilindungi. Dibuat oleh <span class="animate-underline"><a class="animate-target text-dark-emphasis text-decoration-none" href="https://coderthemes.com/" rel="noreferrer" target="_blank">:company</a></span>',
|
||||
'sending' => 'Mengirim...',
|
||||
'error' => 'Terjadi kesalahan. Silakan coba lagi.',
|
||||
];
|
||||
|
|
@ -46,7 +46,6 @@ return [
|
|||
'apple' => 'Apple',
|
||||
'need_help' => 'Butuh bantuan?',
|
||||
'rights_reserved' => ' Semua hak dilindungi. Dibuat oleh :company',
|
||||
'company_name' => 'Coderthemes',
|
||||
|
||||
// Benefits section
|
||||
'benefits_title' => 'Mengapa membuat akun?',
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ $grays: () !default;
|
|||
$min-contrast-ratio: 2 !default;
|
||||
|
||||
// Theme colors
|
||||
$primary: #f55266 !default;
|
||||
$primary: #000000 !default;
|
||||
$secondary: $gray-500 !default;
|
||||
$success: #33b36b !default;
|
||||
$info: #2f6ed5 !default;
|
||||
|
|
|
|||
|
|
@ -9,23 +9,7 @@
|
|||
<header class="navbar px-0 pb-4 mt-n2 mt-sm-0 mb-2 mb-md-3 mb-lg-4">
|
||||
<a class="navbar-brand pt-0" href="/">
|
||||
<span class="d-flex flex-shrink-0 text-primary me-2">
|
||||
<svg height="36" width="36" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M36 18.01c0 8.097-5.355 14.949-12.705 17.2a18.12 18.12 0 0 1-5.315.79C9.622 36 2.608 30.313.573 22.611.257 21.407.059 20.162 0 18.879v-1.758c.02-.395.059-.79.099-1.185.099-.908.277-1.817.514-2.686C2.687 5.628 9.682 0 18 0c5.572 0 10.551 2.528 13.871 6.517 1.502 1.797 2.648 3.91 3.359 6.201.494 1.659.771 3.436.771 5.292z"
|
||||
fill="currentColor"></path>
|
||||
<g fill="#fff">
|
||||
<path
|
||||
d="M17.466 21.624c-.514 0-.988-.316-1.146-.829-.198-.632.138-1.303.771-1.501l7.666-2.469-1.205-8.254-13.317 4.621a1.19 1.19 0 0 1-1.521-.75 1.19 1.19 0 0 1 .751-1.521l13.89-4.818c.553-.197 1.166-.138 1.64.158a1.82 1.82 0 0 1 .85 1.284l1.344 9.183c.138.987-.494 1.994-1.482 2.33l-7.864 2.528-.375.04zm7.31.138c-.178-.632-.85-1.007-1.482-.81l-5.177 1.58c-2.331.79-3.28.02-3.418-.099l-6.56-8.412a4.25 4.25 0 0 0-4.406-1.758l-3.122.987c-.237.889-.415 1.777-.514 2.686l4.228-1.363a1.84 1.84 0 0 1 1.857.81l6.659 8.551c.751.948 2.015 1.323 3.359 1.323.909 0 1.857-.178 2.687-.474l5.078-1.54c.632-.178 1.008-.829.81-1.481z">
|
||||
</path>
|
||||
<use href="#czlogo"></use>
|
||||
<use href="#czlogo" x="8.516" y="-2.172"></use>
|
||||
</g>
|
||||
<defs>
|
||||
<path
|
||||
d="M18.689 28.654a1.94 1.94 0 0 1-1.936 1.935 1.94 1.94 0 0 1-1.936-1.935 1.94 1.94 0 0 1 1.936-1.935 1.94 1.94 0 0 1 1.936 1.935z"
|
||||
id="czlogo"></path>
|
||||
</defs>
|
||||
</svg>
|
||||
<img src="{{ asset('logo/logo-colored.png') }}" alt="AsiaGolf Logo" style="height: 36px; width: auto;">
|
||||
</span>
|
||||
AsiaGolf
|
||||
</a>
|
||||
|
|
@ -81,9 +65,7 @@
|
|||
href="{{ route('second', ['help', 'topics-v1']) }}">{{ __('otp.need_help') }}</a>
|
||||
</div>
|
||||
<p class="fs-xs mb-0">
|
||||
© All rights reserved. Made by <span class="animate-underline"><a
|
||||
class="animate-target text-dark-emphasis text-decoration-none"
|
||||
href="https://coderthemes.com/" rel="noreferrer" target="_blank">{{ __('signin.company_name') }}</a></span>
|
||||
{!! __('signin.rights_reserved', ['company' => config('app.name')]) !!}
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,23 +9,7 @@
|
|||
<header class="navbar px-0 pb-4 mt-n2 mt-sm-0 mb-2 mb-md-3 mb-lg-4">
|
||||
<a class="navbar-brand pt-0" href="/">
|
||||
<span class="d-flex flex-shrink-0 text-primary me-2">
|
||||
<svg height="36" width="36" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M36 18.01c0 8.097-5.355 14.949-12.705 17.2a18.12 18.12 0 0 1-5.315.79C9.622 36 2.608 30.313.573 22.611.257 21.407.059 20.162 0 18.879v-1.758c.02-.395.059-.79.099-1.185.099-.908.277-1.817.514-2.686C2.687 5.628 9.682 0 18 0c5.572 0 10.551 2.528 13.871 6.517 1.502 1.797 2.648 3.91 3.359 6.201.494 1.659.771 3.436.771 5.292z"
|
||||
fill="currentColor"></path>
|
||||
<g fill="#fff">
|
||||
<path
|
||||
d="M17.466 21.624c-.514 0-.988-.316-1.146-.829-.198-.632.138-1.303.771-1.501l7.666-2.469-1.205-8.254-13.317 4.621a1.19 1.19 0 0 1-1.521-.75 1.19 1.19 0 0 1 .751-1.521l13.89-4.818c.553-.197 1.166-.138 1.64.158a1.82 1.82 0 0 1 .85 1.284l1.344 9.183c.138.987-.494 1.994-1.482 2.33l-7.864 2.528-.375.04zm7.31.138c-.178-.632-.85-1.007-1.482-.81l-5.177 1.58c-2.331.79-3.28.02-3.418-.099l-6.56-8.412a4.25 4.25 0 0 0-4.406-1.758l-3.122.987c-.237.889-.415 1.777-.514 2.686l4.228-1.363a1.84 1.84 0 0 1 1.857.81l6.659 8.551c.751.948 2.015 1.323 3.359 1.323.909 0 1.857-.178 2.687-.474l5.078-1.54c.632-.178 1.008-.829.81-1.481z">
|
||||
</path>
|
||||
<use href="#czlogo"></use>
|
||||
<use href="#czlogo" x="8.516" y="-2.172"></use>
|
||||
</g>
|
||||
<defs>
|
||||
<path
|
||||
d="M18.689 28.654a1.94 1.94 0 0 1-1.936 1.935 1.94 1.94 0 0 1-1.936-1.935 1.94 1.94 0 0 1 1.936-1.935 1.94 1.94 0 0 1 1.936 1.935z"
|
||||
id="czlogo"></path>
|
||||
</defs>
|
||||
</svg>
|
||||
<img src="{{ asset('logo/logo-colored.png') }}" alt="AsiaGolf Logo" style="height: 36px; width: auto;">
|
||||
</span>
|
||||
AsiaGolf
|
||||
</a>
|
||||
|
|
@ -36,10 +20,14 @@
|
|||
<a class="nav-link text-decoration-underline p-0 ms-2"
|
||||
href="{{ route('register') }}">{{ __('signin.create_account') }}</a>
|
||||
</div>
|
||||
|
||||
{{-- show error message --}}
|
||||
<div id="error-message" class="alert alert-danger d-none"></div>
|
||||
|
||||
<!-- Form -->
|
||||
<form class="needs-validation" id="loginForm" novalidate="">
|
||||
<div class="position-relative mb-4">
|
||||
<input class="form-control form-control-lg" placeholder="{{ $type == 'email' ? __('signin.email_placeholder') : __('signin.phone_placeholder') }}" required="" name="identity" id="identity" />
|
||||
<input class="form-control form-control-lg" placeholder="{{ $type == 'email' ? __('signin.email_placeholder') : __('signin.phone_placeholder') }}" required="" name="identity" id="identity" min="1" type="{{ $type == 'email' ? 'email' :'number' }}" />
|
||||
<div class="invalid-tooltip bg-transparent py-0">{{ $type == 'email' ? __('signin.email_invalid') : __('signin.phone_invalid') }}</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -65,9 +53,7 @@
|
|||
href="{{ route('second', ['help', 'topics-v1']) }}">{{ __('signin.need_help') }}</a>
|
||||
</div>
|
||||
<p class="fs-xs mb-0">
|
||||
© All rights reserved. Made by <span class="animate-underline"><a
|
||||
class="animate-target text-dark-emphasis text-decoration-none"
|
||||
href="https://coderthemes.com/" rel="noreferrer" target="_blank">{{ __('signin.company_name') }}</a></span>
|
||||
{!! __('signin.rights_reserved', ['company' => config('app.name')]) !!}
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
@ -94,9 +80,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
const submitBtn = loginForm.querySelector('button[type="submit"]');
|
||||
const identityInput = document.getElementById('identity');
|
||||
|
||||
// Hide error message when user starts typing
|
||||
identityInput.addEventListener('input', function() {
|
||||
const errorDiv = document.getElementById('error-message');
|
||||
errorDiv.classList.add('d-none');
|
||||
});
|
||||
|
||||
loginForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Hide error message when submitting
|
||||
const errorDiv = document.getElementById('error-message');
|
||||
errorDiv.classList.add('d-none');
|
||||
|
||||
// Reset validation
|
||||
loginForm.classList.remove('was-validated');
|
||||
|
||||
|
|
@ -131,13 +127,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
// Redirect to OTP verification page
|
||||
window.location.href = data.redirect;
|
||||
} else {
|
||||
// Show error
|
||||
alert(data.message || '{{ __("signin.error") }}');
|
||||
// Show error in error message div
|
||||
const errorDiv = document.getElementById('error-message');
|
||||
errorDiv.textContent = data.message || '{{ __("signin.error") }}';
|
||||
errorDiv.classList.remove('d-none');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("signin.error") }}');
|
||||
const errorDiv = document.getElementById('error-message');
|
||||
errorDiv.textContent = '{{ __("signin.error") }}';
|
||||
errorDiv.classList.remove('d-none');
|
||||
})
|
||||
.finally(() => {
|
||||
// Reset button state
|
||||
|
|
|
|||
|
|
@ -126,9 +126,7 @@
|
|||
href="{{ route('second', ['help', 'topics-v1']) }}">{{ __('signup.need_help') }}</a>
|
||||
</div>
|
||||
<p class="fs-xs mb-0">
|
||||
© All rights reserved. Made by <span class="animate-underline"><a
|
||||
class="animate-target text-dark-emphasis text-decoration-none"
|
||||
href="https://coderthemes.com/" rel="noreferrer" target="blank">{{ __('signup.company_name') }}</a></span>
|
||||
{!! __('signin.rights_reserved', ['company' => config('app.name')]) !!}
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -235,16 +235,16 @@
|
|||
|
||||
<!-- Account button visible on screens > 768px wide (md breakpoint) -->
|
||||
<a class="btn btn-icon btn-lg fs-lg btn-outline-secondary border-0 rounded-circle animate-shake d-none d-md-inline-flex"
|
||||
href="{{ route('register') }}">
|
||||
href="{{ route('login') }}">
|
||||
<i class="ci-user animate-target"></i>
|
||||
<span class="visually-hidden">Account</span>
|
||||
<span class="visually-hidden">{{ __('header.account') }}</span>
|
||||
</a>
|
||||
|
||||
<!-- Wishlist button visible on screens > 768px wide (md breakpoint) -->
|
||||
<a class="btn btn-icon btn-lg fs-lg btn-outline-secondary border-0 rounded-circle animate-pulse d-none d-md-inline-flex"
|
||||
href="#!">
|
||||
<i class="ci-heart animate-target"></i>
|
||||
<span class="visually-hidden">Wishlist</span>
|
||||
<span class="visually-hidden">{{ __('header.wishlist') }}</span>
|
||||
</a>
|
||||
|
||||
<!-- Cart button -->
|
||||
|
|
@ -301,13 +301,13 @@
|
|||
<!-- Account and Wishlist buttons visible on screens < 768px wide (md breakpoint) -->
|
||||
<div class="offcanvas-header border-top px-0 py-3 mt-3 d-md-none">
|
||||
<div class="nav nav-justified w-100">
|
||||
<a class="nav-link border-end" href="{{ route('second', ['account', 'signin']) }}">
|
||||
<a class="nav-link border-end" href="{{ route('login') }}">
|
||||
<i class="ci-user fs-lg opacity-60 me-2"></i>
|
||||
Account
|
||||
{{ __('header.account') }}
|
||||
</a>
|
||||
<a class="nav-link" href="#!">
|
||||
<i class="ci-heart fs-lg opacity-60 me-2"></i>
|
||||
Wishlist
|
||||
{{ __('header.wishlist') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue