210 lines
6.5 KiB
TypeScript
210 lines
6.5 KiB
TypeScript
// app/(account)/account/page.tsx
|
||
"use client";
|
||
|
||
import { useAuth } from "@/context/AuthContext";
|
||
|
||
function StatChip({
|
||
label,
|
||
value,
|
||
}: {
|
||
label: string;
|
||
value: React.ReactNode;
|
||
}) {
|
||
return (
|
||
<div className="rounded-lg border border-white/10 bg-white/5 px-3 py-2">
|
||
<div className="text-[11px] uppercase tracking-[0.18em] text-white/50">
|
||
{label}
|
||
</div>
|
||
<div className="text-sm font-semibold text-white/90">{value}</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function Card({
|
||
title,
|
||
description,
|
||
children,
|
||
badge,
|
||
}: {
|
||
title: string;
|
||
description?: string;
|
||
children: React.ReactNode;
|
||
badge?: React.ReactNode;
|
||
}) {
|
||
return (
|
||
<section className="rounded-2xl border border-white/10 bg-white/5 p-5">
|
||
<div className="flex items-start justify-between gap-4">
|
||
<div>
|
||
<h3 className="text-sm font-semibold text-white/90">{title}</h3>
|
||
{description ? (
|
||
<p className="mt-1 text-sm text-white/60">{description}</p>
|
||
) : null}
|
||
</div>
|
||
{badge ? <div className="shrink-0">{badge}</div> : null}
|
||
</div>
|
||
|
||
<div className="mt-4">{children}</div>
|
||
</section>
|
||
);
|
||
}
|
||
|
||
function Row({ label, value }: { label: string; value: React.ReactNode }) {
|
||
return (
|
||
<div className="flex items-center justify-between gap-4 py-2">
|
||
<div className="text-sm text-white/60">{label}</div>
|
||
<div className="text-sm font-medium text-white/90">{value}</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default function AccountPage() {
|
||
const { user, loading } = useAuth();
|
||
|
||
if (loading) return <div className="text-sm text-white/60">Loading…</div>;
|
||
|
||
if (!user) {
|
||
return (
|
||
<div className="rounded-2xl border border-white/10 bg-white/5 p-6">
|
||
<h2 className="text-base font-semibold text-white/90">
|
||
You’re not logged in
|
||
</h2>
|
||
<p className="mt-2 text-sm text-white/60">
|
||
Please log in to view your account.
|
||
</p>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const planLabel = user.role === "ADMIN" ? "Admin" : "Beta Access";
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* Quick stats (lightweight “premium” feel) */}
|
||
{/* <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
||
<StatChip label="Email" value={user.email} />
|
||
<StatChip label="Display Name" value={user.displayName || "—"} />
|
||
<StatChip label="Role" value={user.role} />
|
||
<StatChip label="Plan" value={planLabel} />
|
||
</div> */}
|
||
|
||
<div id="profile">
|
||
<Card
|
||
title="Profile"
|
||
description="Basic account info."
|
||
badge={
|
||
<span className="rounded-full border border-white/10 bg-white/5 px-2 py-1 text-[11px] text-white/60">
|
||
Read-only (for now)
|
||
</span>
|
||
}
|
||
>
|
||
<div className="divide-y divide-white/10">
|
||
<Row label="Email" value={user.email} />
|
||
<Row label="Display name" value={user.displayName || "—"} />
|
||
<Row label="Role" value={user.role} />
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
|
||
<div id="preferences">
|
||
<Card
|
||
title="Preferences"
|
||
description="Placeholders until we wire the backend."
|
||
badge={
|
||
<span className="rounded-full border border-white/10 bg-white/5 px-2 py-1 text-[11px] text-white/60">
|
||
Coming soon
|
||
</span>
|
||
}
|
||
>
|
||
<div className="space-y-3">
|
||
<label className="flex items-center justify-between gap-4 rounded-xl border border-white/10 bg-white/5 p-3">
|
||
<div>
|
||
<div className="text-sm font-medium text-white/90">
|
||
Default new builds to private
|
||
</div>
|
||
<div className="text-sm text-white/60">
|
||
Keeps builds off the public feed until you publish.
|
||
</div>
|
||
</div>
|
||
<input
|
||
type="checkbox"
|
||
disabled
|
||
className="h-4 w-4 accent-orange-400"
|
||
/>
|
||
</label>
|
||
|
||
<label className="flex items-center justify-between gap-4 rounded-xl border border-white/10 bg-white/5 p-3">
|
||
<div>
|
||
<div className="text-sm font-medium text-white/90">
|
||
Weekly digest
|
||
</div>
|
||
<div className="text-sm text-white/60">
|
||
Price drops, new parts, and updates.
|
||
</div>
|
||
</div>
|
||
<input
|
||
type="checkbox"
|
||
disabled
|
||
className="h-4 w-4 accent-orange-400"
|
||
/>
|
||
</label>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
|
||
<div id="security">
|
||
<Card
|
||
title="Security"
|
||
description="Sessions, password change, and 2FA will live here."
|
||
badge={
|
||
<span className="rounded-full border border-white/10 bg-white/5 px-2 py-1 text-[11px] text-white/60">
|
||
Coming soon
|
||
</span>
|
||
}
|
||
>
|
||
<div className="space-y-3">
|
||
<div className="rounded-xl border border-white/10 bg-white/5 p-3">
|
||
<div className="text-sm font-medium text-white/90">2FA</div>
|
||
<div className="text-sm text-white/60">
|
||
Not enabled yet (on the roadmap).
|
||
</div>
|
||
</div>
|
||
|
||
<div className="rounded-xl border border-white/10 bg-white/5 p-3">
|
||
<div className="text-sm font-medium text-white/90">
|
||
Active sessions
|
||
</div>
|
||
<div className="text-sm text-white/60">
|
||
We’ll show devices + allow logout everywhere.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
|
||
<div id="danger">
|
||
<Card
|
||
title="Danger Zone"
|
||
description="Destructive actions. Handle with care."
|
||
>
|
||
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||
<div>
|
||
<div className="text-sm font-medium text-white/90">
|
||
Delete account
|
||
</div>
|
||
<div className="text-sm text-white/60">
|
||
Removes your account and builds. (We’ll add this flow later.)
|
||
</div>
|
||
</div>
|
||
<button
|
||
type="button"
|
||
disabled
|
||
className="inline-flex items-center justify-center rounded-lg border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-red-200/90 opacity-60"
|
||
>
|
||
Delete (coming soon)
|
||
</button>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |