"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/components/AuthProvider";
import { c2api } from "@/lib/c2api";
interface LinkStatus {
linked: boolean;
discord_user_id?: string;
discord_username?: string;
linked_at?: string;
}
function fmtDate(iso: string) {
return new Date(iso).toLocaleDateString("en-US", {
month: "short", day: "numeric", year: "numeric",
});
}
function Initials({ name }: { name: string }) {
const parts = name.trim().split(/\s+/);
const letters = parts.length >= 2
? parts[0][0] + parts[parts.length - 1][0]
: name.slice(0, 2);
return (
{letters.toUpperCase()}
);
}
export default function ProfilePage() {
const { user, isAdmin, role, signOut } = useAuth();
const router = useRouter();
const [linkStatus, setLinkStatus] = useState(null);
const [linkLoading, setLinkLoading] = useState(true);
const [code, setCode] = useState(null);
const [codeExpiry, setCodeExpiry] = useState(null);
const [generating, setGenerating] = useState(false);
const [unlinking, setUnlinking] = useState(false);
useEffect(() => {
if (!user) return;
c2api.getLinkStatus()
.then(setLinkStatus)
.catch(() => setLinkStatus({ linked: false }))
.finally(() => setLinkLoading(false));
}, [user]);
async function generateCode() {
setGenerating(true);
try {
const res = await c2api.generateLinkCode();
if (res.already_linked) {
setLinkStatus((prev) => prev ? { ...prev, linked: true } : prev);
} else if (res.code) {
setCode(res.code);
setCodeExpiry(res.expires_minutes ?? 15);
}
} finally {
setGenerating(false);
}
}
async function unlink() {
setUnlinking(true);
try {
await c2api.unlinkDiscord();
setLinkStatus({ linked: false });
setCode(null);
} finally {
setUnlinking(false);
}
}
async function handleSignOut() {
await signOut();
router.push("/login");
}
if (!user) return null;
const displayName = user.displayName || user.email || "Account";
return (
{/* Header */}
{displayName}
{user.displayName && user.email && (
{user.email}
)}
{role && (
{role === "admin" ? "Admin" : role === "operator" ? "Operator" : "Viewer"}
)}
{/* Firebase account */}
Account
{user.metadata.creationTime && (
)}
{user.metadata.lastSignInTime && (
)}
{/* Discord linking */}
Discord
{linkLoading ? (
Loading…
) : linkStatus?.linked ? (
{linkStatus.discord_username && (
)}
{linkStatus.discord_user_id && (
)}
{linkStatus.linked_at && (
)}
) : (
Link your Discord account to access private trips from both the web and Discord.
{code ? (
{code}
Run /link {code} in Discord. Code expires in {codeExpiry} minutes.
) : (
)}
)}
{/* Sign out */}
Sign out of this device
);
}
function Row({ label, value, mono = false, truncate = false }: {
label: string;
value: string;
mono?: boolean;
truncate?: boolean;
}) {
return (
{label}
{value}
);
}