import type { MenuItem } from '../config/menu';
import type { DMenuItem } from '@react-devui/ui/components/menu';
import { isObject, isUndefined } from 'lodash';
import { useStore } from 'rcl-store';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Link, useLocation } from 'react-router-dom';
import { useACL, useMount } from '@react-devui/hooks';
import { MENU } from '../config/menu';
import { GlobalStore } from './store';
export function useMenu() {
const acl = useACL();
const { t } = useTranslation();
const location = useLocation();
const [{ appMenu }, { appMenu: setAppMenu }] = useStore(GlobalStore, ['appMenu']);
const res: {
active?: { path: string; parentSub: MenuItem[] };
firstCanActive?: { path: string; parentSub: MenuItem[] };
} = {};
const reduceMenu = (arr: MenuItem[], parentSub: MenuItem[]): DMenuItem<string>[] => {
const newArr: DMenuItem<string>[] = [];
for (const item of arr) {
if (item.acl) {
const params =
isObject(item.acl) && 'control' in item.acl
? item.acl
: {
control: item.acl,
};
if (!acl.can(params.control, params.mode)) {
continue;
}
}
const { title: _title, titleI18n } = item;
const title = _title ?? (isUndefined(titleI18n) ? undefined : t(titleI18n as any, { ns: 'title' }));
const obj: DMenuItem<string> = {
id: item.path,
title: item.type === 'item' ? React.createElement(Link, { className: 'app-menu-link', tabIndex: -1, to: item.path }, title) : title,
icon: item.icon ? React.createElement(item.icon) : undefined,
type: item.type,
};
if (item.children) {
obj.children = reduceMenu(item.children, parentSub.concat(item.type === 'sub' ? [item] : []));
if (obj.children.length > 0) {
newArr.push(obj);
}
} else {
newArr.push(obj);
if (item.path === location.pathname || (item.greedyMatch && location.pathname.startsWith(item.path + '/'))) {
res.active = {
path: item.path,
parentSub,
};
}
if (!item.disabled && isUndefined(res.firstCanActive)) {
res.firstCanActive = {
path: item.path,
parentSub,
};
}
}
}
return newArr;
};
const menu = reduceMenu(MENU, []);
const getDefaultExpands = () =>
(location.pathname === '/' ? res.firstCanActive?.parentSub : res.active?.parentSub)?.map((item) => item.path);
useMount(() => {
if (isUndefined(appMenu.expands)) {
setAppMenu((draft) => {
draft.expands = getDefaultExpands();
});
}
});
return [
{
menu,
active: location.pathname === '/' ? res.firstCanActive : res.active,
firstCanActive: res.firstCanActive,
expands: appMenu.expands ?? getDefaultExpands(),
},
setAppMenu,
] as const;
}