diff --git a/src/app/(dashboard)/dashboard/settings/components/AutoDisableCard.tsx b/src/app/(dashboard)/dashboard/settings/components/AutoDisableCard.tsx new file mode 100644 index 0000000000..3d3d0c3387 --- /dev/null +++ b/src/app/(dashboard)/dashboard/settings/components/AutoDisableCard.tsx @@ -0,0 +1,132 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { Card, Button, Input } from "@/shared/components"; +import { useTranslations } from "next-intl"; +import { useNotificationStore } from "@/store/notificationStore"; + +export default function AutoDisableCard() { + const [data, setData] = useState({ enabled: false, threshold: 3 }); + const [draft, setDraft] = useState({ enabled: false, threshold: 3 }); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [editMode, setEditMode] = useState(false); + const t = useTranslations("settings"); + const tc = useTranslations("common"); + const notify = useNotificationStore(); + + useEffect(() => { + fetch("/api/settings/auto-disable-accounts") + .then((res) => res.json()) + .then((json) => { + setData(json); + setDraft(json); + setLoading(false); + }) + .catch(() => setLoading(false)); + }, []); + + const handleSave = async () => { + setSaving(true); + try { + const res = await fetch("/api/settings/auto-disable-accounts", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(draft), + }); + if (!res.ok) throw new Error("Failed to save auto-disable config"); + const savedData = await res.json(); + setData(savedData); + setEditMode(false); + notify.success(t("savedSuccessfully") || "Saved successfully"); + } catch (err) { + notify.error(err instanceof Error ? err.message : "Error saving"); + } finally { + setSaving(false); + } + }; + + if (loading) return null; + + return ( + +
+
+
+ +

{t("autoDisableBannedAccounts")}

+
+ {editMode ? ( +
+ + +
+ ) : ( + + )} +
+ +

{t("autoDisableDescription")}

+ +
+
+ +
+ +
+

+ {t("autoDisableThreshold")} +

+ {editMode ? ( + + setDraft((prev) => ({ ...prev, threshold: parseInt(e.target.value) || 1 })) + } + disabled={!draft.enabled} + /> + ) : ( + + {data.threshold} {t("failures", { count: data.threshold })} + + )} +

{t("autoDisableThresholdDesc")}

+
+
+
+
+ ); +} diff --git a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx index 4ee1bc349f..6e127dac38 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx @@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from "react"; import { Card, Button } from "@/shared/components"; import { useNotificationStore } from "@/store/notificationStore"; import { useLocale, useTranslations } from "next-intl"; +import AutoDisableCard from "./AutoDisableCard"; // ─── State colors and labels ────────────────────────────────────────────── const STATE_STYLES = { @@ -656,6 +657,8 @@ export default function ResilienceTab() { onSave={handleSaveProfiles} saving={saving} /> + {/* 1.5 Auto Disable Banned Accounts */} + {/* 2. Rate Limiting (editable defaults + active limiters) */}