refactor(dashboard): extract RoleGuard and unify mobile nav with Button

This commit is contained in:
zetaloop
2026-02-25 15:18:20 +08:00
parent f8659b5ebc
commit 37d83d8805
5 changed files with 86 additions and 51 deletions
+46 -30
View File
@@ -33,6 +33,8 @@ import { useAuthStore } from "@/store/auth"
import { useNotificationStore } from "@/store/notifications"
import { useShopStore } from "@/store/shops"
import { canAccessDashboard } from "@/components/role-guard"
const roleLabels: Record<UserRole, string> = {
consumer: "客户",
player: "打手",
@@ -53,6 +55,7 @@ export function Header() {
? [
{ href: "/", label: "发现" },
{ href: "/community", label: "社区" },
{ href: "/orders", label: "订单" },
{ href: "/chat", label: "消息" },
]
: [
@@ -69,7 +72,9 @@ export function Header() {
const handleRoleSwitch = (role: UserRole) => {
switchRole(role)
router.push(role === "consumer" ? "/" : "/dashboard")
if (pathname.startsWith("/dashboard") && !canAccessDashboard(role, pathname)) {
router.push(role === "consumer" ? "/" : "/dashboard")
}
setMobileOpen(false)
}
@@ -247,7 +252,7 @@ export function Header() {
<Menu className="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent side="left" className="w-72">
<SheetContent side="right" className="w-72">
<SheetHeader>
<SheetTitle className="flex items-center gap-2">
<Gamepad2 className="h-5 w-5" />
@@ -269,38 +274,49 @@ export function Header() {
)}
<nav className="flex flex-col gap-1">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
onClick={() => setMobileOpen(false)}
className={cn(
"px-3 py-2 rounded-full text-sm font-medium transition-colors",
pathname === link.href ||
(link.href !== "/" && pathname.startsWith(link.href))
? "bg-primary/10 text-primary"
: "text-muted-foreground hover:text-foreground hover:bg-accent/50",
)}
>
{link.label}
</Link>
))}
{navLinks.map((link) => {
const isActive =
pathname === link.href ||
(link.href !== "/" && pathname.startsWith(link.href))
return (
<Button
key={link.href}
variant={isActive ? "secondary" : "ghost"}
className={cn("w-full justify-start", !isActive && "text-muted-foreground")}
asChild
>
<Link href={link.href} onClick={() => setMobileOpen(false)}>
{link.label}
</Link>
</Button>
)
})}
{isAuthenticated && (
<>
<Link
href="/wallet"
onClick={() => setMobileOpen(false)}
className="px-3 py-2 rounded-full text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-accent/50"
<Button
variant={pathname === "/wallet" ? "secondary" : "ghost"}
className={cn(
"w-full justify-start",
pathname !== "/wallet" && "text-muted-foreground",
)}
asChild
>
</Link>
<Link
href="/settings"
onClick={() => setMobileOpen(false)}
className="px-3 py-2 rounded-full text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-accent/50"
<Link href="/wallet" onClick={() => setMobileOpen(false)}>
</Link>
</Button>
<Button
variant={pathname === "/settings" ? "secondary" : "ghost"}
className={cn(
"w-full justify-start",
pathname !== "/settings" && "text-muted-foreground",
)}
asChild
>
</Link>
<Link href="/settings" onClick={() => setMobileOpen(false)}>
</Link>
</Button>
</>
)}
</nav>