Menu.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <!--
  2. Menu principal de l'application
  3. Prend en paramètre une liste de ItemMenu et les met en forme
  4. -->
  5. <template>
  6. <v-navigation-drawer
  7. :mini-variant.sync="miniVariant"
  8. v-model="open"
  9. class="bg-ot-dark-grey text-ot-menu-color"
  10. >
  11. <template #prepend>
  12. <slot name="title"></slot>
  13. </template>
  14. <v-list class="left-menu">
  15. <div v-for="(item, i) in menu.children" :key="i">
  16. <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien -->
  17. <v-list-item
  18. v-if="!item.children"
  19. :href="isExternalLink(item) ? item.to : undefined"
  20. :to="!isExternalLink(item) ? item.to : undefined"
  21. exact
  22. >
  23. <template v-slot:prepend>
  24. <v-list-item-action start>
  25. <v-icon :icon="item.icon.name" class="text-ot-menu-color" small />
  26. </v-list-item-action>
  27. </template>
  28. <v-list-item-title
  29. v-text="item.title"
  30. class="text-ot-menu-color"
  31. />
  32. </v-list-item>
  33. <!-- Cas 2 : l'item a des enfants, c'est un groupe -->
  34. <v-list-group
  35. v-else
  36. v-model="item.active"
  37. >
  38. <template #activator>
  39. <v-list-item-action>
  40. <v-icon :icon="item.icon.name" class="text-ot-menu-color" small />
  41. </v-list-item-action>
  42. <v-list-item-title class="text-ot-menu-color" v-text="item.title" />
  43. </template>
  44. <v-list-item
  45. v-for="child in item.children"
  46. :key="child.label"
  47. :href="isExternalLink(child) ? child.to : undefined"
  48. :to="!isExternalLink(child) ? child.to : undefined"
  49. router
  50. exact
  51. >
  52. <v-list-item-action>
  53. <v-icon :icon="child.icon.name" class="text-ot-white" small />
  54. </v-list-item-action>
  55. <v-list-item-title class="text-ot-white" v-text="child.title" />
  56. </v-list-item>
  57. <template #appendIcon>
  58. <v-icon class="text-ot-menu-color" small>mdi-chevron-down</v-icon>
  59. </template>
  60. </v-list-group>
  61. </div>
  62. </v-list>
  63. <template #append>
  64. <slot name="foot"></slot>
  65. </template>
  66. </v-navigation-drawer>
  67. </template>
  68. <script setup lang="ts">
  69. import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
  70. import {ref, toRefs} from "@vue/reactivity";
  71. import {MENU_LINK_TYPE, MenuGroup, MenuItem} from "~/types/menus";
  72. const props = defineProps({
  73. menu: {
  74. type: Object as () => MenuGroup,
  75. required: true
  76. },
  77. miniVariant: {
  78. type: Boolean,
  79. required: true
  80. },
  81. openMenu: {
  82. type: Boolean,
  83. required: true
  84. }
  85. })
  86. const { openMenu } = toRefs(props)
  87. const open = ref(true)
  88. // Par défaut si l'écran est trop petit au chargement de la page, le menu doit être fermé.
  89. if(process.client)
  90. open.value = window.innerWidth >= 1264
  91. // TODO : ajouter une petite explication de ce qu'on fait dans ce watch
  92. const unwatch: WatchStopHandle = watch(openMenu, (newValue, oldValue) => {
  93. if (newValue !== oldValue) {
  94. open.value = true
  95. }
  96. })
  97. const isExternalLink = (menuItem: MenuItem | MenuGroup) => 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.EXTERNAL
  98. onUnmounted(() => {
  99. unwatch()
  100. })
  101. </script>
  102. <style scoped>
  103. .v-list-item__action, .v-list-group__header__prepend-icon {
  104. margin-right: 10px !important;
  105. }
  106. .v-application--is-ltr .v-list-group--no-action > .v-list-group__header {
  107. margin-left: 0;
  108. padding-left: 0;
  109. }
  110. .v-application--is-ltr .v-list-group--no-action > .v-list-group__items > .v-list-item {
  111. padding-left: 30px;
  112. }
  113. .v-list-item__title {
  114. font-size: 14px;
  115. }
  116. .v-list-item {
  117. min-height: 10px !important;
  118. }
  119. .v-list-item__action {
  120. margin: 10px 0;
  121. }
  122. .v-list-item__content {
  123. padding: 8px 0;
  124. }
  125. .home_menu {
  126. font-size: 23px;
  127. }
  128. </style>