import { ThemeControl } from "./ThemeProvider"; import { ReminderSettings } from "./ReminderSettings"; import { useId, useRef, useState } from "react"; import type { PublicUser } from "../shared/user"; import { habitRequest } from "../lib/dashboard"; import { Button, ButtonLink } from "./design-system/primitives"; import { Download, Trash2 } from "lucide-react"; import { FormMessage, SettingRow, WorkspacePanel } from "./design-system/WorkspacePanel"; import { Field } from "./design-system/Field"; export function AccountSettings({ user, onChanged, onClose }: { user: PublicUser; onChanged: () => void; onClose: () => void }) { const [timezone, setTimezone] = useState(user.timezone); const [confirmation, setConfirmation] = useState(""); const [deleting, setDeleting] = useState(false); const [busy, setBusy] = useState(false); const [reminderBusy, setReminderBusy] = useState(false); const saving = useRef(false); const [error, setError] = useState(""); const listId = useId(); async function run(action: () => Promise) { if (saving.current || reminderBusy) return; saving.current = true; setBusy(true); setError(""); try { await action(); onChanged(); } catch (error) { setError(error instanceof Error ? error.message : "Could not save. Try again."); } finally { saving.current = false; setBusy(false); } } return Sets day boundaries. Earlier deadlines stay unchanged.

}>
{ event.preventDefault(); void run(() => habitRequest("/me", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ timezone }) })); }}> {id => setTimezone(event.target.value)} />} {["UTC", ...Intl.supportedValuesOf("timeZone")].map(zone =>
Download your profile, habits, and history.

}>
JSON file
Permanently remove your account and habit history, and sign out every device.

}> {!deleting ?
:
{ event.preventDefault(); void run(() => habitRequest("/account", { method: "DELETE", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ confirmation }) })); }}>

This cannot be undone.

Download an export first if you want a copy. Images already posted to Discord remain there; server backups expire under the operator’s retention policy.

{id => setConfirmation(event.target.value)} />}
}
{error}
; }