(() => { const { Button, Input, Field, Card, Checkbox, Icon, IconButton } = window.TaskFlowDesignSystem_dd53c2; /* Kredensial diperiksa terhadap akun yang tersimpan (localStorage sekarang, API CI3 nanti). Di produksi: POST auth/login → password_hash() di server → cookie session httpOnly. */ const MAX_TRY = 5; const LOCK_SEC = 60; function LoginScreen({ onLogin }) { const [email, setEmail] = React.useState(""); const [pass, setPass] = React.useState(""); const [reveal, setReveal] = React.useState(false); const [err, setErr] = React.useState(""); const [tries, setTries] = React.useState(0); const [lock, setLock] = React.useState(0); const bp = useBreakpoint(); const compact = bp !== "desktop"; // Lockout mundur otomatis — menahan percobaan menebak password berulang. React.useEffect(() => { if (!lock) return; const t = setInterval(() => setLock((s) => (s <= 1 ? 0 : s - 1)), 1000); return () => clearInterval(t); }, [lock]); const [busy, setBusy] = React.useState(false); const submit = () => { if (lock || busy) return; if (!email.trim() || !pass) return setErr("Email dan password wajib diisi."); // Server aktif: akun diperiksa di server sehingga bisa dipakai dari perangkat mana pun. if (window.TMSNet && TMSNet.online) { setBusy(true); setErr(""); TMSNet.login(email.trim(), pass).then((acc) => { setBusy(false); setPass(""); setTries(0); onLogin({ id: acc.id, access: acc.access || "user", mustChange: !!acc.mustChange }); }).catch((e) => { setBusy(false); setPass(""); setErr(e.message || "Tidak bisa menghubungi server."); }); return; } const acc = findAccount(email); if (!acc || acc.pass !== pass) { const n = tries + 1; setTries(n); setPass(""); if (n >= MAX_TRY) { setLock(LOCK_SEC); setTries(0); setErr("Terlalu banyak percobaan. Login dikunci sementara."); } else setErr(`Email atau password salah. Sisa percobaan: ${MAX_TRY - n}.`); return; } if (acc.active === false) { setPass(""); return setErr("Akun ini dinonaktifkan. Hubungi Direktur."); } setPass(""); setErr(""); setTries(0); onLogin({ id: acc.id, access: acc.access || "user", mustChange: !!acc.mustChange }); }; return (
“Pelayanan medis yang hebat selalu ditopang oleh manajemen yang kuat. Kehadiran Anda hari ini membuat segalanya menjadi jauh lebih baik.”
Silahkan sign in untuk melihat task anda