import React, { useState, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; import { User, Briefcase, Lock, ArrowRight, AlertCircle, Eye, EyeOff } from 'lucide-react'; import { SpotlightCard } from '../components/SpotlightCard'; import Logo from '../assets/images/LynkedUp_Pro_F_logo_Y.png'; // Rainbow Button Component const RainbowButton = ({ children, onClick, type = "button", className = "" }) => { const btnRef = useRef(null); const [position, setPosition] = useState({ x: 0, y: 0 }); const [opacity, setOpacity] = useState(0); const handleMouseMove = (e) => { if (!btnRef.current) return; const rect = btnRef.current.getBoundingClientRect(); setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top }); }; return ( ); }; // Demo account roster — each entry maps directly to MOCK_USERS credentials const DEMO_ACCOUNTS = { customer: [ { name: 'Alice Carter', loginType: 'customer', id: 'alice', pw: 'password' }, ], employee: [ { name: 'Wade Hollis — Admin', loginType: 'employee', id: 'LUP-1010', pw: 'password' }, { name: 'Darlene Brooks — Admin', loginType: 'employee', id: 'LUP-1011', pw: 'password' }, { name: 'Roy Schaefer — Admin', loginType: 'employee', id: 'LUP-1012', pw: 'password' }, { name: 'Cody Tatum — Agent', loginType: 'employee', id: 'LUP-1040', pw: 'password' }, { name: 'Hannah Reyes — Agent', loginType: 'employee', id: 'LUP-1041', pw: 'password' }, { name: 'Travis Boone — Agent', loginType: 'employee', id: 'LUP-1042', pw: 'password' }, { name: 'Shelby Greer — Agent', loginType: 'employee', id: 'LUP-1043', pw: 'password' }, { name: 'Dalton Pruitt — Agent', loginType: 'employee', id: 'LUP-1044', pw: 'password' }, ], owner: [ { name: 'Justin Johnson', loginType: 'owner', id: 'justin', pw: 'password' }, { name: 'Diana Reeves', loginType: 'owner', id: 'diana', pw: 'password' }, ], contractor: [ { name: 'Mike Brennan', loginType: 'contractor', id: 'mike', pw: 'password' }, ], subcontractor: [ { name: 'Carlos Mendoza', loginType: 'subcontractor', id: 'carlos', pw: 'password' }, { name: 'Maya Patel', loginType: 'subcontractor', id: 'maya', pw: 'password' }, { name: 'Dwayne Boudreaux', loginType: 'subcontractor', id: 'dwayne', pw: 'password' }, { name: 'Jennifer Castillo', loginType: 'subcontractor', id: 'jennifer', pw: 'password' }, { name: 'Greg Alston', loginType: 'subcontractor', id: 'greg', pw: 'password' }, ], }; // Color palette per demo role chip const DEMO_ROLE_STYLES = { customer: { chip: 'bg-zinc-100 dark:bg-zinc-900/50 border-zinc-200 dark:border-white/5 text-zinc-500 hover:border-zinc-300 dark:hover:border-white/20 hover:text-zinc-800 dark:hover:text-zinc-300', active: 'bg-zinc-200 dark:bg-zinc-800 border-zinc-400 dark:border-white/20 text-zinc-900 dark:text-white' }, employee: { chip: 'bg-zinc-100 dark:bg-zinc-900/50 border-zinc-200 dark:border-white/5 text-zinc-500 hover:border-zinc-300 dark:hover:border-white/20 hover:text-zinc-800 dark:hover:text-zinc-300', active: 'bg-zinc-200 dark:bg-zinc-800 border-zinc-400 dark:border-white/20 text-zinc-900 dark:text-white' }, owner: { chip: 'bg-amber-100 dark:bg-amber-900/20 border-amber-200 dark:border-amber-500/20 text-amber-600 dark:text-amber-400 hover:bg-amber-200 dark:hover:bg-amber-900/30', active: 'bg-amber-200 dark:bg-amber-900/40 border-amber-400 dark:border-amber-400/50 text-amber-800 dark:text-amber-300' }, contractor: { chip: 'bg-blue-100 dark:bg-blue-900/20 border-blue-200 dark:border-blue-500/20 text-blue-600 dark:text-blue-400 hover:bg-blue-200 dark:hover:bg-blue-900/30', active: 'bg-blue-200 dark:bg-blue-900/40 border-blue-400 dark:border-blue-400/50 text-blue-800 dark:text-blue-300' }, subcontractor: { chip: 'bg-purple-100 dark:bg-purple-900/20 border-purple-200 dark:border-purple-500/20 text-purple-600 dark:text-purple-400 hover:bg-purple-200 dark:hover:bg-purple-900/30', active: 'bg-purple-200 dark:bg-purple-900/40 border-purple-400 dark:border-purple-400/50 text-purple-800 dark:text-purple-300' }, }; const DEMO_ROLE_LABELS = { customer: 'Customer', employee: 'Employee', owner: 'Owner', contractor: 'Contractor', subcontractor: 'Sub-Con', }; const Login = () => { const [loginType, setLoginType] = useState('customer'); // 'customer', 'employee', 'owner', 'contractor', 'subcontractor' const [identifier, setIdentifier] = useState(''); const [password, setPassword] = useState(''); const [showPassword, setShowPassword] = useState(false); const [error, setError] = useState(''); const [expandedDemoRole, setExpandedDemoRole] = useState(null); const { login } = useAuth(); const navigate = useNavigate(); const handleLogin = (e) => { e.preventDefault(); setError(''); if (!identifier || !password) { setError('Please fill in all fields'); return; } const result = login(identifier, password, loginType); if (result.success) { // Role-based Redirect switch (result.role) { case 'CUSTOMER': navigate('/'); break; case 'OWNER': navigate('/owner/snapshot'); break; case 'CONTRACTOR': navigate('/contractor/dashboard'); break; case 'VENDOR': navigate('/vendor/dashboard'); break; case 'SUBCONTRACTOR': navigate('/subcontractor/dashboard'); break; default: navigate('/emp/fa/dashboard'); // Default for Employee/Admin } } else { setError(result.message); } }; // Called when a person is selected from the demo picker — logs in immediately const handleDemoLogin = (account) => { setError(''); const result = login(account.id, account.pw, account.loginType); if (result.success) { switch (result.role) { case 'CUSTOMER': navigate('/'); break; case 'OWNER': navigate('/owner/snapshot'); break; case 'CONTRACTOR': navigate('/contractor/dashboard'); break; case 'VENDOR': navigate('/vendor/dashboard'); break; case 'SUBCONTRACTOR': navigate('/subcontractor/dashboard'); break; default: navigate('/emp/fa/dashboard'); } } else { setError(result.message); } }; const toggleDemoRole = (roleKey) => { const accounts = DEMO_ACCOUNTS[roleKey]; if (!accounts) return; // Single-person roles → log in directly; multi-person roles → expand picker if (accounts.length === 1) { handleDemoLogin(accounts[0]); } else { setExpandedDemoRole(prev => (prev === roleKey ? null : roleKey)); } }; return (
{/* Subtle Ambient Background */}
{/* Autofill CSS Override */}
{/* ADJUSTED PADDING FOR MOBILE */}
LynkedUp Pro

Welcome Back

Sign in to your LynkedUp Pro account

{/* Role Tabs — 3-col grid on mobile, 6-col on desktop */}
{[ { key: 'customer', label: 'Customer' }, { key: 'employee', label: 'Employee' }, { key: 'owner', label: 'Owner' }, { key: 'contractor', label: 'Contract.' }, { key: 'vendor', label: 'Vendor' }, { key: 'subcontractor', label: 'Sub-Con' }, ].map(({ key, label }) => ( ))}
{loginType === 'customer' ? : }
setIdentifier(e.target.value)} className="w-full bg-zinc-100 dark:bg-zinc-900/50 border border-zinc-200 dark:border-white/5 text-zinc-900 dark:text-white rounded-xl py-4 pl-12 pr-4 focus:outline-none focus:ring-1 focus:ring-black/10 dark:focus:ring-white/20 focus:bg-white dark:focus:bg-zinc-900 transition-all placeholder:text-zinc-400 dark:placeholder:text-zinc-700 font-medium relative z-0" placeholder={loginType === 'employee' ? "e.g., FA001" : "e.g., username"} />
setPassword(e.target.value)} className="w-full bg-zinc-100 dark:bg-zinc-900/50 border border-zinc-200 dark:border-white/5 text-zinc-900 dark:text-white rounded-xl py-4 pl-12 pr-12 focus:outline-none focus:ring-1 focus:ring-black/10 dark:focus:ring-white/20 focus:bg-white dark:focus:bg-zinc-900 transition-all placeholder:text-zinc-400 dark:placeholder:text-zinc-700 font-medium relative z-0" placeholder="Enter your password" />
{error && (
{error}
)} Sign In
{/* Demo Quick Links — per-role person picker */}

Quick Demo Access

{Object.keys(DEMO_ACCOUNTS).map((roleKey) => { const styles = DEMO_ROLE_STYLES[roleKey] || DEMO_ROLE_STYLES.customer; const isExpanded = expandedDemoRole === roleKey; const isSingle = DEMO_ACCOUNTS[roleKey].length === 1; return ( ); })}
{/* Person picker — expands below chips when a multi-person role is selected */} {expandedDemoRole && DEMO_ACCOUNTS[expandedDemoRole] && (
{DEMO_ACCOUNTS[expandedDemoRole].map((account) => ( ))}
)}
{'5'}{'_'}{'@'}{'_'}{'7'}{'_'}{'y'}{'_'}{'@'}{'_'}{'m'} {'R'}{'_'}{'@'}{'_'}{'5'}{'_'}{'7'}{'_'}{'0'}{'_'}{'g'}{'_'}{'1'} | LynkedUpPro - Turns out roofing CRMs don't build themselves. Who knew?
); }; export default Login;