index.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <template>
  2. <div>
  3. <v-container fluid class="inner-container">
  4. <v-row>
  5. <!-- Bloc événements -->
  6. <v-col cols="12" md="7">
  7. <v-card>
  8. <v-tabs v-model="tab" class="tabs-title">
  9. <v-tab value="future">{{ $t('futur_event') }}</v-tab>
  10. <v-tab value="past">{{ $t('past_event') }}</v-tab>
  11. </v-tabs>
  12. <v-btn color="primary" to="freemium/events/new" class="ml-5 mt-5">{{
  13. $t('add_event')
  14. }}</v-btn>
  15. <v-tabs-window v-model="tab">
  16. <v-tabs-window-item value="future">
  17. <UiLoadingPanel
  18. v-if="statusUpcomingEvents == FETCHING_STATUS.PENDING"
  19. />
  20. <span v-if="upcomingEvents?.items.length == 0" class="no_event">
  21. {{ $t('no_future_event') }}
  22. </span>
  23. <UiEventList
  24. v-if="
  25. statusUpcomingEvents == FETCHING_STATUS.SUCCESS &&
  26. upcomingEvents?.items
  27. "
  28. :events="upcomingEvents.items"
  29. :pagination="upcomingEvents.pagination"
  30. @load="loadUpcomingEvents"
  31. @edit="editEvent"
  32. />
  33. </v-tabs-window-item>
  34. <v-tabs-window-item value="past">
  35. <UiLoadingPanel
  36. v-if="statusPastEvents == FETCHING_STATUS.PENDING"
  37. />
  38. <span v-if="pastEvents?.items.length == 0" class="no_event">
  39. {{ $t('no_past_event') }}
  40. </span>
  41. <UiEventList
  42. v-if="
  43. statusPastEvents == FETCHING_STATUS.SUCCESS &&
  44. pastEvents?.items
  45. "
  46. :events="pastEvents.items"
  47. :pagination="pastEvents.pagination"
  48. @load="loadPastEvents"
  49. @edit="editEvent"
  50. />
  51. </v-tabs-window-item>
  52. </v-tabs-window>
  53. </v-card>
  54. </v-col>
  55. <!-- Bloc structure -->
  56. <v-col cols="12" md="5">
  57. <v-card
  58. v-if="statusOrganization == FETCHING_STATUS.SUCCESS"
  59. class="pa-5"
  60. >
  61. <v-card-title class="text-h6">
  62. <v-icon icon="fa fa-hotel" class="text-button icon-hotel" />
  63. <span class="organization_title">{{
  64. $t('my_organization')
  65. }}</span>
  66. </v-card-title>
  67. <v-card-text>
  68. <div>
  69. <strong>{{ $t('name') }} :</strong> {{ organization?.name }}
  70. </div>
  71. <div>
  72. <strong>{{ $t('email') }} :</strong> {{ organization?.email }}
  73. </div>
  74. </v-card-text>
  75. </v-card>
  76. <v-btn block class="mb-2 btn btn_edit_orga" to="freemium/organization">
  77. <i class="fa fa-pen mr-2" />{{ $t('edit_organization') }}
  78. </v-btn>
  79. <v-btn block class="text-black btn btn_trial" @click="startTrial">
  80. <span
  81. ><v-icon icon="fa fa-ticket" /> {{ $t('try_premium_light')
  82. }}<br />
  83. {{ $t('30_days_free') }}</span
  84. >
  85. </v-btn>
  86. </v-col>
  87. </v-row>
  88. </v-container>
  89. <LayoutDialogTrialAlreadyDid
  90. :show="showDialogTrialAlReadyDid"
  91. @close-dialog="showDialogTrialAlReadyDid = false"
  92. />
  93. </div>
  94. </template>
  95. <script setup lang="ts">
  96. import Query from '~/services/data/Query'
  97. import { type Ref, ref } from 'vue'
  98. import { useEntityFetch } from '~/composables/data/useEntityFetch'
  99. import Organization from '~/models/Freemium/Organization'
  100. import Event from '~/models/Freemium/Event'
  101. import OrderBy from '~/services/data/Filters/OrderBy'
  102. import {
  103. FETCHING_STATUS,
  104. ORDER_BY_DIRECTION,
  105. TIME_STRATEGY,
  106. } from '~/types/enum/data'
  107. import PageFilter from '~/services/data/Filters/PageFilter'
  108. import TimeFilter from '~/services/data/Filters/TimeFilter'
  109. import Country from '~/models/Core/Country'
  110. import DateUtils from '~/services/utils/dateUtils'
  111. import UrlUtils from '~/services/utils/urlUtils'
  112. import { useApiLegacyRequestService } from '~/composables/data/useApiLegacyRequestService'
  113. import { useAdminUrl } from '~/composables/utils/useAdminUrl'
  114. definePageMeta({
  115. name: 'freemium_dashboard_page',
  116. })
  117. //Ref Définition
  118. const { fetch, fetchCollection } = useEntityFetch()
  119. const { apiRequestService } = useApiLegacyRequestService()
  120. const { makeAdminUrl } = useAdminUrl()
  121. const tab = ref(null)
  122. const upcomingPage = ref(1)
  123. const pastPage = ref(1)
  124. const showDialogTrialAlReadyDid: Ref<boolean> = ref(false)
  125. //Fetch
  126. const { data: organization, status: statusOrganization } = fetch(Organization)
  127. const {
  128. data: upcomingEvents,
  129. status: statusUpcomingEvents,
  130. refresh: refreshUpcomingEvents,
  131. } = fetchEvents()
  132. const {
  133. data: pastEvents,
  134. status: statusPastEvents,
  135. refresh: refreshPastEvents,
  136. } = fetchEvents(true)
  137. /**
  138. * Charge une page des événements à venir
  139. * @param pageNumber
  140. */
  141. function loadUpcomingEvents(pageNumber: number) {
  142. upcomingPage.value = pageNumber
  143. refreshUpcomingEvents()
  144. }
  145. /**
  146. * Cahrge une page des événements passées
  147. * @param pageNumber
  148. */
  149. function loadPastEvents(pageNumber: number) {
  150. pastPage.value = pageNumber
  151. refreshPastEvents()
  152. }
  153. /**
  154. * Redirige vers la page d'édition d'un événement
  155. * @param eventId
  156. */
  157. function editEvent(eventId: number) {
  158. navigateTo(UrlUtils.join('freemium/events', eventId))
  159. }
  160. /**
  161. * Récupère la liste des événements
  162. * @param past
  163. */
  164. function fetchEvents(past: boolean = false) {
  165. const today = computed(() => DateUtils.formatIsoShortDate(new Date()))
  166. const query = new Query(
  167. new OrderBy(
  168. 'datetimeStart',
  169. past ? ORDER_BY_DIRECTION.DESC : ORDER_BY_DIRECTION.ASC,
  170. ),
  171. new PageFilter(past ? pastPage : upcomingPage, ref(5)),
  172. new TimeFilter(
  173. 'datetimeStart',
  174. today,
  175. past ? TIME_STRATEGY.BEFORE : TIME_STRATEGY.AFTER,
  176. ),
  177. )
  178. return fetchCollection(Event, null, query)
  179. }
  180. /**
  181. * Action lorsque l'on souhaite démarrer l'essai
  182. */
  183. async function startTrial() {
  184. try {
  185. await apiRequestService.get('/trial/is_available')
  186. await navigateTo(makeAdminUrl('trial'), {
  187. external: true,
  188. })
  189. } catch (error) {
  190. showDialogTrialAlReadyDid.value = true
  191. }
  192. }
  193. /**
  194. * Nettoyage du store
  195. */
  196. onUnmounted(() => {
  197. useRepo(Organization).flush()
  198. useRepo(Event).flush()
  199. useRepo(Country).flush()
  200. })
  201. </script>
  202. <style scoped lang="scss">
  203. .tabs-title {
  204. margin-top: 20px;
  205. padding-left: 20px;
  206. background-color: rgb(var(--v-theme-neutral));
  207. .v-tab--selected {
  208. color: rgb(var(--v-theme-on-neutral--clickable));
  209. }
  210. }
  211. .v-card {
  212. margin-bottom: 16px;
  213. color: rgb(var(--v-theme-on-primary-alt));
  214. }
  215. .v-card-text {
  216. div {
  217. line-height: 2;
  218. }
  219. }
  220. .organization_title {
  221. font-weight: 500;
  222. }
  223. .icon-hotel {
  224. margin: 0 5px 4px 0;
  225. }
  226. .btn {
  227. border: 1px solid;
  228. cursor: pointer;
  229. }
  230. .inner-container {
  231. margin: 0 auto;
  232. padding: 30px;
  233. }
  234. .btn_trial {
  235. height: 55px;
  236. background-color: rgb(var(--v-theme-x-create-btn));
  237. color: #000;
  238. span {
  239. text-align: center;
  240. line-height: 1.2; /* optionnel : pour resserrer ou espacer */
  241. }
  242. .v-icon {
  243. transform: rotate(135deg); /* angle en degrés */
  244. font-size: 16px;
  245. padding-right: 5px;
  246. margin: 0 5px 4px 0;
  247. }
  248. }
  249. .btn_edit_orga {
  250. color: rgb(var(--v-theme-on-primary-alt)) !important;
  251. }
  252. .no_event {
  253. padding: 25px;
  254. font-size: 16px;
  255. display: block;
  256. }
  257. </style>