import React, { useState } from 'react'; import { useNavigate, NavLink } from 'react-router-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { Truck, ShieldCheck, Lock, User, ArrowRight, Cpu, KeyRound, ShieldAlert, Eye, EyeOff, MapPin, Activity } from 'lucide-react'; import { authApi } from '../api/auth'; import './Login.css'; export const FleetLogin = () => { const [username, setUsername] = useState('fleet_operator'); const [password, setPassword] = useState('Fleet@123'); const [mfaCode, setMfaCode] = useState(''); const [isLoading, setIsLoading] = useState(false); const [showError, setShowError] = useState(''); const [mfaSessionToken, setMfaSessionToken] = useState(''); const [tempUser, setTempUser] = useState | null>(null); const [loginStep, setLoginStep] = useState<'login' | 'mfa'>('login'); const [showPassword, setShowPassword] = useState(false); const navigate = useNavigate(); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); setShowError(''); // Clear any leftover mock tokens to ensure a real network call console.log('--- STARTING FLEET LOGIN ---'); console.log('Clearing local storage tokens...'); localStorage.removeItem('teleems_token'); localStorage.removeItem('teleems_auth'); localStorage.removeItem('teleems_user'); try { console.log('[FleetLogin] Logging in as:', username); // Clear old session first localStorage.removeItem('teleems_token'); localStorage.removeItem('teleems_user'); localStorage.removeItem('teleems_auth'); // Step 1: Login — use raw fetch, NOT apiClient (bypass mock/401 interceptors) const loginRes = await fetch('https://teleems-api-gateway.onrender.com/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); const loginJson = await loginRes.json(); console.log('[FleetLogin] Login response status:', loginRes.status, loginJson); if (loginRes.status === 201 || loginRes.status === 200) { if (loginJson.data?.mfa_required) { setMfaSessionToken(loginJson.data.mfa_session_token || ''); setTempUser(loginJson.data.user || null); setLoginStep('mfa'); } else { const accessToken = loginJson.data?.access_token || ''; if (!accessToken) { setShowError('Login failed: No access token received.'); return; } // Store token immediately localStorage.setItem('teleems_auth', 'true'); localStorage.setItem('teleems_token', accessToken); console.log('[FleetLogin] Token stored. Fetching /auth/me...'); // Step 2: Fetch real profile from /auth/me try { const meRes = await fetch('https://teleems-api-gateway.onrender.com/v1/auth/me', { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}`, }, }); const meJson = await meRes.json(); console.log('[FleetLogin] /auth/me status:', meRes.status, meJson); const profile = meJson?.data || loginJson.data?.user || {}; const roles: string[] = Array.isArray(profile.roles) ? [...profile.roles] : ['Fleet Operator']; localStorage.setItem('teleems_user', JSON.stringify({ ...profile, roles })); } catch (meErr) { console.warn('[FleetLogin] /auth/me failed, using login user data:', meErr); const fallback = loginJson.data?.user || {}; localStorage.setItem('teleems_user', JSON.stringify({ ...fallback, roles: ['Fleet Operator'] })); } navigate('/fleet-operator?tab=overview'); } } else { setShowError(loginJson?.message || 'Access Denied: Invalid Credentials'); } } catch (err: unknown) { console.error('[FleetLogin] Error:', err); setShowError('Tactical Network Unavailable: Check Connection'); } finally { setIsLoading(false); } }; const handleMfaVerify = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); setShowError(''); try { const response = await authApi.verifyMfa(mfaSessionToken, mfaCode); if (response.status === 201 || response.status === 200) { localStorage.setItem('teleems_auth', 'true'); localStorage.setItem('teleems_token', response.data.access_token || ''); const baseUser: Record = (response.data.user || tempUser || {}) as Record; const roles = Array.isArray(baseUser.roles) ? [...baseUser.roles] : []; if (!roles.includes('FLEET_OPERATOR')) roles.push('FLEET_OPERATOR'); const userToStore = { ...baseUser, roles, mfa_enabled: true }; localStorage.setItem('teleems_user', JSON.stringify(userToStore)); navigate('/fleet-operator?tab=overview'); } else { setShowError('Invalid Security Token'); } } catch { setShowError('Token Verification Failed'); } finally { setIsLoading(false); } }; return (
{/* LEFT SIDE - IMAGE & TACTICAL HUD */}
{/* Background Image */}
{/* Gradients to blend image with the tactical theme */}
{/* Decorative Grid & Radar (HUD elements) */}
{/* Content Top */}
TELE_EMS FLEET_OPERATOR
{/* Content Middle/Bottom */}
Command The Fleet.
Save Lives Faster.
Access real-time telemetry, manage dispatch routes, and monitor critical resources from a single, secure tactical terminal.
REAL-TIME SYNC
GPS TRACKING
ENCRYPTED
{/* RIGHT SIDE - LOGIN FORM */}
{/* Subtle background glow */}

{loginStep === 'login' ? 'TERMINAL ACCESS' : 'MFA REQUIRED'}

{loginStep === 'login' ? 'Sector: Dispatch • Active Node: CS-88' : 'Identity Verification'}

{loginStep === 'login' ? (
setUsername(e.target.value)} required style={{ width: '100%', padding: '16px 16px 16px 48px', background: 'rgba(15, 23, 42, 0.03)', border: '1px solid rgba(15, 23, 42, 0.1)', borderRadius: '12px', color: '#0F172A', fontSize: '15px', fontWeight: 500, outline: 'none', transition: 'all 0.3s', fontFamily: "'Outfit', sans-serif" }} onFocus={(e) => e.target.style.borderColor = '#06b6d4'} onBlur={(e) => e.target.style.borderColor = 'rgba(15, 23, 42, 0.1)'} />
setPassword(e.target.value)} required style={{ width: '100%', padding: '16px 48px 16px 48px', background: 'rgba(15, 23, 42, 0.03)', border: '1px solid rgba(15, 23, 42, 0.1)', borderRadius: '12px', color: '#0F172A', fontSize: '15px', fontWeight: 500, outline: 'none', transition: 'all 0.3s', fontFamily: "'Outfit', sans-serif", letterSpacing: showPassword ? 'normal' : '3px' }} onFocus={(e) => e.target.style.borderColor = '#06b6d4'} onBlur={(e) => e.target.style.borderColor = 'rgba(15, 23, 42, 0.1)'} />
) : (
setMfaCode(e.target.value.replace(/\D/g, ''))} required style={{ width: '100%', padding: '16px 16px 16px 48px', background: 'rgba(15, 23, 42, 0.03)', border: '1px solid rgba(15, 23, 42, 0.1)', borderRadius: '12px', color: '#0F172A', fontSize: '20px', fontWeight: 600, letterSpacing: '4px', textAlign: 'center', outline: 'none', transition: 'all 0.3s', fontFamily: "'Outfit', sans-serif" }} onFocus={(e) => e.target.style.borderColor = '#06b6d4'} onBlur={(e) => e.target.style.borderColor = 'rgba(15, 23, 42, 0.1)'} />
)} {showError && (
{showError}
)}
e.currentTarget.style.color = '#06b6d4'} onMouseOut={(e) => e.currentTarget.style.color = '#64748B'}> RETURN TO STANDARD PORTAL
{/* Embedded Global Styles to avoid breaking any other page, since we are overriding locally */}
); };