const DEMO = [['u5', 'Employee'], ['u4', 'Manager'], ['u3', 'HR admin'], ['u1', 'Super admin']];
const DEMO_OTP = '1234';
const OTP_LEN = 4;
function OtpBoxes({ value, onChange }) {
const refs = React.useRef([]);
const set = (i, ch) => {
const digits = value.split(''); digits[i] = ch; const next = digits.join('').slice(0, OTP_LEN);
onChange(next); if (ch && i < OTP_LEN - 1) refs.current[i + 1].focus();
};
return (
{Array.from({ length: OTP_LEN }, (_, i) => (
(refs.current[i] = el)} inputMode="numeric" maxLength={1} aria-label={'Digit ' + (i + 1)} value={value[i] || ''}
onChange={(e) => set(i, e.target.value.replace(/\D/g, '').slice(-1))}
onKeyDown={(e) => { if (e.key === 'Backspace' && !value[i] && i > 0) refs.current[i - 1].focus(); }}
onPaste={(e) => { const p = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, OTP_LEN); if (p) { e.preventDefault(); onChange(p); refs.current[Math.min(p.length, OTP_LEN - 1)].focus(); } }}
style={{ width: '100%', minWidth: 0, height: '56px', textAlign: 'center', fontSize: '22px', fontWeight: 800, color: '#06367E', background: value[i] ? '#fff' : '#F8FAFE', border: '1px solid ' + (value[i] ? '#2F80EC' : '#E1E8F4'), borderRadius: '12px', outline: 'none', fontFamily: 'inherit', boxSizing: 'border-box' }} />
))}
);
}
function AuthNote({ icon, tone = 'blue', title, children }) {
const c = { blue: ['#E7F1FD', '#1D6AE3'], amber: ['#FDF1DC', '#8A5A00'], red: ['#FCEAE8', '#B9382F'], green: ['#E3F5EC', '#0F7A55'] }[tone];
return (
);
}
function AuthScreen() {
const { m } = useApp();
const [step, setStep] = React.useState('login');
const [mode, setMode] = React.useState('mobile');
const [id, setId] = React.useState('');
const [acct, setAcct] = React.useState(null);
const [otp, setOtp] = React.useState('');
const [err, setErr] = React.useState('');
const [timer, setTimer] = React.useState(0);
const [reg, setReg] = React.useState({ name: '', email: '', phone: '', dept: 'Recruitment', designation: '' });
React.useEffect(() => { if (!timer) return; const t = setTimeout(() => setTimer(timer - 1), 1000); return () => clearTimeout(t); }, [timer]);
const sendOtp = () => {
setErr('');
if (mode === 'mobile' && id.replace(/\D/g, '').length !== 10) return setErr('Enter your 10-digit mobile number.');
if (mode === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(id.trim())) return setErr('Enter a valid email address.');
const u = AKStore.act.findAccount(id);
if (!u || u.status === 'rejected') return setErr("We couldn't find an account with that " + (mode === 'mobile' ? 'number' : 'email') + '. New here? Request access below.');
setAcct(u);
if (u.status === 'pending') return setStep('pending');
if (u.status === 'suspended') return setStep('suspended');
setOtp(''); setTimer(30); setStep('otp');
};
const verify = () => { if (otp.length < OTP_LEN) return setErr('Enter all ' + OTP_LEN + ' digits.'); if (otp !== DEMO_OTP) return setErr('That code is incorrect. Check the message and try again.'); AKStore.act.signIn(acct.id); };
const register = () => {
setErr('');
if (!reg.name.trim() || !reg.designation.trim()) return setErr('Fill in your name and designation.');
if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(reg.email.trim())) return setErr('Enter a valid email address.');
if (reg.phone.replace(/\D/g, '').length !== 10) return setErr('Enter your 10-digit mobile number.');
if (AKStore.act.findAccount(reg.email) || AKStore.act.findAccount(reg.phone)) return setErr('An account already exists with that email or mobile number.');
setAcct(AKStore.act.register(reg)); setStep('registered');
};
const masked = acct ? (mode === 'mobile' ? '+91 ••••• ' + acct.phone.slice(-5) : acct.email.replace(/^(.{2}).*(@.*)$/, '$1•••$2')) : '';
const back = (s) => () => { setErr(''); setStep(s); };
let body;
if (step === 'login') body = (
<>
Sign in
Use the mobile number or email you registered with. We'll send you a one-time code.
{ setMode(v); setId(''); setErr(''); }} />
New to Aarniksha? { e.preventDefault(); setErr(''); setStep('register'); }} style={{ fontWeight: 700 }}>Request access
Demo accounts
{DEMO.map(([uid, role]) => { const u = AKH.user(uid); return (
{ setErr(''); setId(mode === 'mobile' ? u.phone.replace(/(\d{5})(\d{5})/, '$1 $2') : u.email); }}
style={{ display: 'inline-flex', alignItems: 'center', gap: '8px', padding: '6px 12px 6px 6px', borderRadius: '999px', border: '1px solid #DCE5F5', background: '#fff', cursor: 'pointer', fontFamily: 'inherit', fontSize: '13px', fontWeight: 700, color: '#43506A' }}>
{role}
); })}
>
);
if (step === 'otp') body = (
<>
Enter the code
We sent a 4-digit code to {masked} . It expires in 10 minutes.
{timer ? 'Resend code in 0:' + String(timer).padStart(2, '0') : { e.preventDefault(); setTimer(30); }} style={{ fontWeight: 700 }}>Resend code }
>
);
if (step === 'register') body = (
<>
Request access
HR reviews every request. You'll get an email as soon as your account is approved.
>
);
if (step === 'registered') body = (
<>
Request sent
Your request is with HR. We'll email {acct.email} once it's approved — usually within one working day.
Back to sign in
>
);
if (step === 'pending') body = (
<>
Almost there
HR hasn't approved {acct.name.split(' ')[0]}'s access yet. You'll get an email at {acct.email} as soon as it's done.
>
);
if (step === 'suspended') body = (
<>
Access suspended
Your portal access has been suspended{acct.suspendedReason ? ' (' + acct.suspendedReason.toLowerCase() + ')' : ''}. Please contact hr@aarnikshasolutions.com .
>
);
const brand = (
Aarniksha Solutions
Employee portal
Your workday, in one place.
{!m ?
{[['Clock', 'Check in from the office or from home'], ['CalendarDays', 'Apply for leave and follow every approval'], ['ListChecks', 'Tasks, goals and the holiday calendar together']].map(([ic, t]) => (
))}
: null}
{!m ?
← Back to aarnikshasolutions.com : null}
);
return (
);
}
const hS = { margin: '0 0 8px', fontSize: '30px', lineHeight: 1.08, letterSpacing: '-.03em', fontWeight: 800, color: '#101B33' };
const pS = { margin: '0 0 22px', fontSize: '15px', lineHeight: 1.6, color: '#5B6577' };
function BackLink({ onClick }) {
return Back ;
}
Object.assign(window, { AuthScreen });