import { useEffect, useState, type ReactNode } from "react";
import { authApi } from "../api/auth";
import { tokens } from "../api/client";
import { settingsApi, type SettingsPatch } from "../api/endpoints";
import type { Settings as SettingsData } from "../api/types";
import { MemoryNotes } from "../components/MemoryNotes";
import { ConfirmButton, errorMessage, formatDate, Loading, PageHeader } from "../components/ui";
import { useAuth } from "../hooks/useAuth";
import { useUpgrade } from "../hooks/useUpgrade";
import { setSoundsEnabled, soundsEnabled } from "../lib/sound";
function Meter({ label, used, limit, unit }: { label: string; used: number; limit: number; unit: string }) {
const unlimited = limit < 0;
const pct = unlimited ? 0 : Math.min(100, Math.round((used / Math.max(limit, 1)) * 100));
return (
{label}
{used} / {unlimited ? "unlimited" : limit} {unit}
);
}
function Section({ title, saved, children }: { title: string; saved?: boolean; children: ReactNode }) {
return (
{title}
{saved && Saved }
{children}
);
}
export default function Settings() {
const [s, setS] = useState(null);
const [name, setName] = useState("");
const [workspace, setWorkspace] = useState("");
const [saved, setSaved] = useState(null);
const [error, setError] = useState(null);
const [sounds, setSounds] = useState(soundsEnabled);
const { logout, signingOut } = useAuth();
const upgrade = useUpgrade();
const hydrate = (d: SettingsData) => {
setS(d);
setName(d.user.name ?? "");
setWorkspace(d.workspace.name);
};
useEffect(() => {
settingsApi.get().then(hydrate, () => setError("Could not load settings."));
}, []);
const save = async (patch: SettingsPatch, what: string) => {
setError(null);
try {
hydrate(await settingsApi.update(patch));
setSaved(what);
setTimeout(() => setSaved(null), 1500);
} catch (e) {
setError(errorMessage(e));
}
};
if (!s) return error ? {error}
: ;
const u = s.usage;
// Fields save on their own when the writer leaves them, so there are no Save buttons.
const saveProfile = () => {
if (name !== (s.user.name ?? "") || workspace !== s.workspace.name) void save({ name, workspace_name: workspace }, "profile");
};
return (
{error &&
{error}
}
{s.plan.name} plan
{u.limits.audio_overviews >= 0
?
: }
Refills on the 1st of every month.
{u.videos_resets_at && ` Videos refill on ${formatDate(u.videos_resets_at)}.`}
{s.billing_enabled && (
{upgrade.status?.can_upgrade && (
upgrade.openUpgrade()}>
Upgrade now
)}
{upgrade.status?.has_billing_account && (
upgrade.manageBilling()}>
Manage billing
)}
)}
{upgrade.error && !upgrade.modal && {upgrade.error}
}
Sign out everywhere
{
await authApi.deleteAccount();
tokens.clear();
window.location.href = "/";
}}
>
Delete account
);
}