Md.vue 3.9 KB

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