|
@@ -0,0 +1,251 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <v-container fluid class="inner-container">
|
|
|
|
|
+ <v-row>
|
|
|
|
|
+ <!-- Bloc événements -->
|
|
|
|
|
+ <v-col cols="12" md="7">
|
|
|
|
|
+ <v-card>
|
|
|
|
|
+ <v-tabs v-model="tab" class="tabs-title">
|
|
|
|
|
+ <v-tab value="future">{{$t('futur_event')}}</v-tab>
|
|
|
|
|
+ <v-tab value="past">{{$t('past_event')}}</v-tab>
|
|
|
|
|
+ </v-tabs>
|
|
|
|
|
+
|
|
|
|
|
+ <v-btn color="primary" to="events/new" class="ml-5 mt-5">{{$t('add_event')}}</v-btn>
|
|
|
|
|
+
|
|
|
|
|
+ <v-tabs-window v-model="tab">
|
|
|
|
|
+ <v-tabs-window-item value="future">
|
|
|
|
|
+ <UiLoadingPanel v-if="statusUpcomingEvents == FETCHING_STATUS.PENDING" />
|
|
|
|
|
+
|
|
|
|
|
+ <UiEventList
|
|
|
|
|
+ v-if="statusUpcomingEvents == FETCHING_STATUS.SUCCESS && upcomingEvents?.items"
|
|
|
|
|
+ :events="upcomingEvents.items"
|
|
|
|
|
+ :pagination="upcomingEvents.pagination"
|
|
|
|
|
+ @load="loadUpcomingEvents"
|
|
|
|
|
+ @edit="editEvent"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span v-if="upcomingEvents.items.length == 0" class="no_event">
|
|
|
|
|
+ {{$t('no_future_event')}}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </v-tabs-window-item>
|
|
|
|
|
+ <v-tabs-window-item value="past">
|
|
|
|
|
+ <UiLoadingPanel v-if="statusPastEvents == FETCHING_STATUS.PENDING" />
|
|
|
|
|
+
|
|
|
|
|
+ <UiEventList
|
|
|
|
|
+ v-if="statusPastEvents == FETCHING_STATUS.SUCCESS && pastEvents?.items"
|
|
|
|
|
+ :events="pastEvents.items"
|
|
|
|
|
+ :pagination="pastEvents.pagination"
|
|
|
|
|
+ @load="loadPastEvents"
|
|
|
|
|
+ @edit="editEvent"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span v-if="pastEvents.items.length == 0" class="no_event">
|
|
|
|
|
+ {{$t('no_past_event')}}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </v-tabs-window-item>
|
|
|
|
|
+ </v-tabs-window>
|
|
|
|
|
+
|
|
|
|
|
+ </v-card>
|
|
|
|
|
+ </v-col>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Bloc structure -->
|
|
|
|
|
+ <v-col cols="12" md="5">
|
|
|
|
|
+ <v-card v-if="statusOrganization == FETCHING_STATUS.SUCCESS" class="pa-5">
|
|
|
|
|
+ <v-card-title class="text-h6" >
|
|
|
|
|
+ <v-icon icon="fa fa-hotel" class="text-button icon-hotel" />
|
|
|
|
|
+ <span class="organization_title">{{$t('my_organization')}}</span>
|
|
|
|
|
+ </v-card-title>
|
|
|
|
|
+ <v-card-text>
|
|
|
|
|
+ <div><strong>{{$t('name')}} :</strong> {{ organization?.name }}</div>
|
|
|
|
|
+ <div><strong>{{$t('email')}} :</strong> {{ organization?.email }}</div>
|
|
|
|
|
+ </v-card-text>
|
|
|
|
|
+ </v-card>
|
|
|
|
|
+
|
|
|
|
|
+ <v-btn block class="mb-2 btn btn_edit_orga" to="organization">
|
|
|
|
|
+ <i class="fa fa-pen mr-2" />{{$t('edit_organization')}}
|
|
|
|
|
+ </v-btn>
|
|
|
|
|
+
|
|
|
|
|
+ <v-btn block class="text-black btn btn_trial" @click="startTrial">
|
|
|
|
|
+ <span><v-icon icon="fa fa-ticket" /> {{$t('try_premium_light')}}<br /> {{$t('30_days_free')}}</span>
|
|
|
|
|
+ </v-btn>
|
|
|
|
|
+
|
|
|
|
|
+ </v-col>
|
|
|
|
|
+ </v-row>
|
|
|
|
|
+
|
|
|
|
|
+ </v-container>
|
|
|
|
|
+
|
|
|
|
|
+ <LayoutDialogTrialAlreadyDid
|
|
|
|
|
+ :show="showDialogTrialAlReadyDid"
|
|
|
|
|
+ @close-dialog="showDialogTrialAlReadyDid = false"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+
|
|
|
|
|
+import Query from "~/services/data/Query";
|
|
|
|
|
+
|
|
|
|
|
+definePageMeta({
|
|
|
|
|
+ name: 'freemium_dashboard_page',
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+import {type Ref, ref} from 'vue'
|
|
|
|
|
+import {useEntityFetch} from "~/composables/data/useEntityFetch";
|
|
|
|
|
+import Organization from "~/models/Freemium/Organization";
|
|
|
|
|
+import Event from "~/models/Freemium/Event";
|
|
|
|
|
+import type {AsyncData} from "#app";
|
|
|
|
|
+import OrderBy from "~/services/data/Filters/OrderBy";
|
|
|
|
|
+import {FETCHING_STATUS, ORDER_BY_DIRECTION, TIME_STRATEGY} from "~/types/enum/data";
|
|
|
|
|
+import PageFilter from "~/services/data/Filters/PageFilter";
|
|
|
|
|
+import TimeFilter from "~/services/data/Filters/TimeFilter";
|
|
|
|
|
+import Country from "~/models/Core/Country";
|
|
|
|
|
+import DateUtils from "~/services/utils/dateUtils";
|
|
|
|
|
+import UrlUtils from "~/services/utils/urlUtils";
|
|
|
|
|
+import {useApiLegacyRequestService} from "~/composables/data/useApiLegacyRequestService";
|
|
|
|
|
+import {useAdminUrl} from "~/composables/utils/useAdminUrl";
|
|
|
|
|
+
|
|
|
|
|
+//Ref Définition
|
|
|
|
|
+const runtimeConfig = useRuntimeConfig()
|
|
|
|
|
+const { fetch, fetchCollection } = useEntityFetch()
|
|
|
|
|
+const { apiRequestService } = useApiLegacyRequestService()
|
|
|
|
|
+const {makeAdminUrl} = useAdminUrl()
|
|
|
|
|
+const tab = ref(null)
|
|
|
|
|
+const upcomingPage = ref(1)
|
|
|
|
|
+const pastPage = ref(1)
|
|
|
|
|
+const showDialogTrialAlReadyDid: Ref<boolean> = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+//Fetch
|
|
|
|
|
+const { data: organization, status:statusOrganization } = fetch(Organization)
|
|
|
|
|
+const { data: upcomingEvents, status: statusUpcomingEvents, refresh: refreshUpcomingEvents } = fetchEvents()
|
|
|
|
|
+const { data: pastEvents, status: statusPastEvents, refresh: refreshPastEvents } = fetchEvents(true)
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Charge une page des événements à venir
|
|
|
|
|
+ * @param pageNumber
|
|
|
|
|
+ */
|
|
|
|
|
+function loadUpcomingEvents(pageNumber: number) {
|
|
|
|
|
+ upcomingPage.value = pageNumber
|
|
|
|
|
+ refreshPastEvents()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Cahrge une page des événements passées
|
|
|
|
|
+ * @param pageNumber
|
|
|
|
|
+ */
|
|
|
|
|
+function loadPastEvents(pageNumber: number) {
|
|
|
|
|
+ pastPage.value = pageNumber
|
|
|
|
|
+ refreshPastEvents()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Redirige vers la page d'édition d'un événement
|
|
|
|
|
+ * @param eventId
|
|
|
|
|
+ */
|
|
|
|
|
+function editEvent(eventId: number) {
|
|
|
|
|
+ navigateTo(UrlUtils.join('events', eventId))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Récupère la liste des événements
|
|
|
|
|
+ * @param past
|
|
|
|
|
+ */
|
|
|
|
|
+function fetchEvents(past:boolean = false){
|
|
|
|
|
+ const today = computed(() => DateUtils.formatIsoShortDate(new Date()))
|
|
|
|
|
+ const query =
|
|
|
|
|
+ new Query(
|
|
|
|
|
+ new OrderBy('datetimeStart', past ? ORDER_BY_DIRECTION.DESC : ORDER_BY_DIRECTION.ASC),
|
|
|
|
|
+ new PageFilter(past ? pastPage : upcomingPage, ref(5)),
|
|
|
|
|
+ new TimeFilter('datetimeStart', today, past ? TIME_STRATEGY.BEFORE : TIME_STRATEGY.AFTER)
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return fetchCollection(Event, null, query)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Action lorsque l'on souhaite démarrer l'essai
|
|
|
|
|
+ */
|
|
|
|
|
+async function startTrial() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await apiRequestService.get('/trial/is_available')
|
|
|
|
|
+ await navigateTo(makeAdminUrl('trial'), {
|
|
|
|
|
+ external: true,
|
|
|
|
|
+ })
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ showDialogTrialAlReadyDid.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Nettoyage du store
|
|
|
|
|
+ */
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ useRepo(Organization).flush()
|
|
|
|
|
+ useRepo(Event).flush()
|
|
|
|
|
+ useRepo(Country).flush()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+
|
|
|
|
|
+.tabs-title{
|
|
|
|
|
+ margin-top: 20px;
|
|
|
|
|
+ padding-left: 20px;
|
|
|
|
|
+ background-color: rgb(var(--v-theme-neutral));
|
|
|
|
|
+ .v-tab--selected{
|
|
|
|
|
+ color: rgb(var(--v-theme-on-neutral--clickable));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+.v-card {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ color: rgb(var(--v-theme-on-neutral));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.v-card-text{
|
|
|
|
|
+ div{
|
|
|
|
|
+ line-height: 2;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.organization_title{
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.icon-hotel{
|
|
|
|
|
+ margin: 0 5px 4px 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn {
|
|
|
|
|
+ border: 1px solid;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.inner-container {
|
|
|
|
|
+ margin: 0 auto;
|
|
|
|
|
+ padding: 30px;
|
|
|
|
|
+}
|
|
|
|
|
+.btn_trial {
|
|
|
|
|
+ height: 55px;
|
|
|
|
|
+ background-color: rgb(var(--v-theme-standout));
|
|
|
|
|
+ color: #000;
|
|
|
|
|
+
|
|
|
|
|
+ span {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ line-height: 1.2; /* optionnel : pour resserrer ou espacer */
|
|
|
|
|
+ }
|
|
|
|
|
+ .v-icon {
|
|
|
|
|
+ transform: rotate(135deg); /* angle en degrés */
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ padding-right: 5px;
|
|
|
|
|
+ margin: 0 5px 4px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn_edit_orga {
|
|
|
|
|
+ color: rgb(var(--v-theme-on-neutral)) !important;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.no_event{
|
|
|
|
|
+ padding: 25px;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|