Files
smart-go/web/lib/hooks/use-nav-menu.ts
T
2026-04-23 18:58:13 +08:00

71 lines
2.0 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { iamMenu } from '@/lib/api/iam';
import type { MenuNode } from '@/lib/api/types/menu';
import { useAuthStore } from '@/stores/auth-store';
import { useLayoutStore } from '@/stores/layout-store';
import { useTenantStore } from '@/stores/tenant-store';
type NavMenuState = {
items: MenuNode[];
loading: boolean;
error: string | null;
authed: boolean;
permissions: string[];
};
/** 从 AppChrome 提取的导航菜单数据获取逻辑 */
export function useNavMenu(): NavMenuState {
const accessToken = useAuthStore((s) => s.accessToken);
const authed = Boolean(accessToken);
const tenantId = useTenantStore((s) => s.tenantId);
const setPerms = useLayoutStore((s) => s.setPerms);
const [items, setItems] = useState<MenuNode[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [permissions, setPermissions] = useState<string[]>([]);
useEffect(() => {
if (!accessToken) {
setItems([]);
setError(null);
setPerms([]);
setPermissions([]);
return;
}
let cancelled = false;
setLoading(true);
setError(null);
Promise.all([
iamMenu.nav().catch(() => [] as MenuNode[]),
iamMenu.perms().catch(() => ({ perms: [] as string[] })),
])
.then(([tree, pr]) => {
if (cancelled) return;
const navItems = Array.isArray(tree) ? tree : [];
const perms = Array.isArray(pr?.perms) ? pr.perms : [];
setItems(navItems);
setPerms(perms);
setPermissions(perms);
})
.catch((e: unknown) => {
if (!cancelled) {
setError(e instanceof Error ? e.message : String(e));
setItems([]);
setPerms([]);
setPermissions([]);
}
})
.finally(() => {
if (!cancelled) setLoading(false);
});
return () => {
cancelled = true;
};
}, [accessToken, tenantId, setPerms]);
return { items, loading, error, authed, permissions };
}