Md.vue 3.7 KB

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