diff --git a/app/profile/page.tsx b/app/profile/page.tsx index 6d338c5..d22035b 100644 --- a/app/profile/page.tsx +++ b/app/profile/page.tsx @@ -8,20 +8,16 @@ import { StatsRow } from "@/components/profile/stats-row" import { ContributionList } from "@/components/profile/contribution-list" import { SavedGamesGrid } from "@/components/saved-games/saved-games-grid" import { Bookmark, Settings, Loader2, TrendingUp } from "lucide-react" -import { SettingsProfileTab } from "@/components/profile/settings-profile-tab" -import { SettingsSecurityTab } from "@/components/profile/settings-security-tab" -import { SettingsAccountsTab } from "@/components/profile/settings-accounts-tab" +import { SettingsContainer } from "@/components/profile/settings-container" import { motion } from "motion/react" import type { ContributionEntry } from "@/types/api" type Tab = "overview" | "saved" | "settings" -type SettingsTab = "profile" | "security" | "accounts" export default function ProfilePage() { const router = useRouter() const { data: session, isPending: isSessionLoading } = useSession() const [activeTab, setActiveTab] = useState("overview") - const [settingsSubTab, setSettingsSubTab] = useState("profile") const [profile, setProfile] = useState<{ id: string name: string @@ -173,56 +169,13 @@ export default function ProfilePage() { {activeTab === "saved" && } - {activeTab === "settings" && ( -
- {/* Settings sub-tabs */} -
- {[ - { - id: "profile" as SettingsTab, - label: "Profile", - }, - { - id: "security" as SettingsTab, - label: "Security", - }, - { - id: "accounts" as SettingsTab, - label: "Linked Accounts", - }, - ].map((subTab) => ( - - ))} -
- - {/* Settings sub-tab content */} - {settingsSubTab === "profile" && ( - - )} - {settingsSubTab === "security" && ( - - )} - {settingsSubTab === "accounts" && ( - - )} -
+ {activeTab === "settings" && profile && ( + )} diff --git a/components/profile/settings-container.tsx b/components/profile/settings-container.tsx new file mode 100644 index 0000000..8d8924a --- /dev/null +++ b/components/profile/settings-container.tsx @@ -0,0 +1,114 @@ +"use client" + +import { useState, useEffect, useRef } from "react" +import { User, Shield, Link as LinkIcon } from "lucide-react" +import { SettingsProfileTab } from "@/components/profile/settings-profile-tab" +import { SettingsSecurityTab } from "@/components/profile/settings-security-tab" +import { SettingsAccountsTab } from "@/components/profile/settings-accounts-tab" + +interface AuthMethods { + hasPassword: boolean + passkeyCount: number + oauthProviders: Array<{ providerId: string; id: string }> + totalAuthMethods: number +} + +type SettingsSubTab = "profile" | "security" | "accounts" + +const subTabs: { id: SettingsSubTab; label: string; icon: typeof User }[] = [ + { id: "profile", label: "Profile", icon: User }, + { id: "security", label: "Security", icon: Shield }, + { id: "accounts", label: "Linked Accounts", icon: LinkIcon }, +] + +interface SettingsContainerProps { + name: string + email: string + role: string | null + createdAt: string +} + +export function SettingsContainer({ name, email, role, createdAt }: SettingsContainerProps) { + const [activeSubTab, setActiveSubTab] = useState("profile") + const [authMethods, setAuthMethods] = useState(null) + const [isLoadingAuthMethods, setIsLoadingAuthMethods] = useState(true) + + const fetchRef = useRef(false) + useEffect(() => { + if (fetchRef.current) return + fetchRef.current = true + + let cancelled = false + fetch("/api/user/me/auth-methods", { credentials: "include" }) + .then(r => r.ok ? r.json() : null) + .then(data => { + if (cancelled) return + if (data) setAuthMethods(data) + setIsLoadingAuthMethods(false) + }) + .catch(() => { + setIsLoadingAuthMethods(false) + }) + + return () => { cancelled = true } + }, []) + + const refreshAuthMethods = async () => { + try { + const res = await fetch("/api/user/me/auth-methods", { credentials: "include" }) + if (res.ok) setAuthMethods(await res.json()) + } catch { + // silently fail + } + } + + return ( +
+ {/* Sidebar Navigation */} + + + {/* Content Area */} +
+ {activeSubTab === "profile" && ( + + )} + {activeSubTab === "security" && ( + + )} + {activeSubTab === "accounts" && ( + + )} +
+
+ ) +}