| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- <!--
- Menu principal de l'application
- Prend en paramètre une liste de ItemMenu et les met en forme
- -->
- <template>
- <v-navigation-drawer
- v-model="displayMenu"
- :rail="isRail"
- :disable-resize-watcher="true"
- class="theme-secondary main-menu"
- >
- <div
- v-if="organizationProfile.isArtist && (accessProfile.isCaMember || accessProfile.isAdmin)"
- class="btn_trial"
- :class="{['btn_mini'] : isRail}"
- @click="trialAction()"
- ><v-icon icon="fa fa-ticket" /> <span v-if="!isRail">{{btnLabel}}</span></div>
- <template #prepend>
- <slot name="title"></slot>
- </template>
- <v-list open-strategy="single" active-class="active" class="left-menu">
- <!-- TODO: que se passe-t-il si le menu ne comprend qu'un seul MenuItem? -->
- <div v-for="(item, i) in items" :key="i">
- <!-- Cas 1 : l'item n'a pas d'enfants, c'est un lien (ou le menu est en mode réduit) -->
- <v-list-item
- v-if="!item.children || isRail"
- :title="$t(item.label)"
- :prepend-icon="item.icon.name"
- :href="!isInternalLink(item) ? item.to : undefined"
- :to="isInternalLink(item) ? item.to : undefined"
- :target="item.target"
- exact
- height="48px"
- class="menu-item"
- />
- <!-- Cas 2 : l'item a des enfants, c'est un groupe -->
- <v-list-group
- v-else
- expand-icon="fas fa-angle-down"
- collapse-icon="fas fa-angle-up"
- >
- <template #activator="{ props }">
- <v-list-item
- v-bind="props"
- :prepend-icon="item.icon.name"
- :title="$t(item.label)"
- class="theme-secondary menu-item"
- height="48px"
- />
- </template>
- <v-list-item
- v-for="child in item.children"
- :key="$t(child.label)"
- :title="$t(child.label)"
- :prepend-icon="child.icon.name"
- :href="!isInternalLink(child) ? child.to : undefined"
- :to="isInternalLink(child) ? child.to : undefined"
- exact
- height="38px"
- class="theme-secondary-alt"
- />
- </v-list-group>
- </div>
- </v-list>
- <template #append>
- <slot name="foot"></slot>
- </template>
- </v-navigation-drawer>
- <DialogTrialAllReadyDid
- :show="showDialog"
- @closeDialog = "showDialog = false"
- />
- </template>
- <script setup lang="ts">
- import { useMenu } from '~/composables/layout/useMenu'
- import { computed } from '@vue/reactivity'
- import { useDisplay } from 'vuetify'
- import type { MenuGroup, MenuItem } from '~/types/layout'
- import UrlUtils from "~/services/utils/urlUtils";
- import {useAp2iRequestService} from "~/composables/data/useAp2iRequestService";
- const runtimeConfig = useRuntimeConfig()
- const i18n = useI18n()
- const organizationProfile = useOrganizationProfileStore()
- const accessProfile = useAccessProfileStore()
- const { getMenu, hasMenu, isInternalLink, setMenuState, isMenuOpened } = useMenu()
- const { apiRequestService } = useAp2iRequestService()
- const { mdAndUp, lgAndUp } = useDisplay()
- const showDialog: Ref<boolean> = ref(false)
- const menu = getMenu('Main')
- // En vue lg+, on affiche toujours le menu
- const displayMenu = computed(() => {
- return menu !== null && hasMenu('Main') && (lgAndUp.value || isOpened.value)
- })
- const isOpened = computed(() => isMenuOpened('Main'))
- const items: Array<MenuGroup | MenuItem> = getItems(menu)
- // En vue md+, fermer le menu le passe simplement en mode rail
- // Sinon, le fermer le masque complètement
- const isRail = computed(() => {
- return (
- menu !== null &&
- mdAndUp.value &&
- !isOpened.value &&
- !items.some((item) => item.expanded)
- )
- })
- const btnLabel = computed(() => {
- return organizationProfile.principalType === 'ARTISTIC_PRACTICE_ONLY' ? i18n.t('try_premium') : i18n.t('discover_offer')
- })
- const unwatch = watch(lgAndUp, (newValue, oldValue) => {
- // Par défaut si l'écran est trop petit au chargement de la page, le menu doit rester fermé.
- if (process.client && menu !== null) {
- setMenuState('Main', lgAndUp.value)
- }
- })
- onUnmounted(() => {
- unwatch()
- })
- /**
- * Lorsque l'on appuie sur le bouton pour démarrer l'essai / découvrir les offres
- */
- const trialAction = async () => {
- if(organizationProfile.principalType === 'ARTISTIC_PRACTICE_ONLY'){
- try{
- const apiV1BaseURL = runtimeConfig.baseUrlLegacy || runtimeConfig.public.baseUrlLegacy
- await apiRequestService.get(
- UrlUtils.join(apiV1BaseURL, '/api/trial/is_available')
- )
- const v1BaseURL = runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
- await navigateTo(UrlUtils.join(v1BaseURL, '#', 'trial'), {
- external: true
- })
- }catch(error){
- showDialog.value = true
- }
- }else{
- await navigateTo('/subscription')
- }
- }
- /**
- * Récupère les menuItem disponibles
- * @param menu
- */
- function getItems(menu: MenuGroup|MenuItem|null) : Array<MenuGroup | MenuItem>{
- let items: Array<MenuGroup | MenuItem>
- if (menu === null) {
- items = []
- } else if (menu.hasOwnProperty('children')) {
- items = (menu as MenuGroup).children ?? []
- } else {
- items = [menu]
- }
- return items;
- }
- </script>
- <style scoped lang="scss">
- .v-list-item {
- min-height: 10px !important;
- }
- :deep(.v-list-item-title),
- :deep(.v-icon) {
- font-size: 14px;
- color: rgb(var(--v-theme-on-secondary));
- }
- .v-list-item__prepend {
- margin: 10px 0;
- margin-right: 10px !important;
- }
- .v-application--is-ltr .v-list-group--no-action > .v-list-group__header {
- margin-left: 0;
- padding-left: 0;
- }
- .v-application--is-ltr
- .v-list-group--no-action
- > .v-list-group__items
- > .v-list-item {
- padding-left: 30px;
- }
- .v-list-item__content {
- padding: 8px 0;
- }
- .v-list-group__items .v-list-item {
- padding-inline-start: 30px !important;
- }
- .v-list-group--no-action > .v-list-group__header,
- .v-list-item {
- border-left: 3px solid rgb(var(--v-theme-secondary));
- height: 48px;
- }
- .v-list-item:hover,
- .v-list-item.active,
- :deep(.v-list-group__items .v-list-item) {
- border-left: 3px solid rgb(var(--v-theme-primary));
- background-color: rgb(var(--v-theme-secondary-alt)) !important;
- color: rgb(var(--v-theme-on-secondary-alt)) !important;
- }
- :deep(.v-list-group__items .v-list-item-title) {
- color: rgb(var(--v-theme-on-secondary-alt));
- }
- :deep(.v-list-group__items .v-icon) {
- color: rgb(var(--v-theme-on-secondary-alt));
- }
- :deep(.v-list-item .v-icon) {
- margin-right: 10px;
- }
- :deep(.menu-item .fa) {
- text-align: center;
- }
- .btn_trial{
- background-color: rgb(var(--v-theme-x-create-btn));
- border-radius: 5px;
- border: 1px solid #fff;
- margin-left: 15px;
- margin-right: 15px;
- font-size: 12px;
- text-align: center;
- color:#000;
- margin-top: 5px;
- padding: 5px;
- padding-left: 10px;
- padding-right: 10px;
- cursor: pointer;
- .v-icon{
- font-size: 15px;
- color:#000;
- padding-right: 5px;
- }
- }
- .btn_mini{
- font-size: 17px;
- margin-left: 7px;
- margin-right: 7px;
- padding: 0px;
- .v-icon{
- padding-right: 0px;
- }
- }
- </style>
|