From 86086a7054afad8619647c4cfd64ab49b374b000 Mon Sep 17 00:00:00 2001 From: tone Date: Wed, 17 Dec 2025 15:36:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=89=8D=E7=AB=AF=E6=B7=BB=E5=8A=A0use?= =?UTF-8?q?r=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/frontend/app/ClientProvider.tsx | 25 +++++++++++++++++++++++ apps/frontend/app/layout.tsx | 30 +++++++++++++++++----------- apps/frontend/store/useUserStore.ts | 27 +++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 apps/frontend/app/ClientProvider.tsx create mode 100644 apps/frontend/store/useUserStore.ts diff --git a/apps/frontend/app/ClientProvider.tsx b/apps/frontend/app/ClientProvider.tsx new file mode 100644 index 0000000..1e0e03d --- /dev/null +++ b/apps/frontend/app/ClientProvider.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { useEffect } from 'react'; +import { useUserStore } from '@/store/useUserStore'; +import { User } from '@/lib/types/user'; + +export function ClientProvider({ + initialUser, + children, +}: { + initialUser: User | null; + children: React.ReactNode; +}) { + const setUser = useUserStore((state) => state.setUser); + const setInitialized = useUserStore((state) => state.setInitialized); + + useEffect(() => { + if (initialUser) { + setUser(initialUser); + } + setInitialized(); + }, [initialUser, setUser, setInitialized]); + + return <>{children}; +} \ No newline at end of file diff --git a/apps/frontend/app/layout.tsx b/apps/frontend/app/layout.tsx index 599f128..cdac60f 100644 --- a/apps/frontend/app/layout.tsx +++ b/apps/frontend/app/layout.tsx @@ -3,6 +3,8 @@ import "./globals.css"; import { ThemeProvider } from "../components/theme-provider"; import { metadata } from "./config/metadata"; import { Toaster } from "sonner"; +import { UserAPI } from "@/lib/api/server"; +import { ClientProvider } from "./ClientProvider"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -16,28 +18,32 @@ const geistMono = Geist_Mono({ export { metadata }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const user = await UserAPI.me().catch(() => null); + return ( - -
- {children} - -
-
+ + +
+ {children} + +
+
+
); diff --git a/apps/frontend/store/useUserStore.ts b/apps/frontend/store/useUserStore.ts new file mode 100644 index 0000000..54819d4 --- /dev/null +++ b/apps/frontend/store/useUserStore.ts @@ -0,0 +1,27 @@ +// store/useUserStore.ts +import { User } from '@/lib/types/user'; +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; + +interface UserState { + user: User | null; + isLoading: boolean; + initialized: boolean; + + // Actions + setInitialized: () => void; + setUser: (user: User | null) => void; + clearUser: () => void; +} + +export const useUserStore = create()( + devtools((set, get) => ({ + user: null, + isLoading: false, + initialized: false, + + setInitialized: () => set({ initialized: true }), + setUser: (user) => set({ user, isLoading: false }), + clearUser: () => set({ user: null }), + })) +); \ No newline at end of file