| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- <!--
- Menu principal de l'application
- Prend en paramètre une liste de ItemMenu et les met en forme
- -->
- <template>
- <v-navigation-drawer
- :mini-variant.sync="miniVariant"
- v-model="open"
- class="bg-ot-dark-grey text-ot-menu-color main-menu"
- >
- <template #prepend>
- <slot name="title"></slot>
- </template>
- <v-list
- open-strategy="single"
- active-class="active"
- class="left-menu"
- >
- <div v-for="(item, i) in menu.children" :key="i">
- <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien -->
- <v-list-item
- v-if="!item.children"
- :title="$t(item.label)"
- :prepend-icon="item.icon.name"
- :href="!isInternalLink(item) ? item.to : undefined"
- :to="isInternalLink(item) ? item.to : undefined"
- exact
- class="text-ot-menu-color"
- height="48px"
- ></v-list-item>
- <!-- Cas 2 : l'item a des enfants, c'est un groupe -->
- <v-list-group
- v-else
- expand-icon="fas fa-angle-right"
- collapse-icon="fas fa-angle-down"
- class="text-ot-menu-color"
- v-model="item.expanded"
- >
- <template #activator="{ props }">
- <v-list-item
- v-bind="props"
- :prepend-icon="item.icon.name"
- :title="$t(item.label)"
- class="text-ot-menu-color"
- height="48px"
- ></v-list-item>
- </template>
- <v-list-item
- v-for="child in item.children"
- :key="$t(child.label)"
- :title="$t(child.label)"
- :prepend-icon="child.icon.name"
- :href="!isInternalLink(child) ? child.to : undefined"
- :to="isInternalLink(child) ? child.to : undefined"
- exact
- height="48px"
- class="text-ot-white"
- ></v-list-item>
- </v-list-group>
- </div>
- </v-list>
- <template #append>
- <slot name="foot"></slot>
- </template>
- </v-navigation-drawer>
- </template>
- <script setup lang="ts">
- import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
- import {ref, toRefs} from "@vue/reactivity";
- import {MenuGroup, MenuItem} from "~/types/layout";
- import {MENU_LINK_TYPE} from "~/types/enum/layout";
- const props = defineProps({
- menu: {
- type: Object as () => MenuGroup,
- required: true
- },
- miniVariant: {
- type: Boolean,
- required: true
- },
- openMenu: {
- type: Boolean,
- required: true
- }
- })
- const { openMenu } = toRefs(props)
- const open = ref(true)
- // Par défaut si l'écran est trop petit au chargement de la page, le menu doit être fermé.
- if(process.client)
- open.value = window.innerWidth >= 1264
- // TODO : ajouter une petite explication de ce qu'on fait dans ce watch
- const unwatch: WatchStopHandle = watch(openMenu, (newValue, oldValue) => {
- if (newValue !== oldValue) {
- open.value = true
- }
- })
- const isInternalLink = (menuItem: MenuItem | MenuGroup) => {
- return 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.INTERNAL
- }
- onUnmounted(() => {
- unwatch()
- })
- </script>
- <style scoped lang="scss">
- .v-list-item {
- min-height: 10px !important;
- }
- :deep(.v-list-item-title),
- :deep(.v-icon),
- {
- font-size: 14px;
- color: rgb(var(--v-theme-ot-menu-color));
- }
- .v-list-item__prepend {
- margin: 10px 0;
- margin-right: 10px !important;
- }
- .v-application--is-ltr .v-list-group--no-action > .v-list-group__header {
- margin-left: 0;
- padding-left: 0;
- }
- .v-application--is-ltr .v-list-group--no-action > .v-list-group__items > .v-list-item {
- padding-left: 30px;
- }
- .v-list-item__content {
- padding: 8px 0;
- }
- .v-list-group__items .v-list-item {
- padding-inline-start: 30px !important;
- }
- .v-list-group--no-action > .v-list-group__header,
- .v-list-item
- {
- border-left:3px solid rgb(var(--v-theme-ot-dark-grey));
- height: 48px;
- }
- .v-list-item:hover,
- .v-list-item.active,
- :deep(.v-list-group__items .v-list-item)
- {
- border-left: 3px solid rgb(var(--v-theme-ot-green));
- background: rgb(var(--v-theme-ot-dark-grey-hover));
- }
- :deep(.v-list-group__items .v-list-item-title) {
- color: rgb(var(--v-theme-ot-white));
- }
- :deep(.v-list-item .v-icon) {
- margin-right: 10px;
- }
- </style>
|