Web: Kassenzettel-Trefferschwelle in den Einstellungen

Prozent-Feld fuer receipt_match_threshold (Default 45) analog zur Ablaufwarnung;
speichert ueber den generischen Settings-Endpunkt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-30 18:26:20 +02:00
parent 91adee5333
commit 9cc3e325bb

View File

@@ -10,11 +10,13 @@ import { DATE_FORMATS, formatDate } from "../units";
import { applyFavicon } from "../branding"; import { applyFavicon } from "../branding";
const EXPIRY_KEY = "expiry_warning_days"; const EXPIRY_KEY = "expiry_warning_days";
const RECEIPT_KEY = "receipt_match_threshold";
export default function Settings() { export default function Settings() {
const { reload } = useSettings(); const { reload } = useSettings();
const toast = useToast(); const toast = useToast();
const [days, setDays] = useState(""); const [days, setDays] = useState("");
const [threshold, setThreshold] = useState("");
const [dateFormat, setDateFormat] = useState("de"); const [dateFormat, setDateFormat] = useState("de");
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [busy, setBusy] = useState(false); const [busy, setBusy] = useState(false);
@@ -23,6 +25,7 @@ export default function Settings() {
try { try {
const settings = await api.listSettings(); const settings = await api.listSettings();
setDays(settings.find((s) => s.key === EXPIRY_KEY)?.value ?? "7"); setDays(settings.find((s) => s.key === EXPIRY_KEY)?.value ?? "7");
setThreshold(settings.find((s) => s.key === RECEIPT_KEY)?.value ?? "45");
setDateFormat(settings.find((s) => s.key === DATE_FORMAT_KEY)?.value ?? "de"); setDateFormat(settings.find((s) => s.key === DATE_FORMAT_KEY)?.value ?? "de");
} catch (err) { } catch (err) {
setError(err.message); setError(err.message);
@@ -36,6 +39,7 @@ export default function Settings() {
setError(null); setBusy(true); setError(null); setBusy(true);
try { try {
await api.setSetting(EXPIRY_KEY, String(parseInt(days, 10))); await api.setSetting(EXPIRY_KEY, String(parseInt(days, 10)));
await api.setSetting(RECEIPT_KEY, String(Math.max(0, Math.min(100, parseInt(threshold, 10) || 0))));
await api.setSetting(DATE_FORMAT_KEY, dateFormat); await api.setSetting(DATE_FORMAT_KEY, dateFormat);
await reload(); await reload();
toast("Gespeichert."); toast("Gespeichert.");
@@ -71,6 +75,20 @@ export default function Settings() {
bereits überschritten ist), erscheinen auf der Übersicht unter Bald ablaufend. bereits überschritten ist), erscheinen auf der Übersicht unter Bald ablaufend.
</p> </p>
<div className="card-head" style={{ marginTop: "var(--sp-5)" }}>
<Icon name="cart" /><h2>Kassenzettel-Scan</h2>
</div>
<label>
Trefferschwelle (%)
<input type="number" min="0" max="100" step="1" value={threshold}
onChange={(e) => setThreshold(e.target.value)} style={{ maxWidth: 160 }} />
</label>
<p className="muted small mt-0">
Beim Scannen eines Kassenzettels (iOS) werden je Zeile nur Artikel vorgeschlagen,
deren Übereinstimmung mindestens so hoch ist. Höher = strenger (weniger, dafür
sicherere Vorschläge), niedriger = mehr Vorschläge.
</p>
<div className="card-head" style={{ marginTop: "var(--sp-5)" }}> <div className="card-head" style={{ marginTop: "var(--sp-5)" }}>
<Icon name="settings" /><h2>Darstellung</h2> <Icon name="settings" /><h2>Darstellung</h2>
</div> </div>