commits
tags
import { useEffect, useRef, type FormEvent } from "react";
import type { Schema } from "../lib/schema";
import { fieldLabel } from "../lib/schema";
import type { Lang, T } from "../lib/i18n";
interface Props {
open: boolean;
schema: Schema;
lang: Lang;
t: T;
settings: Record<string, unknown>;
onClose: () => void;
onSave: (settings: Record<string, unknown>) => void;
}
export function SettingsDialog({ open, schema, lang, t, settings, onClose, onSave }: Props) {
const ref = useRef<HTMLDialogElement>(null);
useEffect(() => {
const d = ref.current;
if (!d) return;
if (open && !d.open) d.showModal();
if (!open && d.open) d.close();
}, [open]);
function save(e: FormEvent) {
e.preventDefault();
const form = e.currentTarget as HTMLFormElement;
const next: Record<string, unknown> = {};
for (const s of schema.settings) {
const el = form.elements.namedItem(s.key) as HTMLInputElement | null;
if (!el) continue;
if (s.kind === "bool") next[s.key] = el.checked;
else if (s.kind === "number") next[s.key] = Number(el.value) || Number(s.default) || 0;
else next[s.key] = el.value || String(s.default);
}
onSave(next);
}
return (
<dialog ref={ref} onClose={onClose}>
<form onSubmit={save} method="dialog">
<h2>{t("settings")}</h2>
<p className="hint">{t("settings_hint")}</p>
<div className="fields">
{schema.settings.map((s) => (
<label className={"field" + (s.kind === "bool" ? " field-bool" : "")} key={s.key}>
<span>{fieldLabel(s, lang)}</span>
{s.kind === "bool" ? (
<input type="checkbox" name={s.key} defaultChecked={settings[s.key] === true} />
) : (
<input
type={s.kind === "number" ? "number" : "text"}
name={s.key}
defaultValue={String(settings[s.key] ?? s.default)}
/>
)}
</label>
))}
</div>
<div className="dialog-actions">
<button type="button" className="secondary" onClick={onClose}>
{t("cancel")}
</button>
<button type="submit">{t("save")}</button>
</div>
</form>
</dialog>
);
}