CreateButton.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <!--
  2. Bouton Créer du header de l'application et boite de dialogue associée
  3. -->
  4. <template>
  5. <main>
  6. <v-btn
  7. v-if="asIcon"
  8. :elevation="0"
  9. class="theme-primary"
  10. :icon="true"
  11. size="small"
  12. @click="show"
  13. >
  14. <v-icon>fas fa-plus</v-icon>
  15. </v-btn>
  16. <v-btn
  17. v-else
  18. :elevation="2"
  19. height="30"
  20. class="theme-x-create-btn"
  21. @click="show"
  22. >
  23. <span>{{ $t('create') }}</span>
  24. </v-btn>
  25. <LayoutDialog :show="showCreateDialog" :max-width="850">
  26. <template #dialogType>{{ $t('creative_assistant') }}</template>
  27. <template #dialogTitle>
  28. <span v-if="location === 'home'">{{
  29. $t('what_do_you_want_to_create')
  30. }}</span>
  31. <span v-else-if="location === 'access'">{{
  32. $t('what_type_of_contact_do_you_want_to_create')
  33. }}</span>
  34. <span v-else-if="location === 'event'">{{
  35. $t('what_do_you_want_to_add_to_your_planning')
  36. }}</span>
  37. <span v-else-if="location === 'message'">{{
  38. $t('what_do_you_want_to_send')
  39. }}</span>
  40. <span v-else-if="location === 'event-params'">{{
  41. $t('which_date_and_which_hour')
  42. }}</span>
  43. </template>
  44. <template #dialogText>
  45. <LayoutHeaderUniversalCreationGenerateCardsSteps
  46. :path="path"
  47. @cardClick="onCardClick"
  48. @urlUpdate="onUrlUpdate"
  49. />
  50. </template>
  51. <template #dialogBtn>
  52. <div class="text-center">
  53. <v-btn class="theme-neutral-soft" @click="close">
  54. {{ $t('cancel') }}
  55. </v-btn>
  56. <v-btn
  57. v-if="path.length > 1"
  58. class="theme-neutral-soft"
  59. @click="goToPrevious"
  60. >
  61. {{ $t('previous_step') }}
  62. </v-btn>
  63. <v-btn
  64. v-if="targetUrl !== null && !directRedirectionOngoing"
  65. class="theme-primary"
  66. @click="validate"
  67. >
  68. {{ $t('validate') }}
  69. </v-btn>
  70. </div>
  71. </template>
  72. </LayoutDialog>
  73. </main>
  74. </template>
  75. <script setup lang="ts">
  76. import { ref } from '@vue/reactivity'
  77. import type { Ref } from '@vue/reactivity'
  78. import { useDisplay } from 'vuetify'
  79. import type { ComputedRef } from 'vue'
  80. import { usePageStore } from '~/stores/page'
  81. const { mdAndDown: asIcon } = useDisplay()
  82. // Set to true to show the Create dialog
  83. const showCreateDialog: Ref<boolean> = ref(false)
  84. // The succession of menus the user has been through; used to keep track of the navigation
  85. const path: Ref<Array<string>> = ref(['home'])
  86. // The current menu
  87. const location: ComputedRef<string> = computed(() => {
  88. return path.value.at(-1) ?? 'home'
  89. })
  90. // The current target URL (@see onUrlUpdate())
  91. const targetUrl: Ref<string | null> = ref(null)
  92. // Already redirecting (to avoid the display of the 'validate' button when page has already been redirected and is loading)
  93. const directRedirectionOngoing: Ref<boolean> = ref(false)
  94. /**
  95. * Return to the home menu
  96. */
  97. const reset = () => {
  98. path.value = ['home']
  99. }
  100. /**
  101. * Go back to the previous step
  102. */
  103. const goToPrevious = () => {
  104. if (path.value.length === 1) {
  105. return
  106. }
  107. path.value.pop()
  108. }
  109. /**
  110. * Display the create dialog
  111. */
  112. const show = () => {
  113. reset()
  114. showCreateDialog.value = true
  115. }
  116. const pageStore = usePageStore()
  117. /**
  118. * Redirect the user to the given url
  119. * @param url
  120. */
  121. const redirect = (url: string) => {
  122. pageStore.loading = true
  123. window.location.href = url
  124. }
  125. /**
  126. * Go to the current targetUrl
  127. */
  128. const validate = () => {
  129. if (targetUrl.value === null) {
  130. console.warn('No url defined')
  131. return
  132. }
  133. redirect(targetUrl.value)
  134. }
  135. /**
  136. * Close the Create dialog
  137. */
  138. const close = () => {
  139. showCreateDialog.value = false
  140. }
  141. /**
  142. * A cart has been clicked. The reaction depends on the card's properties.
  143. *
  144. * @param to Target location in the wizard
  145. * @param href Target absolute url
  146. */
  147. const onCardClick = (to: string | null, href: string | null) => {
  148. if (to !== null) {
  149. // La carte définit une nouvelle destination : on se dirige vers elle.
  150. path.value.push(to)
  151. } else if (href !== null) {
  152. // La carte définit une url avec href, et pas de nouvelle destination : on suit directement le lien pour éviter
  153. // l'étape de validation devenue inutile.
  154. directRedirectionOngoing.value = true
  155. redirect(href)
  156. } else {
  157. console.warn('Error: card has no `to` nor `href` defined')
  158. }
  159. }
  160. /**
  161. * The url has been updated in the GenerateCardsStep component
  162. * @param url
  163. */
  164. const onUrlUpdate = (url: string) => {
  165. targetUrl.value = url
  166. }
  167. </script>
  168. <style scoped lang="scss">
  169. :deep(.v-btn .v-icon) {
  170. font-size: 16px !important;
  171. }
  172. :deep(.v-btn) {
  173. text-transform: none !important;
  174. font-weight: 600;
  175. }
  176. </style>