172 lines
6.4 KiB
PHP
172 lines
6.4 KiB
PHP
@extends('layouts.login')
|
||
|
||
@section('content')
|
||
<div class="login-box">
|
||
<div class="login-logo">
|
||
<a><b>So-Manager </b>{{ __('管理パネル') }}</a>
|
||
</div>
|
||
<!-- /.login-logo -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">{{ __('セキュリティ認証') }}</h5>
|
||
</div>
|
||
<div class="card-body login-card-body">
|
||
<p class="login-box-msg mb-3">
|
||
{{ __('登録されたメールアドレス') }} <strong>{{ $maskedEmail }}</strong>
|
||
<br/>{{ __('に6桁の認証コードが送信されました。') }}
|
||
</p>
|
||
|
||
@if ($errors->any())
|
||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||
<strong>{{ __('エラー') }}</strong>
|
||
<ul class="mb-0">
|
||
@foreach ($errors->all() as $error)
|
||
<li>{{ $error }}</li>
|
||
@endforeach
|
||
</ul>
|
||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
@endif
|
||
|
||
@if (session('error'))
|
||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||
{{ session('error') }}
|
||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
@endif
|
||
|
||
@if (session('success'))
|
||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||
{{ session('success') }}
|
||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
@endif
|
||
|
||
<form action="{{ route('otp.verify') }}" method="POST" novalidate>
|
||
@csrf
|
||
|
||
<div class="form-group mb-3">
|
||
<label for="code" class="form-label">
|
||
<strong>{{ __('認証コード(6桁)') }}</strong>
|
||
</label>
|
||
<div class="input-group mb-3">
|
||
<input
|
||
type="text"
|
||
id="code"
|
||
name="code"
|
||
class="form-control form-control-lg text-center"
|
||
placeholder="000000"
|
||
maxlength="6"
|
||
pattern="[0-9]{6}"
|
||
inputmode="numeric"
|
||
required
|
||
autofocus
|
||
value="{{ old('code') }}"
|
||
/>
|
||
<div class="input-group-append">
|
||
<span class="fa fa-key input-group-text"></span>
|
||
</div>
|
||
</div>
|
||
<small class="d-block text-muted">
|
||
{{ __('数字のみで6桁入力してください。有効期限は10分です。') }}
|
||
</small>
|
||
</div>
|
||
|
||
<div class="row mt40">
|
||
<div class="col-12 col-lg-8 offset-0 offset-lg-2">
|
||
<button type="submit" class="btn btn-lg btn-primary btn-block btn-flat">
|
||
{{ __('認証する') }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<div class="text-center mt-3">
|
||
<form action="{{ route('otp.resend') }}" method="POST" class="d-inline">
|
||
@csrf
|
||
<button
|
||
type="submit"
|
||
class="btn btn-sm btn-outline-secondary"
|
||
id="resendBtn"
|
||
@if ($resendWaitSeconds > 0) disabled @endif
|
||
>
|
||
<span id="resendText">
|
||
@if ($resendWaitSeconds > 0)
|
||
{{ __('コード再送(') }}{{ $resendWaitSeconds }}{{ __('秒待機)') }}
|
||
@else
|
||
{{ __('コードを再送信する') }}
|
||
@endif
|
||
</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="mt-3 text-center">
|
||
<a href="{{ route('logout') }}" class="text-muted small">
|
||
{{ __('ログアウト') }}
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// 入力フィールドの自動フォーカス制御
|
||
const codeInput = document.getElementById('code');
|
||
const resendBtn = document.getElementById('resendBtn');
|
||
const resendText = document.getElementById('resendText');
|
||
|
||
// 数字のみ許可
|
||
codeInput.addEventListener('keypress', function(e) {
|
||
if (!/\d/.test(e.key)) {
|
||
e.preventDefault();
|
||
}
|
||
});
|
||
|
||
// 貼り付け時に数字のみを許可
|
||
codeInput.addEventListener('paste', function(e) {
|
||
e.preventDefault();
|
||
const pastedText = (e.clipboardData || window.clipboardData).getData('text');
|
||
const numbers = pastedText.replace(/\D/g, '').slice(0, 6);
|
||
codeInput.value = numbers;
|
||
});
|
||
|
||
// 再送ボタンのカウントダウン処理
|
||
let waitSeconds = {{ $resendWaitSeconds }};
|
||
|
||
if (waitSeconds > 0) {
|
||
const countdown = setInterval(function() {
|
||
waitSeconds--;
|
||
if (waitSeconds <= 0) {
|
||
clearInterval(countdown);
|
||
resendBtn.disabled = false;
|
||
resendText.textContent = '{{ __("コードを再送信する") }}';
|
||
} else {
|
||
resendText.textContent = '{{ __("コード再送(") }}' + waitSeconds + '{{ __("秒待機)") }}';
|
||
}
|
||
}, 1000);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
#code {
|
||
letter-spacing: 0.5em;
|
||
font-size: 1.5rem;
|
||
font-weight: bold;
|
||
font-family: 'Courier New', monospace;
|
||
}
|
||
|
||
#code::placeholder {
|
||
letter-spacing: 0.5em;
|
||
}
|
||
</style>
|
||
@endsection
|