"use client"; import { useEffect, useState } from "react"; import { ChevronDown, Plus } from "lucide-react"; import { useTranslation } from "react-i18next"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { DeleteAccountDialog } from "@/components/settings/delete-account-dialog"; import { CopyField, FieldLabel, SettingsCard, SettingsSection, ToggleRow, } from "@/components/settings/settings-parts"; import { authClient } from "@/lib/auth-client"; import { supportedLanguages } from "@/lib/i18n/config"; import { getSettings, saveSettings, type UserPreferences, } from "@/lib/settings"; import { notify } from "@/lib/toast"; // Keys into settings.profile.notif.* — each maps to a persisted preference. const patientNotifications = [ { titleKey: "newLab", descKey: "newLabDesc" }, { titleKey: "recordUpdated", descKey: "recordUpdatedDesc" }, { titleKey: "approvalRequested", descKey: "approvalRequestedDesc" }, { titleKey: "changeApproved", descKey: "changeApprovedDesc" }, { titleKey: "newMessage", descKey: "newMessageDesc" }, { titleKey: "visitScheduled", descKey: "visitScheduledDesc" }, ] as const; const accountNotifications = [ { titleKey: "pendingApprovals", descKey: "pendingApprovalsDesc" }, { titleKey: "recordsShared", descKey: "recordsSharedDesc" }, ] as const; // All notification toggles default to on; profile extras default to empty. const DEFAULT_PREFS: UserPreferences = { "notif.newLab": true, "notif.recordUpdated": true, "notif.approvalRequested": true, "notif.changeApproved": true, "notif.newMessage": true, "notif.visitScheduled": true, "notif.pendingApprovals": true, "notif.recordsShared": true, clinic: "", contactEmail: "", }; export function ProfilePanel() { const { t, i18n } = useTranslation(); const { data: session } = authClient.useSession(); const user = session?.user; // The active UI language — `i18n.changeLanguage` persists the choice to // localStorage (the detector's cache), so it survives reloads. const activeLang = i18n.resolvedLanguage ?? i18n.language; const [prefs, setPrefs] = useState(DEFAULT_PREFS); const [baseline, setBaseline] = useState(DEFAULT_PREFS); const [name, setName] = useState(""); const [baselineName, setBaselineName] = useState(""); const [saving, setSaving] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false); useEffect(() => { let cancelled = false; getSettings() .then((stored) => { if (cancelled) return; const merged = { ...DEFAULT_PREFS, ...stored }; setPrefs(merged); setBaseline(merged); }) .catch(() => { // Keep the defaults; the page still works and Save will retry. }); return () => { cancelled = true; }; }, []); // Seed the display name from the session once it loads. useEffect(() => { if (user?.name) { setName((prev) => prev || user.name); setBaselineName((prev) => prev || user.name); } }, [user?.name]); const setPref = (key: string, value: boolean | string) => setPrefs((prev) => ({ ...prev, [key]: value })); const dirty = name !== baselineName || JSON.stringify(prefs) !== JSON.stringify(baseline); const save = async () => { setSaving(true); try { const saved = await saveSettings(prefs); const trimmed = name.trim(); if (trimmed && trimmed !== baselineName) { const { error } = await authClient.updateUser({ name: trimmed }); if (error) throw new Error(error.message ?? "updateUser failed"); setName(trimmed); setBaselineName(trimmed); } const merged = { ...DEFAULT_PREFS, ...saved }; setPrefs(merged); setBaseline(merged); notify.success( t("settings.profile.savedTitle"), t("settings.profile.savedBody"), ); } catch { notify.error( t("settings.profile.saveFailedTitle"), t("settings.profile.saveFailedBody"), ); } finally { setSaving(false); } }; const initial = (name || user?.name || "?").trim().charAt(0).toUpperCase(); const username = (user as { username?: string | null } | undefined)?.username ?? null; return ( <>
{t("settings.profile.avatar")} {initial}
{t("settings.profile.displayName")} setName(event.target.value)} value={name} />
{t("settings.profile.specialty")}
{t("settings.profile.clinic")} setPref("clinic", event.target.value)} placeholder={t("settings.profile.clinicPlaceholder")} value={String(prefs.clinic ?? "")} />
{t("settings.profile.contactEmail")} setPref("contactEmail", event.target.value) } placeholder={t("settings.profile.contactEmailPlaceholder")} value={String(prefs.contactEmail ?? "")} />
{t("settings.profile.professionalLinks")}

{t("settings.profile.professionalLinksHint")}

{t("settings.profile.language.label")}
{supportedLanguages.map((lng) => ( ))}
{patientNotifications.map((item) => ( setPref(`notif.${item.titleKey}`, checked) } title={t(`settings.profile.notif.${item.titleKey}`)} /> ))}
{accountNotifications.map((item) => ( setPref(`notif.${item.titleKey}`, checked) } title={t(`settings.profile.notif.${item.titleKey}`)} /> ))}
{/* Future features — intentionally not wired to persistence yet. */}

{t("settings.profile.deleteAccount")}

{t("settings.profile.deleteAccountDescription")}

{dirty ? (

{t("settings.profile.unsavedChanges")}

) : null} ); }