// auth-login.jsx — login screen (pilih nama + PIN)
const { useState: useSL, useEffect: useEL } = React;
function Login({ onLogin }) {
const [emps, setEmps] = useSL(null);
const [sel, setSel] = useSL(null);
const [pickerOpen, setPickerOpen] = useSL(false);
const [pin, setPin] = useSL('');
const [err, setErr] = useSL('');
const [busy, setBusy] = useSL(false);
const [q, setQ] = useSL('');
useEL(() => { MA.getEmployees().then(r => setEmps(r.ok ? r.employees : [])); }, []);
const submit = async (code) => {
if (!sel) { setErr('Pilih nama dulu'); return; }
setBusy(true); setErr('');
const r = await MA.login(sel.id, code);
setBusy(false);
if (r.ok) { MA.saveSession(r.user); onLogin(r.user); }
else { setErr(r.err || 'Login gagal'); setPin(''); }
};
const tapKey = (d) => {
if (busy) return;
setErr('');
if (d === 'del') { setPin(p => p.slice(0, -1)); return; }
setPin(p => {
const np = (p + d).slice(0, 4);
if (np.length === 4) setTimeout(() => submit(np), 120);
return np;
});
};
const list = (emps || []).filter(e => e.name.toLowerCase().includes(q.toLowerCase()) || e.jabatan.toLowerCase().includes(q.toLowerCase()));
return (
{/* hero */}
Absensi Karyawan
{MA.DEALER.branch}
{/* name field */}
Nama Karyawan
{/* PIN */}
Masukkan PIN
{[0, 1, 2, 3].map(i => (
i ? 'var(--accent)' : 'var(--surface-3)', border: pin.length > i ? 'none' : '2px solid var(--border-2)', transition: 'all .15s' }}>
))}
{busy ? 'Memeriksa…' : err}
{/* keypad */}
{['1','2','3','4','5','6','7','8','9'].map(d => (
))}
{MA.DEMO && (
Mode Demo · PIN karyawan 1234, pemilik 0000
)}
{/* name picker sheet */}
{pickerOpen && (
setPickerOpen(false)}>
e.stopPropagation()} style={{ maxHeight: '78%', display: 'flex', flexDirection: 'column' }}>
Pilih Nama
setQ(e.target.value)} placeholder="Cari nama…" style={{ border: 'none', outline: 'none', background: 'transparent', flex: 1, fontSize: 14, color: 'var(--text)', fontFamily: 'inherit' }} />
{emps === null &&
Memuat…
}
{list.map(e => (
))}
)}
);
}
const keyStyle = {
height: 58, borderRadius: 16, background: 'var(--surface)', border: '1px solid var(--border)',
boxShadow: 'var(--shadow-sm)', fontSize: 24, fontWeight: 700, color: 'var(--text)',
};
window.Login = Login;