import { useState, useRef, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { X } from "lucide-react"; import { verifyPin } from "../../services/profileService"; interface Props { profileName: string; storedHash: string; onSuccess: (rehashed?: string | null) => void; onCancel: () => void; } export default function PinDialog({ profileName, storedHash, onSuccess, onCancel }: Props) { const { t } = useTranslation(); const [digits, setDigits] = useState(["", "", "", "", "", ""]); const [error, setError] = useState(false); const [checking, setChecking] = useState(false); const inputRefs = useRef<(HTMLInputElement | null)[]>([]); useEffect(() => { inputRefs.current[0]?.focus(); }, []); const handleInput = async (index: number, value: string) => { if (!/^\d?$/.test(value)) return; const newDigits = [...digits]; newDigits[index] = value; setDigits(newDigits); setError(false); if (value && index < 5) { inputRefs.current[index + 1]?.focus(); } // Check PIN when we have at least 4 digits filled const pin = newDigits.join(""); if (pin.length >= 4 && !newDigits.slice(0, 4).includes("")) { // If all filled digits are present and we're at the last one typed const filledCount = newDigits.filter((d) => d !== "").length; if (value && filledCount === index + 1) { setChecking(true); try { const result = await verifyPin(pin.replace(/\s/g, ""), storedHash); if (result.valid) { onSuccess(result.rehashed); } else if (filledCount >= 6 || (filledCount >= 4 && index === filledCount - 1 && !value)) { setError(true); setDigits(["", "", "", "", "", ""]); inputRefs.current[0]?.focus(); } } finally { setChecking(false); } } } }; const handleKeyDown = (index: number, e: React.KeyboardEvent) => { if (e.key === "Backspace" && !digits[index] && index > 0) { inputRefs.current[index - 1]?.focus(); } if (e.key === "Escape") { onCancel(); } if (e.key === "Enter") { const pin = digits.join(""); if (pin.length >= 4) { setChecking(true); verifyPin(pin, storedHash).then((result) => { setChecking(false); if (result.valid) { onSuccess(result.rehashed); } else { setError(true); setDigits(["", "", "", "", "", ""]); inputRefs.current[0]?.focus(); } }); } } }; return (

{profileName}

{t("profile.enterPin")}

{digits.map((digit, i) => ( { inputRefs.current[i] = el; }} type="password" inputMode="numeric" maxLength={1} value={digit} onChange={(e) => handleInput(i, e.target.value)} onKeyDown={(e) => handleKeyDown(i, e)} disabled={checking} className={`w-10 h-12 text-center text-lg font-bold rounded-lg border-2 bg-[var(--background)] text-[var(--foreground)] ${ error ? "border-[var(--negative)]" : "border-[var(--border)] focus:border-[var(--primary)]" } outline-none transition-colors`} /> ))}
{error && (

{t("profile.wrongPin")}

)}
); }