"use client"; import { useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Loader2, Mail } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { SettingsCard } from "@/components/settings/settings-card"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { TestConnectionButton } from "@/components/settings/test-connection-button"; import { useTranslations } from "@/lib/i18n/context"; import { queryKeys } from "@/lib/query-keys"; import { apiFetchRaw, apiGet } from "@/lib/api/api-fetch"; interface EmailSettings { enabled: boolean; recipient: string; /** Operator-side: false when SMTP_* env is unset (card hides itself). */ smtpConfigured: boolean; } export function EmailCard({ isAuthenticated }: { isAuthenticated: boolean }) { const { t } = useTranslations(); const queryClient = useQueryClient(); const [recipient, setRecipient] = useState(""); const [saveMsg, setSaveMsg] = useState(null); const [saveMsgType, setSaveMsgType] = useState<"success" | "error" | null>( null, ); const { data: settings } = useQuery({ queryKey: queryKeys.settingsEmail(), queryFn: async () => { return apiGet("/api/settings/email"); }, enabled: isAuthenticated, }); // React-recommended sync-from-server pattern (no setState-in-effect). const settingsKey = settings ? settings.recipient : null; const [seededKey, setSeededKey] = useState(null); if (settingsKey !== null && settingsKey !== seededKey) { setSeededKey(settingsKey); setRecipient(settings!.recipient); } const save = useMutation({ mutationFn: async (enabled: boolean) => { const res = await apiFetchRaw("/api/settings/email", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ recipient, enabled }), }); if (!res.ok) { const json = await res.json(); throw new Error(json.error || t("common.error")); } }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.settingsEmail() }); setSaveMsg(t("settings.saved")); setSaveMsgType("success"); }, onError: (err: Error) => { setSaveMsg(err.message); setSaveMsgType("error"); }, }); // Operator hasn't configured SMTP — no transport, so no card. The dispatcher // skips the channel too; surfacing an unusable toggle would only confuse. if (settings && !settings.smtpConfigured) return null; return (
save.mutate(checked)} disabled={save.isPending} />
{ e.preventDefault(); save.mutate(settings?.enabled ?? false); }} className="space-y-4" >
setRecipient(e.target.value)} />
{saveMsg && (

{saveMsg}

)}
); }