Here is home.index -> home/index.blade.php blade view that holds the Single Page Application
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="user-id" content="@if (auth()->check()) {{ auth()->user()->uid }} @else null @endif" />
<title>{{ config('app.name', 'Laravel') }} | @yield('title')</title>
<!-- Include SweetAlert CSS and JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js"></script>
<!-- Scripts -->
@viteReactRefresh
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
@laravelPWA
</head>
<body>
<div id="app">
@yield('content')
</div>
</body>
</html>
And here is the LoginVerifyModal.jsx component
import React, { createRef, useState } from 'react';
import axiosClient from "../../route/axios-client";
import { useForm } from "../../control/hooks/useForm";
import { useStateContext } from "../../control/context/ContextProvider";
import ClipLoader from 'react-spinners/ClipLoader';
const LoginVerifyModal = ({ isOpen, onClose, phoneNumber }) => {
const { notification, setUser, setToken, setNotification } = useStateContext()
const { errors, setErrors, renderFieldError, message, setMessage, navigate } = useForm()
const [ waitResponse, setWaitResponse ] = useState(false)
const codeRef = createRef()
const onSubmit = async (event) => {
event.preventDefault()
setErrors(null);
setMessage('');
const code = codeRef.current.value.trim();
// Validate the code as a 6-digit number
const codePattern = /^\d{6}$/;
if (!codePattern.test(code)) {
Swal.fire({
title: 'Warning!',
text: 'Verification code must be a 6-digit number',
icon: 'warning',
});
return;
}
const payload = {
code: code,
}
setWaitResponse(true)
await axiosClient.post('/verify', payload)
.then(({data}) => {
setUser(data.data.user)
setToken(data.data.token)
setNotification(`Welcome ${data.data.user.name}`)
setWaitResponse(false)
onClose(); // Close the modal after confirming
// After successful OTP verification and state update
window.location.reload();
})
.catch(({response}) => {
if (response.data.message) {
setMessage(response.data.message)
}
if (response.data.errors) {
setErrors(response.data.errors)
}
setWaitResponse(false)
})
}
if (!isOpen) {
return null;
}
return (
<div id="loginModal" className={`modal ${isOpen ? 'open' : ''}`}>
<div className="modal-content">
<h2 className="header-login">
Verify Login
</h2>
<form onSubmit={onSubmit}>
{waitResponse ? (
<div className="d-flex justify-content-center">
<ClipLoader color={'#0d6efd'} loading={waitResponse} size={150} />
</div>
) : (
<>
<div className="mb-3">
<label htmlFor="code" className="form-label">Verification Code</label>
<input ref={codeRef}
type="text"
className={`form-control ${errors && errors.hasOwnProperty('code') ? 'is-invalid' : ''}`}
placeholder="Code sent"
id="code"
aria-describedby="code"/>
{ renderFieldError('code') &&
<span className="invalid-feedback" role="alert">
<strong>{renderFieldError('code')}</strong>
</span>
}
</div>
</>
)}
<div className="btn-continue-and-cancel">
<button id="cancelLogin" onClick={onClose}>Cancel</button>
<button id="confirmLogin" type="submit" disabled={!!waitResponse}>Verify</button>
</div>
</form>
</div>
</div>
);
};
export default LoginVerifyModal;
For clarity and context, I shared these snippets to emphasize that even when reloading the page after OTP success, the meta value user-id is still null, meaning the user is still invalidated since I am not accessing a route with auth middleware
NOTE: the catch-all route does not hold any middleware