Md.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <template>
  2. <div class="app-container">
  3. <v-app class="navigation-sm">
  4. <!-- Top bar -->
  5. <v-app-bar app>
  6. <v-app-bar-nav-icon
  7. @click="toggleMenu"
  8. />
  9. <nuxt-link to="/">
  10. <v-img
  11. class="logo-md"
  12. :src="smAndUp ? '/images/logo/navigation-logo.png' : '/images/Opentalent_Griffe.png'"
  13. />
  14. </nuxt-link>
  15. <v-spacer />
  16. <div class="mx-4">
  17. <v-btn
  18. href="https://admin.opentalent.fr/#/login/"
  19. icon="fas fa-user"
  20. class="icon"
  21. />
  22. <v-btn
  23. to="/nous-contacter"
  24. icon="fas fa-phone"
  25. class="icon"
  26. />
  27. <AgendaLink href="/agenda-culturel">
  28. <v-btn
  29. icon="fas fa-calendar"
  30. class="icon"
  31. />
  32. </AgendaLink>
  33. </div>
  34. </v-app-bar>
  35. <!-- Tiroir de navigation principal -->
  36. <v-navigation-drawer
  37. v-model="isMenuOpen"
  38. app
  39. temporary
  40. >
  41. <v-list nav dense>
  42. <v-list-item
  43. v-if="isSubMenu"
  44. class="menuItem back-item"
  45. @click="onBackItemClick"
  46. >
  47. <v-list-item-title>
  48. <v-icon icon="fas fa-caret-left" class="mr-1"/> Retour
  49. </v-list-item-title>
  50. </v-list-item>
  51. <v-list-item
  52. v-for="(item, index) in activeMenu"
  53. :key="item.label"
  54. :to="item.to"
  55. class="menuItem"
  56. @click="onMenuItemClick(index, item)"
  57. >
  58. <v-list-item-title class="d-flex flex-row w-100">
  59. <span class="flex-grow-1">
  60. {{ item.label }}
  61. </span>
  62. <span v-if="item.children?.length! > 0">
  63. <v-icon icon="fa fa-angle-right" />
  64. </span>
  65. </v-list-item-title>
  66. </v-list-item>
  67. </v-list>
  68. </v-navigation-drawer>
  69. </v-app>
  70. </div>
  71. </template>
  72. <script setup lang="ts">
  73. import AgendaLink from "~/components/Common/AgendaLink.vue";
  74. import type { PropType } from "@vue/runtime-core";
  75. import type { MainMenuItem } from "~/types/interface";
  76. import { useDisplay } from "vuetify";
  77. const { smAndUp } = useDisplay()
  78. const props = defineProps({
  79. menu: {
  80. type: Array as PropType<Array<MainMenuItem>>
  81. }
  82. })
  83. const isMenuOpen: Ref<boolean> = ref(false);
  84. const toggleMenu = () => {
  85. isMenuOpen.value = !isMenuOpen.value;
  86. };
  87. const activeMenuIndex: Ref<number | null> = ref(null)
  88. const activeMenu = computed(() =>
  89. activeMenuIndex.value !== null ? props.menu![activeMenuIndex.value].children : props.menu
  90. )
  91. /**
  92. * Determines if the is active menu is a sub-menu .
  93. *
  94. * @function isSubMenu
  95. * @returns {boolean} - True if a sub-menu is active, otherwise false.
  96. */
  97. const isSubMenu = computed(() => activeMenuIndex.value !== null)
  98. /**
  99. * Handles the click event on a menu item.
  100. *
  101. * @param {number} index - The index of the clicked menu item.
  102. * @param {MainMenuItem} item - The clicked menu item.
  103. * @returns {void}
  104. */
  105. const onMenuItemClick = (index: number, item: MainMenuItem): void => {
  106. if (!item.children) {
  107. return
  108. }
  109. withAnimation(() => activeMenuIndex.value = index)
  110. }
  111. /**
  112. * Function to handle back button click event.
  113. */
  114. const onBackItemClick = (): void => {
  115. withAnimation(() => activeMenuIndex.value = null)
  116. }
  117. /**
  118. * Déclenche une animation de changement de menu en fermant et rouvrant le drawer
  119. * @param callback
  120. */
  121. const withAnimation = (callback: () => void) => {
  122. isMenuOpen.value = false
  123. callback()
  124. setTimeout(() => {isMenuOpen.value = true}, 85)
  125. }
  126. </script>
  127. <style scoped lang="scss">
  128. .app-container {
  129. height: 54px;
  130. }
  131. .navigation-sm {
  132. background-color: var(--neutral-color);
  133. position: fixed;
  134. top: 0;
  135. z-index: 1000;
  136. }
  137. .logo-md {
  138. width: 150px;
  139. height: 50px;
  140. @media (max-width: 600px) {
  141. width: 50px;
  142. }
  143. }
  144. .back-item {
  145. border-bottom: solid 1px var(--on-neutral-color-light);
  146. border-radius: 0;
  147. .v-list-item-title {
  148. display: flex;
  149. align-items: center;
  150. }
  151. }
  152. .icon {
  153. color: var(--on-neutral-color-light);
  154. }
  155. </style>