Files
spsays-training/app/(app)/settings/page.tsx
T
2026-07-14 18:26:20 +05:30

121 lines
3.6 KiB
TypeScript

"use client";
/**
* /settings — the settings hub.
*
* A plain entry menu: one tappable row per setting type, each routing to its
* own dedicated page. This keeps the top level uncluttered — the actual
* controls live on the sub-pages (`/settings/reading`, `/settings/notifications`,
* `/settings/account`, `/settings/legal`) plus the existing
* `/settings/profile` editor. The "Offline" row is a direct shortcut to the
* device-local download library at `/downloads` (no intermediate page).
*
* Sign out is an action rather than a destination, so it sits on its own
* below the menu.
*/
import { useState } from "react";
import { useRouter } from "next/navigation";
import {
Bell,
BookOpenText,
DownloadCloud,
LogOut,
MessageSquareText,
Scale,
ShieldCheck,
UserRound,
} from "lucide-react";
import { useAuth } from "@/components/auth/auth-provider";
import {
NavList,
NavRow,
SettingsShell,
} from "@/components/settings/settings-ui";
export default function SettingsPage() {
return (
<SettingsShell backHref="/u/me" backLabel="Back to profile" title="Settings">
<NavList>
<NavRow
href="/settings/profile"
icon={<UserRound className="size-5" />}
label="Profile"
description="Name, handle, bio, and avatar."
/>
<NavRow
href="/settings/reading"
icon={<BookOpenText className="size-5" />}
label="Reading preferences"
description="Theme, palette, font, and size — synced across devices."
/>
<NavRow
href="/settings/notifications"
icon={<Bell className="size-5" />}
label="Notifications"
description="What reaches you, and on which channels."
/>
<NavRow
href="/downloads"
icon={<DownloadCloud className="size-5" />}
label="Offline downloads"
description="Manage pages and lectures saved to this device."
/>
<NavRow
href="/settings/account"
icon={<ShieldCheck className="size-5" />}
label="Account & security"
description="Connected accounts, email, and password."
/>
<NavRow
href="/settings/feedbacks"
icon={<MessageSquareText className="size-5" />}
label="My feedback"
description="Your submissions, their status, and our responses."
/>
<NavRow
href="/settings/legal"
icon={<Scale className="size-5" />}
label="Legal"
description="Terms, privacy, and data deletion."
/>
</NavList>
<SignOut />
</SettingsShell>
);
}
function SignOut() {
const { logOut } = useAuth();
const router = useRouter();
const [busy, setBusy] = useState(false);
async function onSignOut() {
setBusy(true);
try {
await logOut();
router.push("/");
router.refresh();
} catch {
// Logout errors are silent — the cookie is cleared on the server
// either way and the next protected request will redirect anyway.
setBusy(false);
}
}
return (
<button
type="button"
onClick={onSignOut}
disabled={busy}
className="w-full flex items-center justify-between gap-4 rounded-xl border border-border bg-card px-4 py-3.5 group transition-colors hover:bg-muted/50 disabled:opacity-60"
>
<span className="text-sm font-medium text-foreground group-hover:text-destructive transition-colors">
{busy ? "Signing out…" : "Sign out from this device"}
</span>
<LogOut className="size-4 shrink-0 text-muted-foreground group-hover:text-destructive transition-colors" />
</button>
);
}