import { useEffect, useState } from "react"; import { Copy, Dice5, RefreshCw } from "lucide-react"; import Button from "./Button"; import Dialog from "./Dialog"; import DismissibleAlert from "./DismissibleAlert"; import FormField from "./FormField"; import IconButton from "./IconButton"; import ToggleSwitch from "./ToggleSwitch"; import { DEFAULT_PASSWORD_GENERATOR_OPTIONS, generateSecurePassword, PasswordGeneratorError, type PasswordGeneratorErrorCode, type PasswordGeneratorOptions } from "./passwordGenerator"; import { usePlatformLanguage } from "../i18n/LanguageContext"; import type { PlatformInterfaceIdentityProps } from "../types"; const GENERATION_ERROR_LABELS: Record = { "invalid-length": "i18n:govoplan-core.password_length_must_be_between_12_and_128_character.4d147c07", "no-character-set": "i18n:govoplan-core.select_at_least_one_character_set.6150a9c2", "length-too-short": "i18n:govoplan-core.password_length_is_too_short_for_the_selected_charact.1d7845f1", "invalid-random-range": "i18n:govoplan-core.password_generation_could_not_use_the_selected_setti.c2f0da38", "secure-random-unavailable": "i18n:govoplan-core.secure_browser_password_generation_is_unavailable.55275f10" }; export type PasswordGeneratorDialogProps = PlatformInterfaceIdentityProps & { open: boolean; initialOptions?: Partial; onUse: (password: string) => void; onClose: () => void; }; export default function PasswordGeneratorDialog({ open, initialOptions, helpContextId, helpModuleId, helpTopicId, onUse, onClose }: PasswordGeneratorDialogProps) { const { translateText } = usePlatformLanguage(); const [options, setOptions] = useState({ ...DEFAULT_PASSWORD_GENERATOR_OPTIONS, ...initialOptions }); const [candidate, setCandidate] = useState(""); const [error, setError] = useState(""); const [copied, setCopied] = useState(false); const generate = () => { try { setCandidate(generateSecurePassword(options)); setError(""); setCopied(false); } catch (generationError) { setCandidate(""); setError(translateText( generationError instanceof PasswordGeneratorError ? GENERATION_ERROR_LABELS[generationError.code] : "i18n:govoplan-core.password_generation_failed.5a40a004" )); } }; useEffect(() => { if (!open) return; setOptions({ ...DEFAULT_PASSWORD_GENERATOR_OPTIONS, ...initialOptions }); }, [initialOptions, open]); useEffect(() => { if (open) generate(); // Generation must react to the exact selected candidate policy. // eslint-disable-next-line react-hooks/exhaustive-deps }, [open, options]); const setOption = ( key: K, value: PasswordGeneratorOptions[K] ) => setOptions((current) => ({ ...current, [key]: value })); const copy = async () => { if (!candidate || typeof navigator === "undefined" || !navigator.clipboard?.writeText) return; try { await navigator.clipboard.writeText(candidate); setCopied(true); } catch { setCopied(false); setError(translateText("i18n:govoplan-core.the_generated_password_could_not_be_copied_select_it.569e025e")); } }; return ( )} > {error ? {error} : null}
setOption("length", Number(event.target.value))} />
setOption("lowercase", checked)} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} /> setOption("uppercase", checked)} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} /> setOption("digits", checked)} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} /> setOption("symbols", checked)} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} />
} onClick={() => void copy()} disabled={!candidate || typeof navigator === "undefined" || !navigator.clipboard?.writeText} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} /> } onClick={generate} helpContextId={helpContextId} helpModuleId={helpModuleId} helpTopicId={helpTopicId} />

i18n:govoplan-core.the_current_field_is_not_changed_until_you_choose_use_pass.447608e7

); }