Pārlūkot izejas kodu

apply prettier fix

Olivier Massot 8 mēneši atpakaļ
vecāks
revīzija
9b3eae5708

+ 2 - 2
assets/css/theme.scss

@@ -52,12 +52,12 @@
   color: rgb(var(--v-theme-on-x-create-btn)) !important;
 }
 
-.theme-artist{
+.theme-artist {
   background-color: rgb(var(--v-theme-artist)) !important;
   color: rgb(var(--v-theme-on-surface)) !important;
 }
 
-.theme-school{
+.theme-school {
   background-color: rgb(var(--v-theme-school)) !important;
   color: rgb(var(--v-theme-on-primary)) !important;
 }

+ 1 - 1
components/Layout/Dialog.vue

@@ -85,7 +85,7 @@ const _show = computed(() => props.show) as boolean
     transform: rotate(-180deg);
   }
 
-  .v-icon{
+  .v-icon {
     font-size: 25px;
     transform: rotate(90deg);
     padding-right: 20px;

+ 21 - 10
components/Layout/Dialog/Trial/AlreadyDid.vue

@@ -4,9 +4,21 @@
     <template #dialogTitle>{{ $t('trial_all_ready_did') }}</template>
     <template #dialogText>
       <v-card-text class="text">
-        <p>Au cours des 6 derniers mois, vous avez bénéficié d’un essai gratuit de 30 jours du logiciel Opentalent Artist Premium.</p>
-        <p>Pour continuer à explorer toutes les fonctionnalités de notre solution et optimiser la gestion de votre structure, nous vous invitons à souscrire à l’une de nos offres adaptées à vos besoins.</p>
-        <p>Si toutefois vous souhaitez une réactivation exceptionnelle de l’essai, n’hésitez pas à contacter notre équipe Opentalent. 
Nous serons ravis d’évaluer votre demande et de vous accompagner dans vos projets.</p>
+        <p>
+          Au cours des 6 derniers mois, vous avez bénéficié d’un essai gratuit
+          de 30 jours du logiciel Opentalent Artist Premium.
+        </p>
+        <p>
+          Pour continuer à explorer toutes les fonctionnalités de notre solution
+          et optimiser la gestion de votre structure, nous vous invitons à
+          souscrire à l’une de nos offres adaptées à vos besoins.
+        </p>
+        <p>
+          Si toutefois vous souhaitez une réactivation exceptionnelle de
+          l’essai, n’hésitez pas à contacter notre équipe Opentalent. 
Nous
+          serons ravis d’évaluer votre demande et de vous accompagner dans vos
+          projets.
+        </p>
       </v-card-text>
     </template>
     <template #dialogBtn>
@@ -21,7 +33,6 @@
 </template>
 
 <script setup lang="ts">
-
 const props = defineProps({
   show: {
     type: Boolean,
@@ -42,16 +53,16 @@ const contactOpentalent = async () => {
     open: {
       target: '_blank',
     },
-    external: true
+    external: true,
   })
 }
 </script>
 
 <style scoped lang="scss">
-  .text{
-    font-size: 13px;
-    p{
-      margin-bottom: 10px;
-    }
+.text {
+  font-size: 13px;
+  p {
+    margin-bottom: 10px;
   }
+}
 </style>

+ 24 - 13
components/Layout/Dialog/Trial/StopConfirmation.vue

@@ -1,11 +1,23 @@
 <template>
   <LazyLayoutDialog :show="show" theme="danger">
     <template #dialogType>{{ $t('important') }}</template>
-    <template #dialogTitle>{{ $t('you_want_to_stop_your_premium_trial_period') }} ? </template>
+    <template #dialogTitle
+      >{{ $t('you_want_to_stop_your_premium_trial_period') }} ?
+    </template>
     <template #dialogText>
       <v-card-text class="text">
-        <p>{{ $t('stop_trial_period_warning_1a') }} {{ $t(organizationProfile.productBeforeTrial ?? 'stop_trial_missing_version_label') }}, {{ $t('stop_trial_period_warning_1b') }}</p>
-        <p><strong>{{ $t('stop_trial_period_warning_2') }}</strong></p>
+        <p>
+          {{ $t('stop_trial_period_warning_1a') }}
+          {{
+            $t(
+              organizationProfile.productBeforeTrial ??
+                'stop_trial_missing_version_label',
+            )
+          }}, {{ $t('stop_trial_period_warning_1b') }}
+        </p>
+        <p>
+          <strong>{{ $t('stop_trial_period_warning_2') }}</strong>
+        </p>
         <ul>
           <li>{{ $t('stop_trial_period_warning_3') }}</li>
           <li>{{ $t('stop_trial_period_warning_4') }}</li>
@@ -26,8 +38,7 @@
 </template>
 
 <script setup lang="ts">
-
-import {useOrganizationProfileStore} from "~/stores/organizationProfile";
+import { useOrganizationProfileStore } from '~/stores/organizationProfile'
 
 defineProps({
   show: {
@@ -50,14 +61,14 @@ const stopTrial = () => {
 </script>
 
 <style scoped lang="scss">
-  .text {
-    p {
-      margin-bottom: 10px;
-    }
+.text {
+  p {
+    margin-bottom: 10px;
+  }
 
-    ul {
-      padding-left: 20px;
-      margin-bottom: 10px;
-    }
+  ul {
+    padding-left: 20px;
+    margin-bottom: 10px;
   }
+}
 </style>

+ 1 - 4
components/Layout/Header/Menu.vue

@@ -16,10 +16,7 @@ header principal (configuration, paramètres du compte...)
           :defaultImage="menu.icon.avatarByDefault"
           :width="30"
         /> -->
-        <UiImage
-          :defaultImage="menu.icon.avatarByDefault"
-          :width="30"
-        />
+        <UiImage :defaultImage="menu.icon.avatarByDefault" :width="30" />
       </v-avatar>
 
       <v-icon v-else :icon="menu.icon.name" class="on-primary" />

+ 79 - 75
components/Layout/Pages/Subscription/Card.vue

@@ -1,36 +1,41 @@
 <template>
-    <v-card elevation="2" outlined shaped class="card" :class="{['border-'+color] : true}">
-      <span v-if="extraHeader" class="extraBorder" :class="'extraBorder-'+color">{{extraHeader}}</span>
+  <v-card
+    elevation="2"
+    outlined
+    shaped
+    class="card"
+    :class="{ ['border-' + color]: true }"
+  >
+    <span
+      v-if="extraHeader"
+      class="extraBorder"
+      :class="'extraBorder-' + color"
+      >{{ extraHeader }}</span
+    >
 
-      <!-- Titre -->
-      <v-card-title class="title" :class="{['margin-sup'] : !extraHeader}">
-        {{title}}
-      </v-card-title>
+    <!-- Titre -->
+    <v-card-title class="title" :class="{ ['margin-sup']: !extraHeader }">
+      {{ title }}
+    </v-card-title>
 
-      <v-card-subtitle class="subtitle">
-        {{subTitle}}
-        <slot name="card.subTitle" />
-      </v-card-subtitle>
-
-      <!-- Texte -->
-      <v-card-text>
-        <LayoutPagesSubscriptionList
-          :elements="list"
-          :color="color" />
-      </v-card-text>
-
-      <!-- Actions -->
-      <v-card-actions class="mb-3">
-        <slot name="card.action" />
-      </v-card-actions>
-
-    </v-card>
+    <v-card-subtitle class="subtitle">
+      {{ subTitle }}
+      <slot name="card.subTitle" />
+    </v-card-subtitle>
 
+    <!-- Texte -->
+    <v-card-text>
+      <LayoutPagesSubscriptionList :elements="list" :color="color" />
+    </v-card-text>
 
+    <!-- Actions -->
+    <v-card-actions class="mb-3">
+      <slot name="card.action" />
+    </v-card-actions>
+  </v-card>
 </template>
 
 <script setup lang="ts">
-
 const props = defineProps({
   title: {
     type: String,
@@ -56,61 +61,60 @@ const props = defineProps({
 </script>
 
 <style scoped lang="scss">
+.card {
+  border-width: 1px;
+  border-top-width: 4px;
+  height: 100%;
 
-  .card{
-    border-width: 1px;
-    border-top-width: 4px;
-    height: 100%;
-
-    .title{
-      padding-top: 10px;
-      white-space: normal;
-    }
-    .subtitle{
-      text-transform: uppercase;
-      font-weight: bold;
-      font-size: 1.25rem;
-      opacity: unset;
-    }
-//1280 1670
-    :deep(.v-btn){
-      padding: 10px;
-      width: 100%;
-      @media (min-width:1280px) and (max-width: 1670px) {
-        letter-spacing: 0px;
-        font-size: 11px;
-      }
-    }
+  .title {
+    padding-top: 10px;
+    white-space: normal;
   }
-
-  .extraBorder{
-    text-align: center;
+  .subtitle {
     text-transform: uppercase;
-    margin: auto;
-    border-radius: 0px 0px 5px 5px;
-    width: 90%;
-    padding: 2px 10px 2px 10px;
     font-weight: bold;
-    display: block;
-  }
-  .card.border-primary{
-    border-color: rgb(var(--v-theme-primary));
-  }
-  .card.border-artist{
-    border-color: rgb(var(--v-theme-artist));
-  }
-  .card.border-school{
-    border-color: rgb(var(--v-theme-school));
+    font-size: 1.25rem;
+    opacity: unset;
   }
-  .extraBorder.extraBorder-artist{
-    background: rgb(var(--v-theme-artist));
-  }
-  .extraBorder.extraBorder-school{
-    background: rgb(var(--v-theme-school));
-    color:#fff;
+  //1280 1670
+  :deep(.v-btn) {
+    padding: 10px;
+    width: 100%;
+    @media (min-width: 1280px) and (max-width: 1670px) {
+      letter-spacing: 0px;
+      font-size: 11px;
+    }
   }
+}
 
-  .margin-sup{
-    margin-top: 30px;
-  }
+.extraBorder {
+  text-align: center;
+  text-transform: uppercase;
+  margin: auto;
+  border-radius: 0px 0px 5px 5px;
+  width: 90%;
+  padding: 2px 10px 2px 10px;
+  font-weight: bold;
+  display: block;
+}
+.card.border-primary {
+  border-color: rgb(var(--v-theme-primary));
+}
+.card.border-artist {
+  border-color: rgb(var(--v-theme-artist));
+}
+.card.border-school {
+  border-color: rgb(var(--v-theme-school));
+}
+.extraBorder.extraBorder-artist {
+  background: rgb(var(--v-theme-artist));
+}
+.extraBorder.extraBorder-school {
+  background: rgb(var(--v-theme-school));
+  color: #fff;
+}
+
+.margin-sup {
+  margin-top: 30px;
+}
 </style>

+ 7 - 7
components/Layout/Pages/Subscription/List.vue

@@ -7,7 +7,7 @@
         icon="fa-solid fa-check"
         size="large"
       ></v-icon>
-      <span class="pl-2">{{li}}</span>
+      <span class="pl-2">{{ li }}</span>
     </li>
   </ul>
 </template>
@@ -26,11 +26,11 @@ const props = defineProps({
 </script>
 
 <style scoped lang="scss">
-  ul{
-    list-style: none;
-    .check{
-      font-size: 15px;
-      font-weight: bold;
-    }
+ul {
+  list-style: none;
+  .check {
+    font-size: 15px;
+    font-weight: bold;
   }
+}
 </style>

+ 2 - 2
components/Ui/SystemBar.vue

@@ -8,10 +8,10 @@ System bars
     :class="
       'd-flex flex-row justify-center align-center text-center ' + classes
     "
-    style="z-index: 1006;"
+    style="z-index: 1006"
     @click="onClick !== undefined ? onClick() : null"
   >
-  <!-- Forcing z-index to avoid this : https://github.com/vuetifyjs/nuxt-module/issues/205 -->
+    <!-- Forcing z-index to avoid this : https://github.com/vuetifyjs/nuxt-module/issues/205 -->
     <slot>
       <v-icon v-if="icon" small :icon="icon" />
       {{ text }}

+ 5 - 2
composables/data/useApiLegacyRequestService.ts

@@ -5,7 +5,7 @@ import ApiRequestService from '~/services/data/apiRequestService'
 import { usePageStore } from '~/stores/page'
 import UnauthorizedError from '~/services/error/UnauthorizedError'
 import { useAccessProfileStore } from '~/stores/accessProfile'
-import UrlUtils from "~/services/utils/urlUtils";
+import UrlUtils from '~/services/utils/urlUtils'
 
 /**
  * Retourne une instance de ApiRequestService configurée pour interroger l'api legacy
@@ -16,7 +16,10 @@ let apiRequestServiceClass: null | ApiRequestService = null
 export const useApiLegacyRequestService = () => {
   const runtimeConfig = useRuntimeConfig()
 
-  const baseURL = UrlUtils.join(runtimeConfig.baseUrlLegacy || runtimeConfig.public.baseUrlLegacy, 'api')
+  const baseURL = UrlUtils.join(
+    runtimeConfig.baseUrlLegacy || runtimeConfig.public.baseUrlLegacy,
+    'api',
+  )
 
   const pending: Ref<boolean> = ref(false)
 

+ 1 - 1
composables/utils/useDownloadFromRoute.ts

@@ -11,7 +11,7 @@ export const useDownloadFromRoute = async (route: string, filename: string) => {
   const { apiRequestService } = useAp2iRequestService()
 
   // @ts-expect-error La méthode get renvoie bien un blob dans ce cas là
-  const response = await apiRequestService.get(route) as Blob
+  const response = (await apiRequestService.get(route)) as Blob
 
   if (!response || response.size === 0) {
     console.error('Error: no file found at ' + route)

+ 2 - 2
config/theme.ts

@@ -34,8 +34,8 @@ interface Theme {
     'on-warning': string
     info: string
     'on-info': string
-    artist:string
-    school:string
+    artist: string
+    school: string
 
     // Special cases
     // TODO: voir ceux dont on peut se passer

+ 1 - 1
models/OnlineRegistration/RegistrationStatus.ts

@@ -1,5 +1,5 @@
 import { Str, Uid, Num } from 'pinia-orm/dist/decorators'
-import {IdField} from "~/models/decorators";
+import { IdField } from '~/models/decorators'
 import ApiResource from '~/models/ApiResource'
 
 /**

+ 1 - 1
models/Organization/Cotisation.ts

@@ -1,6 +1,6 @@
 import { Num, Str, Uid } from 'pinia-orm/dist/decorators'
 import ApiResource from '~/models/ApiResource'
-import {IdField} from "~/models/decorators";
+import { IdField } from '~/models/decorators'
 
 /**
  * Ap2i ApiResource : Cotisation

+ 1 - 1
models/Organization/DolibarrAccount.ts

@@ -1,6 +1,6 @@
 import { Attr, Str, Uid, Num } from 'pinia-orm/dist/decorators'
 import ApiResource from '~/models/ApiResource'
-import {IdField} from "~/models/decorators";
+import { IdField } from '~/models/decorators'
 
 /**
  * The Dolibarr account of an organization

+ 1 - 1
models/Organization/MobytUserStatus.ts

@@ -1,6 +1,6 @@
 import { Bool, Num, Uid } from 'pinia-orm/dist/decorators'
 import ApiResource from '~/models/ApiResource'
-import {IdField} from "~/models/decorators";
+import { IdField } from '~/models/decorators'
 
 /**
  * The Mobyt user status of an organization

+ 213 - 213
nuxt.config.ts

@@ -30,216 +30,216 @@ if (process.env.NUXT_ENV === 'dev') {
  * @see https://nuxt.com/docs/api/configuration/nuxt-config
  */
 export default defineNuxtConfig({
- ssr: true,
-
- experimental: {
-   // Fix the 'Cannot stringify non POJO' bug
-   // @see https://github.com/nuxt/nuxt/issues/20787
-   renderJsonPayloads: false,
- },
-
- runtimeConfig: {
-   // Private config that is only available on the server
-   env: '',
-   baseUrl: '',
-   baseUrlLegacy: '',
-   baseUrlAdminLegacy: '',
-   baseUrlTypo3: '',
-   baseUrlMercure: '',
-   fileStorageBaseUrl: '',
-   supportUrl: '',
-   basicomptaUrl: 'https://app.basicompta.fr/',
-   // Config within public will be also exposed to the client
-   public: {
-     env: '',
-     baseUrl: '',
-     baseUrlLegacy: '',
-     baseUrlAdminLegacy: '',
-     baseUrlTypo3: '',
-     baseUrlMercure: '',
-     fileStorageBaseUrl: '',
-     supportUrl: '',
-     basicomptaUrl: 'https://app.basicompta.fr/',
-   },
- },
-
- hooks: {
-   'builder:watch': console.log,
- },
-
- app: {
-   head: {
-     title: 'Opentalent',
-     meta: [
-       { charset: 'utf-8' },
-       { name: 'viewport', content: 'width=device-width, initial-scale=1' },
-       { name: 'msapplication-TileColor', content: '#324250' },
-       {
-         name: 'msapplication-TileImage',
-         content: '/favicon/favicon-144x144.png',
-       },
-     ],
-     link: [
-       { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '57x57',
-         href: '/favicon/apple-touch-icon-57x57.png',
-       },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '114x114',
-         href: '/favicon/apple-touch-icon-114x114.png',
-       },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '72x72',
-         href: '/favicon/apple-touch-icon-72x72.png',
-       },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '144x144',
-         href: '/favicon/apple-touch-icon-144x144.png',
-       },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '120x120',
-         href: '/favicon/apple-touch-icon-120x120.png',
-       },
-       {
-         rel: 'apple-touch-icon-precomposed',
-         sizes: '152x152',
-         href: '/favicon/apple-touch-icon-152x152.png',
-       },
-       {
-         rel: 'icon',
-         sizes: '32x32',
-         type: 'image/x-icon',
-         href: '/favicon/favicon-32x32.png',
-       },
-       {
-         rel: 'icon',
-         sizes: '16x16',
-         type: 'image/x-icon',
-         href: '/favicon/favicon-16x16.png',
-       },
-     ],
-   },
- },
-
- css: [
-   '@/assets/css/global.scss',
-   '@/assets/css/theme.scss',
-   '@/assets/css/import.scss',
-   '@vuepic/vue-datepicker/dist/main.css',
- ],
-
- typescript: {
-   strict: true,
- },
-
- modules: [
-   // eslint-disable-next-line require-await
-   async (_, nuxt) => {
-     nuxt.hooks.hook('vite:extendConfig', (config) =>
-       // @ts-expect-error A revoir après que les lignes aient été décommentées
-       (config.plugins ?? []).push(
-         vuetify(),
-         // Remplacer par cela quand l'issue https://github.com/vuetifyjs/vuetify-loader/issues/273 sera règlée..
-         // voir aussi : https://github.com/nuxt/nuxt/issues/15412 et https://github.com/vuetifyjs/vuetify-loader/issues/290
-         // voir aussi : https://github.com/jrutila/nuxt3-vuetify3-bug
-         // vuetify({
-         //     styles: { configFile: './assets/css/settings.scss' }
-         // })
-       ),
-     )
-   },
-   [
-     '@pinia/nuxt',
-     {
-       autoImports: [
-         // automatically imports `usePinia()`
-         'defineStore',
-         // automatically imports `usePinia()` as `usePiniaStore()`
-         ['defineStore', 'definePiniaStore'],
-       ],
-     },
-   ],
-   '@pinia-orm/nuxt',
-   '@nuxtjs/i18n',
-   '@nuxt/devtools',
-   '@nuxt/image',
-   'nuxt-prepare',
-   'nuxt-vitalizer',
- ],
-
- vite: {
-   esbuild: {
-     drop: process.env.DEBUG ? [] : ['console', 'debugger'],
-     tsconfigRaw: {
-       compilerOptions: {
-         experimentalDecorators: true,
-       },
-     },
-   },
-   ssr: {
-     // with ssr enabled, this config is required to load vuetify properly
-     noExternal: ['vuetify'],
-   },
-   server: {
-     https,
-     // @ts-expect-error J'ignore pourquoi cette erreur TS se produit, cette propriété est valide
-     port: 443,
-     hmr: {
-       protocol: 'wss',
-       port: 24678,
-     },
-   },
- },
-
- // Hide the sourcemaps warnings with vuetify
- // @see https://github.com/vuetifyjs/vuetify-loader/issues/290#issuecomment-1435702713
- sourcemap: {
-   server: false,
-   client: false,
- },
-
- i18n: {
-   langDir: 'lang',
-   lazy: true,
-   strategy: 'no_prefix',
-   locales: [
-     {
-       code: 'en',
-       iso: 'en-US',
-       file: 'en.json',
-       name: 'English',
-     },
-     {
-       code: 'fr',
-       iso: 'fr-FR',
-       file: 'fr.json',
-       name: 'Français',
-     },
-   ],
-   defaultLocale: 'fr',
-   detectBrowserLanguage: false,
-   vueI18n: './i18n.config.ts',
- },
-
- image: {
-   provider: 'none',
- },
-
- build: {
-   transpile,
- },
-
- ignore: [process.env.NUXT_ENV === 'prod' ? 'pages/dev/*' : ''],
-
- prepare: {
-   scripts: ['prepare/buildIndex.ts'],
- },
-
- compatibilityDate: '2025-02-07'
-})
+  ssr: true,
+
+  experimental: {
+    // Fix the 'Cannot stringify non POJO' bug
+    // @see https://github.com/nuxt/nuxt/issues/20787
+    renderJsonPayloads: false,
+  },
+
+  runtimeConfig: {
+    // Private config that is only available on the server
+    env: '',
+    baseUrl: '',
+    baseUrlLegacy: '',
+    baseUrlAdminLegacy: '',
+    baseUrlTypo3: '',
+    baseUrlMercure: '',
+    fileStorageBaseUrl: '',
+    supportUrl: '',
+    basicomptaUrl: 'https://app.basicompta.fr/',
+    // Config within public will be also exposed to the client
+    public: {
+      env: '',
+      baseUrl: '',
+      baseUrlLegacy: '',
+      baseUrlAdminLegacy: '',
+      baseUrlTypo3: '',
+      baseUrlMercure: '',
+      fileStorageBaseUrl: '',
+      supportUrl: '',
+      basicomptaUrl: 'https://app.basicompta.fr/',
+    },
+  },
+
+  hooks: {
+    'builder:watch': console.log,
+  },
+
+  app: {
+    head: {
+      title: 'Opentalent',
+      meta: [
+        { charset: 'utf-8' },
+        { name: 'viewport', content: 'width=device-width, initial-scale=1' },
+        { name: 'msapplication-TileColor', content: '#324250' },
+        {
+          name: 'msapplication-TileImage',
+          content: '/favicon/favicon-144x144.png',
+        },
+      ],
+      link: [
+        { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '57x57',
+          href: '/favicon/apple-touch-icon-57x57.png',
+        },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '114x114',
+          href: '/favicon/apple-touch-icon-114x114.png',
+        },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '72x72',
+          href: '/favicon/apple-touch-icon-72x72.png',
+        },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '144x144',
+          href: '/favicon/apple-touch-icon-144x144.png',
+        },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '120x120',
+          href: '/favicon/apple-touch-icon-120x120.png',
+        },
+        {
+          rel: 'apple-touch-icon-precomposed',
+          sizes: '152x152',
+          href: '/favicon/apple-touch-icon-152x152.png',
+        },
+        {
+          rel: 'icon',
+          sizes: '32x32',
+          type: 'image/x-icon',
+          href: '/favicon/favicon-32x32.png',
+        },
+        {
+          rel: 'icon',
+          sizes: '16x16',
+          type: 'image/x-icon',
+          href: '/favicon/favicon-16x16.png',
+        },
+      ],
+    },
+  },
+
+  css: [
+    '@/assets/css/global.scss',
+    '@/assets/css/theme.scss',
+    '@/assets/css/import.scss',
+    '@vuepic/vue-datepicker/dist/main.css',
+  ],
+
+  typescript: {
+    strict: true,
+  },
+
+  modules: [
+    // eslint-disable-next-line require-await
+    async (_, nuxt) => {
+      nuxt.hooks.hook('vite:extendConfig', (config) =>
+        // @ts-expect-error A revoir après que les lignes aient été décommentées
+        (config.plugins ?? []).push(
+          vuetify(),
+          // Remplacer par cela quand l'issue https://github.com/vuetifyjs/vuetify-loader/issues/273 sera règlée..
+          // voir aussi : https://github.com/nuxt/nuxt/issues/15412 et https://github.com/vuetifyjs/vuetify-loader/issues/290
+          // voir aussi : https://github.com/jrutila/nuxt3-vuetify3-bug
+          // vuetify({
+          //     styles: { configFile: './assets/css/settings.scss' }
+          // })
+        ),
+      )
+    },
+    [
+      '@pinia/nuxt',
+      {
+        autoImports: [
+          // automatically imports `usePinia()`
+          'defineStore',
+          // automatically imports `usePinia()` as `usePiniaStore()`
+          ['defineStore', 'definePiniaStore'],
+        ],
+      },
+    ],
+    '@pinia-orm/nuxt',
+    '@nuxtjs/i18n',
+    '@nuxt/devtools',
+    '@nuxt/image',
+    'nuxt-prepare',
+    'nuxt-vitalizer',
+  ],
+
+  vite: {
+    esbuild: {
+      drop: process.env.DEBUG ? [] : ['console', 'debugger'],
+      tsconfigRaw: {
+        compilerOptions: {
+          experimentalDecorators: true,
+        },
+      },
+    },
+    ssr: {
+      // with ssr enabled, this config is required to load vuetify properly
+      noExternal: ['vuetify'],
+    },
+    server: {
+      https,
+      // @ts-expect-error J'ignore pourquoi cette erreur TS se produit, cette propriété est valide
+      port: 443,
+      hmr: {
+        protocol: 'wss',
+        port: 24678,
+      },
+    },
+  },
+
+  // Hide the sourcemaps warnings with vuetify
+  // @see https://github.com/vuetifyjs/vuetify-loader/issues/290#issuecomment-1435702713
+  sourcemap: {
+    server: false,
+    client: false,
+  },
+
+  i18n: {
+    langDir: 'lang',
+    lazy: true,
+    strategy: 'no_prefix',
+    locales: [
+      {
+        code: 'en',
+        iso: 'en-US',
+        file: 'en.json',
+        name: 'English',
+      },
+      {
+        code: 'fr',
+        iso: 'fr-FR',
+        file: 'fr.json',
+        name: 'Français',
+      },
+    ],
+    defaultLocale: 'fr',
+    detectBrowserLanguage: false,
+    vueI18n: './i18n.config.ts',
+  },
+
+  image: {
+    provider: 'none',
+  },
+
+  build: {
+    transpile,
+  },
+
+  ignore: [process.env.NUXT_ENV === 'prod' ? 'pages/dev/*' : ''],
+
+  prepare: {
+    scripts: ['prepare/buildIndex.ts'],
+  },
+
+  compatibilityDate: '2025-02-07',
+})

+ 412 - 305
pages/subscription.vue

@@ -5,120 +5,166 @@ Page 'Mon abonnement'
 -->
 <template>
   <LayoutContainer>
-      <v-expansion-panels v-model="openedPanels" :multiple="true">
-        <UiExpansionPanel title="subscription_page" icon="fas fa-info">
-          <v-container fluid class="container">
-            <v-row>
-              <v-col cols="12" lg="6" sm="12">
-                {{ $t('version') }} : <strong>{{ dolibarrAccount ? $t(dolibarrAccount.product) : '-' }}</strong>
-              </v-col>
-              <v-col cols="12" lg="6" sm="12">
-                {{ $t('client_id') }} : {{ dolibarrAccount ? dolibarrAccount.clientNumber : '-' }}
-              </v-col>
-            </v-row>
-          </v-container>
-        </UiExpansionPanel>
-
-        <UiExpansionPanel title="service_detail" icon="fas fa-info"
-                          v-if="dolibarrAccount && dolibarrAccount.contract"
-        >
-          <v-container fluid class="container">
-            <v-row>
-              <v-col cols="12"
-                     lg="12"
-                     v-for="line in dolibarrAccount.contract.lines"
-                     :key="line.id"
+    <v-expansion-panels v-model="openedPanels" :multiple="true">
+      <UiExpansionPanel title="subscription_page" icon="fas fa-info">
+        <v-container fluid class="container">
+          <v-row>
+            <v-col cols="12" lg="6" sm="12">
+              {{ $t('version') }} :
+              <strong>{{
+                dolibarrAccount ? $t(dolibarrAccount.product) : '-'
+              }}</strong>
+            </v-col>
+            <v-col cols="12" lg="6" sm="12">
+              {{ $t('client_id') }} :
+              {{ dolibarrAccount ? dolibarrAccount.clientNumber : '-' }}
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiExpansionPanel>
+
+      <UiExpansionPanel
+        title="service_detail"
+        icon="fas fa-info"
+        v-if="dolibarrAccount && dolibarrAccount.contract"
+      >
+        <v-container fluid class="container">
+          <v-row>
+            <v-col
+              cols="12"
+              lg="12"
+              v-for="line in dolibarrAccount.contract.lines"
+              :key="line.id"
+            >
+              <strong>{{ line.serviceLabel }}</strong> - {{ $t('until') }} :
+              {{ $d(line.dateEnd) }}
+            </v-col>
+
+            <v-col cols="12" lg="12" v-if="ability.can('manage', 'texto')">
+              <strong>{{ $t('remaining_sms_credit') }}</strong> -
+              <span
+                v-if="
+                  !mobytPending && mobytStatus !== null && mobytStatus.active
+                "
               >
-                <strong>{{ line.serviceLabel }}</strong> - {{ $t('until') }} : {{ $d(line.dateEnd) }}
-              </v-col>
-
-              <v-col cols="12" lg="12" v-if="ability.can('manage', 'texto')">
-                <strong>{{ $t('remaining_sms_credit') }}</strong> -
-                <span v-if="!mobytPending && mobytStatus !== null && mobytStatus.active">
-                        {{
-                    mobytStatus.money.toLocaleString($i18n.locale, {
-                      style: 'currency',
-                      currency: 'EUR',
-                    })
-                  }}
-                        {{
-                    i18n.t('convert_price_to_sms', {
-                      nb_sms: mobytStatus.amount,
-                    })
-                  }}
-                </span>
-              </v-col>
-            </v-row>
-          </v-container>
-        </UiExpansionPanel>
-
-        <UiExpansionPanel
-          v-if="showDolibarrPanel"
-          title="bills"
-          icon="fas fa-file"
-        >
-          <v-container :fluid="true" class="container">
-            <v-row>
-              <v-table v-if="dolibarrAccount !== null">
-                <thead>
-                  <tr>
-                    <th>{{ $t('reference') }}</th>
-                    <th>{{ $t('date') }}</th>
-                    <th>{{ $t('taxExcludedAmount') }}</th>
-                    <th>{{ $t('status') }}</th>
-                    <th></th>
-                  </tr>
-                </thead>
-                <tbody>
-                  <tr v-for="bill in dolibarrAccount.bills" :key="bill.id">
-                    <td>{{ bill.ref }}</td>
-                    <td>{{ $d(bill.date) }}</td>
-                    <td>
-                      {{
-                        bill.taxExcludedAmount.toLocaleString($i18n.locale, {
-                          style: 'currency',
-                          currency: 'EUR',
-                        })
-                      }}
-                    </td>
-                    <td>
-                      {{ bill.paid === true ? $t('paid') : $t('unpaid') }}
-                    </td>
-                    <td>
-                      <a @click="downloadDolibarrBill(bill.ref)" class="clickable">
-                        {{ $t('download') }}
-                      </a>
-                    </td>
-                  </tr>
-                </tbody>
-              </v-table>
-            </v-row>
-          </v-container>
-        </UiExpansionPanel>
-
-        <UiExpansionPanel title="opentalent_offers" icon="fas fa-plus" v-if="!organizationProfile.isManagerProduct">
-          <v-container fluid class="container">
-            <v-row class="offer_title" v-if="!md && mdAndUp && !organizationProfile.isSchool">
-              <v-col cols="12" :lg="organizationProfile.isArtistPremiumProduct ? 3 : 6" sm="12">
-                <span class="theme-artist">Pour les orchestres, chorales, compagnies et troupes artistiques</span>
-              </v-col>
-              <v-col cols="12" :lg="organizationProfile.isArtistPremiumProduct ? 3 : 5" sm="12" :offset="organizationProfile.isArtistPremiumProduct ? 0 : 1">
-                <span class="theme-school">Pour les établissements d'enseignements artistiques*</span>
-              </v-col>
-            </v-row>
-
-            <v-row class="card-container">
-              <v-col lg="3" sm="12" md="6" v-if="organizationProfile.isArtistProduct">
-                <LayoutPagesSubscriptionCard
+                {{
+                  mobytStatus.money.toLocaleString($i18n.locale, {
+                    style: 'currency',
+                    currency: 'EUR',
+                  })
+                }}
+                {{
+                  i18n.t('convert_price_to_sms', {
+                    nb_sms: mobytStatus.amount,
+                  })
+                }}
+              </span>
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiExpansionPanel>
+
+      <UiExpansionPanel
+        v-if="showDolibarrPanel"
+        title="bills"
+        icon="fas fa-file"
+      >
+        <v-container :fluid="true" class="container">
+          <v-row>
+            <v-table v-if="dolibarrAccount !== null">
+              <thead>
+                <tr>
+                  <th>{{ $t('reference') }}</th>
+                  <th>{{ $t('date') }}</th>
+                  <th>{{ $t('taxExcludedAmount') }}</th>
+                  <th>{{ $t('status') }}</th>
+                  <th></th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr v-for="bill in dolibarrAccount.bills" :key="bill.id">
+                  <td>{{ bill.ref }}</td>
+                  <td>{{ $d(bill.date) }}</td>
+                  <td>
+                    {{
+                      bill.taxExcludedAmount.toLocaleString($i18n.locale, {
+                        style: 'currency',
+                        currency: 'EUR',
+                      })
+                    }}
+                  </td>
+                  <td>
+                    {{ bill.paid === true ? $t('paid') : $t('unpaid') }}
+                  </td>
+                  <td>
+                    <a
+                      @click="downloadDolibarrBill(bill.ref)"
+                      class="clickable"
+                    >
+                      {{ $t('download') }}
+                    </a>
+                  </td>
+                </tr>
+              </tbody>
+            </v-table>
+          </v-row>
+        </v-container>
+      </UiExpansionPanel>
+
+      <UiExpansionPanel
+        title="opentalent_offers"
+        icon="fas fa-plus"
+        v-if="!organizationProfile.isManagerProduct"
+      >
+        <v-container fluid class="container">
+          <v-row
+            class="offer_title"
+            v-if="!md && mdAndUp && !organizationProfile.isSchool"
+          >
+            <v-col
+              cols="12"
+              :lg="organizationProfile.isArtistPremiumProduct ? 3 : 6"
+              sm="12"
+            >
+              <span class="theme-artist"
+                >Pour les orchestres, chorales, compagnies et troupes
+                artistiques</span
+              >
+            </v-col>
+            <v-col
+              cols="12"
+              :lg="organizationProfile.isArtistPremiumProduct ? 3 : 5"
+              sm="12"
+              :offset="organizationProfile.isArtistPremiumProduct ? 0 : 1"
+            >
+              <span class="theme-school"
+                >Pour les établissements d'enseignements artistiques*</span
+              >
+            </v-col>
+          </v-row>
+
+          <v-row class="card-container">
+            <v-col
+              lg="3"
+              sm="12"
+              md="6"
+              v-if="organizationProfile.isArtistProduct"
+            >
+              <LayoutPagesSubscriptionCard
                 class="artistCard"
                 title="Logiciel Artist Standard"
-                :extraHeader="organizationProfile.isArtistProduct ? 'Votre version' : undefined"
+                :extraHeader="
+                  organizationProfile.isArtistProduct
+                    ? 'Votre version'
+                    : undefined
+                "
                 color="artist"
                 :list="listCheck.artist"
               >
                 <template #card.subTitle>
                   <div class="priceBlock">
-                    <span class="price">{{formatCurrency(11, 'EUR')}}</span> TTC/mois
+                    <span class="price">{{ formatCurrency(11, 'EUR') }}</span>
+                    TTC/mois
                   </div>
                 </template>
                 <template #card.action>
@@ -128,180 +174,231 @@ Page 'Mon abonnement'
                     href="https://logiciels.opentalent.fr/opentalent-artist"
                     target="_blank"
                   >
-                    {{ $t('to_know_more') }} <i class="fa-solid fa-greater-than small"></i>
+                    {{ $t('to_know_more') }}
+                    <i class="fa-solid fa-greater-than small"></i>
                   </v-btn>
                 </template>
               </LayoutPagesSubscriptionCard>
-              </v-col>
-
-              <v-col lg="3" sm="12" md="6" v-if="organizationProfile.isArtist">
-                <LayoutPagesSubscriptionCard
-                  class="artistCard"
-                  title="Logiciel Artist Premium*"
-                  :extraHeader="organizationProfile.isArtistPremiumProduct ? (organizationProfile.isTrialActive ? `Version en cours d'essai J-${organizationProfile.trialCountDown}` : 'Votre version') : '1 mois d\'essai offert'"
-                  color="artist"
-                  :list="listCheck.artistPremium"
-                >
-                  <template #card.subTitle>
-                    <div class="priceBlock">
-                      <span class="price">{{organizationProfile.isCmf ? formatCurrency(7.5, 'EUR') : formatCurrency(18.0, 'EUR')}}</span> TTC/mois
-                    </div>
-                  </template>
-                  <template #card.action>
-                    <v-row >
-                      <v-col cols="12" v-if="!organizationProfile.isArtistPremiumProduct && (accessProfileStore.isAdmin || accessProfileStore.isCaMember)">
-                        <v-btn
-                          class="btn trialBtn"
-                          @click="startTrial"
-                        >
-                          {{ $t('try_premium_version') }} <i class="fa-solid fa-greater-than small"></i>
-                        </v-btn>
-                      </v-col>
-                      <v-col cols="12" v-if="(!organizationProfile.isArtistPremiumProduct || organizationProfile.isTrialActive) && (accessProfileStore.isAdmin || accessProfileStore.isCaMember)">
-                        <v-btn
-                          class="theme-artist btn"
-                          @click="subscription"
-                        >
-                          {{ $t('subscribe_to_the_offer') }} <i class="fa-solid fa-greater-than small"></i>
-                        </v-btn>
-                      </v-col>
-
-                      <v-col cols="12" v-if="organizationProfile.isTrialActive && (accessProfileStore.isAdmin || accessProfileStore.isCaMember)">
-                        <v-btn
-                          class="stop_btn"
-                          @click="showStopTrialDialog"
-                        >
-                          {{ $t('stop_trial') }}
-                        </v-btn>
-                      </v-col>
-                      <v-col cols="12">
-                          <span class="special_conditions">
-                          *Convient aux petites écoles sans besoins spécifiques de gestion pédagogique, de facturation, etc.
-                          Pour une solution complète optez pour Opentalent School
-                        </span>
-                      </v-col>
-                    </v-row>
-                  </template>
-                </LayoutPagesSubscriptionCard>
-              </v-col>
-
-              <v-col lg="3" sm="12" md="6" :offset="!md && mdAndUp ? (organizationProfile.isSchool ? 4 : (organizationProfile.isArtistPremiumProduct ? 0 : 2)) : 0">
-                <LayoutPagesSubscriptionCard
-                  class="schoolCard"
-                  :title="!organizationProfile.isSchool ? 'Logiciel School Standard / Premium' : (
-                    organizationProfile.isSchoolPremiumProduct ? 'Logiciel School Premium' : 'Logiciel School Standard'
-                  )"
-                  :subTitle="!organizationProfile.isSchool ? 'Sur devis' : ''"
-                  :extraHeader="organizationProfile.isSchool ? 'Votre version' : undefined"
-                  color="school"
-                  :list="listCheck.school"
-                >
-                  <template #card.action>
-                    <v-row>
-                      <v-col cols="12">
-                        <v-btn
-                          v-if="!organizationProfile.isSchool"
-                          class="theme-school btn"
-                          href="https://logiciels.opentalent.fr/opentalent-school"
-                          target="_blank"
-                        >
-                          {{ $t('to_know_more') }} <i class="fa-solid fa-greater-than small"></i>
-                        </v-btn>
-                      </v-col>
-                      <v-col cols="12">
-                          <span class="special_conditions">
-                          *Extranet disponible uniquement dans la version Opentalent School Premium
-                        </span>
-                      </v-col>
-                    </v-row>
-                  </template>
-                </LayoutPagesSubscriptionCard>
-              </v-col>
-            </v-row>
-          </v-container>
-        </UiExpansionPanel>
-
-        <UiExpansionPanel title="opentalent_options" icon="fas fa-plus">
-          <v-container fluid class="container card-container">
-            <v-row cols="12" >
-              <v-col lg="3" sm="12" md="6">
-                <LayoutPagesSubscriptionCard
-                  class="optionsCard"
-                  title="SMS"
-                  sub-title="Option payante"
-                  color="primary"
-                  :list="listCheck.sms"
-                >
-                  <template #card.action>
-                    <v-btn
-                      class="theme-primary btn"
-                      :href="
-                          runtimeConfig.public.fileStorageBaseUrl +
-                          (organizationProfile.isCmf ? '/Bon_de_commande/Achat_SMS_CMF.pdf' : '/Bon_de_commande/Achat_SMS_Public.pdf')
-                        "
-                      target="_blank"
+            </v-col>
+
+            <v-col lg="3" sm="12" md="6" v-if="organizationProfile.isArtist">
+              <LayoutPagesSubscriptionCard
+                class="artistCard"
+                title="Logiciel Artist Premium*"
+                :extraHeader="
+                  organizationProfile.isArtistPremiumProduct
+                    ? organizationProfile.isTrialActive
+                      ? `Version en cours d'essai J-${organizationProfile.trialCountDown}`
+                      : 'Votre version'
+                    : '1 mois d\'essai offert'
+                "
+                color="artist"
+                :list="listCheck.artistPremium"
+              >
+                <template #card.subTitle>
+                  <div class="priceBlock">
+                    <span class="price">{{
+                      organizationProfile.isCmf
+                        ? formatCurrency(7.5, 'EUR')
+                        : formatCurrency(18.0, 'EUR')
+                    }}</span>
+                    TTC/mois
+                  </div>
+                </template>
+                <template #card.action>
+                  <v-row>
+                    <v-col
+                      cols="12"
+                      v-if="
+                        !organizationProfile.isArtistPremiumProduct &&
+                        (accessProfileStore.isAdmin ||
+                          accessProfileStore.isCaMember)
+                      "
                     >
-                      acheter des credits SMS <i class="fa-solid fa-greater-than small"></i>
-                    </v-btn>
-                  </template>
-                </LayoutPagesSubscriptionCard>
-              </v-col>
-
-              <v-col lg="3" sm="12" md="6">
-                <LayoutPagesSubscriptionCard
-                  class="optionsCard"
-                  title="Nom de domaine"
-                  sub-title="Option payante"
-                  color="primary"
-                  :list="listCheck.domain"
-                >
-                  <template #card.action>
-                    <v-btn
-                      class="theme-primary btn"
-                      :href="
-                          runtimeConfig.public.fileStorageBaseUrl +
-                          '/Bon_de_commande/Nom_de_domaine.pdf'
-                        "
-                      target="_blank"
+                      <v-btn class="btn trialBtn" @click="startTrial">
+                        {{ $t('try_premium_version') }}
+                        <i class="fa-solid fa-greater-than small"></i>
+                      </v-btn>
+                    </v-col>
+                    <v-col
+                      cols="12"
+                      v-if="
+                        (!organizationProfile.isArtistPremiumProduct ||
+                          organizationProfile.isTrialActive) &&
+                        (accessProfileStore.isAdmin ||
+                          accessProfileStore.isCaMember)
+                      "
                     >
-                      souscrire à l'option <i class="fa-solid fa-greater-than small"></i>
-                    </v-btn>
-                  </template>
-                </LayoutPagesSubscriptionCard>
-              </v-col>
-            </v-row>
-          </v-container>
-        </UiExpansionPanel>
-
-      </v-expansion-panels>
-
+                      <v-btn class="theme-artist btn" @click="subscription">
+                        {{ $t('subscribe_to_the_offer') }}
+                        <i class="fa-solid fa-greater-than small"></i>
+                      </v-btn>
+                    </v-col>
+
+                    <v-col
+                      cols="12"
+                      v-if="
+                        organizationProfile.isTrialActive &&
+                        (accessProfileStore.isAdmin ||
+                          accessProfileStore.isCaMember)
+                      "
+                    >
+                      <v-btn class="stop_btn" @click="showStopTrialDialog">
+                        {{ $t('stop_trial') }}
+                      </v-btn>
+                    </v-col>
+                    <v-col cols="12">
+                      <span class="special_conditions">
+                        *Convient aux petites écoles sans besoins spécifiques de
+                        gestion pédagogique, de facturation, etc. Pour une
+                        solution complète optez pour Opentalent School
+                      </span>
+                    </v-col>
+                  </v-row>
+                </template>
+              </LayoutPagesSubscriptionCard>
+            </v-col>
+
+            <v-col
+              lg="3"
+              sm="12"
+              md="6"
+              :offset="
+                !md && mdAndUp
+                  ? organizationProfile.isSchool
+                    ? 4
+                    : organizationProfile.isArtistPremiumProduct
+                      ? 0
+                      : 2
+                  : 0
+              "
+            >
+              <LayoutPagesSubscriptionCard
+                class="schoolCard"
+                :title="
+                  !organizationProfile.isSchool
+                    ? 'Logiciel School Standard / Premium'
+                    : organizationProfile.isSchoolPremiumProduct
+                      ? 'Logiciel School Premium'
+                      : 'Logiciel School Standard'
+                "
+                :subTitle="!organizationProfile.isSchool ? 'Sur devis' : ''"
+                :extraHeader="
+                  organizationProfile.isSchool ? 'Votre version' : undefined
+                "
+                color="school"
+                :list="listCheck.school"
+              >
+                <template #card.action>
+                  <v-row>
+                    <v-col cols="12">
+                      <v-btn
+                        v-if="!organizationProfile.isSchool"
+                        class="theme-school btn"
+                        href="https://logiciels.opentalent.fr/opentalent-school"
+                        target="_blank"
+                      >
+                        {{ $t('to_know_more') }}
+                        <i class="fa-solid fa-greater-than small"></i>
+                      </v-btn>
+                    </v-col>
+                    <v-col cols="12">
+                      <span class="special_conditions">
+                        *Extranet disponible uniquement dans la version
+                        Opentalent School Premium
+                      </span>
+                    </v-col>
+                  </v-row>
+                </template>
+              </LayoutPagesSubscriptionCard>
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiExpansionPanel>
+
+      <UiExpansionPanel title="opentalent_options" icon="fas fa-plus">
+        <v-container fluid class="container card-container">
+          <v-row cols="12">
+            <v-col lg="3" sm="12" md="6">
+              <LayoutPagesSubscriptionCard
+                class="optionsCard"
+                title="SMS"
+                sub-title="Option payante"
+                color="primary"
+                :list="listCheck.sms"
+              >
+                <template #card.action>
+                  <v-btn
+                    class="theme-primary btn"
+                    :href="
+                      runtimeConfig.public.fileStorageBaseUrl +
+                      (organizationProfile.isCmf
+                        ? '/Bon_de_commande/Achat_SMS_CMF.pdf'
+                        : '/Bon_de_commande/Achat_SMS_Public.pdf')
+                    "
+                    target="_blank"
+                  >
+                    acheter des credits SMS
+                    <i class="fa-solid fa-greater-than small"></i>
+                  </v-btn>
+                </template>
+              </LayoutPagesSubscriptionCard>
+            </v-col>
+
+            <v-col lg="3" sm="12" md="6">
+              <LayoutPagesSubscriptionCard
+                class="optionsCard"
+                title="Nom de domaine"
+                sub-title="Option payante"
+                color="primary"
+                :list="listCheck.domain"
+              >
+                <template #card.action>
+                  <v-btn
+                    class="theme-primary btn"
+                    :href="
+                      runtimeConfig.public.fileStorageBaseUrl +
+                      '/Bon_de_commande/Nom_de_domaine.pdf'
+                    "
+                    target="_blank"
+                  >
+                    souscrire à l'option
+                    <i class="fa-solid fa-greater-than small"></i>
+                  </v-btn>
+                </template>
+              </LayoutPagesSubscriptionCard>
+            </v-col>
+          </v-row>
+        </v-container>
+      </UiExpansionPanel>
+    </v-expansion-panels>
   </LayoutContainer>
 
   <LayoutDialogTrialAlreadyDid
     :show="showDialogTrialAllReadyDid"
-    @closeDialog = "showDialogTrialAllReadyDid = false"
+    @closeDialog="showDialogTrialAllReadyDid = false"
   />
 
   <LayoutDialogTrialStopConfirmation
     :show="showDialogTrialStopConfirmation"
-    @closeDialog = "showDialogTrialStopConfirmation = false"
-    @stopTrial = "stopTrial"
+    @closeDialog="showDialogTrialStopConfirmation = false"
+    @stopTrial="stopTrial"
   />
 </template>
 
 <script setup lang="ts">
-import {useAbility} from '@casl/vue'
-import type {Ref} from 'vue'
-import {useDisplay} from 'vuetify'
-import type {AsyncData} from '#app'
-import {useOrganizationProfileStore} from '~/stores/organizationProfile'
-import {useEntityFetch} from '~/composables/data/useEntityFetch'
+import { useAbility } from '@casl/vue'
+import type { Ref } from 'vue'
+import { useDisplay } from 'vuetify'
+import type { AsyncData } from '#app'
+import { useOrganizationProfileStore } from '~/stores/organizationProfile'
+import { useEntityFetch } from '~/composables/data/useEntityFetch'
 import DolibarrAccount from '~/models/Organization/DolibarrAccount'
 import MobytUserStatus from '~/models/Organization/MobytUserStatus'
-import UrlUtils from '~/services/utils/urlUtils';
-import {useDownloadFromRoute} from '~/composables/utils/useDownloadFromRoute';
-import {useApiLegacyRequestService} from "~/composables/data/useApiLegacyRequestService";
-import {usePageStore} from "~/stores/page";
+import UrlUtils from '~/services/utils/urlUtils'
+import { useDownloadFromRoute } from '~/composables/utils/useDownloadFromRoute'
+import { useApiLegacyRequestService } from '~/composables/data/useApiLegacyRequestService'
+import { usePageStore } from '~/stores/page'
 
 //meta
 definePageMeta({
@@ -311,8 +408,8 @@ definePageMeta({
 //Get composables
 const ability = useAbility()
 const runtimeConfig = useRuntimeConfig()
-const {mdAndUp, md} = useDisplay()
-const {fetch} = useEntityFetch()
+const { mdAndUp, md } = useDisplay()
+const { fetch } = useEntityFetch()
 const i18n = useI18n()
 const { apiRequestService } = useApiLegacyRequestService()
 
@@ -324,7 +421,7 @@ const organizationProfile = getOrganizationProfile()
 const accessProfileStore = useAccessProfileStore()
 const { mobytStatus, mobytPending } = getMobytInformations()
 
-const {data: dolibarrAccount, pending: dolibarrPending} = fetch(
+const { data: dolibarrAccount, pending: dolibarrPending } = fetch(
   DolibarrAccount,
   organizationProfile.id,
 )
@@ -343,14 +440,14 @@ const formatCurrency = (value: number, currency: string): string => {
 }
 
 const listCheck: Record<string, Array<string>> = {
-  'artist' : [
+  artist: [
     '100 Mo de stockage',
     '75 comptes utilisateurs',
     'Gestion de la structure',
     'Site internet restreint',
     'Options disponibles',
   ],
-  'artistPremium' : [
+  artistPremium: [
     '1Go de stockage',
     '150 comptes utilisateurs',
     'Gestion de la structure',
@@ -358,7 +455,7 @@ const listCheck: Record<string, Array<string>> = {
     'Site internet illimité',
     'Options disponibles',
   ],
-  'school' : [
+  school: [
     '500 Mo ou 1Go de stockage',
     '3 comptes administrateurs',
     'Extranet élèves, tuteurs, professeurs*',
@@ -367,14 +464,14 @@ const listCheck: Record<string, Array<string>> = {
     'Site internet complet',
     'Options adaptées à chaque structure',
   ],
-  'sms': [
+  sms: [
     'Envoyez des SMS depuis votre logiciel',
-    'Choisissez le nombre de crédits'
+    'Choisissez le nombre de crédits',
   ],
-  'domain':[
+  domain: [
     'Bénéficiez de votre propre nom de domaine',
-    'Et d\'une adresse mail personnalisée'
-  ]
+    "Et d'une adresse mail personnalisée",
+  ],
 }
 
 /**
@@ -385,7 +482,13 @@ function initPanel(): Ref<Array<string>> {
   // TODO: quand le bug ci dessus est résolu, remplacer par `const openedPanels: Ref<Array<string>> = ref([...])`
   const openedPanels: Ref<Array<string>> = ref([])
   onMounted(() => {
-    openedPanels.value = ['subscription_page', 'service_detail', 'bills', 'opentalent_offers', 'opentalent_options']
+    openedPanels.value = [
+      'subscription_page',
+      'service_detail',
+      'bills',
+      'opentalent_offers',
+      'opentalent_options',
+    ]
   })
   return openedPanels
 }
@@ -404,12 +507,15 @@ function getOrganizationProfile() {
 /**
  * Récupération des informations Mobyt
  */
-function getMobytInformations(): { mobytStatus: Ref<MobytUserStatus | null>; mobytPending: Ref<boolean> } {
+function getMobytInformations(): {
+  mobytStatus: Ref<MobytUserStatus | null>
+  mobytPending: Ref<boolean>
+} {
   let mobytStatus: Ref<MobytUserStatus | null> = ref(null)
   let mobytPending: Ref<boolean> = ref(false)
 
   if (ability.can('manage', 'texto')) {
-    const {data, pending} = fetch(
+    const { data, pending } = fetch(
       MobytUserStatus,
       organizationProfile!.id!,
     ) as AsyncData<MobytUserStatus | null, Error | null>
@@ -420,18 +526,19 @@ function getMobytInformations(): { mobytStatus: Ref<MobytUserStatus | null>; mob
   return { mobytStatus, mobytPending }
 }
 
-
 /**
  * Action lorsque l'on souhaite démarrer l'essai
  */
-async function startTrial(){
-  try{
+async function startTrial() {
+  try {
     await apiRequestService.get('/trial/is_available')
-    const v1BaseURL = runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
+    const v1BaseURL =
+      runtimeConfig.baseUrlAdminLegacy ||
+      runtimeConfig.public.baseUrlAdminLegacy
     await navigateTo(UrlUtils.join(v1BaseURL, '#', 'trial'), {
-      external: true
+      external: true,
     })
-  }catch(error){
+  } catch (error) {
     showDialogTrialAllReadyDid.value = true
   }
 }
@@ -439,17 +546,18 @@ async function startTrial(){
 /**
  * Action lorsque l'on souhaite souscrire à artist premium
  */
-async function subscription(){
-  const v1BaseURL = runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
+async function subscription() {
+  const v1BaseURL =
+    runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
   await navigateTo(UrlUtils.join(v1BaseURL, '#', 'subscribe'), {
-    external: true
+    external: true,
   })
 }
 
 /**
  * Action lorsque l'on souhaite afficher la modal de confirmation pour stopper
  */
-function showStopTrialDialog(){
+function showStopTrialDialog() {
   showDialogTrialStopConfirmation.value = true
 }
 
@@ -459,13 +567,13 @@ function showStopTrialDialog(){
 async function stopTrial() {
   usePageStore().loading = true
   await apiRequestService.post('/trial/stop')
-  const v1BaseURL = runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
+  const v1BaseURL =
+    runtimeConfig.baseUrlAdminLegacy || runtimeConfig.public.baseUrlAdminLegacy
   await navigateTo(UrlUtils.join(v1BaseURL, '#', 'dashboard'), {
-    external: true
+    external: true,
   })
 }
 
-
 const downloadDolibarrBill = (ref: string): void => {
   const route = UrlUtils.join('api/dolibarr/download/invoice', ref)
 
@@ -473,15 +581,14 @@ const downloadDolibarrBill = (ref: string): void => {
 }
 </script>
 
-
 <style scoped lang="scss">
 .clickable {
   cursor: pointer;
   text-decoration: underline;
 }
 
-.offer_title{
-  span{
+.offer_title {
+  span {
     border-radius: 5px;
     display: block;
     font-weight: bold;
@@ -490,60 +597,60 @@ const downloadDolibarrBill = (ref: string): void => {
   }
 }
 
-.card-container{
+.card-container {
   .v-row {
     display: -webkit-box;
     display: -webkit-flex;
     display: -ms-flexbox;
-    display:  flex;
+    display: flex;
     flex-wrap: wrap;
   }
   .v-row > [class*='v-col-'] {
     display: flex;
     flex-direction: column;
   }
-  .small{
-    font-size:6px;
+  .small {
+    font-size: 6px;
     padding-top: 5px;
     padding-left: 5px;
   }
-  .priceBlock{
+  .priceBlock {
     text-align: center;
     font-size: 15px;
     font-weight: normal;
-    .price{
+    .price {
       font-size: 30px;
       font-weight: bold;
     }
   }
 }
 
-.artistCard{
-  :deep(.v-card-title){
+.artistCard {
+  :deep(.v-card-title) {
     text-align: center;
   }
 }
 
-.special_conditions{
+.special_conditions {
   font-size: 10px;
 }
 
-.trialBtn{
+.trialBtn {
   color: #000;
   border: 1px solid rgb(var(--v-theme-artist));
 }
 
-.optionsCard{
-  :deep(.margin-sup){
+.optionsCard {
+  :deep(.margin-sup) {
     margin-top: 0;
   }
 }
 
-.stop_btn{
+.stop_btn {
   color: rgb(var(--v-theme-danger));
 }
 
-.plus_btn{
+.plus_btn {
   color: rgb(var(--v-theme-on-neutral));
 }
 </style>

+ 16 - 14
services/data/normalizer/hydraNormalizer.ts

@@ -1,7 +1,7 @@
 import * as _ from 'lodash-es'
-import type {AnyJson, ApiResponse, HydraMetadata} from '~/types/data'
+import type { AnyJson, ApiResponse, HydraMetadata } from '~/types/data'
 import UrlUtils from '~/services/utils/urlUtils'
-import {METADATA_TYPE} from '~/types/enum/data'
+import { METADATA_TYPE } from '~/types/enum/data'
 import models from '~/models/models'
 import ApiResource from '~/models/ApiResource'
 
@@ -76,7 +76,7 @@ class HydraNormalizer {
   protected static getMetadata(data: AnyJson): HydraMetadata {
     if (data['@type'] !== 'hydra:Collection') {
       // A single item, no metadata
-      return {type: METADATA_TYPE.ITEM}
+      return { type: METADATA_TYPE.ITEM }
     }
 
     const metadata: HydraMetadata = {
@@ -163,15 +163,14 @@ class HydraNormalizer {
 
     throw new Error(
       'De-normalization error : Could not determine the type of the entity ' +
-      item['@id'] +
-      ' (found: ' +
-      entity +
-      ')',
+        item['@id'] +
+        ' (found: ' +
+        entity +
+        ')',
     )
   }
 
   protected static denormalizeEntity(model: typeof ApiResource, item: AnyJson) {
-
     item['id'] = this.getItemIdValue(model, item)
 
     // eslint-disable-next-line new-cap
@@ -235,14 +234,14 @@ class HydraNormalizer {
     iri: string,
     expectedEntity: string,
   ): number | string {
-    const {entity, id} = HydraNormalizer.parseEntityIRI(iri)
+    const { entity, id } = HydraNormalizer.parseEntityIRI(iri)
     if (entity !== expectedEntity) {
       throw new Error(
         "IRI entity does not match the field's target entity (" +
-        entity +
-        ' != ' +
-        expectedEntity +
-        ')',
+          entity +
+          ' != ' +
+          expectedEntity +
+          ')',
       )
     }
     return id
@@ -259,7 +258,10 @@ class HydraNormalizer {
       return item.id
     }
 
-    if (model.getIdField() !== undefined && item[model.getIdField()] !== undefined) {
+    if (
+      model.getIdField() !== undefined &&
+      item[model.getIdField()] !== undefined
+    ) {
       return item[model.getIdField()]
     }