// This is the active login page — matched by routes/LoginRoutes.js, which is // registered before MainRoutes.js and wins the route match for both '/' and // '/login'. (login1.js is dead code — MainRoutes.js's own '/login' route is // unreachable because LoginRoutes.js's un-prefixed '/login' matches first.) import { useState, useEffect } from 'react'; import AnimateButton from 'components/@extended/AnimateButton'; import { Box, Card, CardContent, Stack, TextField, Button, Typography, Link, IconButton, InputAdornment } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; import Loader from 'components/Loader'; import doormileLogo from 'assets/images/doormile-logo.png'; import { useSelector, useDispatch } from 'react-redux'; import { OpenToast } from 'components/third-party/OpenToast'; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; import { setLoginUser } from 'store/reducers/loginUserSlice'; import { markSessionStart } from 'utils/session'; // doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for light surfaces. const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)'; const Login = () => { const dispatch = useDispatch(); const fcmtoken = useSelector((state) => state.fcm); const theme = useTheme(); const [loading, setLoading] = useState(false); let navigate = useNavigate(); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [showPassword, setShowPassword] = useState(false); useEffect(() => { if (localStorage.getItem('authname')) { navigate('/nearle/dispatch'); } }, []); const loginsend = async () => { if (!username || !password) { opentoast('Fill All required fields'); return; } setLoading(true); try { const res = await axios.post(`${process.env.REACT_APP_URL}/admin/login`, { email: username, password, userfcmtoken: fcmtoken?.token }); if (res.data.success) { OpenToast('Login Successful', 'success', 1000); const { token, data } = res.data; dispatch(setLoginUser(data)); localStorage.setItem('authname', data.email || data.firstname); localStorage.setItem('userid', data.userid); localStorage.setItem('roleid', data.roleid); localStorage.setItem('token', token); axios.defaults.headers.common.Authorization = `Bearer ${token}`; markSessionStart(); navigate('/nearle/dispatch'); } else { OpenToast(res.data.message || 'Invalid Data', 'error', 3000); } } catch (err) { console.error(err); OpenToast(err.response?.data?.message || err.message, 'error', 5000); } finally { setLoading(false); } }; const opentoast = (message) => { OpenToast(message, 'error', 1500); }; return ( {loading && } {/* ---- Left brand panel (hidden on small screens) ---- */} {/* Logo at the top-left corner */} Doormile {/* decorative light glows */} Operate your dispatch,
end to end.
Orders, AI route optimisation, live rider tracking and billing — all in the Doormile operator console. {['Real-time fleet visibility', 'AI-optimised dispatch routes', 'Tenant, pricing & invoice control'].map((t) => ( {t} ))}
{/* ---- Right form panel ---- */} {/* Logo */} Doormile {/* Title */} Welcome back Sign in to the Doormile console
{ e.preventDefault(); loginsend(); }} > {/* Email */} setUsername(e.target.value.toLocaleLowerCase())} /> {/* Password */} setPassword(e.target.value)} InputProps={{ endAdornment: ( setShowPassword((prev) => !prev)} edge="end"> {showPassword ? : } ) }} /> {/* Submit */}
{/* footer */} © All rights reserved Terms and Conditions Privacy Policy
); }; export default Login;