refactor: Remove AuthStateSync component and update layout

This commit is contained in:
wood chen 2025-02-22 00:49:22 +08:00
parent a2964a177b
commit aed648fed5
5 changed files with 219 additions and 24 deletions

View File

@ -18,12 +18,12 @@ import {
TypographyLead,
TypographyMuted,
} from "@/components/ui/typography";
import { NavBar } from "@/components/layout/nav-bar";
import { Header } from "@/components/layout/header";
export default function HomePage() {
return (
<div className="flex min-h-screen flex-col">
<NavBar />
<Header />
<main className="flex-1">
<Section className="pb-0">
<Container>

View File

@ -1,7 +1,6 @@
import { redirect } from "next/navigation";
import { getCurrentUser } from "@/lib/session";
import { AuthStateSync } from "@/components/auth/auth-state-sync";
export default async function AuthLayout({
children,
@ -17,7 +16,6 @@ export default async function AuthLayout({
return (
<>
<AuthStateSync />
<div className="min-h-screen">
<div className="flex h-screen w-screen flex-col items-center justify-center">
{children}

View File

@ -1,20 +0,0 @@
"use client";
import { useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
export function AuthStateSync() {
const { data: session, status, update } = useSession();
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
// 当状态从"loading"变为"authenticated"时,强制刷新路由
if (status === "authenticated" && session?.user) {
router.refresh();
}
}, [status, session]);
return null;
}

View File

@ -0,0 +1,191 @@
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { ChevronDown, User } from "lucide-react";
import { signOut } from "next-auth/react";
import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { ThemeToggle } from "../theme-toggle";
interface HeaderClientProps {
initialUser: any;
}
export function HeaderClient({ initialUser }: HeaderClientProps) {
const [user, setUser] = useState(initialUser);
const router = useRouter();
const pathname = usePathname();
const handleSignOut = async () => {
await signOut({ redirect: false });
setUser(null);
router.refresh();
router.push("/");
};
const renderNavLinks = () => {
if (!user) return null;
return (
<div className="ml-8 flex items-center space-x-1">
<Link
href="/dashboard"
className={cn(
"rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
pathname === "/dashboard"
? "bg-accent text-accent-foreground"
: "text-muted-foreground",
)}
>
</Link>
<Link
href="/dashboard/clients"
className={cn(
"rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
pathname.startsWith("/dashboard/clients")
? "bg-accent text-accent-foreground"
: "text-muted-foreground",
)}
>
</Link>
<Link
href="/dashboard/settings"
className={cn(
"rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
pathname === "/dashboard/settings"
? "bg-accent text-accent-foreground"
: "text-muted-foreground",
)}
>
</Link>
{user.role === "ADMIN" && (
<>
<div className="mx-2 h-4 w-px bg-border" />
<Link
href="/admin"
className={cn(
"rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
pathname === "/admin"
? "bg-accent text-accent-foreground"
: "text-muted-foreground",
)}
>
</Link>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="sm"
className={cn(
"rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
pathname.startsWith("/admin/") && pathname !== "/admin"
? "bg-accent text-accent-foreground"
: "text-muted-foreground",
)}
>
<ChevronDown className="ml-1 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem asChild>
<Link
href="/admin/users"
className={cn(
"w-full",
pathname === "/admin/users" && "bg-accent",
)}
>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
href="/admin/clients"
className={cn(
"w-full",
pathname === "/admin/clients" && "bg-accent",
)}
>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
href="/admin/authorizations"
className={cn(
"w-full",
pathname === "/admin/authorizations" && "bg-accent",
)}
>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
href="/admin/logs"
className={cn(
"w-full",
pathname === "/admin/logs" && "bg-accent",
)}
>
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
)}
</div>
);
};
return (
<div className="flex items-center space-x-4">
{renderNavLinks()}
<ThemeToggle />
{user ? (
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarImage src={user.avatarUrl || undefined} />
<AvatarFallback>
{user.name?.charAt(0) || user.username?.charAt(0)}
</AvatarFallback>
</Avatar>
<Button
variant="ghost"
size="sm"
onClick={handleSignOut}
className="text-muted-foreground hover:text-red-600"
>
退
</Button>
</div>
) : (
<Button
variant="outline"
size="sm"
className="border-[#25263A] text-[#25263A] hover:bg-[#25263A] hover:text-white dark:border-[#A0A1B2] dark:text-[#A0A1B2] dark:hover:bg-[#A0A1B2] dark:hover:text-[#25263A]"
onClick={() => router.push("/sign-in")}
>
</Button>
)}
</div>
);
}

View File

@ -0,0 +1,26 @@
import Link from "next/link";
import { getCurrentUser } from "@/lib/session";
import { HeaderClient } from "@/components/layout/header-client";
export async function Header() {
const user = await getCurrentUser();
return (
<header className="sticky top-0 z-10 bg-white shadow-md dark:bg-gray-800">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex h-14 items-center justify-between">
<div className="flex items-center">
<Link href="/" className="flex items-center space-x-3">
<h1 className="text-2xl font-bold text-[#25263A] dark:text-white">
Q58 Connect
</h1>
</Link>
</div>
<HeaderClient initialUser={user} />
</div>
</div>
</header>
);
}