ActionMenu.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <!--
  2. Menu d'actions rapides (appel, contact, ...), qui reste accroché au bord droit
  3. de l'écran (ou au bas de l'écran sur les petits écrans)
  4. -->
  5. <template>
  6. <!-- Écrans larges : menu lateral, accroché au bord droit de l'écran -->
  7. <div class="sticky-menu lateral" v-if="lgAndUp">
  8. <v-row
  9. v-for="(action, index) in actionsOrDefault"
  10. :key="index"
  11. :class="['square', action.color]"
  12. @click="() => onActionClick(action)"
  13. >
  14. <NuxtLink :to="action.url" class="link">
  15. <div>
  16. <v-icon
  17. :class="action.icon"
  18. />
  19. <p class="text-square mt-2">
  20. {{ action.text }}
  21. </p>
  22. </div>
  23. </NuxtLink>
  24. </v-row>
  25. </div>
  26. <!-- Petits écrans : menu sous forme de bandeau en pied de page (sauf si le footer du site est visible) -->
  27. <div class="sticky-menu band" v-else-if="!layoutStore.isFooterVisible">
  28. <v-btn
  29. v-for="(action, index) in actionsOrDefault"
  30. :key="index"
  31. :class="[action.color]"
  32. @click="() => onActionClick(action)"
  33. >
  34. {{ action.text }}
  35. </v-btn>
  36. </div>
  37. </template>
  38. <script setup lang="ts">
  39. import { defineProps, ComputedRef } from "vue";
  40. import { useRouter } from "vue-router";
  41. import { useDisplay } from "vuetify";
  42. import { useLayoutStore } from "~/stores/layoutStore";
  43. import { ActionMenuItemType } from "~/types/enum/layout";
  44. import { ActionMenuItem } from "~/types/interface";
  45. const { mdAndDown, lgAndUp } = useDisplay();
  46. const router = useRouter();
  47. const layoutStore = useLayoutStore()
  48. const { isMobileDevice } = useClientDevice()
  49. // TODO: passer en conf?
  50. const telephoneNumber = "09 72 12 60 17";
  51. // Actions par défaut du menu, peut-être surchargé via la propriété `actions`
  52. const defaultActions: Array<ActionMenuItem> = [
  53. {
  54. type: ActionMenuItemType.FOLLOW_LINK,
  55. color: "secondary",
  56. icon: "far fa-comments",
  57. text: "Nous contacter",
  58. url: "/nous-contacter",
  59. },
  60. {
  61. type: ActionMenuItemType.CALL_US,
  62. color: "primary",
  63. icon: "fas fa-phone",
  64. text: "Nous Appeler",
  65. },
  66. ];
  67. const props = defineProps({
  68. /**
  69. * Actions accessibles via le menu (par défaut : "Nous contacter", "Nous appeler")
  70. */
  71. actions: {
  72. type: Array<ActionMenuItem>,
  73. required: false,
  74. default: []
  75. }
  76. })
  77. const actionsOrDefault: ComputedRef<Array<ActionMenuItem>> = computed(() => {
  78. return props.actions.length > 0 ? props.actions : defaultActions
  79. })
  80. const callUs = () => {
  81. if (isMobileDevice()) {
  82. window.location.href = `tel:${telephoneNumber}`;
  83. } else {
  84. alert(`Notre numéro de téléphone : ${telephoneNumber}`);
  85. }
  86. }
  87. /**
  88. * On a cliqué sur une des actions du menu
  89. * @param action
  90. */
  91. const onActionClick = (action: ActionMenuItem) => {
  92. switch (action.type) {
  93. case ActionMenuItemType.ASK_FOR_A_DEMO:
  94. router.push({ path: action.url, query: { request: "demo" } });
  95. break;
  96. case ActionMenuItemType.CALL_US:
  97. callUs()
  98. break;
  99. case ActionMenuItemType.FOLLOW_LINK:
  100. if (!action.url) {
  101. throw Error('Missing prop : url')
  102. }
  103. router.push({ path: action.url });
  104. break
  105. default:
  106. throw Error('Unrecognized action')
  107. }
  108. };
  109. </script>
  110. <style scoped lang="scss">
  111. .sticky-menu {
  112. z-index: 100;
  113. }
  114. // Menu format lateral (pour affichage écrans larges)
  115. .sticky-menu.lateral {
  116. position: sticky;
  117. right: 0;
  118. top: 60%;
  119. transform: translateY(-50%);
  120. float: right;
  121. display: flex;
  122. flex-direction: column;
  123. font-weight: 500;
  124. font-size: 0.7rem;
  125. line-height: 15px;
  126. text-align: center;
  127. letter-spacing: 0.2em;
  128. text-transform: uppercase;
  129. }
  130. // Menu format ruban (pour affichage petits écrans)
  131. .sticky-menu.band {
  132. position: fixed;
  133. height: 46px;
  134. bottom: 0;
  135. width: 100%;
  136. display: flex;
  137. justify-content: center;
  138. .v-btn {
  139. margin: 4px 6px;
  140. }
  141. }
  142. .square {
  143. position: relative;
  144. font-family: "Barlow", serif;
  145. width: 7rem;
  146. padding: 1rem;
  147. cursor: pointer;
  148. transition: transform 0.3s ease-in-out;
  149. }
  150. .square:hover {
  151. transform: translateX(-10px);
  152. }
  153. .link {
  154. text-decoration: none;
  155. }
  156. .primary {
  157. background: var(--primary-color);
  158. color: var(--on-primary-color);
  159. a {
  160. color: var(--on-primary-color);
  161. }
  162. }
  163. .secondary {
  164. background: var(--secondary-color);
  165. color: var(--on-secondary-color);
  166. a {
  167. color: var(--on-secondary-color);
  168. }
  169. }
  170. .on-primary-color-alt {
  171. background: var(--on-primary-color-alt);
  172. color: var(--on-alt-theme);
  173. a {
  174. color: var(--on-alt-theme);
  175. }
  176. }
  177. //.yellow-square {
  178. // background: rgb(250, 194, 10);
  179. // color: #0e2d32;
  180. //}
  181. //
  182. //.green-square {
  183. // background: #9edbdd;
  184. //}
  185. //
  186. //.red-square {
  187. // background: #d8050b;
  188. //}
  189. //
  190. //.blue-square {
  191. // background: #2093be;
  192. //}
  193. //
  194. //.logo-square {
  195. // background: var(--Bleu-School-60, rgba(32, 147, 190));
  196. //}
  197. //
  198. //.darkblue-square {
  199. // background: #0e2d32;
  200. //}
  201. </style>