From 6ed8620ca6be813d77be406b47a8b336bc874a73 Mon Sep 17 00:00:00 2001 From: zetaloop Date: Sat, 21 Feb 2026 15:53:46 +0800 Subject: [PATCH] fix: sync verification state with auth guards --- app/(account)/verify/page.tsx | 18 +++++++++++++++--- app/(dashboard)/layout.tsx | 20 +++++++++++++++++++- components/auth-guard.tsx | 10 ++++++++-- lib/types.ts | 3 +++ store/auth.ts | 26 +++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/app/(account)/verify/page.tsx b/app/(account)/verify/page.tsx index 6c49a56..e339823 100644 --- a/app/(account)/verify/page.tsx +++ b/app/(account)/verify/page.tsx @@ -16,9 +16,14 @@ import { } from "@/components/ui/select" import { Separator } from "@/components/ui/separator" import { Textarea } from "@/components/ui/textarea" +import type { UserRole } from "@/lib/types" +import { useAuthStore } from "@/store/auth" export default function VerifyPage() { - const [submitted, setSubmitted] = useState(false) + const [verifyRole, setVerifyRole] = useState("") + const verificationStatus = useAuthStore((state) => state.verificationStatus) + const submitVerification = useAuthStore((state) => state.submitVerification) + const submitted = Object.values(verificationStatus).includes("pending") if (submitted) { return ( @@ -68,7 +73,7 @@ export default function VerifyPage() {
- setVerifyRole(value as UserRole)}> @@ -115,7 +120,14 @@ export default function VerifyPage() {

支持 JPG、PNG 格式,单张不超过 5MB

-
diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx index e4bd69f..458a344 100644 --- a/app/(dashboard)/layout.tsx +++ b/app/(dashboard)/layout.tsx @@ -1,8 +1,16 @@ +"use client" + +import Link from "next/link" import { AuthGuard } from "@/components/auth-guard" import { DashboardSidebar } from "@/components/dashboard-sidebar" import { Header } from "@/components/header" +import { Button } from "@/components/ui/button" +import { useAuthStore } from "@/store/auth" export default function DashboardLayout({ children }: { children: React.ReactNode }) { + const isAuthenticated = useAuthStore((state) => state.isAuthenticated) + const currentRole = useAuthStore((state) => state.currentRole) + return (
@@ -11,7 +19,17 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
- {children} + + {isAuthenticated && currentRole === "consumer" ? ( +
+ +
+ ) : ( + children + )} +
diff --git a/components/auth-guard.tsx b/components/auth-guard.tsx index bca9f4f..7f13c2e 100644 --- a/components/auth-guard.tsx +++ b/components/auth-guard.tsx @@ -1,6 +1,6 @@ "use client" -import { useEffect } from "react" +import { useEffect, useRef } from "react" import { Button } from "@/components/ui/button" import { useAuthStore } from "@/store/auth" import { useLoginDialogStore } from "@/store/login-dialog" @@ -12,9 +12,15 @@ interface AuthGuardProps { export function AuthGuard({ children }: AuthGuardProps) { const isAuthenticated = useAuthStore((s) => s.isAuthenticated) const openLoginDialog = useLoginDialogStore((s) => s.openLoginDialog) + const hasTriggered = useRef(false) useEffect(() => { - if (!isAuthenticated) { + if (isAuthenticated) { + hasTriggered.current = false + return + } + if (!hasTriggered.current) { + hasTriggered.current = true openLoginDialog() } }, [isAuthenticated, openLoginDialog]) diff --git a/lib/types.ts b/lib/types.ts index 5e7cd98..8b237c1 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,4 +1,5 @@ export type UserRole = "consumer" | "player" | "owner" +export type VerificationStatus = "pending" | "approved" | "rejected" export interface User { id: string @@ -6,6 +7,8 @@ export interface User { nickname: string avatar: string role: UserRole + verifiedRoles?: UserRole[] + verificationStatus?: Partial> phone?: string bio?: string createdAt: string diff --git a/store/auth.ts b/store/auth.ts index 54e1e84..6954454 100644 --- a/store/auth.ts +++ b/store/auth.ts @@ -1,12 +1,14 @@ import { create } from "zustand" -import type { User, UserRole } from "@/lib/types" +import type { User, UserRole, VerificationStatus } from "@/lib/types" interface AuthState { isAuthenticated: boolean currentRole: UserRole verifiedRoles: UserRole[] + verificationStatus: Partial> user: User | null switchRole: (role: UserRole) => void + submitVerification: (role: UserRole) => void login: (user: User, verifiedRoles?: UserRole[]) => void logout: () => void } @@ -15,6 +17,7 @@ export const useAuthStore = create((set, get) => ({ isAuthenticated: false, currentRole: "consumer", verifiedRoles: ["consumer"], + verificationStatus: { consumer: "approved" }, user: null, switchRole: (role) => { const { verifiedRoles } = get() @@ -22,18 +25,39 @@ export const useAuthStore = create((set, get) => ({ set({ currentRole: role }) } }, + submitVerification: (role) => + set((state) => { + if (state.verifiedRoles.includes(role)) { + return state + } + + return { + verificationStatus: { + ...state.verificationStatus, + [role]: "pending", + }, + } + }), login: (user, verifiedRoles = ["consumer"]) => set({ isAuthenticated: true, user, currentRole: user.role, verifiedRoles, + verificationStatus: verifiedRoles.reduce>>( + (acc, role) => { + acc[role] = "approved" + return acc + }, + {}, + ), }), logout: () => set({ isAuthenticated: false, currentRole: "consumer", verifiedRoles: ["consumer"], + verificationStatus: { consumer: "approved" }, user: null, }), }))