File: /var/www/html/resources/views/livewire/auth/verify-phone.blade.php
<div class="col-lg-6">
<div class="log-reg-form search-modal form-style1 bgc-white p50 p30-sm default-box-shadow1 bdrs12">
<div class="mb30">
<h3>Account Verification</h3>
<p class="text mt20">A 6 digit OTP has been sent to your phone number <span class="text-thm fw-bold">{{ $phone ?? '' }}</span></p>
</div>
<form wire:submit.prevent="verifyPhone">
<div class="mb25">
<label class="form-label fw500 dark-color">OTP</label>
<div class="otp-inputs">
<div class="otp-inputs">
<input type="text" wire:model.defer="phone_code1" maxlength="1" class="otp-field" id="otp-1" oninput="moveToNext(1)" onkeydown="handleBackspace(event, 1)" />
<input type="text" wire:model.defer="phone_code2" maxlength="1" class="otp-field" id="otp-2" oninput="moveToNext(2)" onkeydown="handleBackspace(event, 2)" />
<input type="text" wire:model.defer="phone_code3" maxlength="1" class="otp-field" id="otp-3" oninput="moveToNext(3)" onkeydown="handleBackspace(event, 3)" />
<input type="text" wire:model.defer="phone_code4" maxlength="1" class="otp-field" id="otp-4" oninput="moveToNext(4)" onkeydown="handleBackspace(event, 4)" />
<input type="text" wire:model.defer="phone_code5" maxlength="1" class="otp-field" id="otp-5" oninput="moveToNext(5)" onkeydown="handleBackspace(event, 5)" />
<input type="text" wire:model.defer="phone_code6" maxlength="1" class="otp-field" id="otp-6" oninput="moveToNext(6)" onkeydown="handleBackspace(event, 6)" />
</div>
</div>
@error('phone_code')
<span class="text-danger">{{ $message }}</span>
@enderror
<script>
function moveToNext(index) {
const currentInput = document.getElementById(`otp-${index}`);
const nextInput = document.getElementById(`otp-${index + 1}`);
if (currentInput.value.length === 1 && nextInput) {
nextInput.focus();
}
}
function handleBackspace(event, index) {
const currentInput = document.getElementById(`otp-${index}`);
const prevInput = document.getElementById(`otp-${index - 1}`);
if (event.key === "Backspace" && currentInput.value === "" && prevInput) {
prevInput.focus();
prevInput.value = ""; // Clear the previous input
}
}
function otpSend(num) {
const milliseconds = num * 7500 //5 mints
const currentDate = Date.now() + milliseconds
var countDownTime = new Date(currentDate).getTime()
let interval;
return {
countDown: milliseconds,
countDownTimer: new Date(currentDate).getTime(),
intervalID: null,
init() {
if (!this.intervalID) {
this.intervalID = setInterval(() => {
this.countDown = this.countDownTimer - new Date().getTime();
}, 1000);
}
},
getTime() {
if (this.countDown < 0) {
this.clearTimer()
}
return this.countDown;
},
formatTime(num) {
var date = new Date(num);
return new Date(this.countDown).toLocaleTimeString(navigator.language, {
minute: '2-digit',
second: '2-digit'
});
},
clearTimer() {
clearInterval(this.intervalID);
}
}
}
</script>
<style>
.otp-inputs {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 10px;
}
.otp-field {
width: 50px;
height: 50px;
text-align: center;
font-size: 18px;
border: 2px solid #ccc;
border-radius: 8px;
outline: none;
transition: border-color 0.2s;
}
.otp-field:focus {
border-color: #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
}
</style>
<div class="grid gap-y-2 mt-2" x-data="otpSend(40)" x-init="init()">
<template x-if="getTime() <= 0">
<button wire:click="resendOtp" class="btn btn-light-primary default-box-shadow2 mt-2"> Resend OTP </button>
</template>
<template x-if="getTime() > 0">
<small class="form-label fw500 dark-color">
Resend OTP in
<span class="fw-bold" x-text="formatTime(getTime())"></span>
</small>
</template>
</div>
</div>
<div class="d-grid mb20">
<button type="submit" wire:loading.attr="disabled" class="ud-btn btn-thm default-box-shadow2 mt-4">
<span wire:loading wire:target="verifyPhone" class="spinner-border spinner-border-sm"> </span>
<span wire:loading wire:target="verifyPhone"> Please wait... </span>
<span wire:loading wire:target="resendOtp"> Resending otp... </span>
<span wire:loading.remove> Continue </span>
</button>
</div>
</form>
</div>
</div>