import { useAbility } from '@casl/vue' import { useAccessProfileStore } from '~/stores/accessProfile' import { useOrganizationProfileStore } from '~/stores/organizationProfile' import type { MenuGroup, MenuItem } from '~/types/layout' import { MENU_LINK_TYPE } from '~/types/enum/layout' import type { AccessProfile } from '~/types/interfaces' import { useLayoutStore } from '~/stores/layout' import MenuComposer from '~/services/layout/menuComposer' /** * Renvoie des méthodes pour interagir avec les menus * * Exemple d'usage : * * const { buildMenu, hasMenu } = useMenuBuilder() * const menu = buildMenu('Main') * * console.log(hasMenu('Main')) // true */ export const useMenu = () => { const runtimeConfig = useRuntimeConfig() const ability = useAbility() const organizationProfile = useOrganizationProfileStore() const accessProfile = useAccessProfileStore() const layoutState = useLayoutStore() const router = useRouter() /** * Construct all Menus * TODO: ce serait mieux de conserver les ids des menus même non possédés, de façon à pouvoir différencier un menu * non possédé et un id incorrect dans getMenu par exemple. J'ai eu du mal capter pourquoi hasMenu('Family') renvoyait * false, jusqu'à ce que je tilte que le menu s'appelait MyFamily, et pas Family */ const buildAllMenu = () => { MenuComposer.build( runtimeConfig, ability, organizationProfile, accessProfile as AccessProfile, router, layoutState, ) } /** * Retourne le menu depuis le store ou retourne null * si le menu n'a pas été construit pour l'utilisateur courant * * @param name */ const getMenu = (name: string): MenuGroup | MenuItem | null => { return layoutState.menus[name] || null } /** * L'utilisateur en cours a-t-il accès au menu portant ce nom ? * * @param name */ const hasMenu = (name: string): boolean => { return getMenu(name) !== null } /** * Soulève une erreur si aucun menu portant ce nom n'est enregistré dans le store * * @param name */ const assertExists = (name: string) => { if (getMenu(name) === null) { throw new Error('Unknown menu : ' + name) } } /** * Retourne vrai si le menu est actuellement ouvert / déplié * * @param name */ const isMenuOpened = (name: string): boolean => { assertExists(name) return layoutState.menusOpened[name] } /** * Met à jour l'état du menu portant ce nom * * @param name * @param state */ const setMenuState = (name: string, state: boolean) => { assertExists(name) layoutState.menusOpened[name] = state } /** * Ouvre / déplie le menu portant ce nom * * @param name */ const openMenu = (name: string) => { setMenuState(name, true) } /** * Ferme / replie le menu portant ce nom * * @param name */ const closeMenu = (name: string) => { setMenuState(name, false) } /** * Bascule l'état du menu entre ouvert et fermé * * @param name */ const toggleMenu = (name: string) => { setMenuState(name, !layoutState.menusOpened[name]) } /** * Le lien menuItem est-il un lien interne à l'application * * @param menuItem */ const isInternalLink = (menuItem: MenuItem | MenuGroup): boolean => { return 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.INTERNAL } return { buildAllMenu, getMenu, hasMenu, setMenuState, openMenu, closeMenu, toggleMenu, isMenuOpened, isInternalLink, } }