浏览代码

Merge V8-5674-recette--refactoring

Olivier Massot 1 年之前
父节点
当前提交
2be7d9a4da
共有 100 个文件被更改,包括 6229 次插入7843 次删除
  1. 5 1
      .eslintrc.yaml
  2. 9 9
      .gitlab-ci.yml
  3. 2 0
      .nuxtignore
  4. 1 1
      .nvmrc
  5. 0 2
      .prettierrc
  6. 5 3
      README.md
  7. 5 1
      app.vue
  8. 2 0
      assets/style/.gitignore
  9. 12 5
      assets/style/main.scss
  10. 73 0
      assets/style/theme.scss
  11. 0 39
      components/About/Banner.vue
  12. 198 200
      components/About/Chronologie.vue
  13. 104 140
      components/About/Equipe.vue
  14. 45 41
      components/About/FAQ.vue
  15. 0 127
      components/About/Histoire.vue
  16. 125 120
      components/About/Logiciels.vue
  17. 0 125
      components/About/MenuScroll.vue
  18. 128 0
      components/About/Presentation.vue
  19. 49 85
      components/About/Valeurs.vue
  20. 197 0
      components/Common/ActionMenu.vue
  21. 119 114
      components/Common/Agenda.vue
  22. 52 0
      components/Common/Avantages.vue
  23. 64 62
      components/Common/Banner.vue
  24. 0 72
      components/Common/Banner/BannerTitle.vue
  25. 0 109
      components/Common/Card/AvantageCard.vue
  26. 98 0
      components/Common/Card/Benefit.vue
  27. 23 26
      components/Common/Card/Stat.vue
  28. 122 0
      components/Common/Carousel/Clients.vue
  29. 129 210
      components/Common/Carousel/Fonctionnalite.vue
  30. 0 142
      components/Common/Carousel/TrustCompanie.vue
  31. 47 79
      components/Common/ContainerVideo.vue
  32. 48 68
      components/Common/MenuScroll.vue
  33. 176 210
      components/Common/Presentation.vue
  34. 0 203
      components/Common/ReviewCard.vue
  35. 213 0
      components/Common/ReviewSection.vue
  36. 84 0
      components/Common/Share.vue
  37. 0 142
      components/Common/StickyMenu.vue
  38. 96 106
      components/Common/Table/Comparatif.vue
  39. 92 0
      components/Contact/AddressSection.vue
  40. 12 343
      components/Contact/Banner.vue
  41. 355 0
      components/Contact/Form.vue
  42. 138 0
      components/Contact/Map.vue
  43. 4 0
      components/Form/Application.vue
  44. 0 96
      components/Formation/Banner.vue
  45. 181 185
      components/Formation/Catalogue.vue
  46. 22 27
      components/Formation/Certification.vue
  47. 26 47
      components/Formation/OPCA.vue
  48. 48 58
      components/Formation/Participation.vue
  49. 42 58
      components/Formation/Presentation.vue
  50. 12 39
      components/Formation/Reviews.vue
  51. 0 187
      components/Formation/Solutions.vue
  52. 18 29
      components/Home/Besoin.vue
  53. 218 254
      components/Home/Caroussel.vue
  54. 45 47
      components/Home/EventAgenda.vue
  55. 133 145
      components/Home/Help.vue
  56. 0 299
      components/Home/News.vue
  57. 194 237
      components/Home/Promotion.vue
  58. 228 224
      components/Home/Reviews.vue
  59. 197 317
      components/Home/Solution.vue
  60. 0 56
      components/JoinUs/Banner.vue
  61. 185 0
      components/JoinUs/MissionDetail.vue
  62. 214 140
      components/JoinUs/Missions.vue
  63. 67 0
      components/Layout/AnchoredSection.vue
  64. 77 0
      components/Layout/Captcha.vue
  65. 2 17
      components/Layout/Container.vue
  66. 113 146
      components/Layout/FAQ.vue
  67. 216 283
      components/Layout/Footer/Footer.vue
  68. 49 66
      components/Layout/Footer/Prefooter.vue
  69. 41 53
      components/Layout/Footer/Solutions.vue
  70. 194 259
      components/Layout/Navigation.vue
  71. 63 0
      components/Layout/Navigation/Topbar.vue
  72. 35 0
      components/Layout/Pagination.vue
  73. 23 52
      components/Layout/UI/SubTitle.vue
  74. 17 23
      components/Layout/UI/Title.vue
  75. 22 43
      components/Layout/UI/TitlePage.vue
  76. 62 84
      components/Logiciels/Artist/Abonnement.vue
  77. 14 56
      components/Logiciels/Artist/Avantages.vue
  78. 0 29
      components/Logiciels/Artist/Banner.vue
  79. 58 71
      components/Logiciels/Artist/Comparatif.vue
  80. 17 26
      components/Logiciels/Artist/Fonctionnalites.vue
  81. 61 132
      components/Logiciels/Artist/Formations.vue
  82. 24 21
      components/Logiciels/Artist/Presentation.vue
  83. 18 11
      components/Logiciels/Artist/Reviews.vue
  84. 74 0
      components/Logiciels/Artist/SomeNumbers.vue
  85. 0 61
      components/Logiciels/Manager/Agenda.vue
  86. 14 67
      components/Logiciels/Manager/Avantages.vue
  87. 0 33
      components/Logiciels/Manager/Banner.vue
  88. 11 21
      components/Logiciels/Manager/Fonctionnalites.vue
  89. 73 156
      components/Logiciels/Manager/Formation.vue
  90. 49 0
      components/Logiciels/Manager/Network.vue
  91. 34 44
      components/Logiciels/Manager/Presentation.vue
  92. 0 98
      components/Logiciels/Manager/Projet.vue
  93. 0 67
      components/Logiciels/Manager/Pyramide.vue
  94. 20 17
      components/Logiciels/Manager/Reviews.vue
  95. 0 181
      components/Logiciels/Manager/Solutions.vue
  96. 106 0
      components/Logiciels/Manager/SomeNumbers.vue
  97. 0 324
      components/Logiciels/School/Agenda.vue
  98. 10 48
      components/Logiciels/School/Avantages.vue
  99. 0 37
      components/Logiciels/School/Banner.vue
  100. 70 87
      components/Logiciels/School/Comparatif.vue

+ 5 - 1
.eslintrc.yaml

@@ -1,5 +1,6 @@
 env:
   browser: true
+  node: true
 parser: vue-eslint-parser
 parserOptions:
   parser: '@typescript-eslint/parser'
@@ -8,11 +9,14 @@ parserOptions:
 plugins:
   - vue
   - '@typescript-eslint'
-extends: 
+extends:
+  - '@nuxtjs/eslint-config-typescript',
   - eslint:recommended
   - plugin:vue/recommended
   - plugin:nuxt/recommended
   - plugin:@typescript-eslint/recommended
+  - plugin:vue/vue3-recommended
+  - plugin:prettier/recommended
 rules:
   vue/multi-word-component-names: off
   vue/no-multiple-template-root: off

+ 9 - 9
.gitlab-ci.yml

@@ -12,13 +12,13 @@ before_script:
 qa:
   stage: qa
   script:
-    - yarn lint 
+    - yarn lint
 
-deploy_test:
-  stage: deploy_test
-  script:
-    # - apt-get update -qq && apt-get install -y -qq sshpass
-    # - ssh exploitation@test5 "cd /var/opentalent/git/portail_v2 && nvm exec yarn deploy && echo 'Deploy successful' "
-    - ssh exploitation@test3 'ls /tmp'
-  only:
-    - home
+#deploy_test:
+#  stage: deploy_test
+#  script:
+#    # - apt-get update -qq && apt-get install -y -qq sshpass
+#    # - ssh exploitation@test5 "cd /var/opentalent/git/portail_v2 && nvm exec yarn deploy && echo 'Deploy successful' "
+#    - ssh exploitation@test3 'ls /tmp'
+#  only:
+#    - home

+ 2 - 0
.nuxtignore

@@ -0,0 +1,2 @@
+.git/*
+coverage

+ 1 - 1
.nvmrc

@@ -1 +1 @@
-18.10.0
+18.19.0

+ 0 - 2
.prettierrc

@@ -1,6 +1,4 @@
 {
-  "name": "frames",
-  "version": "1.0.0",
   "prettier": {
     "tabWidth": 2,
     "singleQuote": true,

+ 5 - 3
README.md

@@ -6,9 +6,11 @@ Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introdu
 
 Make sure to install the dependencies:
 
-````bash
-# yarn
-yarn install
+    yarn install
+
+Créer le symlink vers le bon fichier env (remplacer <environnement> par l'env courant):
+
+    ln -s .env.<environnement> .env
 
 ## Development Server
 

+ 5 - 1
app.vue

@@ -2,4 +2,8 @@
   <nuxt-page />
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+</script>
+
+<!-- TODO: voir si possible de factoriser les consignes 'custom-row' un peu partout -->
+<!-- TODO: voir si possible d'utilser des sections pour factoriser les marges entre les sections d'une page -->

+ 2 - 0
assets/style/.gitignore

@@ -0,0 +1,2 @@
+*.css
+*.map

+ 12 - 5
assets/css/main.css → assets/style/main.scss

@@ -1,11 +1,12 @@
 @import url('https://fonts.googleapis.com/css2?family=Barlow:wght@500;700&display=swap');
 
-h1, h2, h3, h4, h5, h6, p, small, .btn-event, .btn-contact, .formation-btn, td, .button-faq, li, .btn-school, .btn-artist, .btn-manager, .name, .school, .view-button,
-.presentation-title, .subtitle
-.status {
-  font-family: "Barlow";
+body {
+  font-family: "Barlow", serif;
   font-style: normal;
+
+  --banner-center-image: 20%;
 }
+
 .table-row {
   background-color: white;
   text-align: center;
@@ -15,8 +16,14 @@ h1, h2, h3, h4, h5, h6, p, small, .btn-event, .btn-contact, .formation-btn, td,
 .table-data-left {
   text-align: left;
 }
-.row-custom{
+
+.center-90 {
   width: 90%;
   margin-right: auto;
   margin-left: auto;
 }
+.v-row.center-90 {
+  margin: -12px auto;
+}
+
+

+ 73 - 0
assets/style/theme.scss

@@ -0,0 +1,73 @@
+
+body {
+  --neutral-color: #ffffff;
+  --primary-color-alt: #fef3ce;
+  --on-neutral-color: #000000;
+  --on-neutral-color-light: #888888;
+  --on-neutral-color-extra-light: #d9d9d9;
+  --primary-color: #0e2d32;
+  --on-primary-color: #ffffff;
+  --on-primary-color-alt: #caf5f4;
+  --secondary-color: #9edbdd;
+  --on-secondary-color: #262626;
+  --neutral-color-alt: #dbdbdb;
+  --neutral-color-alt-strong: #999999;
+  --on-neutral-color-alt: #000000;
+
+  --standard-theme: #ffffff;
+  --on-standard-theme: #000000;
+
+  --alt-theme: #0e2d32;
+  --on-alt-theme: #ffffff;
+
+  --artist-color: #FAC20A;
+  --school-color: #2093be;
+  --manager-color: #D8050B;
+
+  --action-menu-primary-color: #0e2d32;
+  --action-menu-on-primary-color: #ffffff;
+  --action-menu-secondary-color: #9edbdd;
+  --action-menu-on-secondary-color: #262626;
+
+  --artist-color-light: #fef3ce;
+  --school-color-light: #9edbdd;
+  --manager-color-light: #f7cdce;
+}
+
+body {
+  // Le thème inversé dans le thème standard est équivalent au thème alternatif
+  .inv-theme {
+    background-color: var(--alt-theme);
+    color: var(--on-alt-theme) !important;
+
+    .v-btn {
+      border-color: var(--on-alt-theme) !important;
+    }
+  }
+  .inv-theme * {
+    color: var(--on-alt-theme) !important;
+  }
+
+  // Thème alternatif
+  .alt-theme {
+    background-color: var(--alt-theme);
+    color: var(--on-alt-theme) !important;
+
+    .v-btn {
+      border-color: var(--on-alt-theme) !important;
+    }
+  }
+
+  .alt-theme * {
+    color: var(--on-alt-theme) !important;
+  }
+
+  // Thème inversé
+  .alt-theme .inv-theme {
+    background-color: var(--standard-theme);
+    color: var(--on-standard-theme) !important;
+  }
+  .alt-theme .inv-theme * {
+    color: var(--on-standard-theme) !important;
+  }
+}

+ 0 - 39
components/About/Banner.vue

@@ -1,39 +0,0 @@
-<template>
-  <LayoutContainer>
-    <LayoutUITitlePage title="Qui sommes-nous ?" />
-
-    <v-row>
-      <v-col cols="12">
-        <CommonBanner
-          :imageSrc="'/images/banner/about_opentalent.png'"
-          imageAlt="'line'"
-        />
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-:deep().logiciel {
-  font-family: "Barlow";
-  font-style: normal;
-  font-size: 3rem;
-  line-height: 85px;
-  text-align: center;
-  color: #000000;
-  width: 100%;
-}
-
-:deep().text-left,
-:deep().text-right,
-:deep().description-square,
-:deep().black-square,
-:deep().blue-square {
-  display: none;
-}
-:deep().text-right {
-  display: none;
-}
-</style>

+ 198 - 200
components/About/Chronologie.vue

@@ -1,119 +1,121 @@
 <template>
-  <LayoutContainer id="story" v-if="!mdAndDown">
-    <v-container >
-      <v-row class="mb-6 mt-6">
-        <v-col cols="6">
-          <LayoutUISubTitle
-            :title-color="'#fff'"
-            :titleText="'découvrez toute notre histoire'"
-            class="mb-12"
-          />
-        </v-col>
+  <AnchoredSection id="history">
+    <LayoutContainer class="alt-theme">
+      <v-container >
+        <v-row class="mb-6 mt-6">
+          <v-col cols="6">
+            <LayoutUISubTitle>
+              Découvrez toute notre histoire
+            </LayoutUISubTitle>
+          </v-col>
 
-        <v-col cols="6">
-          <div class="d-flex align-center">
-            <div class="carousel-button" @click="previousAction">
-              <i class="fas fa-chevron-left"></i>
-            </div>
-            <div class="carousel-button" @click="nextAction">
-              <i class="fas fa-chevron-right"></i>
+          <v-col cols="6">
+            <div class="carousel-controls">
+              <v-btn
+                icon="fas fa-chevron-left"
+                @click="goPrevious"
+              />
+              <v-btn
+                icon="fas fa-chevron-right"
+                @click="goNext"
+              />
             </div>
-          </div>
-        </v-col>
-      </v-row>
-    </v-container>
-    <v-row class="mb-12">
-      <v-col cols="12">
-        <Carousel
-          ref="functionCarousel"
-          :items-to-show="2"
-          :items-to-scroll="1"
-          :wrap-around="true"
-        >
-          <v-row> </v-row>
-          <Slide
-            v-for="(slide, index) in slides"
-            :key="slide.id"
-            :class="{
-              'active-slide': index === activeSlide,
-              'inactive-slide': index !== activeSlide,
-            }"
-            @click="setActiveSlide(index)"
+          </v-col>
+        </v-row>
+      </v-container>
+
+      <v-row class="mb-12">
+        <v-col cols="12">
+          <Carousel
+            v-model="activeSlide"
+            ref="carousel"
+            :items-to-show="2"
+            :items-to-scroll="1"
+            :wrap-around="true"
           >
-            <v-row justify="center" class="carousel-row">
-              <v-col cols="4" class="carousel-col">
-                <div
-                  class="carousel__item"
-                  :style="{ backgroundImage: 'url(' + slide.imageUrl + ')' }"
-                ></div>
-              </v-col>
+            <Slide
+              v-for="(slide, index) in slides"
+              :key="slide.title"
+              :class="{'active': index === activeSlide}"
+            >
+              <v-row justify="center">
+                <v-col cols="4">
+                  <div class="image-container">
+                    <v-img :src="slide.imageUrl" cover />
+                  </div>
+                </v-col>
 
-              <v-col cols="4" class="carousel-col">
-                <div class="description-container">
-                  <h3 class="year">{{ slide.year }}</h3>
-                  <h4 class="title-slide" v-html="slide.title"></h4>
-                  <p class="description mb-6" v-html="slide.description"></p>
-                </div>
-              </v-col>
-              <div class="timeline-container">
-                <div v-if="slide.year" class="timeline">
+                <v-col cols="4">
+                  <div class="description-container">
+                    <h3>
+                      {{ slide.year }}
+                    </h3>
+
+                    <h4>
+                      {{ slide.title }}
+                    </h4>
+
+                    <p class="mb-6">
+                      {{ slide.description }}
+                    </p>
+                  </div>
+                </v-col>
+
+                <div class="timeline-container">
                   <div
-                    class="timeline-point"
-                    :style="{
-                      left: calculateTimelinePosition(slide.year) + '%',
-                    }"
+                    v-if="slide.year"
+                    class="timeline"
                   >
-                    <p
-                      class="timeline-year"
-                      style="color: white; font-weight: bold"
+                    <div
+                      class="timeline-point"
+                      :style="{
+                        left: computePositionOnTimeline(slide.year) + '%',
+                      }"
                     >
-                      {{ slide.year }}
-                    </p>
+                      <p class="timeline-year">
+                        {{ slide.year }}
+                      </p>
+                    </div>
                   </div>
                 </div>
-              </div>
-            </v-row>
-          </Slide>
-        </Carousel>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
+              </v-row>
+            </Slide>
+          </Carousel>
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
 
-<script setup>
+<script setup lang="ts">
 import { useDisplay } from "vuetify";
-import { Carousel, Navigation, Slide } from "vue3-carousel";
+import { Carousel, Slide } from "vue3-carousel";
 import "vue3-carousel/dist/carousel.css";
-const functionCarousel = ref(null);
-const activeSlide = ref(0);
-const { smAndDown, mdAndDown } = useDisplay();
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { ChronologyItem } from "~/types/interface";
 
-const setActiveSlide = (index) => {
-  activeSlide.value = index;
-};
-const nextAction = () => {
-  functionCarousel.value.next();
-  activeSlide.value = activeSlide.value + 1;
-};
+const activeSlide: Ref<number> = ref(0);
 
-const previousAction = () => {
-  functionCarousel.value.prev();
-  activeSlide.value = activeSlide.value - 1;
-};
+const { mdAndDown } = useDisplay();
+
+const carousel: Ref<typeof Carousel | null> = ref(null);
+
+const goPrevious = () => carousel.value!.prev();
+const goNext = () => carousel.value!.next();
+
+const computePositionOnTimeline = (year: string) => {
+  const intYear = parseInt(year)
 
-const calculateTimelinePosition = (year) => {
-  if (!year) {
+  if (!intYear || isNaN(intYear)) {
     return 0;
   }
   const startYear = 2005;
   const endYear = 2024;
-  const position = ((year - startYear) / (endYear - startYear)) * 100;
-  return position;
+  return ((intYear - startYear) / (endYear - startYear)) * 100;
 };
 
-const slides = [
+const slides: Array<ChronologyItem> = [
   {
-    id: 1,
     year: "2005",
     title: "L'origine d'Opentalent",
     description:
@@ -121,7 +123,6 @@ const slides = [
     imageUrl: "/images/about/Origine-Opentalent-outil-collaboratif-pour-la-culture.jpg",
   },
   {
-    id: 2,
     year: "2006",
     title: "Développement et partenariat stratégique",
     description:
@@ -129,7 +130,6 @@ const slides = [
     imageUrl: "/images/about/Developpement-et-partenariat-stratégique-Opentalent.jpg",
   },
   {
-    id: 3,
     year: "2008",
     title: "Naissance de l'entreprise 2iOpenservice",
     description:
@@ -137,7 +137,6 @@ const slides = [
     imageUrl: "/images/about/idee.png",
   },
   {
-    id: 4,
     year: "2009",
     title: "MusAssos - la réponse aux besoins pour les petites structures",
     description:
@@ -145,7 +144,6 @@ const slides = [
     imageUrl: "/images/about/idee.png",
   },
   {
-    id: 5,
     year: "2010",
     title: "CMF Réseau <br> l'innovation communautaire",
     description:
@@ -153,7 +151,6 @@ const slides = [
     imageUrl: "/images/about/idee.png",
   },
   {
-    id: 6,
     year: "2014",
     title: "Vers une Culture Multidisciplinaire avec FFEC",
     description:
@@ -161,7 +158,6 @@ const slides = [
     imageUrl: "/images/about/idee.png",
   },
   {
-    id: 7,
     year: "2015",
     title: "Refonte Technologique",
     description:
@@ -169,7 +165,6 @@ const slides = [
     imageUrl: "/images/about/Refonte-du-site-internet-Opentalent-agenda-et-logiciels-culturels.jpg",
   },
   {
-    id: 8,
     year: "2019",
     title: "Nouvelle Génération Opentalent",
     description:
@@ -177,7 +172,6 @@ const slides = [
     imageUrl: "/images/about/Nouvelle-génération-Opentalent-moderne-securisee-experience-optimisee.jpg",
   },
   {
-    id: 9,
     year: "2024",
     title: "Relooking du site Opentalent",
     description:
@@ -185,7 +179,7 @@ const slides = [
     imageUrl: "/images/about/idee.png",
   },
   {
-    id: 10,
+    year: "",
     title: "LE FUTUR AVEC VOUS... ",
     description:
       "Opentalent, plus qu'une gamme de logiciels ou un agenda culturel, c'est une aventure collective. Ensemble, poursuivons cette quête d'innovation et de partage culturel. <br> Rejoignez-nous dans cette aventure passionnante et façonnons l'avenir de la culture. <br> <strong> Opentalent, c'est vous ! </strong>",
@@ -194,120 +188,124 @@ const slides = [
 ];
 </script>
 
-<style scoped>
-.active-slide {
-  opacity: 1;
-  transform: scale(1.1);
-  transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
-}
-
-.inactive-slide {
-  opacity: 0.5;
-  transition: opacity 0.3s ease-in-out;
-}
-.timeline-year {
-  position: relative;
-  top: 1rem;
-  left: -1rem;
-  font-size: 1.2rem;
-  color: white;
-  font-weight: bold;
-}
-.timeline-container {
-  width: 90%;
-  padding: 10px 0;
-}
-
-.timeline {
-  top: 1rem;
-  height: 1px;
-  background-color: #ddd;
-  position: relative;
+<style scoped lang="scss">
+.v-col {
+  padding: 0;
 }
 
-.timeline-point {
-  position: relative;
-  top: 15px;
-  width: 5px;
-  height: 5px;
-  border-radius: 50%;
-  background-color: white;
-}
-.carousel-button {
+.carousel-controls {
   display: flex;
+  flex-direction: row;
   justify-content: center;
   align-items: center;
-  width: 60px;
-  height: 60px;
-  background-color: transparent;
-  border: 2px solid #fff;
-  cursor: pointer;
-  margin-right: 1rem;
-}
 
-.carousel-button i {
-  color: #fff;
-}
-.container {
-  background-color: #0e2d32;
-}
-.carousel-row {
-  height: 32rem;
+  .v-btn {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 60px;
+    height: 60px;
+    background-color: transparent;
+    border: 2px solid;
+    cursor: pointer;
+    margin-right: 1rem;
+    margin-bottom: 2rem;
+    border-radius: 0;
+  }
 }
 
-.carousel-col {
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-}
+.carousel {
+  .carousel__slide {
+    opacity: 0.5;
+    transition: opacity 0.3s ease-in-out;
+  }
+  .carousel__slide.active {
+    opacity: 1;
+    transform: scale(1.1);
+    transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
+  }
 
-.carousel__item,
-.description-container {
-  height: 300px;
-  width: 300px;
-}
+  .v-row {
+    height: 32rem;
+  }
 
-.carousel__item {
-  width: 100%;
-  background-image: url("/images/about/idee.png");
-  background-size: cover;
-}
+  .v-col {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+  }
 
-.v-col {
-  padding: 0;
-}
+  .image-container,
+  .description-container {
+    height: 300px;
+    width: 300px;
+  }
 
-.description {
-  align-items: center;
-  padding: 1rem;
-  font-size: 0.8rem;
-  color: #95dee9;
-}
+  .image-container {
+    .v-img {
+      height: 100%;
+      width: 100%;
+      border-top-left-radius: 20%;
+      border-bottom-left-radius: 20%;
+    }
+  }
 
-.title-slide {
-  justify-content: flex-end;
-  align-items: center;
-  font-size: 1rem;
-}
+  .description-container {
+    padding: 1rem;
+    text-align: center;
+    margin-left: 1rem;
+    background-color: var(--primary-color);
+    color: var(--on-primary-color);
+    border-top-right-radius: 20%;
+    border-bottom-right-radius: 20%;
 
-.year {
-  font-size: 1.8rem;
-}
+    h3 {
+      font-size: 1.8rem;
+    }
 
-.description-container {
-  padding: 1rem;
-  text-align: center;
-  margin-left: 1rem;
-  background-color: #091d20;
-  color: white;
-  border-top-right-radius: 20%;
-  border-bottom-right-radius: 20%;
+    h4 {
+      justify-content: flex-end;
+      align-items: center;
+      font-size: 1rem;
+    }
+
+    p {
+      align-items: center;
+      padding: 1rem;
+      font-size: 0.8rem;
+      color: var(--secondary-color);
+    }
+  }
 }
-.carousel__item {
-  height: 300px;
-  width: 300px;
-  background-image: url("/images/about/idee.png");
-  border-top-left-radius: 20%;
-  border-bottom-left-radius: 20%;
+
+.timeline-container {
+  width: 90%;
+  padding: 10px 0;
+
+  .timeline {
+    top: 1rem;
+    height: 1px;
+    background-color: var(--neutral-color-alt);
+    position: relative;
+  }
+
+  .timeline-point {
+    position: relative;
+    top: 15px;
+    width: 5px;
+    height: 5px;
+    border-radius: 50%;
+    background-color: var(--neutral-color);
+  }
+
+  .timeline-year {
+    position: relative;
+    top: 1rem;
+    left: -1rem;
+    font-size: 1.2rem;
+    color: var(--neutral-color);
+    font-weight: bold;
+  }
 }
 </style>

+ 104 - 140
components/About/Equipe.vue

@@ -1,154 +1,134 @@
 <template>
-  <LayoutContainer id="team">
-    <v-row class="mt-12 custom-row">
-      <LayoutUISubTitle
-        :iconSize="6"
-        :iconClasses="iconClasses"
-        :titleText="'notre équipe'"
-      />
-    </v-row>
-    <v-row class="custom-row">
-      <LayoutUITitle title="Une équipe spécialisée et passionnée" />
-      <h4 class="details ml-4 mt-6 mb-12">
-        Chez Opentalent, on recherche des compétences mais surtout des hommes et
-        des femmes qui souhaitent s'engager dans un projet porteur de sens.
-      </h4>
-    </v-row>
-
-    <v-row class="custom-row">
-      <v-col
-        cols="12"
-        sm="6"
-        md="4"
-        lg="3"
-        v-for="chef in chefs"
-        :key="chef.id"
-      >
-        <v-card>
-          <v-img :src="chef.photo" height="370px"></v-img>
-          <v-card-title class="name">{{ chef.nom }}</v-card-title>
-          <v-card-subtitle class="poste">{{ chef.poste }}</v-card-subtitle>
-          <!-- <v-card-text clas>{{ chef.description }}</v-card-text> -->
-        </v-card>
-      </v-col>
-    </v-row>
-
-    <v-row class="custom-row">
-      <v-col
-        cols="12"
-        sm="6"
-        md="4"
-        lg="3"
-        v-for="employe in employes"
-        :key="employe.id"
-      >
-        <v-card>
-          <v-img :src="employe.photo" height="370px"></v-img>
-          <v-card-title class="name"> {{ employe.nom }}</v-card-title>
-          <v-card-subtitle class="poste">{{ employe.poste }}</v-card-subtitle>
-          <!-- <v-card-text>{{ employe.description }}</v-card-text> -->
-        </v-card>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
+  <AnchoredSection id="team">
+    <LayoutContainer class="mb-12">
+      <v-row class="mt-12 center-90">
+        <LayoutUISubTitle>
+          Notre équipe
+        </LayoutUISubTitle>
+      </v-row>
+
+      <v-row class="center-90">
+        <LayoutUITitle>
+          Une équipe spécialisée et passionnée
+        </LayoutUITitle>
+
+        <span class="details ml-4 mt-6 mb-12">
+          Chez Opentalent, on recherche des compétences mais surtout des hommes et
+          des femmes qui souhaitent s'engager dans un projet porteur de sens.
+        </span>
+      </v-row>
+
+      <v-row class="center-90">
+        <v-col
+          cols="12" sm="6" md="4" lg="3"
+          v-for="associate in associates"
+          :key="associate.name"
+        >
+          <v-card>
+            <v-img
+              :src="associate.photo"
+              :height="370"
+            />
+
+            <v-card-title class="name">
+              {{ associate.name }}
+            </v-card-title>
+
+            <v-card-subtitle class="position">
+              {{ associate.position }}
+            </v-card-subtitle>
+          </v-card>
+        </v-col>
+      </v-row>
+
+      <v-row class="center-90">
+        <v-col
+          cols="12" sm="6" md="4" lg="3"
+          v-for="employee in employees"
+          :key="employee.name"
+        >
+          <v-card>
+            <v-img
+              :src="employee.photo"
+              :height="370"
+            />
+
+            <v-card-title class="name">
+              {{ employee.name }}
+            </v-card-title>
+
+            <v-card-subtitle class="position">
+              {{ employee.position }}
+            </v-card-subtitle>
+          </v-card>
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { SocietyMember } from "~/types/interface";
 
-const chefs = ref([
+const associates: Array<SocietyMember> = [
   {
-    id: 1,
-    nom: "Guillaume",
-    poste: "Fondateur / DIRECTEUR COMMERCIAL",
+    name: "Guillaume",
+    position: "Fondateur / DIRECTEUR COMMERCIAL",
     photo: "/images/about/equipe/Guillaume_CORCOBA-co-fondateur_et_Gerant.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore.",
   },
   {
-    id: 1,
-    nom: "Michel",
-    poste: "FONDATEUR / Directeur développement",
+    name: "Michel",
+    position: "FONDATEUR / Directeur développement",
     photo: "/images/about/equipe/Michel_PERNET-SOLLIET-Co-fondateur_et_Product_Owner.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore.",
   },
-]);
+];
 
-const employes = ref([
+const employees: Array<SocietyMember> = [
   {
-    id: 1,
-    nom: "Johan",
-    poste: " FORMATEUR",
+    name: "Johan",
+    position: " FORMATEUR",
     photo: "/images/about/equipe/Johan_HAUDIQUET-Formateur_et_Assistance.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Nathalie",
-    poste: "Ch. DEVELOPPEMENT COMMERCIAL",
+    name: "Nathalie",
+    position: "Ch. DEVELOPPEMENT COMMERCIAL",
     photo: "/images/about/equipe/Nathalie_CHEVALON-Chargee_de_developpement_commercial.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolorel",
   },
   {
-    id: 1,
-    nom: "Laetitia",
-    poste: "CH. COMMUNICATION & MARKETING",
+    name: "Laetitia",
+    position: "CH. COMMUNICATION & MARKETING",
     photo: "/images/about/equipe/Laetitia_SIFFOINTE-Chargee_de_Marketing_et_Communication.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Florence",
-    poste: "ASSISTANTE ADMINISTRATIVE",
+    name: "Florence",
+    position: "ASSISTANTE ADMINISTRATIVE",
     photo: "/images/about/equipe/Florence_JOANNIDIS-ADV.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Vincent",
-    poste: "LEAD DEVELOPPEUR",
+    name: "Vincent",
+    position: "LEAD DEVELOPPEUR",
     photo: "/images/about/equipe/Vincent_GUFFON-Lead_dev.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Olivier",
-    poste: "DEVELOPPEUR",
+    name: "Olivier",
+    position: "DEVELOPPEUR",
     photo: "/images/about/equipe/Olivier_MASSOT-Developpeur.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Sébastien",
-    poste: "DEVELOPPEUR",
+    name: "Sébastien",
+    position: "DEVELOPPEUR",
     photo: "/images/about/equipe/Sebastien_FAVRE-BONTE_Developpeur.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
   {
-    id: 1,
-    nom: "Maha",
-    poste: "DEVELOPPEUSE",
+    name: "Maha",
+    position: "DEVELOPPEUSE",
     photo: "/images/about/equipe/Maha_BOUCHIBA-Developpeuse.png",
-    description:
-      "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore",
   },
-]);
+];
 </script>
 
-<style scoped>
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
+<style scoped lang="scss">
 .v-card {
   max-width: 284px;
   border: none !important;
@@ -156,55 +136,39 @@ const employes = ref([
   background-color: transparent !important;
 }
 
+.v-card-subtitle {
+  text-overflow: ellipsis;
+  white-space: normal;
+}
+
 .details {
-  color: var(--Vert-100, #091d20);
-  font-family: Barlow;
+  color: var(--primary-color);
   font-size: 16px;
   font-weight: 300;
   line-height: 20px;
   width: 30rem;
 }
 
-.v-card {
-  max-width: 284px;
-  border: none !important;
-  box-shadow: none !important;
-  background-color: transparent !important;
-}
-
 .description {
-  color: var(--Vert-100, #091d20);
-  font-family: Barlow;
+  color: var(--primary-color);
   font-size: 14px;
-  font-style: normal;
   font-weight: 300;
   line-height: 18px;
 }
 
 .name {
-  color: #112528;
-  /* Subtitle 1 */
-  font-family: Barlow;
+  color: var(--primary-color);
   font-size: 22px;
-  font-style: normal;
   font-weight: 500;
   line-height: 26px;
 }
 
-.poste {
-  color: #071b1f;
-  font-family: Barlow;
+.position {
+  color: var(--primary-color);
   font-size: 10px;
-  font-style: normal;
   font-weight: 600;
   line-height: 15px;
   letter-spacing: 1.8px;
   text-transform: uppercase;
 }
-.v-card-subtitle {
-  text-overflow: ellipsis;
-  white-space: normal;
-}
-
-
 </style>

+ 45 - 41
components/About/FAQ.vue

@@ -1,65 +1,69 @@
 <template>
-  <LayoutContainer id="faq">
-    <v-row no-gutters>
-      <v-col cols="6">
-        <div class="help-img"></div>
-        <!-- <v-img class="help-img" src="/images/help/Help.png" /> -->
-      </v-col>
+  <AnchoredSection id="help">
+    <LayoutContainer>
+      <v-row no-gutters class="alt-theme">
+        <v-col cols="6">
+           <v-img
+             src="/images/help/Help.png"
+             cover
+           />
+        </v-col>
 
-      <v-col cols="6" class="help-col">
-        <div class="ml-6">
-          <h4 class="subtitle-team ml-12">
-            Chez Opentalent, nous avons à coeur de répondre à vos interrogations
-            et de vous apporter la solution faite pour vous.
-          </h4>
-          <nuxt-link to="/nous-contacter">
-            <v-btn class="button-faq ml-12 mt-12">
+        <v-col cols="6">
+          <div class="ml-6">
+            <h4 class="ml-12">
+              Chez Opentalent, nous avons à coeur de répondre à vos interrogations
+              et de vous apporter la solution faite pour vous.
+            </h4>
+
+            <v-btn
+              to="/nous-contacter"
+              class="ml-12 mt-12"
+            >
               Nous contacter
-            </v-btn></nuxt-link
-          >
-          <v-row> </v-row>
-        </div>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
+            </v-btn>
+          </div>
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
-<script setup></script>
 
-<style scoped>
-.button-faq {
-  width: 195px;
-  height: 53px;
-  background: #64afb7;
-  border-radius: 6px;
-  color: white;
-  padding: 19px 28px;
-  gap: 9px;
-  margin-left: 2rem;
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
+
+<style scoped lang="scss">
+.v-col {
+  height: 20rem;
 }
 
 .help-img {
-  background-image: url(/images/help/Help.png);
   background-repeat: no-repeat;
-  background-size: cover;
   background-position: center;
   width: 100%;
   height: 20rem;
 }
-.subtitle-team {
+
+h4 {
   margin-bottom: 2rem;
   margin-top: 3rem;
-  font-style: normal;
   font-weight: 400;
   font-size: 2rem;
   line-height: 34px;
   width: 40rem;
   margin-right: auto;
-  color: white;
+  color: var(--on-primary-color);
 }
 
-.help-col {
-  background: var(--Vert-90, #0e2d32);
-  height: 20rem;
-
+.v-btn {
+  width: 195px;
+  height: 53px;
+  background: var(--secondary-color);
+  border-radius: 6px;
+  color: var(--on-secondary-color);
+  padding: 19px 28px;
+  gap: 9px;
+  margin-left: 2rem;
 }
 </style>

+ 0 - 127
components/About/Histoire.vue

@@ -1,127 +0,0 @@
-<template>
-  <LayoutContainer id="Qui-sommes-nous" >
-    <v-row class="mt-12 custom-row">
-      <v-col cols="4">
-        <LayoutUISubTitle :titleText="'Qui sommes-nous ?'" />
-      </v-col>
-
-      <v-col cols="8">
-        <h3 class="italic-title mr-8">
-          “Imaginé par des musiciens pour des musiciens, Opentalent se veut être
-          la référence pour la gestion et la promotion du spectacle vivant sur
-          les territoires.”
-        </h3>
-      </v-col>
-    </v-row>
-
-    <v-row style="width: 80%; margin-left: auto; margin-right: auto" class="mb-12">
-      <v-col cols="6">
-        <div class="passion-img"></div>
-      </v-col>
-
-      <v-col cols="6">
-        <h2 class="passion-title">Une histoire de passionnés</h2>
-        <p class="passion-details">
-          En 2005, Guillaume CORCOBA, musicien depuis toujours et à ce moment là
-          président d'un orchestre d'harmonie, mais également membre du conseil
-          d'administration de sa fédération, réfléchit à un outil pour
-          centraliser les informations de sa structure, mais également au niveau
-          fédéral. Il souhaite simplifier la gestion des structures culturelles
-          et en faire la promotion, car pour lui, le milieu culturel est
-          indispensable. Il est rapidement rejoint par Michel   PERNET-SOLLIET,
-          lui aussi musicien, et ils montent ensemble Openassos, qui deviendra
-          quelques années plus tard, Opentalent. Opentalent c'est un ensemble de
-          3 logiciels spécialement dédiés à la culture et un agenda culturel
-          pour en faire la promotion.
-        </p>
-
-        <h2 class="culture-title">
-          La Culture au service du développement territorial
-        </h2>
-        <p class="culture-details">
-          Qui n'a jamais entendu que la culture coûtait trop cher ? On l'entend
-          , ha ça oui on l'a même trop entendu ! Mais la culture c'est avant
-          tout un facteur de lien social incroyable. On se retrouve, on échange,
-          on partage... on vit ensemble. On crée des vrais moments et on
-          développe des groupes de passionnés. On participe à rendre nos
-          collectivités attractives et surtout on les fait vivre, toute l'année,
-          à toutes les saisons. Depuis plusieurs décennies, un grand nombre de
-          territoires s'appuie sur le développement de la culture comme un outil
-          de développement territorial pour faire face à la
-          désindustrialisation, à une croissance démographique ralentie ou
-          encore une image défavorable. Ce modèle de développement par la
-          culture pour pallier un déficit d’attractivité touristique inspire de
-          plus en plus de politiques de développement territorial.
-        </p>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.culture-details {
-  font-weight: 300;
-  font-size: 16px;
-  line-height: 20px;
-  color: #091d20;
-  width: 30rem;
-  text-align: justify;
-}
-
-.culture-title {
-  font-weight: 400;
-  font-size: 34px;
-  line-height: 38px;
-  color: #071b1f;
-  margin-bottom: 3rem;
-  width: 25rem;
-  text-align: justify;
-}
-.passion-title {
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  color: #071b1f;
-  flex: none;
-  margin-bottom: 3rem;
-}
-
-.passion-details {
-  text-align: justify;
-  font-weight: 300;
-  font-size: 16px;
-  line-height: 20px;
-  color: #091d20;
-  width: 30rem;
-  margin-bottom: 2rem;
-}
-
-.passion-img {
-  background-image: url(/images/about/passion.jpg);
-  background-repeat: no-repeat;
-  background-size: cover;
-  background-position: center;
-  width: 400px;
-  height: 100%;
-  border-radius: 20px;
-}
-
-.italic-title {
-  text-align: justify;
-  font-style: italic;
-  font-weight: 300;
-  font-size: 34px;
-  line-height: 40px;
-  color: #091d20;
-  width: 80%;
-  margin-left: auto;
-  margin-bottom: auto;
-}
-</style>

+ 125 - 120
components/About/Logiciels.vue

@@ -1,53 +1,70 @@
 <template>
-  <LayoutContainer id="software">
-    <v-row class="mb-6 custom-row">
-      <LayoutUISubTitle titleText="Ce qui nous anime" />
-      <LayoutUITitle title="Nos logiciels dédiés à chaque acteur culturel" />
-    </v-row>
-
-    <v-row class="mb-12 custom-row">
-      <v-col cols="3">
-        <p style="text-align: justify" class="mr-4 ml-6">
-          Découvrez notre gamme de logiciels de gestion & de communication
-          adapté au secteur culturel. <br />
-          Des fonctionnalités complètes:
-        </p>
-        <div class="mb-6"></div>
-        <ul class="custom-list-style ml-6">
-          <li v-for="(feature, index) in features" :key="index">
-            {{ feature }}
-          </li>
-        </ul>
-        <p style="text-align: justify" class="mr-4 ml-6 mt-6">
-          À chaque logiciel sa spécificité !
-        </p>
-      </v-col>
-      <v-col cols="3" v-for="(item, index) in items" :key="index">
-
-        <div
-          class="container-image"
-          :style="{ backgroundImage: 'url(' + item.imageUrl + ')' }"
+  <AnchoredSection id="softwares">
+    <LayoutContainer>
+      <v-row class="mb-6 center-90">
+        <LayoutUISubTitle>
+          Nos logiciels
+        </LayoutUISubTitle>
+
+        <LayoutUITitle>
+          Nos logiciels dédiés à chaque acteur culturel
+        </LayoutUITitle>
+      </v-row>
+
+      <v-row class="mb-12 center-90">
+        <v-col cols="3">
+          <p class="text-justify mr-4 ml-6 mb-6">
+            Découvrez notre gamme de logiciels de gestion & de communication
+            adapté au secteur culturel. <br />
+            Des fonctionnalités complètes:
+          </p>
+
+          <ul class="ml-6">
+            <li
+              v-for="(feature, index) in features"
+              :key="index"
+            >
+              {{ feature }}
+            </li>
+          </ul>
+
+          <p class="text-justify mr-4 ml-6 mt-6">
+            À chaque logiciel sa spécificité !
+          </p>
+        </v-col>
+
+        <v-col
+          cols="3"
+          v-for="(item, index) in items"
+          :key="index"
+          :class="item.class"
         >
-          <div class="footer-container">
-            <v-img class="logo" :src="item.logoUrl"></v-img>
+          <v-img
+            :src="item.imageUrl"
+            cover
+            class="container-image"
+          >
+            <footer>
+              <v-img :src="item.logoUrl" class="logo" />
 
-            <nuxt-link :to="item.link">
               <v-btn
-                :style="{ backgroundColor: item.buttonColor }"
+                :to="item.link"
                 class="plus-button"
               >
                 <v-icon>fas fa-plus</v-icon>
               </v-btn>
-            </nuxt-link>
-          </div>
-        </div>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
+            </footer>
+          </v-img>
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const features = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+
+const features: Array<string> = [
   "Une gestion de vos contacts",
   "un agenda collaboratif et interactif",
   "Une gestion du matériel et du stock",
@@ -57,116 +74,47 @@ const features = [
   "Et bien plus encore...",
 ];
 
-const items = [
+const items: Array<{imageUrl: string, logoUrl: string, class: string, link: string}> = [
   {
     imageUrl: "/images/solutions/artist.jpg",
     logoUrl: "/images/logo/logiciels/Artist-Blanc.png",
-    buttonColor: "#FAC20A",
+    class: "artist",
     link: "/opentalent_artist",
   },
   {
     imageUrl: "/images/solutions/school.jpg",
     logoUrl: "/images/logo/logiciels/School-Blanc.png",
-    buttonColor: "rgba(32, 147, 190)",
+    class: "school",
     link: "/opentalent_school",
   },
-
   {
     imageUrl: "/images/solutions/manager.png",
     logoUrl: "/images/logo/logiciels/Manager-Blanc.png",
-    buttonColor: "#D8050B",
+    class: "manager",
     link: "/opentalent_manager",
   },
 ];
 </script>
 
-<style scoped>
-.v-container {
-  padding: 0 !important;
-}
-
+<style scoped lang="scss">
 .container {
+  padding: 0 !important;
   margin-top: 1rem;
-  background: #f8f8f8;
-}
-:deep().title {
-  width: 100% !important;
-}
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.container-image {
-  position: relative;
-  background-image: url("/images/solutions/school.jpg");
-  background-repeat: no-repeat;
-  background-size: cover;
-  background-position: center;
-  width: 100%;
-  height: 100%;
-  z-index: 0;
-  cursor: pointer;
-}
-
-
-.footer-container {
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  width: 100%;
-  height: 100px;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 0 10px;
+  background: var(--neutral-color);
 }
 
-.logo {
-  width: 100px;
-  z-index: 2;
-  margin-right: 10px;
-}
-
-
-.plus-button {
-  width: 80px;
-  height: 80px;
-  border-radius: 50%;
-  background: var(--Vert-60, #64afb7);
-  color: white;
-}
-
-
-.container-image:hover .plus-button {
-  transform: scale(1.2); 
-  transition: all 0.3s ease-in-out;
-}
-
-.plus-button .v-icon {
-  color: #ffffff;
-  font-size: 2rem;
-}
-
-.plus-button,
-.v-btn {
-  border-radius: 0 !important;
-  box-shadow: none !important;
-  border-top-left-radius: 10% !important;
-}
-
-.custom-list-style {
+ul {
   list-style: none;
   padding-left: 0;
 }
 
-.custom-list-style li {
+li {
   margin-left: 0.8rem;
   position: relative;
   margin-bottom: 10px;
 }
 
-.custom-list-style li:before {
+li:before {
   content: "";
   position: absolute;
   left: -10px;
@@ -174,10 +122,67 @@ const items = [
   transform: translateY(-50%);
   width: 3px;
   height: 3px;
-  background-color: black;
+  background-color: var(--on-neutral-color);
   border-radius: 50%;
 }
 
+.container-image {
+  position: relative;
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center;
+  width: 100%;
+  height: 370px;
+  z-index: 0;
 
+  footer {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 100px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 10px;
+  }
+
+  .logo {
+    width: 100px;
+    z-index: 2;
+    margin-right: 10px;
+  }
+
+  .plus-button {
+    width: 80px;
+    height: 80px;
+    border-radius: 50% 0 0 0;
+    background: var(--primary-color);
+    color: var(--on-primary-color);
+    box-shadow: none !important;
+    border-top-left-radius: 10% !important;
+
+    .v-icon {
+      color: var(--on-primary-color);
+      font-size: 2rem;
+    }
+  }
+
+  :hover .plus-button {
+    transform: scale(1.2);
+    transition: all 0.3s ease-in-out;
+  }
+}
 
+.artist .plus-button {
+  background: var(--artist-color);
+}
+
+.school .plus-button {
+  background: var(--school-color);
+}
+
+.manager .plus-button {
+  background: var(--manager-color);
+}
 </style>

+ 0 - 125
components/About/MenuScroll.vue

@@ -1,125 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <v-col
-        cols="12"
-        class="menu-container"
-        :class="{ 'sticky-menu': isSticky }"
-      >
-        <div v-for="menu in menus" :key="menu.label" @click="navigate(menu)">
-          <v-chip v-if="activeMenu === menu.label" class="active-menu">
-            {{ menu.label }}
-          </v-chip>
-          <span v-else>{{ menu.label }}</span>
-        </div>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup>
-import { ref, onMounted, onUnmounted, reactive } from "vue";
-
-const refs = reactive({
-  about: null,
-  valeurs: null,
-  logiciels: null,
-  agenda: null,
-  histoire: null,
-  equipe: null,
-});
-
-const menus = [
-  { label: "Qui sommes-nous" },
-  { label: "Nos valeurs" },
-  { label: "Nos logiciels" },
-  { label: "L'agenda opentalent" },
-  { label: "Notre Histoire" },
-  { label: "Notre équipe" },
-];
-
-const isSticky = ref(false);
-
-const handleScroll = () => {
-  const scrollPosition = window.scrollY;
-
-  if (scrollPosition > 800) { 
-    isSticky.value = true;
-  } else {
-    isSticky.value = false;
-  }
-
-  for (const key of Object.keys(refs)) {
-    const element = refs[key];
-    if (element) {
-      const top = element.offsetTop;
-      const bottom = top + element.offsetHeight;
-      if (scrollPosition >= top && scrollPosition < bottom) {
-        activeMenu.value = key;
-        break;
-      }
-    }
-  }
-};
-
-onMounted(() => {
-  Object.keys(refs).forEach(key => {
-    refs[key] = document.getElementById(key);
-  });
-
-  window.addEventListener('scroll', handleScroll);
-});
-
-onMounted(() => {
-  window.addEventListener('scroll', handleScroll);
-});
-
-
-const activeMenu = ref(menus[0].label);
-
-const navigate = (menu) => {
-  activeMenu.value = menu.label;
-  const element = document.getElementById(menu.label);
-  if (element) {
-    element.scrollIntoView({ behavior: "smooth" });
-  }
-};
-</script>
-
-<style scoped>
-
-.sticky-menu {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  background: white;
-  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
-}
-.menu-container {
-  z-index: 3;
-  display: flex;
-  justify-content: space-around;
-  background: white;
-  color: #071b1f;
-  font-family: "Barlow";
-  font-size: 1rem;
-  line-height: 19px;
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  border-bottom: 0.1rem solid #eaeaea;
-}
-.v-chip.active-menu {
-  background: var(--Vert-100, #091D20);;
-  color: white;
-}
-
-.menu-container div:hover {
-  cursor: pointer;
-  text-decoration: underline;
-  z-index: 15;
-}
-</style>

+ 128 - 0
components/About/Presentation.vue

@@ -0,0 +1,128 @@
+<template>
+  <AnchoredSection id="about">
+    <LayoutContainer>
+      <v-row class="mt-12 center-90">
+        <v-col cols="4">
+          <LayoutUISubTitle>
+            Qui sommes-nous ?
+          </LayoutUISubTitle>
+        </v-col>
+
+        <v-col cols="8">
+          <h3 class="italic-title mr-8">
+            “Imaginé par des musiciens pour des musiciens, Opentalent se veut être
+            la référence pour la gestion et la promotion du spectacle vivant sur
+            les territoires.”
+          </h3>
+        </v-col>
+      </v-row>
+
+      <v-row class="history mb-12">
+        <v-col cols="6">
+          <v-img src="/images/about/passion.jpg" cover />
+        </v-col>
+
+        <v-col cols="6">
+          <h3>
+            Une histoire de passionnés
+          </h3>
+
+          <p class="mb-8">
+            En 2005, Guillaume CORCOBA, musicien depuis toujours et à ce moment là
+            président d'un orchestre d'harmonie, mais également membre du conseil
+            d'administration de sa fédération, réfléchit à un outil pour
+            centraliser les informations de sa structure, mais également au niveau
+            fédéral. Il souhaite simplifier la gestion des structures culturelles
+            et en faire la promotion, car pour lui, le milieu culturel est
+            indispensable. Il est rapidement rejoint par Michel   PERNET-SOLLIET,
+            lui aussi musicien, et ils montent ensemble Openassos, qui deviendra
+            quelques années plus tard, Opentalent. Opentalent c'est un ensemble de
+            3 logiciels spécialement dédiés à la culture et un agenda culturel
+            pour en faire la promotion.
+          </p>
+
+          <h4>
+            La Culture au service du développement territorial
+          </h4>
+
+          <p>
+            Qui n'a jamais entendu que la culture coûtait trop cher ? On l'entend
+            , ha ça oui on l'a même trop entendu ! Mais la culture c'est avant
+            tout un facteur de lien social incroyable. On se retrouve, on échange,
+            on partage... on vit ensemble. On crée des vrais moments et on
+            développe des groupes de passionnés. On participe à rendre nos
+            collectivités attractives et surtout on les fait vivre, toute l'année,
+            à toutes les saisons. Depuis plusieurs décennies, un grand nombre de
+            territoires s'appuie sur le développement de la culture comme un outil
+            de développement territorial pour faire face à la
+            désindustrialisation, à une croissance démographique ralentie ou
+            encore une image défavorable. Ce modèle de développement par la
+            culture pour pallier un déficit d’attractivité touristique inspire de
+            plus en plus de politiques de développement territorial.
+          </p>
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
+</template>
+
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
+
+<style scoped lang="scss">
+.italic-title {
+  text-align: justify;
+  font-style: italic;
+  font-weight: 300;
+  font-size: 34px;
+  line-height: 40px;
+  color: var(--primary-color);
+  width: 80%;
+  margin-left: auto;
+  margin-bottom: auto;
+}
+
+.v-row.history {
+  width: 80%;
+  margin-left: auto;
+  margin-right: auto;
+
+  .v-img {
+    background-repeat: no-repeat;
+    background-position: center;
+    width: 400px;
+    height: 100%;
+    border-radius: 20px;
+  }
+
+  h3 {
+    font-weight: 600;
+    font-size: 42px;
+    line-height: 42px;
+    flex: none;
+    margin-bottom: 3rem;
+  }
+
+  h4 {
+    font-weight: 400;
+    font-size: 34px;
+    line-height: 38px;
+    color: var(--primary-color);
+    margin-bottom: 3rem;
+    width: 25rem;
+    text-align: justify;
+  }
+
+  p {
+    text-align: justify;
+    font-weight: 300;
+    font-size: 16px;
+    line-height: 20px;
+    width: 30rem;
+    margin-bottom: 2rem;
+  }
+}
+
+
+</style>

+ 49 - 85
components/About/Valeurs.vue

@@ -1,19 +1,24 @@
 <template>
-  <LayoutContainer class="mt-12" id="valeurs">
-    <div id="valeurs">
-      <div class="v-row custom-row">
-        <LayoutUISubTitle :titleText="'Les valeurs qui nous portent'" />
-      </div>
+  <AnchoredSection id="values">
+    <LayoutContainer class="mt-12">
+      <v-row class="center-90">
+        <LayoutUISubTitle>
+          Les valeurs qui nous portent
+        </LayoutUISubTitle>
+      </v-row>
 
-      <v-row class="mt-6 custom-row align-center mb-12">
+      <v-row class="mt-6 center-90 align-center mb-12">
         <v-col cols="6">
-          <div class="valeur-img"></div>
+          <v-img
+            src="/images/about/valeurs/valeur.png"
+            cover
+            class="valeur-img"
+          />
         </v-col>
 
         <v-col cols="6">
-          <div class="valeur-container">
+          <div class="values">
             <v-row
-              class="row"
               v-for="(row, rowIndex) in values"
               :key="rowIndex"
             >
@@ -22,19 +27,29 @@
                 v-for="(value, valueIndex) in row"
                 :key="valueIndex"
               >
-                <v-img :src="value.img" class="icon-valeur" />
-                <h6 class="title-valeurs">{{ value.title }}</h6>
-                <p>{{ value.description }}</p>
+                <v-img :src="value.img" cover />
+
+                <h6>
+                  {{ value.title }}
+                </h6>
+
+                <p>
+                  {{ value.description }}
+                </p>
               </v-col>
             </v-row>
           </div>
         </v-col>
       </v-row>
-    </div>
-  </LayoutContainer>
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
-<script setup>
-const values = [
+
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { SocietyValue } from "~/types/interface";
+
+const values: Array<Array<SocietyValue>> = [
   [
     {
       img: "/images/about/valeurs/Management.svg",
@@ -44,7 +59,6 @@ const values = [
     },
     {
       img: "/images/about/valeurs/Satisfaction-client.svg",
-      icon: "fa-brands fa-react",
       title: "Satisfaction client",
       description:
         "Opentalent met un point d’honneur à satisfaire ses clients en leur proposant des solutions de qualité, un projet global dans lequel ils se retrouvent. L’intention de base est bel et bien de proposer un équilibre entre les solutions informatiques et la volonté personnelle en lien avec la production et les publics concernés.",
@@ -53,14 +67,12 @@ const values = [
   [
     {
       img: "/images/about/valeurs/Ecologie.svg",
-      icon: "fa-brands fa-react",
       title: "Écologie",
       description:
         "Proche des entreprises de l’Économie Sociale et Solidaire, Opentalent accorde une grande importance aux démarches liées à l’écologie et au développement durable. Le code des outils est par exemple optimisé pour limiter les ressources nécessaires des serveurs, réduisant ainsi leur empreinte carbone et améliorant le confort des utilisateurs au quotidien.",
     },
     {
       img: "/images/about/valeurs/Open-source.svg",
-      icon: "fa-brands fa-react",
       title: "Open source",
       description:
         "Opentalent est une entreprise qui croit profondément aux vertus des logiciels Open Source et qui par son action contribue à leur développement.",
@@ -68,80 +80,32 @@ const values = [
   ],
 ];
 </script>
-<style scoped>
+
+<style scoped lang="scss">
 .valeur-img {
-  background-image: url(/images/about/valeurs/valeur.png);
   background-repeat: no-repeat;
-  background-size: cover;
   background-position: center;
   height: 400px;
   width: 450px;
 }
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.icon-valeur {
-  width: 50px;
-  height: 50px;
-  margin-bottom: 1rem;
-}
 
-.row {
-  border-top: 1px solid #e5e5e5;
-}
-.title-valeurs {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 22px;
-  line-height: 26px;
-  color: #091d20;
-  margin-bottom: 1rem;
-}
-.title-valeur {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 400;
-  font-size: 34px;
-  line-height: 38px;
-  color: #071b1f;
-  text-align: center;
-  margin-right: 19rem;
-  margin-left: 12rem;
-  text-align: left;
-}
+.values {
+  .v-row {
+    border-top: 1px solid var(--on-neutral-color-extra-light);
+  }
 
-.left-img {
-  position: relative;
-  right: 2rem;
-}
+  .v-img {
+    width: 50px;
+    height: 50px;
+    margin-bottom: 1rem;
+  }
 
-.right-img {
-  position: relative;
-  left: 2rem;
-}
-.container-img {
-  margin-left: 14rem;
-}
-.bottom-img,
-.top-img {
-  margin-left: 4rem;
-}
-
-.top-img {
-  position: relative;
-  top: 4.5rem;
-}
-
-.bottom-img {
-  position: relative;
-  bottom: 4.5rem;
-}
-.image-ronde {
-  width: 170px;
-  height: 170px;
-  border-radius: 90px;
+  h6 {
+    font-weight: 500;
+    font-size: 22px;
+    line-height: 26px;
+    color: var(--primary-color);
+    margin-bottom: 1rem;
+  }
 }
 </style>

+ 197 - 0
components/Common/ActionMenu.vue

@@ -0,0 +1,197 @@
+<!--
+Menu d'actions rapides (appel, contact, ...), qui reste accroché au bord droit
+de l'écran (ou au bas de l'écran sur les petits écrans)
+-->
+<template>
+  <!-- Écrans larges : menu lateral, accroché au bord droit de l'écran -->
+  <div class="sticky-menu lateral" v-if="lgAndUp">
+    <v-row
+      v-for="(action, index) in actionsOrDefault"
+      :key="index"
+      :class="['square', action.color]"
+      @click="() => onActionClick(action)"
+    >
+      <NuxtLink :to="action.url" class="link">
+        <div>
+          <v-icon
+            :class="action.icon"
+          />
+
+          <p class="text-square mt-2">
+            {{ action.text }}
+          </p>
+        </div>
+      </NuxtLink>
+    </v-row>
+  </div>
+
+  <!-- Petits écrans : menu sous forme de bandeau en pied de page (sauf si le footer du site est visible) -->
+  <div class="sticky-menu band" v-else-if="!layoutStore.isFooterVisible">
+    <v-btn
+      v-for="(action, index) in actionsOrDefault"
+      :key="index"
+      :class="[action.color]"
+      @click="() => onActionClick(action)"
+    >
+      {{ action.text }}
+    </v-btn>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRouter } from "vue-router";
+import { useDisplay } from "vuetify";
+import { useLayoutStore } from "~/stores/layoutStore";
+import { ActionMenuItemType } from "~/types/enum/layout";
+import { ActionMenuItem } from "~/types/interface";
+
+const { mdAndDown, lgAndUp } = useDisplay();
+const router = useRouter();
+const layoutStore = useLayoutStore()
+const { isMobileDevice } = useClientDevice()
+
+const telephoneNumber = "09 72 12 60 17";
+
+// Actions par défaut du menu, peut-être surchargé via la propriété `actions`
+const defaultActions: Array<ActionMenuItem> = [
+  {
+    type: ActionMenuItemType.FOLLOW_LINK,
+    color: "secondary",
+    icon: "far fa-comments",
+    text: "Nous contacter",
+    url: "/nous-contacter",
+  },
+  {
+    type: ActionMenuItemType.CALL_US,
+    color: "primary",
+    icon: "fas fa-phone",
+    text: "Nous Appeler",
+  },
+];
+
+const props = defineProps({
+  /**
+   * Actions accessibles via le menu (par défaut : "Nous contacter", "Nous appeler")
+   */
+  actions: {
+    type: Array<ActionMenuItem>,
+    required: false,
+    default: []
+  }
+})
+
+const actionsOrDefault: ComputedRef<Array<ActionMenuItem>> = computed(() => {
+  return props.actions.length > 0 ? props.actions : defaultActions
+})
+
+const callUs = () => {
+  if (isMobileDevice()) {
+    window.location.href = `tel:${telephoneNumber}`;
+  } else {
+    alert(`Notre numéro de téléphone : ${telephoneNumber}`);
+  }
+}
+
+/**
+ * On a cliqué sur une des actions du menu
+ * @param action
+ */
+const onActionClick = (action: ActionMenuItem) => {
+  switch (action.type) {
+    case ActionMenuItemType.ASK_FOR_A_DEMO:
+      router.push({ path: action.url, query: { request: "demo" } });
+      break;
+
+    case ActionMenuItemType.CALL_US:
+      callUs()
+      break;
+
+    case ActionMenuItemType.FOLLOW_LINK:
+      if (!action.url) {
+        throw Error('Missing prop : url')
+      }
+      router.push({ path: action.url });
+      break
+
+    default:
+      throw Error('Unrecognized action')
+  }
+};
+</script>
+
+<style scoped lang="scss">
+
+.sticky-menu {
+  z-index: 100;
+}
+
+// Menu format lateral (pour affichage écrans larges)
+.sticky-menu.lateral {
+  position: sticky;
+  right: 0;
+  top: 60%;
+  transform: translateY(-50%);
+  float: right;
+
+  display: flex;
+  flex-direction: column;
+  color: var(--on-primary-color);
+  font-weight: 500;
+  font-size: 0.7rem;
+  line-height: 15px;
+  text-align: center;
+  letter-spacing: 0.2em;
+  text-transform: uppercase;
+}
+
+// Menu format ruban (pour affichage petits écrans)
+.sticky-menu.band {
+  position: fixed;
+  height: 46px;
+  bottom: 0;
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  background-color: var(--neutral-color);
+
+  .v-btn {
+    margin: 4px 6px;
+  }
+}
+
+.square {
+  position: relative;
+  width: 7rem;
+  padding: 1rem;
+  cursor: pointer;
+
+  transition: transform 0.3s ease-in-out;
+}
+
+.square:hover {
+  transform: translateX(-10px);
+}
+
+.link {
+  text-decoration: none;
+  color: var(--on-primary-color);
+}
+
+.primary {
+  background: var(--action-menu-primary-color);
+  color: var(--action-menu-on-primary-color);
+
+  a {
+    color: var(--action-menu-on-primary-color);
+  }
+}
+
+.secondary {
+  background: var(--action-menu-secondary-color);
+  color: var(--action-menu-on-secondary-color);
+
+  a {
+    color: var(--action-menu-on-secondary-color);
+  }
+}
+</style>

+ 119 - 114
components/About/Agenda.vue → components/Common/Agenda.vue

@@ -1,45 +1,57 @@
+<!--
+Section "Agenda des évènements"
+-->
 <template>
-    <LayoutContainer id="agenda" class="mb-12" >
-      <v-row class="custom-row align-center">
-        <v-col cols="4">
-          <h2 class="title">L'agenda Opentalent</h2>
+  <AnchoredSection id="agenda">
+    <LayoutContainer class="mb-12" >
+      <v-row class="center-90 align-center my-6">
+        <v-col cols="4" class="align-center">
+          <LayoutUITitle>
+            L'agenda Opentalent
+          </LayoutUITitle>
         </v-col>
 
         <v-col cols="4">
-          <div class="d-flex justify-center align-center">
-            <div class="carousel-button" @click="goPrevious">
-              <i class="fas fa-chevron-left" />
-            </div>
-            <div class="carousel-button" @click="goNext">
-              <i class="fas fa-chevron-right" />
-            </div>
+          <!-- Factoriser les contrôles du carousel dans un component -->
+          <div class="carousel-controls">
+            <v-btn
+              icon="fas fa-chevron-left"
+              @click="goPrevious"
+            />
+            <v-btn
+              icon="fas fa-chevron-right"
+              @click="goNext"
+            />
           </div>
         </v-col>
 
-        <v-col cols="4">
-          <v-btn class="btn-news" text> VOIR TOUS LES EVENEMENTS </v-btn>
+        <v-col cols="4" class="d-flex flex-row flex-1 justify-end align-center">
+          <v-btn class="btn-news" text>
+            Voir tous les évènements
+          </v-btn>
         </v-col>
       </v-row>
 
-      <v-row class="custom-row">
+      <v-row class="center-90">
         <p class="agenda-details">
           Retrouvez tous les évènements culturels autour de chez vous.
         </p>
       </v-row>
 
-      <v-row class="custom-row">
-        <v-col cols="12" lg="12" md="12">
-          <Carousel ref="carousel" :items-to-show="1" :items-to-scroll="2">
+      <v-row class="center-90">
+        <v-col cols="12">
+          <Carousel
+            ref="carousel"
+            :items-to-show="3"
+            :items-to-scroll="2"
+          >
             <Slide
               v-for="(event, eventIndex) in events"
               :key="eventIndex"
-              class="slide-card"
+              class="card"
             >
               <v-card>
-                <div
-                  class="card-img"
-                  :style="{ backgroundImage: 'url(' + event.img + ')' }"
-                ></div>
+                <v-img :src="event.img" cover />
 
                 <v-card-title>
                   {{ event.title }}
@@ -49,32 +61,38 @@
                   {{ event.localisation }}
                 </v-card-text>
 
-                <div class="card-footer">
-                  <v-chip-group active-class="primary--text" column>
+                <footer>
+                  <v-chip-group column>
                     <v-chip
                       v-for="(tag, tagIndex) in event.tags"
                       :key="tagIndex"
-                      class="chip-custom"
                       :color="tagColor(tag)"
                       label
                     >
-                      <span :class="tagTextColor(tag)">{{ tag }}</span>
+                      <span
+                        :class="tagTextColor(tag)"
+                      >
+                        {{ tag }}
+                      </span>
                     </v-chip>
                   </v-chip-group>
-                </div>
+                </footer>
               </v-card>
             </Slide>
           </Carousel>
         </v-col>
       </v-row>
     </LayoutContainer>
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
 import { Carousel, Slide } from "vue3-carousel";
 import "vue3-carousel/dist/carousel.css";
-const tagColor = (tag) => {
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Event } from "~/types/interface";
+
+const tagColor = (tag: string) => {
   switch (tag) {
     case "Payant":
       return "red";
@@ -85,7 +103,7 @@ const tagColor = (tag) => {
   }
 };
 
-const tagTextColor = (tag) => {
+const tagTextColor = (tag: string) => {
   switch (tag) {
     case "Payant":
       return "red--text";
@@ -95,7 +113,8 @@ const tagTextColor = (tag) => {
       return "black--text";
   }
 };
-const events = ref([
+
+const events: Array<Event> = [
   {
     rdv: "20h00",
     title: "LA NUIT DES RÊVES  ",
@@ -136,62 +155,49 @@ const events = ref([
     img: "/images/agenda/agenda1.jpg",
     tags: ["Festival", "Musique", "Tout public", "Payant"],
   },
-]);
+];
 
-let carousel;
+const carousel: Ref<typeof Carousel | null> = ref(null);
 
-const goPrevious = () => carousel.prev();
-const goNext = () => carousel.next();
+const goPrevious = () => carousel.value!.prev();
+const goNext = () => carousel.value!.next();
 </script>
 
 <style scoped>
-
 .v-container{
   padding: 0 !important;
 }
 
 .container{
-  background: #F8F8F8 
-}
-.card-footer{
-  text-align: left !important;
-}
-.v-card {
-  box-shadow: none !important;
-  margin-right: 1rem;
-  text-align: left;
-}
-.card-img {
-  width: 100%;
-  height: 300px;
-  background-size: cover;
-  background-position: center;
-  border-top-left-radius: 20px;
-  border-top-right-radius: 20px;
+  background: var(--neutral-color);
 }
 
-.green--text {
-  color: green;
-}
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.red--text {
-  color: red;
-}
-.black--text {
-  color: black;
+.carousel-controls {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+
+  .v-btn {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 60px;
+    height: 60px;
+    background-color: transparent;
+    border: 2px solid;
+    cursor: pointer;
+    margin-right: 1rem;
+    margin-bottom: 2rem;
+    border-radius: 0;
+  }
 }
+
 .btn-news {
-  color: #9edbdd;
-  border-radius: 2rem;
-  font-family: "Barlow";
+  color: var(--primary-color);
   background: transparent;
-  border: 1px solid #9edbdd;
+  border: 1px solid var(--primary-color);
   border-radius: 6px;
-  font-style: normal;
   font-weight: 600;
   text-transform: uppercase;
   display: flex;
@@ -201,62 +207,61 @@ const goNext = () => carousel.next();
   font-size: 10px;
   line-height: 15px;
 }
-.chip-custom {
-  color: white;
-  border: 1px solid #0e2d32;
-  border-radius: 3rem;
-  text-transform: uppercase;
-  display: flex;
-  align-items: center;
-  text-align: center;
-}
 
-.carousel-button i {
-  color: #000000;
-}
+.card {
+  .v-card {
+    box-shadow: none !important;
+    margin-right: 1rem;
+    text-align: left;
+  }
 
-.card-date {
-  font-size: 0.8em;
-  color: #888;
-  margin-left: 1rem;
-}
+  .v-img {
+    border-top-left-radius: 20px;
+    border-top-right-radius: 20px;
+    width: 100%;
+    height: 300px;
 
-.card-footer {
-  display: flex;
-}
+    img {
+      background-position: center;
+    }
+  }
 
-.title,
-.carousel-button,
-.btn-news {
-  margin-top: 2rem;
-  margin-bottom: 2rem;
+  footer{
+    display: flex;
+    text-align: left !important;
+
+    .v-chip {
+      color: var(--neutral-color);
+      border: 1px solid var(--primary-color);
+      border-radius: 3rem;
+      text-transform: uppercase;
+      display: flex;
+      align-items: center;
+      text-align: center;
+    }
+  }
 }
+
 .agenda-details {
   font-weight: 300;
   font-size: 16px;
   line-height: 20px;
   margin-left: 2rem;
-  color: #091d20;
+  color: var(--primary-color);
   margin-bottom: 3rem;
   width: 15rem;
 }
-.title {
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  margin-left: 2rem;
-  color: #071b1f;
+
+/* -- Classes dynamiques pour les tags --*/
+.black--text {
+  color: black;
 }
 
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 60px;
-  height: 60px;
-  background-color: transparent;
-  border: 2px solid #000000;
-  cursor: pointer;
-  margin-right: 1rem;
+.green--text {
+  color: green;
+}
+
+.red--text {
+  color: red;
 }
 </style>

+ 52 - 0
components/Common/Avantages.vue

@@ -0,0 +1,52 @@
+<template>
+  <LayoutContainer>
+    <v-row class="center-90">
+      <LayoutUISubTitle>
+        Découvrez les avantages de la solution
+      </LayoutUISubTitle>
+
+      <LayoutUITitle>
+        {{ title }}
+      </LayoutUITitle>
+    </v-row>
+
+    <v-row class="center-90">
+      <v-col
+        cols="12"
+        md="4"
+        offset-md="1"
+        v-for="(benefit, index) in benefits"
+        :key="index"
+      >
+        <CommonCardBenefit
+          :benefit="benefit"
+        />
+      </v-col>
+    </v-row>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import type { Benefit } from "~/types/interface";
+
+const props = defineProps({
+  benefits: {
+    type: Array as PropType<Array<Benefit>>,
+    required: true
+  },
+  title: {
+    type: String,
+    required: false,
+    default: "Des avantages concrets"
+  }
+})
+</script>
+
+<style scoped lang="scss">
+.v-row {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+</style>

+ 64 - 62
components/Common/Banner/Banner.vue → components/Common/Banner.vue

@@ -8,27 +8,28 @@
             :alt="imageAlt"
             class="cover-image"
           />
-          <div class="black-square" :style="{ backgroundColor: squareColor }">
+
+          <div v-if="logoSrc" class="details-square">
             <v-row>
               <div class="content-row">
-                <img 
-                  src="/images/logiciels/icons/la-musique.svg" 
+                <img
+                  src="/images/logiciels/icons/la-musique.svg"
                   alt="icon instrument de musique"
-                  class="custom-icon" 
+                  class="custom-icon"
                 />
-                <p class="description-square" :style="{ color: textColor }">
+                <p class="description">
                   {{ squareText }}
                 </p>
               </div>
             </v-row>
           </div>
 
-          <div class="blue-square" :style="{ backgroundColor: blueSquareColor }">
-            <img
-              :src="logoSrc"
-              :alt="logoAlt"
-              class="logo-image"
-            />
+          <div v-if="logoSrc" :class="'logo-square' + (logoAltTheme ? ' alt-theme' : '')">
+            <img :src="logoSrc" :alt="logoAlt"/>
+          </div>
+
+          <div class="image-text mt-12">
+            <slot name="watermark" />
           </div>
         </div>
       </v-col>
@@ -36,8 +37,7 @@
   </LayoutContainer>
 </template>
 
-<script setup>
-import { defineProps } from 'vue';
+<script setup lang="ts">
 
 const props = defineProps({
   imageSrc: {
@@ -48,34 +48,55 @@ const props = defineProps({
     type: String,
     default: ""
   },
-  squareColor: {
-    type: String,
-    default: "#9edbdd" 
-  },
-  textColor: {
-    type: String,
-    default: "#091d20" 
-  },
   squareText: {
     type: String,
     default: "École de musique, d'art, de danse, de cirque, conservatoires et MJC"
   },
-  blueSquareColor: {
-    type: String,
-    default: "#0e2d32"
-  },
   logoSrc: {
-    type: String,
-    required: true
+    type: String as PropType<string | null>,
+    required: false,
+    default: null
   },
   logoAlt: {
     type: String,
+    required: false,
     default: ""
+  },
+  logoAltTheme: {
+    type: Boolean,
+    default: false
   }
 });
 </script>
 
-<style scoped>
+<style scoped lang="scss">
+.banner-container {
+  position: relative;
+  overflow: hidden;
+
+  .image-text {
+    position: absolute;
+    top: 40px;
+    left: 20px;
+    color: white;
+    font-size: 3rem;
+    width: 30rem;
+    font-style: italic;
+    font-weight: 300;
+    line-height: 40px;
+  }
+}
+
+.cover-image {
+  width: 100%;
+  min-height: 400px;
+  max-height: 400px;
+  object-fit: cover;
+  object-position: center var(--banner-center-image);
+  transition: transform 0.2s;
+  margin: 0 auto;
+  transform: scaleX(-1);
+}
 
 .custom-icon {
   width: 3rem;
@@ -83,37 +104,40 @@ const props = defineProps({
   margin-top: .5rem;
 }
 
-.black-square {
+.details-square {
   position: absolute;
   bottom: 0.4rem;
   right: 0;
   width: 13rem;
   height: 10rem;
-  background-color: black;
-  background: #9edbdd;
+  background: var(--secondary-color);
 }
 
-.blue-square {
+.logo-square {
   position: absolute;
   bottom: 0.4rem;
   right: 13rem;
   width: 13rem;
   height: 10rem;
-  background: #0e2d32;
+
+  img {
+    width: 100%;
+    height: 50%;
+    margin-top: 2.5rem;
+  }
+}
+.logo-square:not(.alt-theme) {
+  background: var(--primary-color);
 }
 
-.description-square {
+.description {
+  color: var(--on-secondary-color);
   font-weight: 300;
   font-size: 0.8rem;
   text-align: center;
-  color: #091d20;
   display: flex;
   align-items: center;
-  text-align: center;
-  margin-top: 0.5rem;
-  margin-left: 2rem;
-  margin-right: 2rem;
-  margin-bottom: 1rem;
+  margin: 0.5rem 2rem 1rem;
 }
 
 .content-row {
@@ -129,26 +153,4 @@ const props = defineProps({
   margin-left: 2rem;
   margin-right: 2rem;
 }
-
-.logo-image {
-  width: 100%;
-  height: 50%;
-  margin-top: 2.5rem;
-}
-
-.banner-container {
-  position: relative;
-  overflow: hidden;
-}
-
-.cover-image {
-  width: 100%;
-  min-height: 400px;
-  max-height: 400px;
-  object-fit: cover;
-  object-position: center 20%; 
-  transition: transform 0.2s;
-  margin: 0 auto;
-  transform: scaleX(-1);
-}
 </style>

+ 0 - 72
components/Common/Banner/BannerTitle.vue

@@ -1,72 +0,0 @@
-
-<template>
-  <LayoutContainer>
-  <div class="container-title">
-    <v-col cols="4" class="text-left">
-      <h1>{{ leftText }}</h1>
-    </v-col>
-    <v-col cols="4" class="logiciel">
-      <h1>{{ centerText }}</h1>
-    </v-col>
-    <v-col cols="4" class="text-right">
-      <h1>{{ rightText }}</h1>
-    </v-col>
-  </div>
-</LayoutContainer>
-</template>
-
-<script setup>
-import { defineProps } from 'vue';
-
-const props = defineProps({
-  leftText: String,
-  centerText: String,
-  rightText: String,
-});
-</script>
-
-<style scoped>
-.container-title {
-  display: flex;
-  justify-content: space-around;
-  line-height: 16px;
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.18em;
-  border-bottom: 0.1rem solid #eaeaea;
-}
-
-.text-left {
-  position: absolute;
-  font-weight: 600;
-  font-size: 2.3rem;
-  line-height: 85px;
-  opacity: 0.08;
-  margin-top: 2rem;
-  left:-2rem;
-  margin-bottom: 2rem;
-}
-.text-right {
-  position: absolute;
-  right: -2rem;
-  margin-top: 2rem;
-  font-style: normal;
-  font-weight: 600;
-  font-size: 2.3rem;
-  line-height: 85px;
-  text-align: center;
-  opacity: 0.08;
-  margin-bottom: 2rem;
-
-}
-
-.logiciel {
-  display: flex;
-  justify-content: space-around;
-  font-size: 2.3rem;
-  line-height: 77px;
-  color: #000000;
-  text-align: center;
-}
-</style>

+ 0 - 109
components/Common/Card/AvantageCard.vue

@@ -1,109 +0,0 @@
-<template>
-  <LayoutContainer>
-    <div class="advantage-card">
-      <div class="title-card">
-        <h4 class="description-card">{{ title }}</h4>
-        <span class="number-card" :style="{ color: dynamicNumberColor }">{{
-          number
-        }}</span>
-      </div>
-
-      <hr />
-      <div class="description-container">
-        <p class="details-card mr-4">
-          {{ description }}
-        </p>
-        <ul class="dynamic-list ml-4 mr-4">
-          <li v-for="(item, index) in listItems" :key="index">{{ item }}</li>
-        </ul>
-      </div>
-      <div class="image-container" :style="backgroundImageStyle"></div>
-    </div>
-  </LayoutContainer>
-</template>
-
-<script setup>
-import { defineProps } from "vue";
-
-const props = defineProps({
-  title: String,
-  number: String,
-  description: String,
-  image: String,
-  isMemberCMF: Boolean,
-  dynamicNumberColor: String,
-  listItems: Array,
-});
-
-const backgroundImageStyle = computed(() => ({
-  backgroundImage: `url(${props.image})`,
-  backgroundSize: "cover ",
-  backgroundPosition: "center 10%",
-  width: "100£",
-  height: "400px",
-}));
-</script>
-
-<style scoped>
-.v-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.description-container {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  height: 7rem;
-}
-
-.number-card {
-  font-weight: 500;
-  font-size: 1.3rem;
-}
-
-.description-card {
-  font-weight: 300;
-  font-size: 1.5rem;
-  line-height: 1rem;
-  color: #0e2d32;
-}
-.v-chip {
-  background: white;
-  color: black;
-  margin-top: 2rem;
-  margin-bottom: 1rem;
-}
-
-.dynamic-list {
-  font-weight: normal;
-  font-size: 0.8rem;
-  color: #091d20;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-}
-
-.details-card {
-  font-weight: normal;
-  font-size: 1rem;
-  color: #091d20;
-  margin-top: 1rem;
-  height: 5rem;
-}
-.number-card {
-  font-weight: 500;
-  font-size: 1.3rem;
-  color: #7fcdd2;
-}
-
-.title-card {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  font-weight: 600;
-  font-size: 1.3rem;
-  margin-bottom: 1rem;
-}
-</style>

+ 98 - 0
components/Common/Card/Benefit.vue

@@ -0,0 +1,98 @@
+<!--
+Carte "Avantage" de la section Avantages d'une page Logiciel
+-->
+<template>
+  <LayoutContainer>
+    <div>
+      <div class="card-title">
+        <h4>
+          {{ benefit.title }}
+        </h4>
+
+        <span class="number">
+          {{ benefit.number }}
+        </span>
+      </div>
+
+      <v-divider thickness="2"/>
+
+      <div class="description">
+        <p class="mr-4">
+          {{ benefit.description }}
+        </p>
+      </div>
+
+      <v-img
+        :src="benefit.image"
+        cover
+      />
+    </div>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import type { Benefit } from "~/types/interface";
+
+const props = defineProps({
+  benefit: {
+    type: Object as PropType<Benefit>,
+    required: true
+  }
+});
+</script>
+
+<style scoped lang="scss">
+hr {
+  opacity: 70%;
+}
+
+.v-img {
+  height: 400px;
+}
+
+.card-title {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  font-weight: 600;
+  font-size: 1.3rem;
+  margin-bottom: 1rem;
+
+  h4 {
+    font-weight: 300;
+    font-size: 1.5rem;
+    line-height: 1rem;
+    color: var(--primary-color);
+  }
+
+  .number {
+    font-weight: 500;
+    font-size: 1.3rem;
+    color: var(--on-primary-color-alt);
+  }
+}
+
+.description {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  height: 7rem;
+
+  p {
+    font-weight: normal;
+    font-size: 1rem;
+    color: var(--primary-color);
+    margin-top: 1rem;
+    height: 5rem;
+  }
+
+  ul {
+    font-weight: normal;
+    font-size: 0.8rem;
+    color: var(--primary-color);
+    margin-top: 1rem;
+    margin-bottom: 1rem;
+  }
+}
+</style>

+ 23 - 26
components/Common/Card/Stat.vue

@@ -1,33 +1,29 @@
 <template>
-  <div class="card" :style="{ backgroundColor: props.backgroundColor }">
-    <h3 class="chiffre">
-      {{ props.chiffre }}
-    </h3>
-    <p>{{ props.text }}</p>
+  <div class="card">
+    <p>
+      {{ props.number }}
+    </p>
+    <p>
+      {{ props.text }}
+    </p>
   </div>
 </template>
 
-<script setup>
-import { defineProps } from 'vue'
-
+<script setup lang="ts">
 const props = defineProps({
-  chiffre: {
-    type:String,
-    default: 'XXX',
+  number: {
+    type: String
   },
   text: {
-    type: String,
-    default: 'Texte par défaut',
-  },
-  backgroundColor: {
-    type: String,
-    default: '#fac20a', 
+    type: String
   },
 });
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .card {
+  background: var(--on-primary-color-alt);
+  color: var(--primary-color-alt);
   border-radius: 10px;
   width: 36rem;
   height: 15rem;
@@ -36,14 +32,15 @@ const props = defineProps({
   justify-content: center;
   align-items: center;
   text-align: center;
-}
 
-.chiffre {
-  font-weight: 600;
-  font-size: 60px;
-  line-height: 68px;
-  text-align: center;
-  color: #091d20;
-  margin-bottom: 0.5rem;
+  p:first-child{
+    font-weight: 600;
+    font-size: 60px;
+    line-height: 68px;
+    text-align: center;
+    margin-bottom: 0.5rem;
+  }
 }
+
+
 </style>

+ 122 - 0
components/Common/Carousel/Clients.vue

@@ -0,0 +1,122 @@
+<!-- Carrousel des logos clients -->
+
+<template>
+  <LayoutContainer>
+    <!-- Titre -->
+    <v-row justify="center">
+      <h2 class="text-center">
+        <slot name="title">
+          Plus de <span class="alt-color">5000 structures</span> nous font confiance
+        </slot>
+      </h2>
+    </v-row>
+
+    <v-container>
+      <v-row>
+        <!-- Fléche de gauche -->
+        <v-btn
+          icon="fas fa-chevron-left"
+          @click="goToPrevious"
+        />
+
+        <!-- Carrousel -->
+        <Carousel
+          ref="carousel"
+          class="elevation-4 mb-12"
+          :items-to-show="4"
+          :items-to-scroll="2"
+        >
+          <Slide v-for="(item, index) in items" :key="index">
+            <div>
+              <v-img :src="item.src" alt="Card image cap" />
+            </div>
+          </Slide>
+        </Carousel>
+
+        <!-- Fléche de droite -->
+        <v-btn
+          icon="fas fa-chevron-right"
+          @click="goToNext"
+        />
+      </v-row>
+    </v-container>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { Carousel, Slide } from "vue3-carousel";
+import type { PropType } from "@vue/runtime-core";
+
+const carousel: Ref<typeof Carousel | null> = ref(null);
+
+const props = defineProps({
+  items: {
+    type: Array as PropType<Array<{ src: string }>>,
+    required: true
+  }
+});
+
+const goToPrevious = () => {
+  carousel.value!.prev();
+};
+
+const goToNext = () => {
+  carousel.value!.next();
+};
+</script>
+
+<style scoped lang="scss">
+.v-row {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  max-width: 1300px;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+h2 {
+  margin-bottom: 2rem;
+  text-align: center;
+  font-weight: 600;
+  font-size: 42px;
+  line-height: 42px;
+  color: var(--on-primary-color);
+  width: 50%;
+}
+
+.alt-color {
+  color: var(--on-primary-color-alt);
+}
+
+.v-btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 60px;
+  height: 60px;
+  background-color: transparent;
+  color: var(--on-primary-color);
+  border: 2px solid;
+  border-color: var(--on-primary-color);
+  cursor: pointer;
+  margin-right: 1rem;
+  margin-top: 1rem;
+  border-radius: 0;
+}
+
+.carousel {
+  background-color: var(--neutral-color);
+  margin-top: 2rem;
+  border-radius: 20px;
+  margin-left: auto;
+  margin-right: auto;
+  box-shadow: var(--primary-color);
+}
+
+.v-img {
+  height: 10rem;
+  width: 10rem;
+  margin: 2rem auto;
+}
+</style>

+ 129 - 210
components/Common/Carousel/Fonctionnalite.vue

@@ -1,259 +1,178 @@
 <template>
-  <div id="Fonctionnalites">
-    <LayoutContainer v-if="!mdAndDown">
-      <div class="container-green">
-        <v-row class="custom-row">
-          <v-col cols="6">
-            <LayoutUISubTitle
-              title-color="#fff"
-              :iconSize="6"
-              :iconClasses="iconClasses"
-              :titleText="'Découvrez TOUTES LES FONCTIONNALITÉS DE NOTRE solution'"
-              :iconColor="iconColor"
-            />
-            <LayoutUITitle
-              title="Des fonctionnalités adaptées à vos besoins"
-              title-color="#fff"
-            />
-          </v-col>
-
-          <v-col cols="12" md="6" lg="6">
-            <div class="d-flex align-center">
-              <div class="carousel-button" @click="previousAction">
-                <i class="fas fa-chevron-left"></i>
-              </div>
-              <div class="carousel-button" @click="nextAction">
-                <i class="fas fa-chevron-right"></i>
-              </div>
+  <LayoutContainer>
+    <v-row>
+      <v-col cols="6">
+        <LayoutUISubTitle>
+          Découvrez TOUTES LES FONCTIONNALITÉS DE NOTRE solution
+        </LayoutUISubTitle>
+
+        <LayoutUITitle>
+          Des fonctionnalités adaptées à vos besoins
+        </LayoutUITitle>
+      </v-col>
+
+      <v-col cols="12" md="6" class="d-flex align-center justify-start">
+        <v-btn icon="fas fa-chevron-left" @click="previousAction" />
+        <v-btn icon="fas fa-chevron-right" @click="nextAction" />
+      </v-col>
+    </v-row>
+
+    <v-row>
+      <v-col cols="12" md="12">
+        <Carousel
+          ref="carousel"
+          :items-to-show="4"
+          :items-to-scroll="1"
+          :wrap-around="true"
+        >
+          <Slide v-for="(card, index) in cards" :key="index" >
+            <div class="card-container">
+              <v-card class="inv-theme">
+                <v-img
+                  :src="card.logo"
+                  :alt="card.title"
+                  class="mx-auto"
+                />
+
+                <v-card-title>
+                  <h5>
+                    {{ card.title }}
+                  </h5>
+                </v-card-title>
+
+                <v-card-item>
+                  <v-card-text>
+                    <ul>
+                      <li
+                        v-for="item in card.list"
+                        :key="item"
+                      >
+                        <p>{{ item }}</p>
+                      </li>
+                    </ul>
+                  </v-card-text>
+
+                </v-card-item>
+                <div class="footer">
+                    <p
+                      v-for="option in card.options"
+                      :key="option"
+                    >
+                      {{ option }}
+                    </p>
+                  </div>
+              </v-card>
             </div>
-          </v-col>
-        </v-row>
-
-        <v-row class="custom-row">
-          <v-col cols="12" lg="12" md="12">
-            <Carousel
-              ref="functionCarousel"
-              :items-to-show="4"
-              :items-to-scroll="1"
-              class="carousel"
-              :wrap-around="true"
-            >
-              <Slide
-                v-for="(card, index) in cards"
-                :key="index"
-                :class="{
-                  card: true,
-                }"
-              >
-                <div class="card-container">
-                  <v-card>
-                    <v-img
-                      :src="card.logo"
-                      :alt="card.title"
-                      class="mx-auto card-img"
-                    />
-                    <v-card-title>
-                      <h5 class="card-title">{{ card.title }}</h5>
-                    </v-card-title>
-                    <v-card-item>
-                      <v-card-text class="review-description">
-                        <ul>
-                          <li
-                            class="list-detail"
-                            v-for="item in card.list"
-                            :key="item"
-                          >
-                            <p v-html="item"></p>
-                          </li>
-                        </ul>
-                      </v-card-text>
-                 
-                    </v-card-item>
-                    <div class="card-footer">
-                        <p
-                          v-for="option in card.options"
-                          :key="option"
-                        >
-                          {{ option }}
-                        </p>
-                      </div>
-                  </v-card>
-                </div>
-              </Slide>
-            </Carousel>
-          </v-col>
-        </v-row>
-      </div>
-    </LayoutContainer>
-  </div>
+          </Slide>
+        </Carousel>
+      </v-col>
+    </v-row>
+  </LayoutContainer>
 </template>
 
-<script setup>
+<script setup lang="ts">
 import { useDisplay } from "vuetify";
-import { ref, computed } from "vue";
 import { Carousel, Slide } from "vue3-carousel";
 import "vue3-carousel/dist/carousel.css";
-const { smAndDown, mdAndDown } = useDisplay();
-
-const props = defineProps({
-  cards: Array,
-  itemsToScroll: {
-    type: Number,
-    default: 1,
-  },
-  itemsToShow: {
-    type: Number,
-    default: 5,
-  },
-});
+import type { PropType } from "@vue/runtime-core";
+import type { Functionality } from "~/types/interface";
 
-const functionCarousel = ref(null);
+const { mdAndDown } = useDisplay();
 
-const itemsToShow = computed(() => {
-  if (width.value >= 1280 && width.value <= 1920) {
-    return 3;
-  } else if (width.value > 1920) {
-    return 6;
+const props = defineProps({
+  cards: {
+    type: Array as PropType<Array<Functionality>>,
+    required: true
   }
-  return props.itemsToShow;
-});
+})
+
+const carousel: Ref<typeof Carousel | null> = ref(null);
 
 const nextAction = () => {
-  functionCarousel.value.next();
+  carousel.value!.next();
 };
 
 const previousAction = () => {
-  functionCarousel.value.prev();
+  carousel.value!.prev();
 };
 </script>
 
-<style scoped>
-.custom-row {
+<style scoped lang="scss">
+.v-row {
   width: 95%;
   margin-left: auto;
   margin-right: auto;
 }
 
-.card-img {
-  width: 5rem;
-  height: 3rem;
-  margin-top: 1rem;
-}
-.list-detail {
-  font-weight: 300;
-  font-size: 0.9rem;
-  line-height: 1.2rem;
-  margin-bottom: 1rem;
-  color: #000000;
-  word-break: none;
-}
-.card-title {
-  white-space: pre-wrap;
-}
-.carousel {
-  margin-left: 2rem;
-  margin-right: 2rem;
-}
-
-
-
-.title-container {
-  display: flex;
-  align-items: center;
-}
-.subtitle-avantage {
-  font-weight: 600;
-  font-size: 3rem;
-  line-height: 18px;
-  color: white;
-}
-.subtitle {
-  color: white;
-  font-size: 1rem;
-  font-weight: 600;
-  line-height: 15px;
-  letter-spacing: 1.8px;
-  text-transform: uppercase;
-}
-
-.icon-title {
-  color: #fac20a;
-  margin-right: 0.5rem;
-}
-.card {
-  font-weight: 300;
-  transition: transform 0.3s;
-}
-
-
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
+.v-btn {
   width: 60px;
   height: 60px;
   background-color: transparent;
-  border: 2px solid #fff;
+  color: var(--on-primary-color);
+  border: 2px solid;
+  border-color: var(--on-primary-color);
   cursor: pointer;
-  margin-right: 1rem;
-  margin-top: 5rem;
+  border-radius: 0;
+  margin: 6px;
 }
 
-.carousel-button i {
-  color: #fff;
+.carousel {
+  margin-left: 2rem;
+  margin-right: 2rem;
 }
 
-.reviewer-structure {
-  font-weight: 300;
-  font-size: 0.8rem;
+.card-container {
   display: flex;
+  justify-content: center;
   align-items: center;
-  color: #071b1f;
-}
-
-.review-description {
-  text-align: left;
-}
-.card-footer {
-  position: absolute;
-  left: 0;
-  margin-left: .5rem;
-  font-size: .9rem;
+  margin-bottom: 3rem;
+  margin-right: 2rem;
 }
 
-.card {
+.v-card {
   border-radius: 1rem;
   transition: transform 0.3s;
-}
+  font-weight: 300;
+  min-height: 25rem !important;
 
-.v-card {
+  .v-img {
+    width: 5rem;
+    height: 3rem;
+    margin-top: 1rem;
+  }
 
-  min-height: 400px !important;
-  max-height: 400px !important;
-  min-width: 280px !important;
-  max-width: 280px !important;
-  border-radius: 1rem;
-  min-height: 25rem;
+  .v-card-title {
+    white-space: pre-wrap;
+  }
+
+  .v-card-item {
+    text-align: left;
+  }
+
+  li {
+    font-weight: 300;
+    font-size: 0.9rem;
+    line-height: 1.2rem;
+    margin-bottom: 1rem;
+    color: var(--on-neutral-color);
+  }
+
+  .footer {
+    position: absolute;
+    left: 0;
+    margin-left: .5rem;
+    font-size: .9rem;
+  }
 }
 
 @media(min-width: 1800px){
   .v-card{
     min-height: 400px !important;
-  max-height: 400px !important;
-  min-width: 400px !important;
-  max-width: 400px !important;
+    max-height: 400px !important;
+    min-width: 400px !important;
+    max-width: 400px !important;
   }
 }
 
-.card-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  margin-bottom: 3rem;
-  margin-right: 2rem;
-}
 
-.container-green {
-  background-color: #0e2d32;
-}
 </style>

+ 0 - 142
components/Common/Carousel/TrustCompanie.vue

@@ -1,142 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row justify="center">
-      <h2 class="title text-center" :style="{ color: titleColor }">
-        Plus de&nbsp;
-        <span :style="{ color: structureCountColor }">{{ structureCount }}</span
-        >&nbsp; {{ trustMessage }}
-      </h2>
-    </v-row>
-
-    <v-row justify="center"> </v-row>
-
-    <v-container>
-      <v-row>
-        <div
-          class="carousel-button"
-          @click="goPrevious"
-          :style="{
-            'border-color': carouselBorderColor,
-            color: carouselButtonColor,
-          }"
-        >
-          <i class="fas fa-chevron-left" :style="{ color: iconColor }" />
-        </div>
-        <Carousel
-          ref="carousel"
-          class="carrousel elevation-4 mb-12"
-          :items-to-show="4"
-          :items-to-scroll="2"
-        >
-          <Slide v-for="(item, index) in items" :key="index">
-            <div class="card">
-              <v-img class="card-img" :src="item.src" alt="Card image cap" />
-            </div>
-          </Slide>
-        </Carousel>
-        <div
-          class="carousel-button"
-          @click="goNext"
-          :style="{
-            'border-color': carouselBorderColor,
-            color: carouselButtonColor,
-          }"
-        >
-          <i class="fas fa-chevron-right" :style="{ color: iconColor }" />
-        </div>
-
-        
-      </v-row>
-    </v-container>
-  </LayoutContainer>
-</template>
-
-<script setup>
-import { ref } from "vue";
-import { Carousel, Slide } from "vue3-carousel";
-const carousel = ref(null);
-
-const props = defineProps({
-  titleColor: String,
-  carouselButtonColor: String,
-  carouselBorderColor: String,
-  items: Array,
-  iconColor: String,
-  trustMessage: {
-    type: String,
-    default: "nous font confiance",
-  },
-  structureCount: {
-    type: String,
-    default: "5000 structures",
-  },
-  structureCountColor: {
-    type: String,
-    default: "#c3e5e7",
-  },
-});
-
-const goPrevious = () => {
-  carousel.value.prev();
-};
-
-const goNext = () => {
-  carousel.value.next();
-};
-</script>
-
-<style scoped>
-.v-row {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  max-width: 1300px;
-  margin-right: auto;
-  margin-left: auto;
-}
-.carousel-button i {
-  color: black;
-}
-
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 60px;
-  height: 60px;
-  background-color: transparent;
-  border: 2px solid black;
-  cursor: pointer;
-  margin-right: 1rem;
-  margin-top: 1rem;
-}
-.card-img {
-  height: 10rem;
-  width: 10rem;
-  margin-left: auto;
-  margin-right: auto;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-}
-.carousel {
-  background-color: white;
-  margin-top: 2rem;
-  border-radius: 20px;
-  margin-left: auto;
-  margin-right: auto;
-  box-shadow: #071b1f;
-}
-
-.title {
-  margin-bottom: 2rem;
-  font-style: normal;
-  text-align: center;
-  color: black;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  text-align: center;
-  color: #0e2d32;
-  width: 50%;
-}
-</style>

+ 47 - 79
components/Common/ContainerVideo.vue

@@ -1,97 +1,65 @@
 <template>
-  <div id="Presentation">
-    <LayoutContainer>
-      <div class="container-green">
-        <v-row class="mt-12">
-          <v-row>
-            <v-col cols="6">
-              <LayoutUISubTitle
-                class="mt-6"
-                :iconSize="5"
-                :iconColor="iconColor"
-                :titleText="titleText"
-                :titleColor="'#ffffff'"
-              />
-              <p class="citation-school">
-                {{ currentCitation }}
-              </p>
-            </v-col>
+  <LayoutContainer>
+    <div class="container-green">
+      <v-row class="mt-12">
+        <v-row>
+          <v-col cols="6">
+            <LayoutUISubTitle class="mt-6">
+              {{ title }}
+            </LayoutUISubTitle>
 
-            <v-col cols="6">
-              <div class="screen-img-3"></div>
-              <div class="play-icon-container">
-                <i class="fas fa-play"></i>
-              </div>
-            </v-col>
-          </v-row>
-        </v-row>
-      </div>
-    </LayoutContainer>
-  </div>
-</template>
-
-<script setup>
-import { computed } from "vue";
-import { useRoute } from "vue-router";
-
-const route = useRoute();
+            <p class="quote">
+              {{ quote }}
+            </p>
+          </v-col>
 
-const titleText = computed(() => {
-  if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "Logiciel OpenTalent School";
-  } else if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "Logiciel OpenTalent Artist";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "Logiciel OpenTalent Manager";
-  }
-});
+          <v-col cols="6">
+            <div class="screen-img-3" />
 
-const currentCitation = computed(() => {
-  if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "Pour les petits comme pour les grands établissements d’enseignement artistique.";
-  } else if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "Le logiciel de gestion et communication au service de votre passion";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "Une solution unique, collaborative et innovante pour une gestion optimale de votre réseau culturel.";
-  } else {
-    return "Citation par défaut";
-  }
-});
+            <div class="play-icon-container">
+              <i class="fas fa-play"></i>
+            </div>
+          </v-col>
+        </v-row>
+      </v-row>
+    </div>
+  </LayoutContainer>
+</template>
 
-const iconColor = computed(() => {
-  if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "rgba(32, 147, 190, 0.6)";
-  } else if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "#fac20a";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "rgb(216, 5, 11)";
-  } else {
-    return "rgba(32, 147, 190, 0.6)";
+<script setup lang="ts">
+const props = defineProps({
+  title: {
+    type: String,
+    required: true
+  },
+  quote: {
+    type: String,
+    required: true
   }
-});
+})
 </script>
 
-<style scoped>
+<style scoped lang="scss">
+.v-container {
+  padding: 0 !important;
+}
+
+.v-row {
+  width: 90% !important;
+  margin-left: auto !important;
+  margin-right: auto !important;
+}
 
 .play-icon-container {
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
-  font-size: 3rem; 
-  color: white; 
+  font-size: 3rem;
+  color: #ffffff;
   cursor: pointer;
 }
 
-
-.v-row {
-  width: 90% !important;
-  margin-left: auto !important;
-  margin-right: auto !important;
-}
-.v-container {
-  padding: 0 !important;
-}
 .screen-img-3 {
   background-image: url("/images/logiciels/school/screen2.png");
   background-size: cover;
@@ -100,14 +68,13 @@ const iconColor = computed(() => {
   height: 650px;
 }
 
-.citation-school {
+.quote {
   font-style: italic;
   font-weight: 300;
   font-size: 2rem;
   width: 35rem;
   line-height: 40px;
   color: #ffffff;
-  font-style: italic;
   margin-top: 27rem;
   margin-left: 2rem;
 }
@@ -115,6 +82,7 @@ const iconColor = computed(() => {
 .icon-logiciel {
   margin-right: 1rem;
 }
+
 .container-green {
   background: linear-gradient(180deg, rgba(14, 45, 50, 0) 26.84%, #0e2d32 100%),
     rgba(7, 27, 31, 0.3);

+ 48 - 68
components/Common/MenuScroll.vue

@@ -1,112 +1,92 @@
+<!-- Menu sticky horizontal -->
+<!-- TODO: review -->
 <template>
   <LayoutContainer>
     <v-row>
       <v-col
         cols="12"
-        class="menu-container"
-        :class="{ 'sticky-menu': isSticky }"
       >
-        <div
-          v-for="menu in menus"
-          :key="menu.id"
-          @click="navigate(menu)"
+        <v-list
+          class="menu-container"
+          density="compact"
+          :class="{ 'sticky-menu': isSticky }"
         >
-          <v-chip
-            v-if="activeMenu === menu.id"
-            class="active-menu"
-          >
-            {{ menu.label }}
-          </v-chip>
-          <span v-else>{{ menu.label }}</span>
-        </div>
+          <div v-for="menu in menus" :key="menu.anchor">
+            <nuxt-link :to="{ path: '', hash: '#' + menu.anchor }">
+              <v-list-item
+                :class="{ active : isSticky && layoutStore.isAnchoredSectionOnScreen[menu.anchor] }"
+              >
+                {{ menu.label }}
+              </v-list-item>
+            </nuxt-link>
+          </div>
+        </v-list>
       </v-col>
     </v-row>
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref, onMounted, watch } from 'vue';
+<script setup lang="ts">
+import type { PropType } from "@vue/runtime-core";
+import type { MenuScroll } from "~/types/interface";
+import { useLayoutStore } from "~/stores/layoutStore";
 
 const props = defineProps({
-  menus: Array
+  menus: {
+    type: Array as PropType<Array < MenuScroll >>,
+    required: true
+  }
 });
 
-const isSticky = ref(false);
-const activeMenu = ref('');
+const layoutStore = useLayoutStore()
 
-const scrollToElement = (element) => {
-  if (element) {
-    element.scrollIntoView({ behavior: "smooth" });
-  }
-};
-
-const handleScroll = () => {
-  const scrollPosition = window.scrollY;
-  isSticky.value = scrollPosition > 800; 
-
-  for (const menu of props.menus) {
-    const { element } = menu;
-    if (element && scrollPosition >= element.offsetTop && scrollPosition < element.offsetTop + element.offsetHeight) {
-      activeMenu.value = menu.id;
-      break;
-    }
-  }
-};
+const isSticky: Ref<boolean> = ref(false);
 
 onMounted(() => {
-  props.menus.forEach(menu => {
-    menu.element = document.getElementById(menu.id);
-  });
   window.addEventListener('scroll', handleScroll);
-});
+})
 
-watch(() => props.menus, (newMenus) => {
-  newMenus.forEach(menu => {
-    menu.element = document.getElementById(menu.id);
-  });
-}, { deep: true });
-
-const navigate = (menu) => {
-  activeMenu.value = menu.id;
-  scrollToElement(menu.element);
-};
+const handleScroll = () => {
+  isSticky.value = window.scrollY > 800;
+}
 </script>
 
-<style scoped>
-
+<style scoped lang="scss">
 .sticky-menu {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
-  background: white;
-  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
+  background: var(--neutral-color);
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
 }
+
 .menu-container {
   z-index: 3;
   display: flex;
   justify-content: space-around;
-  background: white;
-  color: #071b1f;
-  font-family: "Barlow";
+  background: var(--neutral-color);
+  color: var(--primary-color);
   font-size: 1rem;
   line-height: 19px;
-  display: flex;
   align-items: center;
   text-align: center;
   letter-spacing: 0.18em;
   text-transform: uppercase;
-  border-bottom: 0.1rem solid #eaeaea;
-}
-.v-chip.active-menu {
-  background: var(--Vert-100, #091D20);;
-  color: white;
+  border-bottom: 0.1rem solid var(--on-neutral-color-extra-light);
+
+  a {
+    text-decoration: none;
+    color: var(--primary-color);
+  }
+
+  a:hover {
+    text-decoration: underline;
+  }
 }
 
-.menu-container div:hover {
-  cursor: pointer;
-  text-decoration: underline;
-  z-index: 15;
+.active {
+  font-weight: 800;
 }
 </style>
 

+ 176 - 210
components/Common/Presentation.vue

@@ -1,279 +1,245 @@
+<!--
+Section "Présentation" d'une page Logiciel
+-->
 <template>
   <div id="Presentation">
     <LayoutContainer>
-      <v-row class="custom-row" >
+      <v-row class="center-90">
+
+        <!-- Colonne 1 (sous-titre, illustration logiciels, prix) -->
         <v-col cols="5">
-          <LayoutUISubTitle
-            :iconSize="5"
-            :iconColor="iconColor"
-            :titleText="titleText"
-            class="ml-8"
+          <LayoutUISubTitle class="ml-8" >
+            {{ title }}
+          </LayoutUISubTitle>
+
+          <v-img
+            src="/images/logiciels/Opentalent-disponible-su-Multi-support.png"
+            class="w-100"
           />
-          <!-- <div class="screen-img"></div> -->
-          <v-img src="/images/logiciels/Opentalent-disponible-su-Multi-support.png" class="screen-img" />
 
-          <div
-            :style="{ backgroundColor: backgroundColor }"
-            class="rectangle-4 ml-6"
-          >
-            <div :style="{ backgroundColor: circleColor }" class="black-circle">
-              <div class="content-flex  ml-6">
-                <v-img :src="logoSrc" class="logo-manager" />
-                <div class="pricing-details">
-                  <p class="pricing-small-text">{{ pricingFromText }}</p>
-                  <p class="pricing-big-text">
-                    {{ pricingAmount }}
-                    <span class="smaller-text">{{ pricingPeriodText }}</span>
-                  </p>
-                  <p class="pricing-small-text">
-                    {{ pricingAnnouncementText }}
-                  </p>
-                </div>
+          <div class="pricing-rectangle rectangle-4 ml-6">
+            <div class="logo-circle">
+              <div class="content-flex ml-6">
+                <v-img
+                  :src="logoSrc"
+                  class="software-logo"
+                />
               </div>
             </div>
+
+            <div v-if="pricingAmount" class="details">
+              <p class="small-text">
+                {{ pricingFromText }}
+              </p>
+              <p class="big-text">
+                {{ pricingAmount }}
+                <span class="smaller-text">
+                  {{ pricingPeriodText }}
+                </span>
+              </p>
+              <p class="small-text">
+                {{ pricingAnnouncementText }}
+              </p>
+            </div>
+            <div v-else class="details medium-text">
+              {{ pricingAltText }}
+            </div>
           </div>
         </v-col>
 
+        <!-- Colonne 2 (présentation, pictogrammes des fonctionnalités) -->
         <v-col cols="6">
-          <LayoutUITitle :title="presentationText.toolTitle" />
-          <ul class="outil-ul ml-12 mt-6">
+          <h3>
+            {{ section1title }}
+          </h3>
+
+          <ul class="ml-12 mt-6">
             <li
-              class="outil-list"
-              v-for="item in presentationText.toolList"
+              v-for="item in features"
               :key="item"
             >
               {{ item }}
             </li>
           </ul>
-          <h2 class="mt-12 ml-6 presentation-caracteristique">
-            {{ presentationText.characteristicsTitle }}
-          </h2>
-            <div class="picto-container">
-              <div
-                class="picto-group"
-                v-for="picto in pictoImages"
-                :key="picto.text"
-              >
-                <div
-                  :style="{ backgroundImage: 'url(' + picto.src + ')' }"
-                  class="picto-img"
-                ></div>
-                <p class="picto-text" :style="{ color: pictoColor }">
-                  {{ picto.text }}
-                </p>
-              </div>
+
+          <h3 class="mt-12 ml-6">
+            {{ section2title }}
+          </h3>
+
+          <div class="d-flex flex-row">
+            <div
+              v-for="picto in pictos"
+              :key="picto.text"
+              class="picto"
+            >
+              <v-img :src="picto.src" class="img" />
+
+              <p class="text">
+                {{ picto.text }}
+              </p>
             </div>
+          </div>
         </v-col>
       </v-row>
     </LayoutContainer>
   </div>
 </template>
 
-<script setup>
-import { computed } from "vue";
-import { useRoute } from "vue-router";
+<script setup lang="ts">
+import type { PropType } from "@vue/runtime-core";
+import type { FeaturePicto } from "~/types/interface";
 
 const route = useRoute();
 
-const pricingAmount = computed(() => {
-  if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "14€";
-  } else if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "20€";
-  }else {
-    return "Sur devis";
-  }
-});
-
-const logoSrc = computed(() => {
-  if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "/images/logo/logiciels/OT_Artist-BLANC.png";
-  } else if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "/images/logo/logiciels/OT_School-blanc.png";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "/images/logo/logiciels/OT_Manager-BLANC.png";
-  }
-});
-
-const titleText = computed(() => {
-  if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "Présentation d'Opentalent Artist";
-  } else if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "Présentation d'Opentalent School";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "Présentation d'Opentalent Manager";
-  } else {
-    return "Titre par défaut"; 
-  }
-});
-
-const iconColor = computed(() => {
-  if (/^\/opentalent_artist(\/|$)/.test(route.path)) {
-    return "#fac20a";
-  } else if (/^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "rgba(32, 147, 190, 0.6)";
-  } else if (/^\/opentalent_manager(\/|$)/.test(route.path)) {
-    return "#d8050b";
-  } else {
-    return "rgba(32, 147, 190, 0.6)"; 
-  }
-});
-
-// on affiche " à partir de" sur opentalent_school et artist
-const pricingFromText = computed(() => {
-  if (/^\/opentalent_artist(\/|$)/.test(route.path) || /^\/opentalent_school(\/|$)/.test(route.path)) {
-    return "à partir de";
-  }else{
-    return ''
-  }
-
-})
 const props = defineProps({
-  pictoImages: {
-    type: Array,
-    default: () => [],
+  title: {
+    type: String,
+    required: true
+  },
+  section1title: {
+    type: String,
+    required: false,
+    default: "Un outil complet en ligne"
   },
-  pictoColor: {
+  section2title: {
     type: String,
-    default: "#000000",
+    required: false,
+    default: "Des caractéristiques uniques & dédiée"
   },
-  presentationText: {
-    type: Object,
-    default: () => ({
-      toolTitle: "Default Title",
-      toolList: [],
-      characteristicsTitle: "Default Characteristics Title",
-    }),
+  features: {
+    type: Object as PropType<Array<string>>,
+    required: true
+  },
+  pictos: {
+    type: Array as PropType<Array<FeaturePicto>>,
+    required: true
   },
   logoSrc: {
     type: String,
     default: "",
   },
   pricingFromText: {
-    type: String
+    type: String,
+    required: false,
+    default: "à partir de"
   },
   pricingAmount: {
     type: String,
-    default: "sur devis",
-    class: "pricing-big-text",
+    default: ""
   },
   pricingPeriodText: {
     type: String,
+    required: false,
+    default: "mois"
   },
   pricingAnnouncementText: {
     type: String,
+    required: false,
+    default: "payable annuellement"
   },
-  backgroundColor: {
-    type: String,
-    default: "rgba(32, 147, 190, 0.2)",
-  },
-  circleColor: {
-    type: String,
-    default: "#091d20",
-  },
+  pricingAltText: {
+    required: false,
+    default: ""
+  }
 });
-
-
 </script>
 
-<style scoped>
+<style scoped lang="scss">
+.pricing-rectangle {
+  display: flex;
+  flex-direction: row;
+  background-color: var(--secondary-color);
+  width: 380px;
+  height: 6rem;
+  border-radius: 3rem;
+  margin-top: 2rem;
 
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.picto-img {
-  width: 200px;
-  height: 200px;
-  background-size: contain;
-  background-repeat: no-repeat;
-  background-position: center;
-}
+  .logo-circle {
+    background-color: #0e2d32;
+    border-radius: 3rem;
+    width: 7rem;
+    height: 6rem;
+  }
 
-.presentation-caracteristique {
-  color: #071b1f;
-  font-size: 34px;
-  font-style: normal;
-  font-weight: 400;
-  line-height: 38px;
-}
-.pricing-details {
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  height: 100%;
-  color: black;
-  font-weight: 500;
-  font-size: 1rem;
-  margin-left: 7rem;
-  margin-top: -3rem;
-  width: 10rem;
-}
+  .software-logo {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    top:1rem;
+    right: .5rem;
+  }
 
-.pricing-small-text {
-  font-size: 0.6em;
-}
+  .details {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    height: 100%;
+    color: var(--on-neutral-color);
+    font-weight: 500;
+    font-size: 1rem;
+    width: 10rem;
+    margin-left: 18px;
+  }
 
-.pricing-big-text {
-  font-size: 2.5rem;
-  font-weight: bold;
-  line-height: 2rem;
-  margin-left: 1rem;
-}
+  .small-text {
+    font-size: 0.6em;
+  }
 
-.smaller-text {
-  font-size: 0.6em;
-}
-.black-circle {
-  border-radius: 3rem;
-  background: #091d20;
-  width: 7rem;
-  height: 6rem;
-}
+  .big-text {
+    font-size: 2.5rem;
+    font-weight: bold;
+    line-height: 2rem;
+    margin-left: 1rem;
+  }
 
+  .smaller-text {
+    font-size: 0.6em;
+  }
 
-.logo-manager {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  top:1rem;
-  right: .5rem;
-}
-.rectangle-4 {
-  width: 380px;
-  height: 6rem;
-  background: rgba(32, 147, 190, 0.2);
-  border-radius: 3rem;
-  margin-top: 2rem;
-}
-.picto-text {
-  font-weight: 300;
-  font-size: 0.9rem;
-  margin-top: -3rem;
-  text-align: center;
-  width: 60%;
-  margin-right: auto;
-  margin-left: auto;
-}
-.picto-container {
-  display: flex;
-  flex-direction: row;
+  .medium-text {
+    font-size: 1.5rem;
+    font-weight: 400;
+  }
 }
-.picto-group {
+
+.picto {
   display: flex;
   flex-direction: column;
   align-items: center;
   margin-left: -4rem;
+
+  .text {
+    font-weight: 300;
+    font-size: 0.9rem;
+    margin-top: -3rem;
+    text-align: center;
+    width: 60%;
+    margin-right: auto;
+    margin-left: auto;
+  }
+
+  .img {
+    width: 200px;
+    height: 200px;
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center;
+  }
 }
 
-.picto-container {
-  display: flex;
-  flex-direction: row;
+h3 {
+  color: var(--on-primary-color);
+  font-size: 34px;
+  font-weight: 400;
+  line-height: 38px;
 }
 
-.screen-img {
-  width: 100%;
+h3:first-child {
+  font-weight: 600;
+  font-size: 3rem;
+  line-height: 3rem;
+  margin-left: 1rem;
+  width: 35rem;
 }
 </style>

+ 0 - 203
components/Common/ReviewCard.vue

@@ -1,203 +0,0 @@
-<template>
-    <LayoutContainer>
-      <div class="container-green">
-        <v-row class="custom-row">
-          <v-col cols="3">
-            <div
-              style="
-                display: flex;
-                flex-direction: column;
-                justify-content: space-between;
-                height: 100%;
-              "
-            >
-              <h3 class="reviews-title">Ce sont eux qui en parlent le mieux</h3>
-              <div class="d-flex justify-center align-center">
-                <div class="carousel-button" @click="goPrevious">
-                  <i class="fas fa-chevron-left" />
-                </div>
-                <div class="carousel-button" @click="goNext">
-                  <i class="fas fa-chevron-right" />
-                </div>
-              </div>
-            </div>
-          </v-col>
-
-          <v-col cols="9">
-            <Carousel ref="carousel" :items-to-show="3" :items-to-scroll="1" :wrap-around="true">
-              <Slide v-for="(card, index) in cards" :key="index" class="card">
-                <v-container>
-                  <v-card>
-                    <v-card-item class="card-container">
-                      <v-card-text class="review-description">
-                        {{ card.description }}
-                      </v-card-text>
-
-                      <div class="card-footer">
-                        <v-card-actions class="reviewer-name">
-                          {{ card.name }}
-                        </v-card-actions>
-
-                        <p class="reviewer-status">
-                          {{ card.status }}
-                        </p>
-                        <p class="reviewer-structure">
-                          {{ card.structure }}
-                        </p>
-                      </div>
-                    </v-card-item>
-                  </v-card>
-                </v-container>
-              </Slide>
-            </Carousel>
-          </v-col>
-        </v-row>
-      </div>
-    </LayoutContainer>
-</template>
-
-<script setup>
-import { Carousel, Slide } from "vue3-carousel";
-import "vue3-carousel/dist/carousel.css";
-import { ref } from "vue";
-
-const carousel = ref(null);
-
-const goPrevious = () => {
-  carousel.value.prev();
-};
-
-const goNext = () => {
-  carousel.value.next();
-};
-
-const props = defineProps({
-  cards: {
-    type: Array,
-    required: true,
-  },
-});
-</script>
-<style scoped>
-
-
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.v-container {
-  padding: 0 !important;
-}
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 60px;
-  height: 60px;
-  background-color: transparent;
-  border: 2px solid #fff;
-  cursor: pointer;
-  margin-right: 1rem;
-  margin-bottom: 2rem;
-}
-
-.carousel-button i {
-  color: #fff;
-}
-.reviewer-name {
-  font-weight: 500;
-  font-size: 20px;
-  line-height: 24px;
-  color: rgba(32, 147, 190);
-  margin-top: 5rem;
-
-  text-align: justify !important;
-}
-
-.reviewer-status {
-  font-weight: 600;
-  font-size: 12px;
-  line-height: 16px;
-  display: flex;
-  align-items: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-
-  text-align: justify !important;
-}
-
-.reviewer-structure {
-  font-weight: 300;
-  font-size: 0.8rem;
-  line-height: 14px;
-  display: flex;
-  align-items: center;
-  margin-bottom: 1rem;
-}
-
-.card-footer {
-  min-height: 100px;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  margin-top: 1rem;
-}
-
-.reviews-title {
-  font-size: 2rem;
-  font-weight: 700;
-  color: #fff;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  margin-left: 1rem;
-  margin-right: 1rem;
-  margin-top: 3rem;
-  text-align: center;
-  
-}
-@media (min-width:2100px) {
-  .review-description {
-    min-height: 150px !important;
-    max-height: 150px   !important;
-  }
-  .v-card {
-    min-height: 360px !important;
-    max-height: 360px !important;
-  }
-}
-.card {
-  margin-left: 0.5rem;
-  border-radius: 1rem;
-}
-.review-description {
-  text-align: justify;
-  min-height: 200px;
-  max-height: 200px;
-  overflow: auto;
-  font-size: 0.9rem;
-}
-.v-card {
-  border-radius: 1rem;
-  min-height: 450px;
-  max-height: 450px;
-  margin-top: 2rem;
-  margin-bottom: 0.6rem;
-  
-}
-
-.card-container {
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
-  height: 100%;
-  
-  
-}
-
-.container-green {
-  background-color: #0e2d32;
-}
-</style>

+ 213 - 0
components/Common/ReviewSection.vue

@@ -0,0 +1,213 @@
+<template>
+    <LayoutContainer>
+      <v-row class="center-90">
+        <v-col cols="3">
+          <div class="controls-section">
+            <h3>
+              Ce sont eux qui en parlent le mieux
+            </h3>
+
+            <div class="carousel-controls">
+              <v-btn
+                icon="fas fa-chevron-left"
+                @click="goPrevious"
+              />
+              <v-btn
+                icon="fas fa-chevron-right"
+                @click="goNext"
+              />
+            </div>
+          </div>
+        </v-col>
+
+        <v-col cols="9">
+          <Carousel
+            ref="carousel"
+            :items-to-show="3"
+            :items-to-scroll="1"
+            :wrap-around="true"
+          >
+            <Slide
+              v-for="(card, index) in cards"
+              :key="index"
+              class="card"
+            >
+              <v-container>
+                <v-card class="inv-theme">
+                  <v-card-item>
+                    <v-card-text>
+                      {{ card.review }}
+                    </v-card-text>
+
+                    <footer>
+                      <v-card-actions>
+                        {{ card.name }}
+                      </v-card-actions>
+
+                      <p class="reviewer-status">
+                        {{ card.status }}
+                      </p>
+                      <p class="reviewer-structure">
+                        {{ card.structure }}
+                      </p>
+                    </footer>
+                  </v-card-item>
+                </v-card>
+              </v-container>
+            </Slide>
+          </Carousel>
+        </v-col>
+      </v-row>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import { Carousel, Slide } from "vue3-carousel";
+import "vue3-carousel/dist/carousel.css";
+import type { PropType } from "@vue/runtime-core";
+import type { Review } from "~/types/interface";
+
+const props = defineProps({
+  cards: {
+    type: Array as PropType<Array<Review>>,
+    required: true,
+  },
+});
+
+const carousel: Ref<typeof Carousel | null> = ref(null);
+
+const goPrevious = () => {
+  carousel.value!.prev();
+};
+
+const goNext = () => {
+  carousel.value!.next();
+};
+</script>
+
+<style scoped lang="scss">
+.v-container {
+  padding: 0 !important;
+}
+
+.controls-section {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  height: 100%;
+
+  h3 {
+    font-weight: 600;
+    font-size: 42px;
+    line-height: 42px;
+    margin-left: 1rem;
+    margin-right: 1rem;
+    margin-top: 3rem;
+    text-align: center;
+  }
+
+  .carousel-controls {
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .v-btn {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 60px;
+    height: 60px;
+    background-color: transparent;
+    border: 2px solid var(--on-standard-theme);
+    cursor: pointer;
+    margin-right: 1rem;
+    margin-bottom: 2rem;
+    border-radius: 0;
+  }
+}
+
+.carousel {
+  .v-card-item {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    height: 100%;
+  }
+
+  .v-card-text {
+    text-align: justify;
+    min-height: 200px;
+    max-height: 200px;
+    overflow: auto;
+    font-size: 0.9rem;
+  }
+
+  footer {
+    min-height: 100px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    margin-top: 1rem;
+  }
+
+  .v-card-actions {
+    font-weight: 500;
+    font-size: 20px;
+    line-height: 24px;
+    color: var(--on-primary-color-alt) !important;
+    margin-top: 5rem;
+    text-align: justify !important;
+  }
+
+  .reviewer-status {
+    font-weight: 600;
+    font-size: 12px;
+    line-height: 16px;
+    display: flex;
+    align-items: center;
+    letter-spacing: 0.18em;
+    text-transform: uppercase;
+    text-align: justify !important;
+  }
+
+  .reviewer-structure {
+    font-weight: 300;
+    font-size: 0.8rem;
+    line-height: 14px;
+    display: flex;
+    align-items: center;
+    margin-bottom: 1rem;
+  }
+
+  @media (min-width:2100px) {
+    .v-card-text {
+      min-height: 150px !important;
+      max-height: 150px !important;
+    }
+  }
+}
+
+.card {
+  margin-left: 0.5rem;
+  border-radius: 1rem;
+}
+
+.v-card {
+  padding: 0 0.5rem;
+  border-radius: 1rem;
+  min-height: 450px;
+  max-height: 450px;
+  margin-top: 2rem;
+  margin-bottom: 0.6rem;
+}
+
+@media (min-width:2100px) {
+  .v-card {
+    min-height: 360px !important;
+    max-height: 360px !important;
+  }
+}
+</style>

+ 84 - 0
components/Common/Share.vue

@@ -0,0 +1,84 @@
+<template>
+  <div v-if="url" class="share">
+    <nuxt-link
+      v-for="network in networks"
+      :key="network.name"
+      :href="network.url"
+      target="_blank"
+      :style="{ color: network.colorOnHover }"
+    >
+      <v-icon :icon="network.icon"/>
+    </nuxt-link>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import type { SocialNetworkShareBtn } from "~/types/interface";
+
+  const url: Ref<string | null> = ref(null)
+  const networks: Ref<Array<SocialNetworkShareBtn>> = ref([])
+
+  if (process.client) {
+    url.value = window.location.href
+
+    networks.value = [
+      {
+        name: "Facebook",
+        icon: "fa-brands fa-facebook",
+        colorOnHover: "#135fc2",
+        url: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url.value)}`
+      },
+      {
+        name: "Twitter",
+        icon: "fa-brands fa-twitter",
+        colorOnHover: "#1781c2",
+        url: `https://twitter.com/intent/tweet?url=${encodeURIComponent(url.value)}`
+      },
+      {
+        name: "Messenger",
+        icon: "fa-brands fa-facebook-messenger",
+        colorOnHover: "#0085ff",
+        url: `https://messenger.com`
+      },
+      {
+        name: "Instagram",
+        icon: "fa-brands fa-instagram",
+        colorOnHover: "#d0006a",
+        url: "https://instagram.com"
+      },
+      {
+        name: "Linkedin",
+        icon: "fa-brands fa-linkedin",
+        colorOnHover: "#006291",
+        url: `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(url.value)}`
+      },
+      {
+        name: "Email",
+        icon: "fas fa-envelope",
+        colorOnHover: "#292929",
+        url: `mailto:?body=${url.value}`
+      },
+    ]
+  }
+
+</script>
+
+<style scoped lang="scss">
+.share {
+  display: flex;
+  gap: 10px;
+  font-size: 16px;
+  font-weight: 400;
+  line-height: 28px;
+
+  i {
+    font-size: 32px;
+    margin: 0.5rem 0.3rem;
+    color: var(--on-neutral-color-light);
+  }
+
+  a:hover i {
+    color: inherit;
+  }
+}
+</style>

+ 0 - 142
components/Common/StickyMenu.vue

@@ -1,142 +0,0 @@
-<template>
-  <div :class="stickyClass" v-if="!mdAndDown">
-    <v-row class="outil-row">
-      <v-col cols="12">
-        <div class="container-square">
-          <v-row
-            v-for="square in squares"
-            :key="square.id"
-            :class="['square', square.bgColor]"
-            @click="() => handleSquareClick(square)"
-          >
-            <NuxtLink :to="square.url" class="link">
-              <div>
-                <v-icon :class="square.iconClass" />
-                <p class="text-square mt-2">{{ square.text }}</p>
-              </div>
-            </NuxtLink>
-          </v-row>
-        </div>
-      </v-col>
-    </v-row>
-  </div>
-
-  <div v-if="mdAndDown">
-    <div class="sticky-menu">
-      <v-btn color="primary">Bouton 1</v-btn>
-      <v-btn color="secondary">Bouton 2</v-btn>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, defineProps } from "vue";
-import { useRouter } from "vue-router";
-import { useDisplay } from "vuetify";
-
-const { mdAndDown } = useDisplay();
-const router = useRouter();
-const props = defineProps({
-  shouldShowStickyMenu: Boolean,
-  squaresData: Array,
-});
-
-const stickyClass = ref("sticky-scroll");
-
-const squares = ref(props.squaresData);
-const telephoneNumber = "09 72 12 60 17";
-const handleSquareClick = (square) => {
-  if (square.id === 2) {
-    router.push({ path: square.url, query: { request: "demo" } });
-  } else if (square.id === 4) {
-    if (isMobileDevice()) {
-      window.location.href = `tel:${telephoneNumber}`;
-    } else {
-      alert(`Notre numéro de téléphone : ${telephoneNumber}`);
-    }
-  } else {
-    router.push({ path: square.url });
-  }
-};
-
-const isMobileDevice = () => {
-  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
-    navigator.userAgent
-  );
-};
-</script>
-
-<style scoped>
-
-
-.sticky-menu {
-  position: fixed;
-  bottom: 0;
-  width: 100%;
-  display: flex;
-  justify-content: center;
-  background-color: white;
-  z-index: 100;
-}
-.square {
-  transition: transform 0.3s ease-in-out;
-}
-
-.square:hover {
-  transform: translateX(-10px);
-}
-
-.link {
-  text-decoration: none;
-  color: white;
-}
-
-.container-square {
-  text-align: center !important;
-  display: flex;
-  flex-direction: column;
-  color: white;
-  font-weight: 500;
-  font-size: 0.7rem;
-  line-height: 15px;
-  text-align: center;
-  letter-spacing: 0.2em;
-  text-transform: uppercase;
-}
-
-.red-square,
-.yellow-square,
-.blue-square,
-.darkblue-square,
-.green-square {
-  position: relative;
-  font-family: "Barlow";
-  width: 7rem;
-  padding: 1rem;
-  cursor: pointer;
-}
-
-.yellow-square {
-  background: rgb(250, 194, 10);
-  color: #0e2d32;
-}
-
-.green-square {
-  background: #9edbdd;
-}
-
-.red-square {
-  background: #d8050b;
-}
-
-.blue-square {
-  background: var(--Bleu-School-60, rgba(32, 147, 190));
-}
-
-.darkblue-square {
-  background: #0e2d32;
-}
-
-.text-square {
-}
-</style>

+ 96 - 106
components/Common/Table/Comparatif.vue

@@ -1,20 +1,22 @@
 <template>
   <LayoutContainer>
-    <v-row class="row-custom">
-      <table class="table-comparatif">
+    <v-row class="center-90">
+      <table>
         <thead>
           <tr>
-            <th class="thead" />
-            <th class="thead">
-              <p class="standard" :style="{ color: color }">Standard</p>
+            <th/>
+
+            <th>
+              <p class="standard">Standard</p>
               <p class="from">À partir de</p>
               <p class="price">
                 {{ standardPrice }} <span class="ttc">ttc</span>
               </p>
               <p class="month">/mois</p>
             </th>
-            <th class="thead premium-column">
-              <p class="standard" :style="{ color: color }">Premium</p>
+
+            <th class="premium-column">
+              <p class="standard">Premium</p>
               <p class="from">À partir de</p>
               <p class="price">
                 {{ premiumPrice }} <span class="ttc">ttc</span>
@@ -23,43 +25,52 @@
             </th>
           </tr>
         </thead>
-        <tbody class="table-body">
+
+        <tbody>
           <tr
-            v-for="(row, index) in tableData"
-            :key="row.id"
-            class="table-row"
-            :style="{
-              backgroundColor: index % 2 !== 0 ? stripeColor : 'white',
-            }"
+            v-for="(item, index) in items"
+            :key="item.label"
           >
-            <td class="table-data-left">{{ row.column1 }}</td>
-            <td class="table-data-second">
+            <td class="label-column">
+              {{ item.label }}
+            </td>
+
+            <td>
               <v-icon
-                v-if="row.column2 === 'check'"
+                v-if="item.includedInStandard === true"
+                icon="far fa-check-circle"
                 size="18"
-                class="far fa-check-circle"
               />
+
               <v-icon
-                v-else-if="row.column2 === 'cross'"
+                v-else-if="item.includedInStandard === false"
+                icon="far fa-times-circle"
                 size="18"
-                class="far fa-times-circle"
                 color="red"
               />
-              <span v-else>{{ row.column2 }}</span>
+
+              <span v-else>
+                {{ item.includedInStandard }}
+              </span>
             </td>
-            <td class="table-data-second">
+
+            <td>
               <v-icon
-                v-if="row.column3 === 'check'"
+                v-if="item.includedInPremium === true"
+                icon="far fa-check-circle"
                 size="18"
-                class="far fa-check-circle"
               />
+
               <v-icon
-                v-else-if="row.column3 === 'cross'"
+                v-else-if="item.includedInPremium === false"
+                icon="far fa-times-circle"
                 size="18"
-                class="far fa-times-circle"
                 color="red"
               />
-              <span v-else>{{ row.column3 }}</span>
+
+              <span v-else>
+                {{ item.includedInPremium }}
+              </span>
             </td>
           </tr>
         </tbody>
@@ -68,60 +79,93 @@
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
+
+import type { ComparisonItem } from "~/types/interface";
 
 const props = defineProps({
   standardPrice: {
     type: String,
-    default: "32,90€",
+    required: true
   },
   premiumPrice: {
     type: String,
-    default: "46,20€",
-  },
-  color: {
-    type: String,
-    default: "#0e2d32", 
-  },
-  stripeColor: {
-    type: String,
-    default: "rgba(32, 147, 190, 0.2)", 
-  },
-  tableData: {
-    type: Array,
-    default: () => [],
+    required: true
   },
+  items: {
+    type: Array as PropType<Array<ComparisonItem>>,
+    required: true
+  }
 });
 </script>
-<style scoped>
 
-.table-data-second {
+<style scoped lang="scss">
+.v-row {
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+}
+
+table {
+  width: 70%;
+  margin-top: 1rem;
+  margin-right: auto;
+  margin-left: auto;
+  border: none;
+  border-collapse: collapse;
+}
+
+th {
+  height: 8rem;
+  font-weight: 400;
+  font-size: 30px;
+  line-height: 34px;
+}
+
+tr {
+  height: 3rem;
+  text-align: center;
+}
+
+tbody tr:nth-child(even) {
+  background-color: var(--secondary-color);
+}
+
+td {
   padding-right: 5rem;
 }
+
+td:first-child {
+  text-align: left;
+  padding-left: 20px;
+  font-weight: 600;
+  font-size: 12px;
+  line-height: 16px;
+  letter-spacing: 0.18em;
+  text-transform: uppercase;
+  color: var(--on-neutral-color-alt);
+}
+
 .standard {
-  font-family: "Barlow";
-  font-style: normal;
   font-weight: 600;
   font-size: 12px;
   line-height: 16px;
   text-align: center;
   letter-spacing: 0.18em;
   text-transform: uppercase;
-  color: #0e2d32;
+  color: var(--primary-color);
   padding-right: 5rem;
   margin-bottom: 1rem;
 }
 
 .from,
 .ttc {
-  font-family: "Barlow";
-  font-style: normal;
   font-weight: 300;
   font-size: 12px;
   line-height: 14px;
   text-align: center;
-  color: #454545;
+  color: var(--on-neutral-color-alt);
   padding-right: 5rem;
 }
 
@@ -131,67 +175,13 @@ const props = defineProps({
 
 .price,
 .month {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 400;
   font-size: 30px;
   line-height: 34px;
   text-align: center;
-  color: #454545;
+  color: var(--on-neutral-color-alt);
 }
 
 .month {
   padding-right: 5rem;
 }
-
-.table-data-left {
-  text-align: left;
-  padding-left: 20px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 12px;
-  line-height: 16px;
-
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  color: #454545;
-}
-.table-data {
-  text-align: left;
-  padding-left: 20px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 12px;
-  line-height: 16px;
-
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  color: #454545;
-}
-
-.thead {
-  background-color: #fff;
-  height: 8rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 400;
-  font-size: 30px;
-  line-height: 34px;
-}
-.table-comparatif {
-  width: 70%;
-  margin-top: 1rem;
-  margin-right: auto;
-  margin-left: auto;
-  border: none;
-  border-collapse: collapse;
-}
-
-
-.table-body .table-row:nth-child(odd) {
-  background-color: rgba(190, 32, 77, 0.2);
-}
-
 </style>

+ 92 - 0
components/Contact/AddressSection.vue

@@ -0,0 +1,92 @@
+<template>
+  <LayoutContainer>
+    <v-row>
+      <v-col cols="6" class="px-8">
+        <ContactMap class="contact-map" />
+      </v-col>
+      <v-col cols="6" class="address-col px-8">
+
+        <h4>
+          <v-icon icon="fas fa-envelope"/> Pour nous écrire
+        </h4>
+
+        <v-card>
+          <div>
+            2iOpenService
+          </div>
+          <div>
+            217, rue Raoul Follereau
+          </div>
+          <div>
+            74300 - Cluses
+          </div>
+        </v-card>
+
+        <div class="mb-6" />
+
+        <h4>
+          <v-icon icon="fas fa-phone"/>
+          Ou par téléphone
+        </h4>
+
+        <div>
+          <v-btn
+            v-if="!revealPhoneNumber"
+            @click="revealPhoneNumber = !revealPhoneNumber"
+          >
+            Cliquer pour afficher le numéro de téléphone
+          </v-btn>
+          <span v-else>
+            <v-card>
+              Contactez nous au
+              <a href="tel:+33972126017">
+                09 72 12 60 17
+              </a>
+            </v-card>
+          </span>
+        </div>
+      </v-col>
+    </v-row>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+  const revealPhoneNumber = ref(false)
+</script>
+
+<style scoped lang="scss">
+  .container {
+    width: 70%;
+  }
+
+  h4 {
+    display: flex;
+    flex-direction: row;
+    color: var(--primary-color);
+    font-size: 20px;
+    font-weight: 500;
+    margin: 24px 0;
+  }
+
+  .v-icon {
+    margin-right: 16px;
+  }
+
+  .address-col > div, .address-col > .v-card > div {
+    padding: 8px 16px;
+  }
+
+  .v-card {
+    margin: 16px 64px;
+    padding: 12px;
+  }
+
+  .v-btn {
+    margin: 16px 64px;
+  }
+
+  a {
+    color: var(--on-neutral-color);
+    text-decoration: underline;
+  }
+</style>

+ 12 - 343
components/Contact/Banner.vue

@@ -1,358 +1,27 @@
 <template>
   <LayoutContainer>
-    <LayoutUITitlePage
-      title="Besoin d'aide ?"
-      subtitle="Notre équipe est là pour vous. contactez-nous!. "
-    />
+    <LayoutUITitlePage>
+      Besoin d'aide ?
+      <template #subtitle>Notre équipe est là pour vous. Contactez-nous! </template>
+    </LayoutUITitlePage>
+
     <v-row>
-      <v-col cols="12" style="position: relative">
-        <img
+      <v-col cols="12" class="position-relative">
+        <v-img
           src="/images/formation/banner.jpg"
-          alt="line"
-          class="cover-image"
+          alt="banner"
+          cover
+          class="banner"
         />
       </v-col>
     </v-row>
-    <div class="container-contact">
-      <v-form ref="form" v-model="valid" lazy-validation>
-        <v-container>
-          <h4 class="title-h4">Veuillez remplir le formulaire ci-dessous</h4>
-
-          <h6 class="infos">Vos coordonnées</h6>
-
-          <!-- Gender selection -->
-          <v-row>
-            <v-col cols="12">
-              <v-radio-group v-model="gender" row mandatory inline>
-                <v-radio label="Madame" value="Madame"></v-radio>
-                <v-radio label="Monsieur" value="Monsieur"></v-radio>
-              </v-radio-group>
-            </v-col>
-          </v-row>
-
-          <!-- Name and Surname -->
-          <v-row>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="name"
-                :rules="nameRules"
-                label="Nom*"
-                required
-              ></v-text-field>
-            </v-col>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="surname"
-                :rules="surnameRules"
-                label="Prénom*"
-                required
-              ></v-text-field>
-            </v-col>
-          </v-row>
-
-          <!-- Postal code and city -->
-          <v-row>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="postalCode"
-                label="Code postal*"
-                type="number"
-              ></v-text-field>
-            </v-col>
-            <v-col cols="12" md="6">
-              <v-text-field v-model="city" label="Ville"></v-text-field>
-            </v-col>
-          </v-row>
-
-          <!-- Email and phone on the same line -->
-          <v-row>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="email"
-                :rules="emailRules"
-                label="Email*"
-                required
-                type="email"
-              ></v-text-field>
-            </v-col>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="phone"
-                label="Téléphone*"
-                type="tel"
-              ></v-text-field>
-            </v-col>
-          </v-row>
-
-          <!-- Structure name  -->
-          <v-row>
-            <v-col cols="12">
-              <v-text-field
-                v-model="structureName"
-                :rules="structureNameRules"
-                label="Nom de la structure*"
-                required
-              ></v-text-field>
-            </v-col>
-          </v-row>
-          <h6 class="infos">Votre demande concerne</h6>
-
-          <!-- Request type and product concerned  -->
-          <v-row>
-            <v-col cols="12" md="6">
-              <v-select
-                v-model="requestType"
-                :items="requestTypes"
-                label="Votre demande concerne*"
-                outlined
-                dense
-              ></v-select>
-            </v-col>
-            <v-col cols="12" md="6">
-              <v-text-field
-                v-model="concernedProduct"
-                label="Le produit concerné"
-                outlined
-                dense
-              ></v-text-field>
-            </v-col>
-          </v-row>
-          <h6 class="infos">Votre message</h6>
-
-          <!-- Message  -->
-          <v-row>
-            <v-col cols="12">
-              <v-textarea
-                v-model="message"
-                :rules="messageRules"
-                label="Votre message*"
-                required
-                outlined
-                dense
-                maxlength="400"
-              ></v-textarea>
-            </v-col>
-          </v-row>
-
-          <!-- Policy and  checkboxes -->
-              <v-checkbox
-                v-model="privacyPolicy"
-                :rules="[(v) => !!v || 'You must accept the privacy policy']"
-                label="J'ai pris connaissance de la politique de confidentialité et j'accepte le traitement de mes données personnelles par Opentalent."
-              ></v-checkbox>
-
-              <v-checkbox
-                v-model="newsletterSubscription"
-                label="Je souhaite recevoir des communications d'Opentalent par email (promotions, informations logiciel…). Je pourrai me désinscrire à tout moment."
-              ></v-checkbox>
-
-              <v-checkbox
-                v-model="captchaChecked"
-                :rules="[(v) => !!v || 'You must pass the captcha']"
-                label="Captcha"
-              ></v-checkbox>
-
-          <!-- Submit Button -->
-          <v-row>
-            <v-col cols="12">
-              <v-btn :disabled="!valid" @click="submitForm">Envoyer</v-btn>
-            </v-col>
-          </v-row>
-        </v-container>
-      </v-form>
-
-      <div v-if="submissionStatus">
-        {{ submissionStatus }}
-      </div>
-    </div>
-
-    <div id="map" style="height: 500px"></div>
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref, reactive, computed, toRefs } from "vue";
-import { useRoute } from "vue-router";
-import { onMounted } from "vue";
-import L from "leaflet";
-import "leaflet/dist/leaflet.css";
-
-onMounted(() => {
-  const map = L.map("map").setView([46.075245, 6.570162], 16);
-
-  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
-    maxZoom: 19,
-    attribution: "© OpenStreetMap contributors",
-  }).addTo(map);
-
-  const marker = L.marker([46.075245, 6.570162]).addTo(map);
-});
-const route = useRoute();
-const defaultRequestType = route.query.request;
-const captchaChecked = ref(false);
-
-const name = ref("");
-const surname = ref("");
-const email = ref("");
-const structureName = ref("");
-const message = ref("");
-const privacyPolicy = ref(false);
-const gender = ref(null);
-const postalCode = ref(null);
-const city = ref("");
-const phone = ref(null);
-const concernedProduct = ref("");
-const newsletterSubscription = ref(false);
-const submissionStatus = ref("");
-
-const validateName = (name) => !!name || "Name is required";
-const validateSurname = (surname) => !!surname || "Surname is required";
-const validateEmail = (email) =>
-  (!!email && /.+@.+\..+/.test(email)) || "E-mail must be valid";
-const validateStructureName = (structureName) =>
-  !!structureName || "Structure name is required";
-const validateMessage = (message) =>
-  (!!message && message.length <= 400) ||
-  "Message cannot exceed 400 characters";
-
-const valid = computed(() => {
-  return (
-    validateName(name.value) === true &&
-    validateSurname(surname.value) === true &&
-    validateEmail(email.value) === true &&
-    validateStructureName(structureName.value) === true &&
-    validateMessage(message.value) === true &&
-    privacyPolicy.value === true &&
-    captchaChecked.value === true
-  );
-});
-
-const requestTypes = [
-  "Demande d'information",
-  "Demande de devis",
-  "Demande de démonstration",
-  "Demande d'option supplémentaire",
-  "Autre",
-];
-const requestType = ref(
-  defaultRequestType === "demo" ? "Demande de démonstration" : null
-);
-
-const formData = reactive({
-  gender: null,
-  postalCode: null,
-  city: "",
-  phone: null,
-  requestType: null,
-  concernedProduct: "",
-  newsletterSubscription,
-});
-
-// Methods
-const submitForm = () => {
-  if (valid.value) {
-    // Logique d'envoi du formulaire
-    submissionStatus.value = "Mail envoyé à contact@opentalent.fr";
-  } else {
-    console.log("Validation failed!");
-    submissionStatus.value = "";
-  }
-};
-
-const formDataRefs = toRefs(formData);
-const formRefs = {
-  ...formDataRefs,
-  name,
-  surname,
-  email,
-  structureName,
-  message,
-  privacyPolicy,
-  valid,
-};
-</script>
-
-<style scoped>
-#map {
-  height: 100%;
-  width: 70%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.infos {
-  font-size: 20px;
-  color: #000000;
-  margin-bottom: 1rem;
-}
-
-.container-contact {
-  max-width: 1400px;
-  margin: 0 auto;
-}
-.title-h4 {
-  font-size: 40px;
-  line-height: 95px;
-  color: #000000;
-  margin-bottom: 1rem;
-  color: rgba(0, 0, 0, 0.3);
-}
-.image-text {
-  position: absolute;
-  top: 40px;
-  left: 20px;
-  font-family: "Barlow";
-  color: white;
-  font-size: 3rem;
-  width: 30rem;
-  font-style: italic;
-  font-weight: 300;
-  line-height: 40px;
-}
-
-:deep().subtitle {
-  font-size: 1.5rem;
-  line-height: 2rem;
-  letter-spacing: 0.1rem;
-  margin-bottom: 1rem;
-  text-transform: uppercase;
-}
-
-.formation {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 90px;
-  line-height: 85px;
-  text-align: center;
-  color: #000000;
-  margin-bottom: 1rem;
-}
-
-.menu-container {
-  display: flex;
-  justify-content: space-around;
-  padding: 1rem 10rem;
-  background: white;
-  color: #bbb8b8;
-  font-family: "Barlow";
-  font-size: 12px;
-  line-height: 16px;
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-}
-
-.v-chip.active-menu {
-  background: black;
-  color: white;
-}
-
-.cover-image {
+<style scoped lang="scss">
+.banner {
   width: 100%;
   height: 15rem;
-  object-fit: cover;
   object-position: center 30%;
   margin: 0 auto;
   transform: scaleX(-1);

+ 355 - 0
components/Contact/Form.vue

@@ -0,0 +1,355 @@
+<template>
+  <LayoutContainer>
+    <div id="anchor" />
+
+    <v-form
+      v-if="!contactRequestSent"
+      ref="form"
+      validate-on="submit lazy"
+      @submit.prevent="submit"
+    >
+      <v-container>
+        <h4>
+          <span class="line" /> Veuillez remplir le formulaire ci-dessous
+        </h4>
+
+        <i>Les champs dont le nom est suivi d'un astérisque (*) sont obligatoires</i>
+
+        <h6>
+          Vos coordonnées
+        </h6>
+
+        <!-- Gender selection -->
+        <v-row>
+          <v-col cols="12">
+            <v-radio-group
+              v-model="contactRequest.gender"
+              row
+              mandatory
+              inline
+            >
+              <v-radio label="Madame" value="Madame" />
+              <v-radio label="Monsieur" value="Monsieur" />
+            </v-radio-group>
+          </v-col>
+        </v-row>
+
+        <!-- Name and Surname -->
+        <v-row>
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.name"
+              :rules="[validateName]"
+              label="Nom*"
+              required
+            />
+          </v-col>
+
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.surname"
+              :rules="[validateSurname]"
+              label="Prénom*"
+              required
+            />
+          </v-col>
+        </v-row>
+
+        <!-- Postal code and city -->
+        <v-row>
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.postalCode"
+              label="Code postal*"
+              :rules="[validatePostalCode]"
+            />
+          </v-col>
+
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.city"
+              label="Ville"
+            />
+          </v-col>
+        </v-row>
+
+        <!-- Email and phone on the same line -->
+        <v-row>
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.email"
+              :rules="[validateEmail]"
+              label="Email*"
+              required
+              type="email"
+            />
+          </v-col>
+
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.phone"
+              :rules="[validatePhone]"
+              label="Téléphone*"
+              type="tel"
+            />
+          </v-col>
+        </v-row>
+
+        <!-- Structure name  -->
+        <v-row>
+          <v-col cols="12">
+            <v-text-field
+              v-model="contactRequest.structureName"
+              :rules="[validateStructureName]"
+              label="Nom de la structure*"
+              required
+            />
+          </v-col>
+        </v-row>
+
+        <h6>
+          Votre demande concerne *
+        </h6>
+
+        <!-- Request type and product concerned  -->
+        <v-row>
+          <v-col cols="12" md="6">
+            <v-select
+              v-model="contactRequest.requestType"
+              :items="requestTypes"
+              item-value="id"
+              item-title="label"
+              variant="outlined"
+            />
+          </v-col>
+
+          <v-col cols="12" md="6">
+            <v-text-field
+              v-model="contactRequest.concernedProduct"
+              label="Produit concerné (facultatif)"
+            />
+          </v-col>
+        </v-row>
+
+        <h6>
+          Votre message
+        </h6>
+
+        <!-- Message  -->
+        <v-row class="mb-8">
+          <v-col cols="12">
+            <v-textarea
+              v-model="contactRequest.message"
+              :rules="[validateNonEmptyMessage, validateMessageLength]"
+              label="Votre message*"
+              required
+              maxlength="400"
+            />
+            <span class="remaining-cars-notice">{{ leftCars }} caractères restants</span>
+          </v-col>
+        </v-row>
+
+        <!-- Policy and  checkboxes -->
+        <v-checkbox
+          v-model="contactRequest.privacyPolicyAccepted"
+          :rules="[(v) => !!v || 'Vous devez accepter la politique de confidentialité']"
+          label="J'ai pris connaissance de la politique de confidentialité et j'accepte le traitement de mes données personnelles par Opentalent."
+        />
+
+        <v-checkbox
+          v-model="contactRequest.newsletterSubscription"
+          label="Je souhaite recevoir des communications d'Opentalent par email (promotions, informations logiciel…). Je pourrai me désinscrire à tout moment."
+        />
+
+        <div class="d-flex flex-row justify-center">
+          <!-- @see https://github.com/hCaptcha/vue-hcaptcha -->
+          <LayoutCaptcha/>
+        </div>
+
+        <!-- Submit Button -->
+        <div class="d-flex flex-row justify-center my-10">
+          <v-btn
+            type="submit"
+            variant="outlined"
+            :height="54"
+            :width="180"
+            class="submit-btn"
+          >
+            Envoyer
+          </v-btn>
+        </div>
+      </v-container>
+
+      <div class="legal">
+        Les données recueillies par Opentalent sont utilisées pour le traitement de votre demande et pour vous informer sur nos offres.
+        Elles sont destinées aux services Opentalent et à ses sous-traitants pour l’exécution des contrats. Conformément à la loi
+        "Informatique et Libertés du 6 Janvier 1978", vous disposez d’un droit d’accès, de modifications, de rectification et de suppression
+        des données vous concernant. Pour toute demande, adressez-vous à : Opentalent, 217 rue Raoul Follereau, 74300 CLUSES,
+        opentalent.fr s’engage à la confidentialité et à la protection de vos données.
+      </div>
+    </v-form>
+
+    <div v-else class="confirmation-message d-flex flex-row justify-center">
+      <v-card>
+        <v-icon icon="fas fa-check mr-1"/>
+        Votre demande de contact a bien été enregistrée, nous reviendrons vers vous dès que possible.
+      </v-card>
+    </div>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import ContactRequest from "~/models/Maestro/ContactRequest";
+import { useEntityManager } from "~/composables/data/useEntityManager";
+import { useRouter } from "vue-router";
+
+const route = useRoute();
+const router = useRouter()
+const { em } = useEntityManager()
+
+const form: Ref<any | null> = ref(null)
+
+const requestTypes: Array<{id: string, label: string}> = [
+  { id: "CONTACT_REQUEST_INFORMATION", label: "Demande d'information"},
+  { id: "CONTACT_REQUEST_ESTIMATE", label: "Demande de devis"},
+  { id: "CONTACT_REQUEST_DEMO", label: "Demande de démonstration"},
+  { id: "CONTACT_REQUEST_OPTION", label: "Demande d'option supplémentaire"},
+  { id: "CONTACT_REQUEST_OTHER", label: "Autre"}
+]
+
+const defaultRequestType = route.query.request ?? 'CONTACT_REQUEST_INFORMATION'
+
+//@ts-ignore
+const contactRequest: ContactRequest = reactive(em.newInstance(ContactRequest, { requestType: defaultRequestType }))
+
+const maxMessageLength = 2000
+
+const leftCars: ComputedRef<number> = computed(() =>
+  maxMessageLength - (contactRequest.message ? contactRequest.message.length : 0)
+)
+
+// --- Validation ---
+const validateName = (name: string | null) => !!name || "Le nom est obligatoire";
+
+const validateSurname = (surname: string | null) => !!surname || "Le prénom est obligatoire";
+
+const validatePostalCode = (postalCode: string | null) =>
+  (!!postalCode && /^\d{5}$/.test(postalCode)) || "Le code postal doit être valide";
+
+const validateEmail = (email: string | null) =>
+  (!!email && /.+@.+\..+/.test(email)) || "L'adresse e-mail doit être valide";
+
+const validatePhone = (email: string | null) =>
+  (!!email && /^((\+|00)33\s?|0)[1-7]([\s.]?\d{2}){4}$/.test(email)) || "Le numéro de téléphone doit être valide";
+
+const validateStructureName = (structureName: string | null) =>
+  !!structureName || "Le nom de la structure est requis";
+
+const validateNonEmptyMessage = (message: string | null) =>
+  (!!message && message.length > 0) ||
+  "Le message ne peut pas être vide";
+
+const validateMessageLength = (message: string | null) =>
+  (!!message && message.length <= maxMessageLength) ||
+  "Le message ne doit pas dépasser " + maxMessageLength + " caractères";
+
+const contactRequestSent: Ref<boolean> = ref(false);
+
+/**
+ * Submits the contact form.
+ *
+ * This function validates the form and sets the value of a variable to indicate whether the form submission was successful.
+ *
+ * @function
+ *
+ * @returns {void}
+ */
+const submit = async (): Promise<void> => {
+  const { valid } = await form.value.validate()
+
+  if (!valid) {
+    contactRequestSent.value = false
+    return
+  }
+
+  await em.persist(ContactRequest, contactRequest)
+
+  contactRequestSent.value = true;
+
+  // Défile vers le début de page pour afficher le message de confirmation
+  setTimeout(
+    () => router.push({ path: '', hash: '#anchor' }),
+    30
+  )
+};
+</script>
+
+<style scoped lang="scss">
+
+.v-form {
+  max-width: 1400px;
+  margin: 0 auto;
+
+  h4 {
+    display: flex;
+    flex-direction: row;
+    font-size: 40px;
+    line-height: 95px;
+    margin-bottom: 1rem;
+    align-items: center;
+    font-weight: 100;
+
+    .line {
+      display: block;
+      height: 1px;
+      width: 64px;
+      min-width: 64px;
+      border-top: solid 1px var(--on-neutral-color);
+      margin-right: 18px;
+    }
+  }
+
+  h6 {
+    margin-top: 32px;
+    font-size: 16px;
+    margin-bottom: 1rem;
+    text-transform: uppercase;
+    font-weight: 600;
+    letter-spacing: 0.1em;
+  }
+
+  .v-select {
+    .v-field {
+      border-radius: 0;
+    }
+  }
+
+  .remaining-cars-notice {
+    font-size: 13px;
+    font-weight: 550;
+    opacity: 0.6;
+  }
+
+  .submit-btn {
+    border-radius: 0;
+    font-weight: 600;
+  }
+
+  .legal {
+    opacity: 0.7;
+  }
+}
+
+.confirmation-message {
+  .v-card {
+    .v-icon {
+      color: green;
+    }
+
+    max-width: 1200px;
+    padding: 24px;
+    margin: 128px 0;
+    font-weight: 500;
+  }
+}
+</style>

+ 138 - 0
components/Contact/Map.vue

@@ -0,0 +1,138 @@
+<template>
+<LayoutContainer>
+    <h4>
+      <span class="line" /> Contactez-nous
+    </h4>
+
+    <v-row>
+      <v-col cols="6">
+        <div class="map-container">
+          <l-map
+            ref="map"
+            :zoom="15"
+            :center="location"
+            :options="{scrollWheelZoom: false}"
+          >
+            <l-tile-layer
+              url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
+              layer-type="base"
+              name="OpenStreetMap"
+              attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
+            />
+
+            <l-marker
+              :icon="icon"
+              :lat-lng="location"
+            />
+<!--              <l-popup>-->
+<!--                <v-row>-->
+<!--                  <v-col cols="4" class="d-flex align-center">-->
+<!--                    <v-img src="/images/Opentalent_Griffe.png"/>-->
+<!--                  </v-col>-->
+<!--                  <v-col cols="8">-->
+<!--                    <div>-->
+<!--                      OPENTALENT-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                      217, rue Raoul Follereau-->
+<!--                    </div>-->
+<!--                    <div>-->
+<!--                      74300 - Cluses-->
+<!--                    </div>-->
+<!--                  </v-col>-->
+<!--                </v-row>-->
+<!--              </l-popup>-->
+          </l-map>
+        </div>
+      </v-col>
+
+      <v-col class="infos">
+        <div class="name mb-8">
+          Opentalent
+        </div>
+
+        <div class="d-flex flex-row align-center mb-8">
+          <v-icon icon="fa fa-map-marker-alt" />
+          <span>
+            217 rue Raoul Follereau<br/>
+            74300 CLUSES
+          </span>
+        </div>
+
+        <div class="d-flex flex-row mb-4">
+          <v-icon icon="fa fa-phone" />
+          09.72.12.60.17
+        </div>
+
+        <div class="d-flex flex-row mb-4">
+          <v-icon icon="far fa-envelope" />
+          contact@opentalent.fr
+        </div>
+      </v-col>
+    </v-row>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import 'leaflet/dist/leaflet.css'
+import { LMap, LTileLayer, LMarker, LIcon } from '@vue-leaflet/vue-leaflet'
+import L from 'leaflet';
+
+const location = [46.075245, 6.570162]
+
+const icon = L.icon({
+  iconUrl: '/images/contact/Pointeur_Opentalent.png',
+  iconSize: [80, 80],
+  iconAnchor: [22, 94],
+  popupAnchor: [5, -100],
+})
+
+</script>
+
+<style scoped lang="scss">
+
+h4 {
+  display: flex;
+  flex-direction: row;
+  font-size: 40px;
+  line-height: 95px;
+  align-items: center;
+  font-weight: 100;
+  margin: 0 auto 1rem auto;
+  max-width: 1400px;
+
+  .line {
+    display: block;
+    height: 1px;
+    width: 64px;
+    min-width: 64px;
+    border-top: solid 1px var(--on-neutral-color);
+    margin-right: 18px;
+  }
+}
+
+
+.map-container {
+  height: 500px;
+  width: 100%;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.infos {
+  padding: 48px 36px;
+  font-size: 21px;
+  font-weight: 300;
+
+  .name {
+    font-size: 36px;
+    text-transform: uppercase;
+    font-weight: 600;
+  }
+
+  .v-icon {
+    margin-right: 16px;
+    opacity: 0.6;
+  }
+}
+</style>

+ 4 - 0
components/Form/ApplicationForm.vue → components/Form/Application.vue

@@ -1,3 +1,7 @@
+<!--
+TODO: n'est pas utilisé pour l'instant
+-->
+
 <template>
   <v-dialog v-model="dialog" persistent max-width="600">
     <v-card>

+ 0 - 96
components/Formation/Banner.vue

@@ -1,96 +0,0 @@
-<template>
-  <LayoutContainer>
-    <LayoutUITitlePage title="Formation" subtitle="Prise en main ou piqûre de rappel,on est toujours à vos côtés. " />
-    
-    <v-row>
-      <v-col cols="12" style="position: relative">
-        <img
-          src="/images/formation/banner.jpg"
-          alt="line"
-          class="cover-image"
-        />
-        <div class="image-text mt-12">
-          Et si vous passiez rapidement à la vitesse supérieure...
-        </div>
-      </v-col>
-    </v-row>
-
-    <v-row>
-      <v-col cols="12" class="menu-container">
-        <div v-for="menu in menus" :key="menu.label">
-          <v-chip v-if="state.activeMenu === menu.label" class="active-menu">
-            {{ menu.label }}
-          </v-chip>
-          <span v-else>{{ menu.label }}</span>
-        </div>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup>
-
-</script>
-
-<style scoped>
-.image-text {
-  position: absolute;
-  top: 40px;
-  left: 20px;
-  font-family: "Barlow";
-  color: white;
-  font-size: 3rem;
-  width: 30rem;
-  font-style: italic;
-  font-weight: 300;
-  line-height: 40px;
-}
-
-:deep().subtitle {
-  font-size: 1.5rem;
-  line-height: 2rem;
-  letter-spacing: .1rem;
-  margin-bottom: 1rem;
-}
-
-.formation {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 90px;
-  line-height: 85px;
-  text-align: center;
-  color: #000000;
-  margin-bottom: 1rem;
-}
-
-.menu-container {
-  display: flex;
-  justify-content: space-around;
-  padding: 1rem 10rem;
-  background: white;
-  color: #bbb8b8;
-  font-family: "Barlow";
-  font-size: 12px;
-  line-height: 16px;
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-}
-
-.v-chip.active-menu {
-  background: black;
-  color: white;
-}
-
-.cover-image {
-  width: 100%;
-  height: 35rem;
-  object-fit: cover;
-  object-position: center 30%;
-  margin: 0 auto;
-  transform: scaleX(-1);
-}
-</style>

+ 181 - 185
components/Formation/Catalogue.vue

@@ -1,91 +1,114 @@
 <template>
-  <div id="Catalogue">
-    <LayoutContainer v-if="!mdAndDown">
-      <div class="grey-container">
-        <v-row class="custom-row">
-          <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Découvrez notre catalogue de formation'"
-        />
+  <AnchoredSection id="catalog">
+    <LayoutContainer>
+      <v-row class="center-90">
+        <LayoutUISubTitle>
+          Découvrez notre catalogue de formation
+        </LayoutUISubTitle>
 
-        <LayoutUITitle title="Catalogue" />
-        </v-row>
- 
+        <LayoutUITitle class="ml-8">
+          Catalogue
+        </LayoutUITitle>
+      </v-row>
 
-        <v-row  class="custom-row" style="  padding: 2rem; max-width: 90%; margin-left: auto; margin-right: auto;">
-          <v-col v-for="(course, index) in courses" :key="index" cols="4">
-            <v-card class="mb-4">
-              <v-card-text>
-                <div class="title-card-container">
-                  <span class="number-card">{{ course.number }}</span>
-                  <h4 class="card-title">{{ course.title }}</h4>
-                  <v-img class="logo-img" :src="course.imageUrl" />
-                </div>
-                <p class="details-card mb-6">{{ course.description }}</p>
+      <v-row class="center-90 catalog">
+        <v-col
+          v-for="(course, index) in courses"
+          :key="index"
+          cols="4"
+        >
+          <v-card class="mb-4">
+            <v-card-text>
+              <div class="title-card-container">
+                <span class="number-card">
+                  {{ course.number }}
+                </span>
 
-                <div class="container-blue">
-                  <h6 class="title-obj">Objectifs pédagogiques</h6>
-                  <ul class="list-obj">
-                    <li
-                      v-for="(objective, objIndex) in course.objectives"
-                      :key="objIndex"
-                    >
-                      {{ objective }}
-                    </li>
-                  </ul>
-                </div>
+                <h4>
+                  {{ course.title }}
+                </h4>
+              </div>
 
-                <div class="container-blue">
-                  <h6 class="title-obj">Programme</h6>
-                  <v-row>
-                    <v-col
-                      v-for="column in course.program"
-                      :key="column.id"
-                      cols="6"
-                    >
-                      <ul class="list-obj">
-                        <li
-                          v-for="(objective, objIndex) in column.objectives"
-                          :key="objIndex"
-                        >
-                          {{ objective }}
-                        </li>
-                      </ul>
-                    </v-col>
-                  </v-row>
-                </div>
+              <p class="details-card mb-6">
+                {{ course.description }}
+              </p>
 
-                <v-chip class="badge-time"
+              <div class="objectives">
+                <h6 class="title-obj">
+                  Objectifs pédagogiques
+                </h6>
+
+                <ul>
+                  <li
+                    v-for="(objective, objIndex) in course.objectives"
+                    :key="objIndex"
+                  >
+                    {{ objective }}
+                  </li>
+                </ul>
+              </div>
+
+              <div class="program">
+                <h6 class="title-obj">
+                  Programme
+                </h6>
+
+                <v-row>
+                  <v-col
+                    v-for="column in course.program"
+                    :key="column.id"
+                    cols="6"
                   >
-                  <span> Durée : {{ course.duration }}</span>
-                 </v-chip
-                >
-                <v-chip class="badge-time">  <span>{{ course.price }}</span></v-chip>
-                <v-chip
-                  class="chip-download"
-                  @click="downloadPdf(course.downloadLink)"
-                >
-                  Télécharger le programme de formation
-                </v-chip>
-              </v-card-text>
-            </v-card>
-          </v-col>
-        </v-row>
-      </div>
+                    <ul>
+                      <li
+                        v-for="(objective, objIndex) in column.objectives"
+                        :key="objIndex"
+                      >
+                        {{ objective }}
+                      </li>
+                    </ul>
+                  </v-col>
+                </v-row>
+              </div>
+
+              <v-chip class="badge-time">
+                <span>
+                  Durée : {{ course.duration }}
+                </span>
+              </v-chip>
+
+              <v-chip class="badge-time">
+                <span>
+                  {{ course.price }}
+                </span>
+              </v-chip>
+
+              <v-chip
+                class="chip-register"
+                @click="downloadPdf(course.downloadLink)"
+              >
+                Télécharger le programme de formation
+              </v-chip>
+            </v-card-text>
+          </v-card>
+        </v-col>
+      </v-row>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-
+<script setup lang="ts">
 import { useDisplay } from "vuetify";
-const { smAndDown, mdAndDown } = useDisplay();
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Training } from "~/types/interface";
+
+const { mdAndDown } = useDisplay();
 
-const downloadPdf = (pdfUrl) => {
+const downloadPdf = (pdfUrl: string) => {
   window.open(pdfUrl, "_blank");
 };
-const courses = [
+
+const courses: Array<Training> = [
   {
     number: "01",
     title: "Formation initiale ",
@@ -96,7 +119,7 @@ const courses = [
       "Gérer les élèves et leurs familles",
       "Générer des factures et faire le suivi des règlements",
       "Gérer le planning des cours",
-      "Evaluer les élèves et générer des bulletins",
+      "Évaluer les élèves et générer des bulletins",
       "Communiquer avec les personnes du répertoire",
     ],
     duration: "14h",
@@ -180,128 +203,101 @@ const courses = [
 
 <style scoped>
 
-*{
+* {
   text-align: justify;
 }
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.v-card {
-  border: none !important;
-  box-shadow: none !important;
-  background-color: transparent !important;
-}
-.grey-container {
-  background-color: #f8f8f8;
 
-}
-.chip-download {
-  border-radius: 3rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 18px;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
+.catalog {
+  padding: 2rem;
 
-.badge-time {
-  color: white;
-  border: 1px solid #0e2d32;
-  border-radius: 3rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 18px;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
+  .v-card {
+    border: none !important;
+    box-shadow: none !important;
+    background-color: transparent !important;
+  }
 
-.badge-time span {
-  color: var(--Vert-90, #0E2D32); 
-}
+  .title-card-container {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    align-items: center;
+    font-weight: 600;
+    font-size: 1.2rem;
+    width: 31rem;
+    border-bottom: 1px solid var(--primary-color);
+    padding: 1rem 0;
 
-.list-obj {
-  margin-top: 0.5rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 14px;
-  line-height: 18px;
+    .number-card {
+      font-weight: 500;
+      font-size: 1.3rem;
+      color: var(--secondary-color);
+      margin-right: 1rem;
+    }
+  }
 
-  color: #000000;
-}
+  .details-card {
+    font-weight: 300;
+    font-size: 1rem;
+    line-height: 1rem;
+    color: var(--primary-color);
+    margin-top: 1rem;
+    margin-bottom: .5rem;
+    height: 5rem;
+  }
 
-.title-obj {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 20px;
-  color: #0e2d32;
-}
+  .objectives, .program {
+    justify-content: space-between;
+    align-items: center;
+    background: var(--secondary-color);
+    margin-top: 1rem;
+    margin-bottom: 1rem;
+    border-radius: 1rem;
+    padding: 1rem 1rem 1rem 1.5rem;
+    height: 13rem;
 
-.container-blue {
-  justify-content: space-between;
-  align-items: center;
-  background: #c3e5e7;
-  padding: 1rem;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-  border-radius: 1rem;
-  padding-left: 1.5rem;
-  height: 13rem;
-}
+    h6 {
+      font-weight: 500;
+      font-size: 16px;
+      line-height: 20px;
+      color: var(--primary-color);
+    }
 
-.details-card {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1rem;
-  line-height: 1rem;
-  color: #091d20;
-  margin-top: 1rem;
-  margin-bottom: .5rem;
-  height: 5rem;
-}
+    ul {
+      margin-top: 0.5rem;
+      font-weight: 300;
+      font-size: 14px;
+      line-height: 18px;
+    }
+  }
 
-.number-card {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 1.3rem;
-  color: #b9e5e7;
-  margin-right: 1rem;
-}
+  .badge-time {
+    color: var(--on-primary-color);
+    border: 1px solid var(--primary-color);
+    border-radius: 3rem;
+    font-weight: 500;
+    font-size: 14px;
+    line-height: 18px;
+    margin-top: 1rem;
+    margin-bottom: 1rem;
+    display: flex;
+    justify-content: center;
+    align-items: center;
 
-.title-card-container {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 1.2rem;
-  width: 31rem;
-  border-bottom: 1px solid #0e2d32;
-}
+    span {
+      color: var(--primary-color);
+    }
+  }
 
-.logo-img {
-  width: 10rem;
-  height: 3rem;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-  margin-left: 4rem;
+  .chip-register {
+    border-radius: 3rem;
+    font-weight: 500;
+    font-size: 14px;
+    line-height: 18px;
+    margin-top: 1rem;
+    margin-bottom: 1rem;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
 }
 </style>

+ 22 - 27
components/Formation/Certification.vue

@@ -1,23 +1,26 @@
 <template>
-  <div id="Certification">
+  <AnchoredSection id="certification">
     <LayoutContainer>
-      <v-row class="custom-row">
+      <v-row class="center-90">
         <v-col cols="5">
-          <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'DES FORMATIONS CERTIFIFIÉES'"
-          />
-          <LayoutUITitle title="Certification" />
-          <LayoutUITitle title="Qualiopi : Marque de certification " />
+          <LayoutUISubTitle>
+            DES FORMATIONS CERTIFIÉES
+          </LayoutUISubTitle>
+
+          <LayoutUITitle>
+            Certification Qualiopi : Marque de certification
+          </LayoutUITitle>
+
           <div class="bloc-certif ml-12 mt-6 mr-12">
             <p>
               Nos formations sont certifiées Qualiopi - Actions de formation.
             </p>
+
             <p class="details-certifications">
               La marque « Qualiopi » vise à :
             </p>
-            <ul class="list-qualiopi">
+
+            <ul>
               <li>
                 attester de la qualité du processus mis en œuvre par les
                 prestataires d’actions concourant au développement des
@@ -36,39 +39,31 @@
         </v-col>
       </v-row>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup></script>
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
 
-<style scoped>
-
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.qualiopi-img {
-  background-image: url("/images/formation/qualiopi.jpg");
-  width: 600px;
-  top: -15rem;
-}
+<style scoped lang="scss">
 .bloc-certif {
   text-align: justify;
 }
 
-.list-qualiopi {
+ul {
   font-weight: 300;
   font-size: 16px;
   line-height: 20px;
-  color: #091d20;
+  color: var(--primary-color);
   margin-top: 1rem;
 }
+
 .details-certifications {
   font-weight: 300;
   font-size: 16px;
   line-height: 20px;
-  color: #091d20;
+  color: var(--primary-color);
   margin-top: 1rem;
 }
 </style>

+ 26 - 47
components/Formation/OPCA.vue

@@ -1,24 +1,25 @@
 <template>
-  <div id="Financement">
-    <LayoutContainer >
-      <v-row class="custom-row">
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Financement des formations'"
-          :title-color="'#ffffff'"
-        />
+  <AnchoredSection id="financing">
+    <LayoutContainer class="alt-theme py-6 my-6">
+      <v-row class="center-90">
+        <LayoutUISubTitle>
+          Financement des formations
+        </LayoutUISubTitle>
       </v-row>
 
       <v-container>
-        <v-row class="align-center custom-row">
+        <v-row class="align-center center-90">
           <v-col cols="6">
-            <div class="opca-img"></div>
+            <v-img
+              src="/images/formation/programme.jpg"
+              class="opca-img"
+              cover
+            />
           </v-col>
 
           <v-col cols="12" md="6" lg="6">
             <v-row>
-              <h3 class="title-opca mt-6 mb-6 mr-6">
+              <h3 class="mt-6 mb-6 mr-6">
                 Des formations éligibles par votre OPCA
               </h3>
             </v-row>
@@ -47,56 +48,34 @@
         </v-row>
       </v-container>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
 </script>
 
-<style scoped>
-@media (min-width: 1200px) {
-  .custom-row {
-    margin-left: auto;
-    margin-right: auto;
-  }
-}
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-
+<style scoped lang="scss">
 .opca-img {
-  background-image: url("/images/formation/programme.jpg");
-  background-size: cover;
-  background-position: center;
   height: 400px;
   width: 450px;
   border-radius: 10%;
 }
 
-.details-opca {
-  font-size: 16px;
-  line-height: 20px;
-  margin-top: 2rem;
-  color: #ffffff;
-  width: 100%;
-  margin: auto;
-  text-align: justify;
-
-}
-
-.title-opca {
+h3 {
   font-weight: 600;
   font-size: 42px;
   line-height: 42px;
-  color: #ffffff;
+  color: var(--on-primary-color);
   margin-top: 0.6rem;
 }
 
-.container {
-  background: #0e2d32;
-  height: 100%;
-  margin-bottom: 1rem;
+.details-opca {
+  font-size: 16px;
+  line-height: 20px;
+  color: var(--on-primary-color);
+  width: 100%;
+  margin: auto;
+  text-align: justify;
 }
 </style>

+ 48 - 58
components/Formation/Participation.vue

@@ -1,32 +1,28 @@
 <template>
-  <div id="Inscription">
-    <LayoutContainer>
-      <v-row class="custom-row">
+  <AnchoredSection id="inscription">
+    <LayoutContainer class="alt-theme">
+      <v-row class="center-90">
         <v-col cols="12">
-          <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'Accessibilité'"
-            :title-color="'#ffffff'"
-          />
+          <LayoutUISubTitle>
+            Accessibilité
+          </LayoutUISubTitle>
         </v-col>
       </v-row>
 
-      <h2 class="title-participation text-center mb-8">
+      <h3 class="title-participation text-center mb-8">
         Vous souhaitez participer à une formation ?
-      </h2>
+      </h3>
 
-      <v-row class="mb-12">
+      <v-row class="mb-12 center-90">
         <v-col cols="12">
-          <div class="participation-img"></div>
-          <!-- <v-img
-            class="participation-img"
+          <v-img
             src="/images/formation/participation.jpg"
-          /> -->
+            class="participation-img"
+          />
         </v-col>
       </v-row>
 
-      <v-row class="mb-12 custom-row">
+      <v-row class="mb-12 center-90">
         <v-col cols="12">
           <div class="details-participations">
             <p class="mb-6">
@@ -56,43 +52,60 @@
         </v-col>
       </v-row>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<style scoped>
-@media (min-width: 1200px) {
-  .custom-row {
-    min-width: 100%;
-    max-width: 100;
-    margin-left: auto;
-    margin-right: auto;
-  }
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
+
+<style scoped lang="scss">
+.container {
+  background-color: var(--primary-color);
+  color: var(--on-primary-color);
 }
-.custom-row {
+
+.v-row {
   width: 90%;
   margin-left: auto;
   margin-right: auto;
 }
-.subtitle {
+
+@media (min-width: 1200px) {
+  .v-row {
+    min-width: 100%;
+  }
+}
+
+.icon-title {
+  font-size: 1rem;
+  margin-right: 1rem;
+}
+.container-title {
   display: flex;
   justify-content: center;
   align-items: center;
-  margin-left: auto;
-  margin-right: auto;
+  margin-bottom: 2rem;
+}
+
+h3 {
+  font-weight: 600;
+  font-size: 42px;
+  line-height: 42px;
+  text-align: center;
+  color: var(--on-primary-color);
 }
+
 .details-participations {
   display: flex;
   flex-direction: column;
   text-align: justify;
-
   font-weight: 300;
   font-size: 16px;
   line-height: 20px;
-  margin-top: 1rem;
-  display: flex;
+  margin: 1rem auto auto auto;
   width: 800px;
-  margin: auto;
-  color: #ffffff;
+  color: var(--on-primary-color);
 }
 
 .participation-img {
@@ -109,27 +122,4 @@
   margin-left: auto;
   margin-right: auto;
 }
-.title-participation {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  text-align: center;
-  color: #ffffff;
-}
-.icon-title {
-  font-size: 1rem;
-  margin-right: 1rem;
-}
-.container-title {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  margin-bottom: 2rem;
-}
-.container {
-  background-color: #0e2d32;
-  color: #ffffff;
-}
 </style>

+ 42 - 58
components/Formation/Presentation.vue

@@ -1,24 +1,25 @@
 <template>
-  <div id="Presentation">
+  <AnchoredSection id="presentation">
     <LayoutContainer>
-      <v-row class="custom-row mt-6">
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Présentation de nos formations'"
-        />
+      <v-row class="mt-6 center-90">
+        <LayoutUISubTitle>
+          Présentation de nos formations
+        </LayoutUISubTitle>
       </v-row>
 
-      <v-row class=" custom-row mb-12">
+      <v-row class="mb-12 center-90">
         <v-col cols="6">
-          <img class="programme-img1" src="/images/formation/programme2.jpg" />
+          <v-img
+            src="/images/formation/programme2.jpg"
+            class="programme-img1"/>
         </v-col>
 
         <v-col cols="6">
           <h3 class="title-programme mb-6">
             Un programme de formation complet sur nos logiciels
           </h3>
-          <p class="details-programme">
+
+          <p class="details-programme mb-4">
             Nous avons défini un programme de formation complet pour
             l’utilisation de notre logiciel
             <span class="school"> Opentalent School </span>pour lequel la
@@ -26,7 +27,7 @@
             formation, votre logiciel sera complètement paramétré et vous serez
             complètement autonome.
           </p>
-          <br />
+
           <p class="details-programme">
             Dans le cadre de notre solution
             <span class="manager">Opentalent Manager</span> , nous pouvons
@@ -37,81 +38,64 @@
         </v-col>
       </v-row>
 
-      <v-row class="custom-row">
+      <v-row class="center-90">
         <v-col cols="6">
-          <h3 class="title-programme mb-6 mt-4 ">
+          <h3 class="title-programme mb-6 mt-4">
             Des formations à la demande et sur-mesure
           </h3>
-          <p class="details-programme ">
+
+          <p class="details-programme">
             Afin de prendre en compte les évolutions de votre structure, nous
             pouvons enseuite organiser des sessions de formations spécifiques
             pour répondre à vos besoins : outils complets, mise en route,
             fonctionnalités spécifiques, utilisation du site web....
           </p>
         </v-col>
+
         <v-col cols="6">
-          <img class="programme-img2" src="/images/formation/programme.jpg" />
+          <v-img
+            src="/images/formation/programme.jpg"
+            class="programme-img2"
+          />
         </v-col>
       </v-row>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup></script>
-
-<style scoped>
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
 
-@media (max-width: 1800px) {
-  .custom-row {
-  margin-left: auto;
-  margin-right: auto;
-}
-}
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-.school {
-  color: #64afb7;
+<style scoped lang="scss">
+.v-img {
+  width: 80%;
+  height: 100%;
+  border-radius: 10%;
 }
 
-.manager {
-  color: #d8050b;
+h3, p {
+    width: 35rem;
 }
 
+h3 {
+  font-weight: 600;
+  font-size: 42px;
+  line-height: 42px;
+}
 
-.details-programme {
-  font-family: "Barlow";
-  font-style: normal;
+p {
   font-weight: 300;
   font-size: 1.2rem;
   line-height: 20px;
-  color: #091d20;
-  width: 35rem;
   text-align: justify;
 }
 
-.title-programme {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  color: #071b1f;
-  width: 35rem;
-}
-
-
-.programme-img1 {
-  width: 80%;
-  height: 100%;
-  border-radius: 10%;
+.school {
+  color: var(--school-color);
 }
 
-.programme-img2 {
-  width: 80%;
-  height: 100%;
-  border-radius: 10%;
+.manager {
+  color: var(--manager-color);
 }
 </style>

+ 12 - 39
components/Formation/Reviews.vue

@@ -1,36 +1,39 @@
 <template>
-  <div id="Temoignages">
+  <AnchoredSection id="testimonials">
     <LayoutContainer>
-      <CommonReviewCard :cards="cards" />
+      <CommonReviewSection :cards="cards" />
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const cards = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Review } from "~/types/interface";
+
+const cards: Array<Review> = [
   {
-    description:
+    review:
       "Formation très personnalisée et très productive. Tout à fait adaptée à nos besoins actuels.",
     name: "Jocelyne DELAPORTE ",
     status: "Responsable administrative",
     structure: "École de Musique Municipale De Pecquencourt (59)",
   },
   {
-    description:
+    review:
       "Merci à Johan d'avoir pris le temps de nous former, de rentrer dans les détails des questions abordées. Et merci à l'équipe pour votre réactivité lorsque l'on demande à être aidés",
     name: "Claire CAGNON ",
     status: "Secrétaire administrative",
     structure: "École de Musique, Théâtre et Cirque Alsace Rhin Brisach (68)",
   },
   {
-    description:
+    review:
       " Une journée de formation précieuse pour un point complet de la prise en main du logiciel et des réponses utiles aux questions et problématiques rencontrées.",
     name: "Sayuri OKA NICOLEAU",
     status: "Directrice administrative & pédagogique",
     structure: "École Municipale de Musique de Croissy-sur-Seine (78)",
   },
   {
-    description:
+    review:
       "Un formateur à l'écoute des besoins de notre structure et des besoins de nous deux débutants sur le logiciel. Besoin compris pour une journée de formation complémentaire pour lancer la campagne d'inscription courant le deuxième trimestre 2022. Merci pour la patience de Johan, pédagogue et fin connaisseur de son logiciel.",
     name: "Alain BATS",
     status: "Président adjoint",
@@ -38,33 +41,3 @@ const cards = [
   },
 ];
 </script>
-
-<style scoped>
-:deep().container-green {
-  background-color: white !important;
-}
-
-:deep().reviews-title {
-  color: black !important;
-}
-
-:deep().v-card,
-.reviewer-name {
-  background-color: #0e2d32;
-  color: white !important;
-}
-
-:deep().reviewer-name {
-  color: white !important;
-}
-
-:deep().carousel-button i {
-  color: #0e2d32 !important;
-}
-:deep().carousel-button {
-  border: 2px solid #0e2d32;
-}
-.v-container {
-  padding: 0 !important;
-}
-</style>

+ 0 - 187
components/Formation/Solutions.vue

@@ -1,187 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <v-col cols="12">
-        <h4 class="solution-title text-center">
-          Ces solutions peuvent vous intéresser
-        </h4>
-      </v-col>
-    </v-row>
-
-    <v-row class="row-artist">
-      <v-col cols="3">
-        <v-img
-          src="/images/opentalent_artist_black.png"
-          class="logo"
-        />
-      </v-col>
-
-      <v-col cols="2">
-        <h5 class="solution-name">
-          Opentalent Artist
-        </h5>
-      </v-col>
-
-      <v-col cols="7">
-        <!-- list v-chip-->
-        <v-chip-group
-          active-class="primary--text"
-          column
-        >
-          <v-chip
-            class="ma-2 chip"
-            label
-          >
-            <span>Agenda</span>
-          </v-chip>
-          <v-chip
-            class="ma-2"
-            label
-          >
-            <span>Facturation</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            label
-          >
-            <span>Comptabilité</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            label
-          >
-            <span>Communication</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            label
-          >
-            <span>Site internet</span>
-          </v-chip>
-        </v-chip-group>
-      </v-col>
-    </v-row>
-
-    <v-row class="row-artist">
-      <v-col cols="3">
-        <v-img
-          src="/images/opentalent_manager_black.jpg"
-          class="logo"
-        />
-      </v-col>
-
-      <v-col cols="2">
-        <h5 class="solution-name">
-          Opentalent Manager
-        </h5>
-      </v-col>
-
-      <v-col cols="7">
-        <!-- list v-chip-->
-        <v-chip-group
-          active-class="primary--text"
-          column
-        >
-          <v-chip
-            class="ma-2 chip"
-            color="primary"
-            label
-          >
-            <span>Agenda</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            color="primary"
-            label
-          >
-            <span>Facturation</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            color="primary"
-            label
-          >
-            <span>Comptabilité</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            color="primary"
-            label
-          >
-            <span>Communication</span>
-          </v-chip>
-          <v-chip
-            class="ma-2 chip"
-            color="primary"
-            label
-          >
-            <span>Site internet</span>
-          </v-chip>
-        </v-chip-group>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-.chip {
-  /* position: inherit; */
-  color: black;
-  border: 1px solid #0e2d32;
-  border-radius: 3rem;
-  text-transform: uppercase;
-
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 16px;
-
-  /* identical to box height, or 114% */
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.2em;
-}
-
-.row-artist {
-  border-top: 1px solid #d1cdc7;
-  margin-left: 2rem;
-  margin-right: 2rem;
-}
-
-.solution-name {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.5rem;
-  line-height: 1.5rem;
-  color: #0e2d32;
-}
-
-.row-artist {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-}
-.solution-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 1.5rem;
-  line-height: 1.5rem;
-  color: #000000;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-  text-align: center;
-}
-
-.logo {
-  width: 10rem;
-  height: 10rem;
-  margin-left: 2rem;
-  margin-right: 2rem;
-}
-</style>

+ 18 - 29
components/Home/Besoin.vue

@@ -1,23 +1,23 @@
 <template>
-  <LayoutContainer :overflow="false">
-    <v-row class="mt-6" justify="center" v-if="!mdAndDown" >
-      <v-col cols="6" class="relative-container" >
-        <div class="screen-img ml-4"></div>
-        <!-- <div class="circle">
-          <v-icon class="fa-brands fa-react icon" />
-          <div class="circle-text">Réponse aux besoins</div>
-        </div> -->
+  <LayoutContainer>
+    <v-row
+      v-if="!mdAndDown"
+      class="mt-6"
+      justify="center"
+    >
+      <v-col cols="6">
+        <div class="screen-img ml-4" />
       </v-col>
 
       <v-col cols="6" >
-        <h3 class="title-event mt-12">
+        <h3 class="mt-12">
           Une solution évolutive pour vous donner entière satisfaction
         </h3>
 
         <p class="details ">
           La satisfaction de nos clients est notre première motivation et nous
           nous tenons à votre écoute pour faire évoluer notre logiciel. <br />
-          <span class="bold">Un besoin ?</span> <br />
+          <b>Un besoin ?</b> <br />
           Notifiez le nous et après l'étude de votre demande en interne puis
           validation, nous intégrerons votre requête à notre processus de
           développement.
@@ -27,13 +27,12 @@
   </LayoutContainer>
 </template>
 
-<script setup>
-import { useDisplay } from "vuetify";
-const { smAndDown, mdAndDown } = useDisplay();
+<script setup lang="ts">
+  import { useDisplay } from "vuetify";
+  const { mdAndDown } = useDisplay();
 </script>
 
-<style scoped>
-
+<style scoped lang="scss">
 .v-row
 {
   margin-left:auto !important;
@@ -41,32 +40,22 @@ const { smAndDown, mdAndDown } = useDisplay();
   max-width: 1400px !important;
 }
 
-
-
-.relative-container {
-  position: relative;
-}
-
-.bold {
-  font-weight: bold;
-}
-
-.title-event {
+h3 {
   font-weight: 400;
   font-size: 1.5rem;
   line-height: 38px;
   margin-top: 1rem;
   margin-left: 2rem;
-  color: #091d20;
+  color: var(--primary-color);
   width: 16rem;
 }
 
-.details {
+p {
   font-weight: 400;
   font-size: 1rem;
   margin-top: 3rem;
   margin-left: 2rem;
-  color: #091d20;
+  color: var(--primary-color);
   width: 20rem;
   text-align: justify;
 }

+ 218 - 254
components/Home/Caroussel.vue

@@ -1,114 +1,115 @@
+<!--
+Carrousel de la page d'accueil
+-->
 <template>
-  <LayoutContainer :class="mdAndDown ? 'mt-12' : ''">
-    <LayoutUITitlePage
-      title="LOGICIELS CULTURELS"
-      subtitle="UNE GAMME DE LOGICIELS ADAPTÉE À CHAQUE STRUCTURE CULTURELLE"
-    />
-    <v-carousel
-      v-if="!mdAndDown"
-      ref="carousel"
-      v-model="activeIndex"
-      :show-arrows="false"
-      :hide-delimiter-background="true"
-      :show-delimiters="false"
-      :touch="true"
-      :wrap-around="true"
-      :interval="5000"
+  <v-carousel
+    ref="carousel"
+    v-model="activeIndex"
+    :show-arrows="false"
+    :hide-delimiter-background="true"
+    :show-delimiters="false"
+    :touch="true"
+    :wrap-around="true"
+    :interval="5000"
+  >
+    <v-carousel-item
+      v-for="(item, index) in carouselItems"
+      :key="index"
     >
-      <v-carousel-item v-for="(item, index) in carouselItems" :key="index">
-        <v-row>
-          <v-col cols="12" md="12" lg="6" sm="12">
-            <v-img class="logo" :src="item.logo" />
-
-            <p
-              v-html="item.description"
-              class="description"
-              style="text-align: justify"
-            ></p>
-
-            <v-row class="align-start">
-              <nuxt-link :to="item.link">
-                <v-btn :class="item.buttonClass">
-                  En savoir plus
-                  <i
-                    class="fas fa-arrow-right"
-                    style="color: black; margin-left: 8px"
-                  ></i>
-                </v-btn>
-              </nuxt-link>
-            </v-row>
-          </v-col>
-
-          <v-col cols="12" md="12" lg="6" sm="12">
-            <v-row class="justify-end">
-              <div
-                class="background-rectangle"
-                :style="{ backgroundColor: item.color }"
-              />
-              <v-card class="card" elevation="5">
-                <v-img
-                  class="profile-image"
-                  :src="item.avatar"
-                  alt="Profile Image"
-                  contain
-                  rounded
-                />
-                <v-card-text>
-                  <v-card-title class="name">
-                    {{ item.name }}
-
-                    <p class="school">
-                      {{ item.school }}
-                    </p>
-                  </v-card-title>
-                  <p class="status">
-                    {{ item.status }}
-                  </p>
-                </v-card-text>
-              </v-card>
-
+      <v-row>
+        <!-- Partie description (logo, description, bouton 'en savoir plus') -->
+        <v-col cols="12" lg="6" class="col presentation">
+          <v-img
+            :src="item.logo"
+            class="logo"
+          />
+
+          <p class="description">
+            {{ item.description }}
+          </p>
+
+          <v-row class="align-start pl-4">
+            <v-btn
+              :to="item.link"
+              append-icon="fas fa-arrow-right"
+              :class="['learn-more-btn', item.buttonClass]"
+            >
+              En savoir plus
+            </v-btn>
+          </v-row>
+        </v-col>
+
+        <!-- Partie Illustration -->
+        <v-col cols="12" lg="6" class="col illustration">
+          <v-row>
+            <div
+              class="background-rectangle"
+              :style="{ backgroundColor: item.color }"
+            />
+
+            <v-card class="card" elevation="5">
               <v-img
-                :src="item.image"
-                :class="smAndDown ? 'image-sm' : 'image'"
+                class="profile-image"
+                :src="item.avatar"
+                alt="Profile Image"
+                contain
+                rounded
               />
-            </v-row>
-          </v-col>
-        </v-row>
-      </v-carousel-item>
-
-      <div class="custom-controls">
-        <div
-          v-for="(item, index) in carouselItems"
-          :key="index"
-          :class="{ 'active-control': index === activeIndex }"
-          @click="changeSlide(index)"
-        />
-      </div>
-    </v-carousel>
-
-  </LayoutContainer>
+              <v-card-text>
+                <v-card-title class="name">
+                  {{ item.name }}
+
+                  <p class="school">
+                    {{ item.school }}
+                  </p>
+                </v-card-title>
+
+                <p class="status">
+                  {{ item.status }}
+                </p>
+              </v-card-text>
+            </v-card>
+
+            <v-img
+              :src="item.image"
+              :class="smAndDown ? 'image-sm' : 'image'"
+            />
+          </v-row>
+        </v-col>
+      </v-row>
+    </v-carousel-item>
+
+    <div class="custom-controls">
+      <!--suppress JSUnusedLocalSymbols -->
+      <div
+        v-for="(_, index) in carouselItems"
+        :key="index"
+        :class="{ 'active-control': index === activeIndex }"
+        @click="setActiveIndex(index)"
+      />
+    </div>
+  </v-carousel>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
+
 import { useDisplay } from "vuetify";
-const { mdAndDown } = useDisplay();
+import type { CarouselItem } from "~/types/interface";
+const { smAndDown, mdAndDown } = useDisplay();
 
-let activeIndex = ref(0);
+// Index de la slide active
+let activeIndex: Ref<number> = ref(0);
 
-const changeSlide = (index) => {
+const setActiveIndex = (index: number) => {
   activeIndex.value = index;
 };
 
-const carouselItems = ref([
+const carouselItems: Ref<Array<CarouselItem>> = ref([
   {
     logo: "/images/logo/logiciels/School-noir.png",
-    description_mobile:
-      "Pour les petits comme pour les GRANDS <br> établissements d’enseignement artistique <br> tels que les écoles de musique, de danse, <br> de théâtre, d'art, de cirque et conservatoire.",
     description:
       "Pour les petits comme pour les GRANDS établissements d’enseignement artistique tels que les écoles de musique, de danse, de théâtre, d'art, de cirque et conservatoire.<br> Il permet la gestion au quotidien et en temps réel de votre établissement, de gérer vos élèves et vos professeurs, vos emplois du temps, le suivi pédagogique, vos salles, la facturation et les encaissements…",
     buttonClass: "btn-school",
-    buttonClassMobile: "btn-school-mobile",
     image:
       "/images/Home_logiciel/Logiciel_Opentalent_School-eleve-Conservatoire_de_Musique.png",
     color: "rgba(32, 147, 190, 0.4)",
@@ -149,125 +150,13 @@ const carouselItems = ref([
 ]);
 </script>
 
-<style scoped>
-.btn-school-mobile {
-  background: rgba(32, 147, 190, 0.4);
-  border-radius: 0.5rem;
-  margin-left: 1rem;
-  padding: 15px;
-  gap: 9px;
-  font-weight: 700;
-  font-size: 0.7rem;
-  line-height: 15px;
-  width: 10rem;
-  height: 2.5rem;
-  margin-top: 1rem;
-}
-::v-deep .v-carousel__controls {
-  display: none;
-}
-
-/* ============= TITLE ===============  */
-.title {
-  font-size: 4rem;
-  line-height: 3.5rem;
-  letter-spacing: 1.1rem;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-}
-
-.subtitle {
-  font-size: 1.5rem;
-  line-height: 2rem;
-  letter-spacing: 0.5rem;
-  margin-bottom: 8rem;
-}
-
-/* ============= CARD ===============  */
-.card {
-  position: relative;
-  left: 10%;
-  height: 100%;
-  width: 27%;
-  border-radius: 1rem;
-  margin-top: 1rem;
-}
-
-.profile-image {
-  width: 100%;
-  height: 12vh;
-}
-
-.name {
-  text-align: center;
-  font-size: 0.9rem;
-  white-space: normal;
-  padding: 0 !important;
-}
-.school,
-.status {
-  text-align: center;
-  white-space: normal;
-}
-
-.school {
-  color: #888888;
-  margin-top: -0.8rem;
-  font-weight: normal !important;
-  font-size: 0.8rem !important;
-  margin-top: 0.2px;
-  line-height: 1rem !important;
-}
-
-.status {
-  text-transform: uppercase;
-  font-weight: bold;
-  color: black !;
-  font-size: 100%;
-  margin-top: 0.8rem;
-}
-/* ============= RECTANGLE ===============  */
-.background-rectangle {
-  position: absolute;
-  width: 70%;
-  height: 20rem;
-  left: 72%;
-  top: 50%;
-  transform: translate(-50%, -50%);
-  border-radius: 200px 0px 0px 15rem;
-  z-index: -1;
-
-  /* ============= LOGO ===============  */
-}
-.logo {
-  width: 20rem;
-  margin-top: 10px;
-  margin-left: 4rem;
-}
-.logo-md {
-  width: 20rem;
-  margin-top: 10px;
-}
-.description {
-  text-align: left;
-  margin-left: 7rem;
-  width: 25vw;
-  margin-bottom: 1rem;
-}
-
-.desccription-md {
-  width: 20rem;
-  margin-top: 10px;
-}
+<style scoped lang="scss">
 
 /* ============= CAROUSEL ===============  */
-
-.carousel-md{
-  height: 100%;
-  width: 100%;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
+:deep(.v-carousel__controls) {
+  display: none;
 }
+
 .custom-controls {
   position: absolute;
   top: 50%;
@@ -276,54 +165,129 @@ const carouselItems = ref([
   display: flex;
   flex-direction: column;
   gap: 1vh;
-}
-
-.image {
-  height: 35rem;
-  right: 5rem;
-}
-
-
-.custom-controls div {
-  width: 0.6rem;
-  height: 0.6rem;
-  border-radius: 50%;
-  background-color: grey;
-  cursor: pointer;
-  margin-bottom: 0.5rem;
-}
-
-.custom-controls .active-control {
-  background-color: #000;
-  margin-right: 2rem;
-}
-
-/* ============= BUTTON ===============  */
-
-.btn-school {
-  background: rgba(32, 147, 190, 0.4);
-}
 
-.btn-artist {
-  background: rgba(250, 194, 10, 0.4);
+  div {
+    width: 0.6rem;
+    height: 0.6rem;
+    border-radius: 50%;
+    background-color: var(--neutral-color-alt-strong);
+    cursor: pointer;
+    margin-bottom: 0.5rem;
+  }
+
+  .active-control {
+    background-color: var(--on-neutral-color);
+    margin-right: 2rem;
+  }
 }
 
-.btn-manager {
-  background: rgba(216, 5, 11, 0.4);
+/* ============= Colonne gauche - Description ===============  */
+.col.presentation {
+  .logo {
+    width: 20rem;
+    margin-top: 10px;
+    margin-left: 6rem;
+  }
+
+  .description {
+    text-align: justify;
+    margin-top: 8px;
+    margin-left: 7rem;
+    width: 25vw;
+    margin-bottom: 1rem;
+  }
+
+  .learn-more-btn {
+    display: flex;
+    align-items: center;
+    margin-top: 16px;
+    border-radius: 0.5rem;
+    padding: 15px;
+    gap: 9px;
+    font-weight: 700;
+    font-size: 0.7rem;
+    line-height: 15px;
+    width: 10rem;
+    height: 2.5rem;
+    margin-left: 7rem;
+  }
+
+  .learn-more-btn :deep(.v-btn__append) {
+    color: var(--on-neutral-color);
+    margin-left: 0;
+  }
+
+  .btn-school {
+    background: var(--school-color-light);
+  }
+
+  .btn-artist {
+    background: var(--artist-color-light);
+  }
+
+  .btn-manager {
+    background: var(--manager-color-light);
+  }
 }
 
-.btn-school,
-.btn-artist,
-.btn-manager {
-  border-radius: 0.5rem;
-  margin-left: 2vw;
-  padding: 15px;
-  gap: 9px;
-  font-weight: 700;
-  font-size: 0.7rem;
-  line-height: 15px;
-  width: 10rem;
-  height: 2.5rem;
-  margin-left: 7rem;
+/* ============= Colonne droite - Illustration ===============  */
+.col.illustration {
+  .card {
+    position: relative;
+    left: 10%;
+    height: 100%;
+    width: 27%;
+    border-radius: 1rem;
+    margin-top: 1rem;
+  }
+
+  .profile-image {
+    width: 100%;
+    height: 12vh;
+  }
+
+  .name {
+    text-align: center;
+    font-size: 0.9rem;
+    white-space: normal;
+    padding: 0 !important;
+  }
+
+  .school, .status {
+    text-align: center;
+    white-space: normal;
+  }
+
+  .school {
+    color: var(--on-neutral-color-light);
+    font-weight: normal !important;
+    font-size: 0.8rem !important;
+    margin-top: 0.2px;
+    line-height: 1rem !important;
+  }
+
+  .status {
+    text-transform: uppercase;
+    font-weight: bold;
+    color: var(--on-neutral-color);
+    font-size: 100%;
+    margin-top: 0.8rem;
+  }
+
+  .background-rectangle {
+    position: absolute;
+    width: 70%;
+    height: 20rem;
+    left: 72%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    border-radius: 200px 0 0 15rem;
+    z-index: -1;
+  }
+
+  .image {
+    height: 35rem;
+    right: 5rem;
+  }
 }
 </style>

+ 45 - 47
components/Home/EventAgenda.vue

@@ -1,25 +1,27 @@
+<!--
+Section "Agenda" de la page d'accueil
+-->
 <template>
-  <LayoutContainer :overflow="false">
-    <div :class="mdAndDown ? '' :'container'">
-      <div class="title-container">
-        <h2 class="title">
+  <LayoutContainer>
+    <div class="container">
+      <div class="d-flex align-center justify-center">
+        <h2>
           Retrouvez tous vos évènements dans l'agenda et référencez vous dans
           l'annuaire
         </h2>
       </div>
+
       <v-row justify="center">
-        <div :class="mdAndDown ? 'btn-container-md' : 'btn-container'">
+        <div class="btn-container">
           <v-col cols="12" md="6">
-            <v-btn class="btn-event">
-              <span>Découvrir l'agenda</span>
-              <v-icon class="fa-solid fa-arrow-right icon-arrow" />
+            <v-btn append-icon="fas fa-arrow-right" class="btn-event">
+              Découvrir l'agenda
             </v-btn>
           </v-col>
 
           <v-col cols="12" md="6">
-            <v-btn class="btn-event">
+            <v-btn append-icon="fas fa-arrow-right" class="btn-event">
               Découvrir l’ANNUAIRE
-              <v-icon class="fa-solid fa-arrow-right icon-arrow" />
             </v-btn>
           </v-col>
         </div>
@@ -30,14 +32,38 @@
 
 <script setup>
 import { useDisplay } from "vuetify";
-const { lgAndUp, mdAndDown } = useDisplay();
+const { mdAndDown } = useDisplay();
 </script>
 
 <style scoped>
-.icon-arrow {
-  font-size: 1rem;
-  margin-left: 1rem;
+
+@media (min-width: 600px) {
+  .container {
+    height: 35rem;
+    background: linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
+    linear-gradient(
+      180deg,
+      rgba(14, 45, 50, 0.04) 0%,
+      rgba(14, 45, 50, 0.2) 100%
+    ),
+    linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
+    url("/images/eventAgenda/eventAgenda.jpg") no-repeat center 60%;
+    background-size: cover;
+  }
+}
+
+h2 {
+  height: 9rem;
+  font-weight: 400;
+  font-size: 3rem;
+  line-height: 3rem;
+  text-align: center;
+  margin-bottom: 3rem;
+  margin-top: 4rem;
+  color: var(--on-primary-color);
+  width: 45rem;
 }
+
 .btn-container {
   display: flex;
   align-items: center;
@@ -45,9 +71,12 @@ const { lgAndUp, mdAndDown } = useDisplay();
   padding: 0 20rem;
 }
 
-.btn-container-md {
-  padding: 0 5rem;
+@media (max-width: 960px) {
+  .btn-container {
+    padding: 0 5rem;
+  }
 }
+
 .btn-event {
   border-radius: 0.5rem;
   gap: 9px;
@@ -60,35 +89,4 @@ const { lgAndUp, mdAndDown } = useDisplay();
   max-width: 20rem;
   height: 3.5rem;
 }
-.title {
-  height: 9rem;
-  font-weight: 400;
-  font-size: 3rem;
-  line-height: 3rem;
-  text-align: center;
-  margin-bottom: 3rem;
-  margin-top: 4rem;
-  color: #ffffff;
-  width: 45rem;
-}
-
-.title-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-
-.container,
-.container-sm {
-  height: 35rem;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
-    linear-gradient(
-      180deg,
-      rgba(14, 45, 50, 0.04) 0%,
-      rgba(14, 45, 50, 0.2) 100%
-    ),
-    linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
-    url("/images/eventAgenda/eventAgenda.jpg") no-repeat center 60%;
-  background-size: cover;
-}
 </style>

+ 133 - 145
components/Home/Help.vue

@@ -1,180 +1,168 @@
+<!--
+Section "Besoin d'aide" de la page d'accueil
+-->
+
 <template>
   <LayoutContainer>
-    <v-row class="mt-12">
-      <v-container>
-        <div :class="!mdAndDown ? 'help-container' : 'help-container-md'" >
-          <v-col cols="12" lg="6" md="12" sm="12">
-            <v-img  :class="!mdAndDown ? 'help-img' : 'help-img-md'" src="/images/Home_logiciel/Opentalent_a_votre_service.png" />
-          </v-col>
-
-            <v-col cols="12" lg="6" md="12" sm="12">
-            <h4  :class="!mdAndDown ? 'subtitle-team ml-10': 'subtitle-team-md'">
-              Notre équipe est à vos côtés 
-              pour vous guider
-            </h4>
-
-            <p :class="!mdAndDown ? 'need-help ml-10' : 'need-help-md'">
-              Besoin d’aide ? <br />
-              Vous souhaitez en savoir plus sur nos solutions ou vous avez
-              besoin d'assistance sur l'utilisation de l'un de nos logiciels ?
-            </p>
-
-            <v-row>
-              <ul :class="!mdAndDown ? 'details ml-10' : 'details-md'">
-                <li class="detail-item">
-                  Ouvert du lundi au vendredi de 8h15 à 17h45
-                </li>
-                <li class="detail-item">Support joignable par mail</li>
-                <li class="detail-item">
-                  De nombreux articles tutoriels accessibles 24h/24
-                </li>
-              </ul>
-            </v-row>
-
-            <v-row class="ml-10">
-              <a href="https://ressources.opentalent.fr/" target="_blank">
-                <v-btn :class="!mdAndDown ? 'button-faq' : 'button-faq-md '">Consulter la FAQ</v-btn>
-              </a>
-            </v-row>
-          </v-col>
-
-        </div>
-      </v-container>
+    <v-row >
+      <v-col cols="12" lg="6" class="col">
+        <v-img src="/images/Home_logiciel/Opentalent_a_votre_service.png" />
+      </v-col>
+
+      <v-col cols="12" lg="6" class="col">
+        <h4>
+          Notre équipe est à vos côtés
+          pour vous guider
+        </h4>
+
+        <p>
+          Besoin d’aide ? <br />
+          Vous souhaitez en savoir plus sur nos solutions ou vous avez
+          besoin d'assistance sur l'utilisation de l'un de nos logiciels ?
+        </p>
+
+        <v-row>
+          <ul>
+            <li>
+              Ouvert du lundi au vendredi de 8h15 à 17h45
+            </li>
+            <li>
+              Support joignable par mail
+            </li>
+            <li>
+              De nombreux articles tutoriels accessibles 24h/24
+            </li>
+          </ul>
+        </v-row>
+
+        <v-row>
+          <v-btn
+            href="https://ressources.opentalent.fr/"
+            target="_blank"
+            class="button-faq"
+          >
+            Consulter la FAQ
+          </v-btn>
+        </v-row>
+      </v-col>
     </v-row>
   </LayoutContainer>
 </template>
-<script setup>
-import "vue3-carousel/dist/carousel.css";
-import { useDisplay } from "vuetify";
-const { smAndDown, mdAndDown} = useDisplay();
-</script>
 
-<style scoped>
+<script setup lang="ts">
+  import { useDisplay } from "vuetify";
 
-.help-container {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.help-container-md {
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
-  align-items: center;
-}
+  const { mdAndDown} = useDisplay();
+</script>
 
+<style scoped lang="scss">
 
-.button-faq {
-  width: 195px;
-  height: 53px;
-  background: #64afb7;
-  border-radius: 6px;
-  color: white;
-  padding: 19px 28px;
-  gap: 9px;
-  margin-left: auto;
-  margin-right: auto;
-}
+.v-container {
+  margin: 64px auto 24px auto;
+  padding: 16px;
+  max-width: 95%;
 
-.button-faq-md {
-  width: 195px;
-  height: 53px;
-  background: #64afb7;
-  border-radius: 6px;
-  color: white;
-  padding: 19px 28px;
-  gap: 9px;
-  margin-left: 3rem;
-  margin-top: 2rem;
-}
+  .col {
+    padding: 0 6px;
+    display: flex;
+    flex-direction: column;
+  }
 
-.details {
-  margin-top: 20px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  color: #0e2d32;
-  font-size: 1.2rem;
-  line-height: 1.6rem;
-}
+  .col:first-child {
+    align-items: center;
+  }
 
-.details-md {
-  margin-top: 20px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  color: #0e2d32;
-  font-size: 1.2rem;
-  line-height: 1.6rem;
-  margin-left: auto;
-  margin-right: auto;
-  width: 30rem;
+  .col:nth-child(2) {
+    padding: 60px;
+    justify-content: center;
+    align-items: self-start;
+  }
 }
 
-.detail-item {
+li {
   margin-left: 28px;
   margin-bottom: 15px;
-  color: #0e2d32;
+  color: var(--primary-color);
   font-size: 1.1rem;
 }
 
-.need-help {
+.v-img {
+  width: 50rem;
+  border-radius: 3rem;
+}
+
+h4 {
+  margin-bottom: 0.7rem;
+  font-weight: 400;
+  font-size: 2rem;
+  line-height: 34px;
   width: 25rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.1rem;
-  line-height: 1.4rem;
-  color: #0e2d32;
 }
 
-.need-help-md {
-  width: 30rem;
-  font-family: "Barlow";
-  font-style: normal;
+p {
+  width: 25rem;
   font-weight: 300;
   font-size: 1.1rem;
   line-height: 1.4rem;
-  color: #0e2d32;
-  width: 30rem;
-  margin-left: auto;
-  margin-right: auto;
+  color: var(--primary-color);
 }
 
-.help-img {
-  width: 50rem;
-  border-radius: 3rem;
+ul {
+  margin-top: 20px;
+  max-height: 160px;
+  font-weight: 500;
+  color: var(--primary-color);
+  font-size: 1.2rem;
+  line-height: 1.6rem;
 }
 
-.help-img-md {
-  width: 40rem;
-  border-radius: 3rem;
+.button-faq {
+  width: 195px;
+  height: 53px;
+  background: var(--secondary-color);
+  border-radius: 6px;
+  color: var(--on-secondary-color);
+  padding: 19px 28px;
+  gap: 9px;
   margin-left: auto;
   margin-right: auto;
-  margin-top: 4rem;
-}
-
-.subtitle-team {
-  margin-bottom: 0.7rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 400;
-  font-size: 2rem;
-  line-height: 34px;
-  width: 25rem;
 }
 
-.subtitle-team-md {
-  margin-bottom: 0.7rem;
-  font-style: normal;
-  font-weight: 400;
-  font-size: 2rem;
-  line-height: 34px;
-  text-align: left;
-  width: 30rem;
-  margin-left: auto;
-  margin-right: auto;
+@media (max-width: 960px) {
+  .v-img {
+    width: 40rem;
+    margin-left: auto;
+    margin-right: auto;
+    margin-top: 4rem;
+  }
+
+  h4 {
+    font-size: 2rem;
+    text-align: left;
+    width: 30rem;
+    margin-left: auto;
+    margin-right: auto;
+  }
+
+  p {
+    width: 30rem;
+    font-weight: 300;
+    font-size: 1.1rem;
+    line-height: 1.4rem;
+    color: var(--primary-color);
+    margin-left: auto;
+    margin-right: auto;
+  }
+
+  ul {
+    margin-left: auto;
+    margin-right: auto;
+    width: 30rem;
+  }
+
+  .button-faq {
+    margin-left: 3rem;
+    margin-top: 2rem;
+  }
 }
 </style>

+ 0 - 299
components/Home/News.vue

@@ -1,299 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <v-col cols="6">
-        <div class="container-title">
-          <v-icon
-            size="10"
-            class="fa-solid fa-circle icon-title"
-          />
-
-          <h6 class="small-title">
-            Découvrez nos dernières actualités
-          </h6>
-        </div>
-        <h2 class="title">
-          Quoi de neuf ?
-        </h2>
-      </v-col>
-
-      <v-col cols="6">
-        <v-btn
-          class="btn-news"
-          text
-        >
-          VOIR TOUTES LES ACTUALITÉS
-        </v-btn>
-      </v-col>
-    </v-row>
-
-    <v-row>
-      <v-col cols="2">
-        <div class="d-flex justify-center align-center">
-          <div
-            class="carousel-button"
-            @click="goPrevious"
-          >
-            <i class="fas fa-chevron-left" />
-          </div>
-          <div
-            class="carousel-button"
-            @click="goNext"
-          >
-            <i class="fas fa-chevron-right" />
-          </div>
-        </div>
-      </v-col>
-
-      <v-col cols="10">
-        <Carousel
-          ref="carousel"
-          :items-to-show="3.5"
-          :items-to-scroll="1"
-        >
-          <Slide
-            v-for="(actu, index) in actus"
-            :key="index"
-            class="slide-card"
-          >
-            <div class="card">
-              <img
-                class="card-img-top"
-                :src="actu.img"
-                alt="Card image cap"
-              >
-              <div class="card-body">
-                <h5 class="card-title">
-                  {{ actu.title }}
-                </h5>
-                <p class="card-text">
-                  {{ actu.content }}
-                </p>
-              </div>
-
-              <div class="card-footer">
-                <p class="card-date">
-                  {{ actu.date }}
-                </p>
-                <button class="card-button">
-                  +
-                </button>
-              </div>
-            </div>
-          </Slide>
-        </Carousel>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup>
-import { ref } from "vue";
-import { Carousel, Slide } from "vue3-carousel";
-import "vue3-carousel/dist/carousel.css";
-
-const carousel = ref(null);
-
-const goPrevious = () => {
-  carousel.value.prev();
-};
-
-const goNext = () => {
-  carousel.value.next();
-};
-
-const actus = ref([
-  {
-    title: "Suivi Pédagogique",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "20/06/2023",
-    img: "/images/actu/actu1.jpg",
-  },
-  {
-    title: "AMÉLIORATION DU RÉPERTOIRE",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "21/06/2023",
-    img: "/images/actu/actu2.jpg",
-  },
-  {
-    title: "fOIRE AUX QUESTIONS",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "22/06/2023",
-    img: "/images/actu/actu3.jpg",
-  },
-  {
-    title: "Suivi Pédagogique",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "23/06/2023",
-    img: "/images/actu/actu4.jpg",
-  },
-  {
-    title: "Actu 1",
-    content: "Sed laeditur hic coetuum magnificus gegr",
-    date: "24/06/2023",
-    img: "/images/actu/actu5.jpg",
-  },
-  {
-    title: "Actu 2",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "25/06/2023",
-    img: "/images/actu/actu6.jpg",
-  },
-  {
-    title: "Actu 3",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "26/06/2023",
-    img: "/images/actu/actu1.jpg",
-  },
-  {
-    title: "Suivi Pédagogique",
-    content: "Sed laeditur hic coetuum magnificus",
-    date: "27/06/2023",
-    img: "/images/actu/actu2.jpg",
-  },
-]);
-</script>
-
-<style scoped>
-.card {
-  border: 0.5px solid #c4c4c4;
-  border-radius: 15px 15px 0 0;
-  margin-bottom: 2rem;
-}
-
-.icon-title {
-  color: #64afb7;
-  margin-top: 4.5rem;
-}
-.container-title {
-  display: flex;
-  align-items: center;
-  margin-left: 2rem;
-  margin-top: 4.5rem;
-}
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 40px;
-  height: 40px;
-  background-color: transparent;
-  border: 2px solid #000000;
-  cursor: pointer;
-  margin-right: 1rem;
-  margin-top: 4rem;
-}
-
-.carousel-button i {
-  color: #000000;
-}
-.card-text {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 18px;
-  margin-bottom: 1rem;
-  color: #091d20;
-}
-.card-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 12px;
-  line-height: 16px;
-  display: flex;
-  align-items: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-}
-.card-date {
-  font-size: 0.8em;
-  color: #888;
-  margin-left: 1rem;
-}
-
-.card-footer {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.card-body {
-  text-align: left;
-  margin-bottom: 1rem;
-  margin-left: 1rem;
-}
-
-.card-button {
-  background-color: transparent;
-  border: none;
-  width: 2.5rem;
-  font-size: 1.5em;
-  text-align: right;
-  color: #ffffff;
-  background-color: #64afb7;
-  border: none;
-  text-align: center;
-}
-.slide-card {
-  margin-left: 1rem;
-  margin-right: 1rem;
-  height: 100%;
-}
-
-.card-img-top {
-  border-radius: 15px 15px 0 0;
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  object-position: center;
-}
-.small-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  width: 12rem;
-  font-size: 12px;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  margin-left: 2rem;
-  color: #071b1f;
-  margin-top: 4.5rem;
-}
-
-.title {
-  margin-top: 2rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  margin-left: 2rem;
-  color: #071b1f;
-  margin-bottom: 2rem;
-}
-
-.btn-news {
-  color: #9edbdd;
-  margin-left: 25rem;
-  margin-top: 8rem;
-  top: 6rem;
-  border-radius: 2rem;
-  font-family: "Barlow";
-  background: transparent;
-  border: 1px solid #9edbdd;
-  border-radius: 6px;
-  font-style: normal;
-  font-weight: 600;
-  text-transform: uppercase;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  padding: 25px;
-  font-size: 10px;
-  line-height: 15px;
-}
-</style>

+ 194 - 237
components/Home/Promotion.vue

@@ -1,32 +1,40 @@
 <template>
   <LayoutContainer>
-    <v-row>
-      <v-col col="12" :class="mdAndDown ? 'col-gestion' : 'col-gestion-md'">
+    <v-row class="gestion">
+      <v-col>
         <div class="d-flex justify-center align-center flex-column">
-          <v-icon size="6" class="fa-solid fa-circle icon-title" />
-          <h5 class="subtitle">GESTION ET PROMOTION</h5>
+          <v-icon
+            size="6"
+            icon="fas fa-circle"
+          />
+          <h5>
+            GESTION ET PROMOTION
+          </h5>
         </div>
+
         <v-row>
-          <p :class="smAndDown ? 'text-gestion-sm' : 'text-gestion'">
-            <span class="span-color">Simplifiez</span>-vous la vie avec un outil
-            <span class="d-inline-flex align-center">
+          <p class="text-block">
+            <span class="highlight">Simplifiez</span>-vous la vie avec un outil
+
+            <span class="inline-pic-container">
               <v-img
                 src="/images/Home_logiciel/ecole_de_musique-piano.jpg"
-                :class="smAndDown ? 'rectangle-img-sm' : 'rectangle-img'"
               />
             </span>
+
             tout en un pour la gestion et la promotion
-            <span class="d-inline-flex align-center">
+
+            <span class="inline-pic-container">
               <v-img
                 src="/images/Home_logiciel/ecole_de_danse-danseuse.jpg"
-                :class="smAndDown ? 'rectangle-img-sm' : 'rectangle-img'"
               />
             </span>
+
             , de votre structure culturelle.
-            <span class="d-inline-flex align-center">
+
+            <span class="inline-pic-container">
               <v-img
                 src="/images/Home_logiciel/ecole_de_cirque.jpg"
-                :class="smAndDown ? 'rectangle-img-sm' : 'rectangle-img'"
               />
             </span>
           </p>
@@ -34,266 +42,215 @@
       </v-col>
     </v-row>
 
-    <v-row class="outil">
-      <v-col cols="12">
+    <v-row class="demo">
+      <v-col>
         <v-img
           src="/images/home/écran.JPG"
-          :class="[
-            smAndDown ? 'screen-sm' : 'screen',
-            !smAndDown && isZoomed ? 'zoom' : '',
-          ]"
-          @mouseover="zoomIn"
-          @mouseleave="zoomOut"
-        />
-        <div class="play-icon-container">
-          <i class="fas fa-play"></i>
-        </div>
-      </v-col>
-    </v-row>
+          class="screen"
+        >
+          <v-icon icon="fas fa-play" class="play-icon" />
+        </v-img>
 
-    <v-row>
-      <v-col cols="12">
-        <h3 class="text-center text-outil">
-          Un outil complet et intuitif <br />
-          pour chaque structure
-        </h3>
       </v-col>
     </v-row>
 
-    <v-row class="mb-6">
-      <v-col cols="12" lg="6" md="12" sm="12">
-        <div class="horizontal-line" />
-        <v-row class="picto-container">
-          <img src="/images/pictoHome/picto4.svg" class="picto" />
-          <p class="text-outil-details">
-            Logiciel de Gestion et communication en ligne
-          </p>
-        </v-row>
-        <div class="horizontal-line" />
-        <v-row class="picto-container">
-          <img src="/images/pictoHome/picto3.svg" class="picto" />
-          <p class="text-outil-details">Site Web intégré et simple d’usage</p>
-        </v-row>
-        <div class="horizontal-line" />
-      </v-col>
+    <section class="outil">
+      <v-row>
+        <v-col>
+          <h3>
+            Un outil complet et intuitif <br />
+            pour chaque structure
+          </h3>
+        </v-col>
+      </v-row>
 
-      <v-col cols="12" lg="6" md="12" sm="12">
-        <div class="horizontal-line" />
-        <v-row class="picto-container">
-          <img src="/images/pictoHome/picto1.svg" class="picto" />
-          <p class="text-outil-details">
-            Augmentez votre visibilité avec l'agenda culturel
-          </p>
-        </v-row>
-        <div class="horizontal-line" />
-        <v-row class="picto-container">
-          <img src="/images/pictoHome/picto2.svg" class="picto" />
-          <p class="text-outil-details">Communiquez en réseau</p>
-        </v-row>
-        <div class="horizontal-line" />
-      </v-col>
-    </v-row>
+      <v-row class="pictos">
+        <v-col cols="12" lg="6">
+          <v-row>
+            <img src="/images/pictoHome/network.svg" alt="network" />
+            <p>
+              Logiciel de gestion et communication en ligne
+            </p>
+          </v-row>
+
+          <v-row>
+            <img src="/images/pictoHome/website.svg" alt="website" />
+            <p>
+              Site web intégré et simple d’usage
+            </p>
+          </v-row>
+        </v-col>
+
+        <v-col cols="12" lg="6">
+          <v-row>
+            <img src="/images/pictoHome/visibility.svg" alt="visibility" />
+            <p>
+              Augmentez votre visibilité avec l'agenda culturel
+            </p>
+          </v-row>
+
+          <v-row>
+            <img src="/images/pictoHome/communication.svg" alt="communication" />
+            <p>
+              Communiquez en réseau
+            </p>
+          </v-row>
+        </v-col>
+      </v-row>
+    </section>
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
 import { useDisplay } from "vuetify";
-const { smAndDown, mdAndDown } = useDisplay();
-const isZoomed = ref(false);
-
-const zoomIn = () => {
-  isZoomed.value = true;
-};
 
-const zoomOut = () => {
-  isZoomed.value = false;
-};
+const { mdAndDown } = useDisplay();
 </script>
 
-<style scoped>
-.outil {
-  margin-bottom: -28rem;
-}
-.play-icon-container {
-  position: absolute;
-  top: 45%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  font-size: 3rem;
-  color: white;
-  cursor: pointer;
-  z-index: 100;
-}
-.text-gestion .d-inline-flex {
-  vertical-align: middle;
-}
+<style scoped lang="scss">
 
-.rectangle-img,
-.rectangle-img-sm {
-  max-width: 100%;
-  height: auto;
+.highlight {
+  color: var(--secondary-color);
 }
 
-.rectangle-img-sm {
-  width: 3.2rem;
-  border-radius: 5rem;
-}
+.v-row.gestion {
+  >.v-col {
+    margin-bottom: 4rem;
+    background: var(--primary-color);
+  }
 
-.align-center {
-  align-items: center;
-  display: inline-flex;
-}
+  h5 {
+    font-size: 1rem;
+    line-height: 1rem;
+    margin-top: 1rem;
+    color: var(--secondary-color);
+    text-align: center;
+    letter-spacing: 2.16px;
+    text-transform: uppercase;
+  }
 
-.picto-container {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-}
-.horizontal-line {
-  width: 80%;
-  margin-left: auto;
-  margin-right: auto;
-  height: 1px;
-  background-color: #d1cdc7;
-  margin-bottom: 1rem;
-}
-.text-outil-sm {
-  font-weight: 400;
-  font-size: 22px;
-  line-height: 26px;
-  width: 19rem;
-  color: #0e2d32;
-}
-.picto-group {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-top: 1rem;
-  margin-bottom: 1rem;
-}
-.picto-sm {
-  margin-left: 4rem;
-  width: 50px;
-  height: 50px;
-  margin-right: 2rem;
-}
-.picto {
-  width: 50px;
-  height: 50px;
-  margin-right: 2rem;
-}
-.screen-sm {
-  width: 100%;
-  object-fit: cover;
-  text-align: center;
-  transition: transform 0.2s;
-}
-.screen {
-  width: 900px;
-  object-fit: cover;
-  margin: 2rem auto;
-  text-align: center;
-  border-radius: 20px;
-  transition: transform 0.2s;
-  bottom: 30rem;
-}
+  .fa-circle{
+    margin-top: 1rem;
+    color: var(--on-primary-color);
+    margin-right: 1rem;
+  }
 
-.screen:hover {
-  transform: scale(1.1);
-}
+  .text-block {
+    font-weight: 600;
+    font-size: 3rem;
+    text-align: center;
+    color: var(--on-primary-color);
+    height: 20rem;
+    width: 45rem;
+    margin: 2rem auto 28rem;
+  }
 
-.subtitle {
-  font-size: 1rem;
-  line-height: 1rem;
-  margin-top: 1rem;
-  color: #c1eff0;
-  text-align: center;
-  letter-spacing: 2.16px;
-  text-transform: uppercase;
-}
+  .inline-pic-container {
+    display: inline-flex;
+    justify-content: center;
+    vertical-align: middle;
+  }
 
-.icon-title {
-  margin-top: 1rem;
-  color: #ffffff;
-  margin-right: 1rem;
-}
+  .v-img {
+    height: auto;
+    width: 7rem;
+    max-width: 100%;
+    border-radius: 5rem;
+  }
 
-.with-border,
-.with-border-top {
-  border-bottom: 1px solid #d1cdc7;
-  padding-top: 1rem;
-  padding-bottom: 1rem;
-}
+  @media (max-width: 960px) {
+    .text-block {
+      font-weight: 500;
+      font-size: 2rem;
+      line-height: 3.5rem;
+      height: 10rem;
+      width: 40rem;
+      margin: 3rem 2rem 5rem;
+    }
 
-.with-border-top {
-  border-top: 1px solid #d1cdc7;
+    .v-img {
+      width: 3.2rem;
+      border-radius: 5rem;
+    }
+  }
 }
 
-.row-outil {
-  margin-left: 4rem;
-}
+.v-row.demo {
+  margin-bottom: -28rem;
 
-.text-outil-details {
-  font-weight: 400;
-  font-size: 22px;
-  line-height: 26px;
-  width: 25rem;
-  color: #0e2d32;
-  margin-bottom: 1rem;
-}
+  .screen {
+    width: 900px;
+    object-fit: cover;
+    margin: 2rem auto;
+    text-align: center;
+    border-radius: 20px;
+    transition: transform 0.2s;
+    bottom: 30rem;
+  }
 
-.text-outil {
-  font-weight: 400;
-  font-size: 2rem;
-  color: #0e2d32;
-  margin-bottom: 3rem;
-}
+  @media (max-width: 960px) {
+    .screen {
+      width: 100%;
+    }
+  }
 
-.col-gestion {
-  margin-bottom: 4rem;
-  background: #0e2d32;
-}
+  @media (min-width: 600px) {
+    .screen:hover {
+      transform: scale(1.1);
+    }
+  }
 
-.col-gestion-md {
-  background: #0e2d32;
-  margin-bottom: 4rem;
+  .play-icon {
+    position: absolute;
+    top: 45%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    font-size: 3rem;
+    color: var(--on-primary-color);
+    cursor: pointer;
+    z-index: 100;
+  }
 }
 
-.text-gestion-sm {
-  font-weight: 500;
-  font-size: 2rem;
-  line-height: 3.5rem;
-  text-align: center;
-  color: white;
-  height: 10rem;
-  width: 40rem;
-  margin: 3rem 2rem 5rem;
-}
+section.outil {
+  margin-bottom: 36px;
 
-.v-container {
-  padding: 0;
-}
+  h3 {
+    color: var(--primary-color);
+    font-size: 2rem;
+    font-weight: 400;
+    margin-bottom: 3rem;
+    text-align: center;
+  }
 
-.text-gestion {
-  font-weight: 600;
-  font-size: 3rem;
-  text-align: center;
-  color: white;
-  height: 20rem;
-  margin-top: 3rem;
-  width: 45rem;
-  margin: 2rem auto 28rem;
-}
+  .pictos {
+    .v-row {
+      border-bottom: solid 1px var(--on-primary-color-alt);
+      margin: 0;
+      height: 100px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
 
-.span-color {
-  color: #caf5f4;
-}
+    .v-row:first-child {
+      border-top: solid 1px var(--on-primary-color-alt);
+    }
+
+    img {
+      width: 50px;
+      height: 50px;
+      margin-right: 2rem;
+    }
 
-.rectangle-img {
-  width: 7rem;
-  border-radius: 5rem;
+    p {
+      font-weight: 400;
+      font-size: 22px;
+      line-height: 26px;
+      width: 25rem;
+      color: var(--primary-color);
+      margin-bottom: 1rem;
+    }
+  }
 }
 </style>

+ 228 - 224
components/Home/Reviews.vue

@@ -1,53 +1,61 @@
 <template>
   <LayoutContainer>
-    <div :class="!smAndDown ? 'container-color' : 'container-color-md'">
+    <div class="container-1">
       <div class="d-flex justify-center align-center flex-column">
-        <v-icon size="6" class="fa-solid fa-circle icon-title" />
-        <h6 class="small-title">Avis Clients</h6>
+        <v-icon
+          icon="fa-solid fa-circle"
+          size="6"
+        />
+        <h6>
+          Avis Clients
+        </h6>
       </div>
 
-      <h1 class="title-review" :class="smAndDown ? 'mb-12 ' : ''">
+      <h3>
         C'est vous qui le dites
-      </h1>
+      </h3>
     </div>
 
-    <div v-if="!smAndDown" class="container-green">
+    <!-- Ecrans larges -->
+    <div v-if="mdAndUp" class="container-2">
+
+      <!-- Partie 1 : Avis clients -->
       <v-row justify="center">
         <div class="col-review">
           <v-col cols="6">
-            <v-card class="review-card left mx-auto">
+            <v-card class="left mx-auto">
               <v-card-title>
-                <span class="review-name">Patrice CATHELIN</span>
+                Patrice CATHELIN
               </v-card-title>
 
               <v-card-text>
-                <p class="description-review">
+                <p>
                   C'est un logiciel très bien conçu et efficace avec une équipe
                   ouverte, dynamique et à l'écoute. L’assistance est très
                   réactive, j'ai toujours eu une réponse rapide à mes besoins,
                   ce qui est fort appréciable.
                 </p>
               </v-card-text>
-              <div class="card-footer">
-                <small class="status"
-                  >Directeur administratif & pédagogique</small
-                >
 
-                <small class="structure"
-                  >Conservatoire de Musique & de Danse de Sens (78)</small
-                >
+              <div class="card-footer">
+                <small class="status">
+                  Directeur administratif & pédagogique
+                </small>
+                <small class="structure">
+                  Conservatoire de Musique & de Danse de Sens (78)
+                </small>
               </div>
             </v-card>
           </v-col>
 
           <v-col cols="6">
-            <v-card class="review-card right mx-auto">
+            <v-card class="right mx-auto">
               <v-card-title>
-                <span class="review-name">Karine GIRAUD </span>
+                Karine GIRAUD
               </v-card-title>
 
               <v-card-text>
-                <p class="description-review">
+                <p>
                   Étant présente depuis presque le début, je suis fière d'avoir
                   vu grandir ce logiciel et d'avoir évoluée avec lui. De plus,
                   je me suis sentie écoutée lors de mes propositions
@@ -58,11 +66,13 @@
               </v-card-text>
 
               <div class="card-footer">
-                <small class="status">Secrétaire administrative</small>
+                <small class="status">
+                  Secrétaire administrative
+                </small>
 
                 <small class="structure">
-                  Association Musicale Sainte Cécile de Lagord (17)</small
-                >
+                  Association Musicale Sainte Cécile de Lagord (17)
+                </small>
               </div>
             </v-card>
           </v-col>
@@ -72,13 +82,13 @@
       <v-row justify="center">
         <div class="col-review">
           <v-col cols="6">
-            <v-card class="review-card left mx-auto">
+            <v-card class="left mx-auto">
               <v-card-title>
-                <span class="review-name">Laurent BEL</span>
+                Laurent BEL
               </v-card-title>
 
               <v-card-text>
-                <p class="description-review">
+                <p>
                   Logiciel très complet qui permet de faire beaucoup de choses.
                   J’apprécie particulièrement la réactivité, la bienveillance et
                   le fait que l’équipe soit à l'écoute pour faire évoluer
@@ -87,26 +97,27 @@
                   face à un problème rencontré..
                 </p>
               </v-card-text>
+
               <div class="card-footer">
-                <small class="status"
-                  >Directeur administratif & pédagogique
+                <small class="status">
+                  Directeur administratif & pédagogique
                 </small>
 
                 <small class="structure">
-                  École de Musique EPIC Musique en 4 Rivières (74)</small
-                >
+                  École de Musique EPIC Musique en 4 Rivières (74)
+                </small>
               </div>
             </v-card>
           </v-col>
 
           <v-col cols="6">
-            <v-card class="review-card right mx-auto">
+            <v-card class="right mx-auto">
               <v-card-title>
-                <span class="review-name">Philippe BORY</span>
+                Philippe BORY
               </v-card-title>
 
               <v-card-text>
-                <p class="description-review">
+                <p>
                   Opentalent est une entreprise avec de vraies valeurs humaines,
                   à l'écoute de chaque structure et qui ne cesse de s'améliorer
                   pour toujours coller aux besoins de ses clients. Plus qu'une
@@ -114,52 +125,50 @@
                   au quotidien.
                 </p>
               </v-card-text>
+
               <div class="card-footer">
-                <small class="status">Personnel administratif</small>
+                <small class="status">
+                  Personnel administratif
+                </small>
 
                 <small class="structure">
-                  École d'Arts de Saint-Michel-sur-Orge (91)</small
-                >
+                  École d'Arts de Saint-Michel-sur-Orge (91)
+                </small>
               </div>
             </v-card>
           </v-col>
         </div>
       </v-row>
 
-      <div class="content-review">
-        <CommonCarouselTrustCompanie
-          :items="items"
-          :title-color="'#fff'"
-          :carousel-border-color="'#fff'"
-          :carousel-button-color="'#fff'"
-          :icon-color="'#fff'"
-        />
+      <!-- Partie 1 : Carrousel logos clients -->
+      <div class="carousel-clients-container">
+        <CommonCarouselClients :items="items" />
       </div>
     </div>
 
-    <div v-if="smAndDown">
+    <!-- Petits écrans -->
+    <div v-else class="container-sm">
       <v-row>
         <v-col cols="12">
-          <Carousel :itemsToShow="1" :wrapAround="true" ref="reviewCaroussel">
+          <Carousel :itemsToShow="1" :wrapAround="true" ref="reviewCarousel">
             <Slide v-for="(card, index) in cards" :key="index">
-              <div class="card-sm">
-                <v-card>
-                  <v-card-title>
-                    <span class="review-name">{{ card.name }}</span>
-                  </v-card-title>
-
-                  <v-card-text>
-                    <p class="description-review">
-                      {{ card.review }}
-                    </p>
-                  </v-card-text>
-                  <div class="card-footer">
-                    <small>{{ card.status }}</small>
-
-                    <small>{{ card.structure }}</small>
-                  </div>
-                </v-card>
-              </div>
+              <v-card>
+                <v-card-title>
+                  <span class="review-name">{{ card.name }}</span>
+                </v-card-title>
+
+                <v-card-text>
+                  <p class="description-review">
+                    {{ card.review }}
+                  </p>
+                </v-card-text>
+
+                <div class="card-footer">
+                  <small>{{ card.status }}</small>
+
+                  <small>{{ card.structure }}</small>
+                </div>
+              </v-card>
             </Slide>
           </Carousel>
         </v-col>
@@ -167,12 +176,12 @@
 
       <v-row class="justify-center align-center">
         <v-col class="d-flex justify-space-around align-center">
-          <i
-            style="cursor: pointer"
-            class="fa-solid fa-arrow-left-long"
-            @click="goPrevious"
+          <v-btn
+            icon="fas fa-arrow-left-long"
+            @click="goToPrevious"
           />
-          <div class="custom-controls">
+
+          <div class="carousel-controls">
             <div
               v-for="(item, index) in cards"
               :key="index"
@@ -180,10 +189,10 @@
               class="ml-6"
             />
           </div>
-          <i
-            style="cursor: pointer"
-            class="fa-solid fa-arrow-right-long"
-            @click="goNext"
+
+          <v-btn
+            icon="fas fa-arrow-right-long"
+            @click="goToNext"
           />
         </v-col>
       </v-row>
@@ -191,37 +200,34 @@
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
 import { Carousel, Slide } from "vue3-carousel";
 import "vue3-carousel/dist/carousel.css";
 import { useDisplay } from "vuetify";
+import type { Review } from "~/types/interface";
 
-const { smAndDown } = useDisplay();
-const reviewCaroussel = ref(null);
+const { mdAndUp } = useDisplay();
+
+const reviewCarousel: Ref<typeof Carousel | null> = ref(null);
 
 const state = ref({
   activeIndex: 0,
 });
 
-const goNext = () => {
-  if (reviewCaroussel.value) {
-    reviewCaroussel.value.next();
-    state.value.activeIndex = (state.value.activeIndex + 1) % cards.length;
-  }
-};
-
-const goPrevious = () => {
-  if (reviewCaroussel.value) {
-    reviewCaroussel.value.prev();
-    state.value.activeIndex =
-      state.value.activeIndex - 1 < 0
-        ? cards.length - 1
-        : state.value.activeIndex - 1;
-  }
-};
+const goToNext = () => {
+  reviewCarousel.value!.next();
+  state.value.activeIndex = (state.value.activeIndex + 1) % cards.length;
+}
+
+const goToPrevious = () => {
+  reviewCarousel.value!.prev();
+  state.value.activeIndex =
+    state.value.activeIndex - 1 < 0
+      ? cards.length - 1
+      : state.value.activeIndex - 1;
+}
 
-const cards = [
+const cards: Array<Review> = [
   {
     name: "Patrice CATHELIN",
     review:
@@ -252,7 +258,7 @@ const cards = [
   },
 ];
 
-const items = ref([
+const items: Ref<Array<{ src: string }>> = ref([
   { src: "/images/reviews/school/review1.svg" },
   { src: "/images/reviews/school/review2.png" },
   { src: "/images/reviews/school/review3.png" },
@@ -263,149 +269,147 @@ const items = ref([
 </script>
 
 <style scoped>
-.custom-controls div {
-  width: 0.6rem;
-  height: 0.6rem;
-  border-radius: 50%;
-  background-color: grey;
-  cursor: pointer;
-  margin-bottom: 0.5rem;
-}
 
-.custom-controls {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
+.container-1 {
+  background-color: var(--neutral-color);
+  height: 22rem;
 
-.custom-controls .active-control {
-  background-color: black;
-  margin-right: 10px;
-}
+  .v-icon {
+    margin-top: 1rem;
+    color: var(--secondary-color);
+  }
 
-.card-sm {
-  width: 300px;
-  height: 800px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-.v-container {
-  padding: 0 !important;
-}
-.content-review {
-  margin-top: -7rem;
-}
-.card-footer {
-  display: flex;
-  flex-direction: column;
-  margin-top: 1rem;
-}
-.col-review {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
+  h6 {
+    font-size: 1rem;
+    line-height: 1rem;
+    margin-top: 1rem;
+    text-align: center;
+    letter-spacing: 2.16px;
+    text-transform: uppercase;
+    margin-bottom: 0.5rem;
+  }
 
-.left {
-  bottom: 12rem;
-  position: relative;
-}
+  h3 {
+    font-size: 2rem;
+    line-height: 42px;
+    text-align: center;
+    color: var(--primary-color);
+  }
 
-.right {
-  position: relative;
-  bottom: 7rem;
-}
+  @media (max-width: 600px) {
+    margin-bottom: 24px;
+  }
 
-.icon-title {
-  margin-top: 1rem;
-  color: #64afb7;
 }
 
-.container-green {
-  background-color: #0e2d32;
+.container-2 {
+  background-color: var(--primary-color);
   height: 60rem;
-}
 
-.status {
-  position: absolute;
-  bottom: 0;
-  right: 0;
-  margin-top: 1rem;
-  font-weight: 600;
-  font-size: 0.7rem;
-  line-height: 15px;
-  width: 90%;
-  display: flex;
-  align-items: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  margin-bottom: 2rem;
-  color: #071b1f;
-}
-
-.structure {
-  position: absolute;
-  bottom: 0;
-  right: 0;
-  font-weight: 600;
-  font-size: 0.8rem;
-  width: 90%;
-  display: flex;
-  align-items: center;
-  color: #071b1f;
-  margin-bottom: 1rem;
-}
-.description-review {
-  text-align: justify !important;
-  height: 10rem;
-  font-size: 1rem;
-  line-height: 1.5rem;
-  color: #071b1f;
-  margin-left: 1rem;
-  margin-right: 1rem;
-  margin-bottom: 1rem;
-  line-height: 20px;
-}
-
-.container-color {
-  background: #f8f8f8;
-  height: 22rem;
-}
+  .col-review {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    .v-card {
+      padding-top: 1rem;
+      width: 21rem;
+      min-height: 21rem;
+      max-height: 21rem;
+      margin-bottom: 0.9rem;
+
+      .v-card-title {
+        margin-left: 1rem;
+        font-weight: 500;
+        font-size: 1.4rem;
+        color: var(--primary-color);
+      }
+
+      .v-card-text p {
+        text-align: justify !important;
+        height: 10rem;
+        font-size: 1rem;
+        color: var(--primary-color);
+        margin: 0 1rem 1rem 1rem;
+        line-height: 20px;
+      }
+
+      .card-footer {
+        display: flex;
+        flex-direction: column;
+        margin-top: 1rem;
+
+        small {
+          position: absolute;
+          display: flex;
+          align-items: center;
+          bottom: 0;
+          right: 0;
+          font-weight: 600;
+          width: 90%;
+          color: var(--primary-color);
+        }
+
+        .status {
+          margin-top: 1rem;
+          font-size: 0.7rem;
+          line-height: 15px;
+          letter-spacing: 0.18em;
+          text-transform: uppercase;
+          margin-bottom: 2rem;
+        }
+
+        .structure {
+          font-size: 0.8rem;
+          margin-bottom: 1rem;
+        }
+      }
+    }
+
+    .left {
+      bottom: 12rem;
+      position: relative;
+    }
+
+    .right {
+      position: relative;
+      bottom: 7rem;
+    }
+  }
 
-.container-color-md {
-}
-.review-card {
-  padding-top: 1rem;
-  width: 21rem;
-  min-height: 21rem;
-  max-height: 21rem;
-  margin-bottom: 0.9rem;
-}
-.review-name {
-  margin-left: 1rem;
-  font-weight: 500;
-  font-family: "Barlow";
-  font-style: normal;
-  font-size: 1.4rem;
-  color: #9edbdd;
+  .carousel-clients-container {
+    margin-top: -7rem;
+  }
 }
 
-.small-title {
-  font-size: 1rem;
-  line-height: 1rem;
-  margin-top: 1rem;
-  text-align: center;
-  letter-spacing: 2.16px;
-  text-transform: uppercase;
-  margin-bottom: 0.5rem;
-}
+.container-sm {
+  .v-card {
+    width: 300px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+  }
 
-.title-review {
-  font-size: 2rem;
-  line-height: 42px;
-  text-align: center;
-  color: #071b1f;
+  .carousel-controls {
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+
+    div {
+      width: 0.6rem;
+      height: 0.6rem;
+      border-radius: 50%;
+      background-color: var(--neutral-color-alt);
+      cursor: pointer;
+      margin-bottom: 0.5rem;
+    }
+
+    .active-control {
+      background-color: var(--on-neutral-color-alt);
+      margin-right: 10px;
+    }
+  }
 }
 </style>

+ 197 - 317
components/Home/Solution.vue

@@ -1,64 +1,73 @@
+<!--
+Section "Solutions" de la page d'accueil
+-->
+
 <template>
-  <LayoutContainer :overflow="false">
+  <LayoutContainer>
+
     <div class="d-flex justify-center align-center flex-column">
-      <v-icon size="8" class="fa-solid fa-circle icon-title" />
-      <p class="text-center solution-subtitle">3 solutions</p>
+      <v-icon
+        size="6"
+        icon="fas fa-circle"
+      />
+      <h5>
+        3 solutions
+      </h5>
     </div>
-    <h3
-      class="text-center title"
-      :style="smAndDown ? '' : 'margin-bottom: 3rem'"
-    >
+
+    <h3 class="text-center" >
       Trouvez la solution faites pour vous
     </h3>
 
-    <v-row class="row-custom">
+    <v-row class="solutions center-90">
       <v-col
         v-for="(solution, index) in solutions"
         :key="index"
         cols="4"
-        class="col-info"
       >
         <v-container>
           <div class="d-flex justify-center align-left flex-column">
-            <small class="opentalent-small">Opentalent</small>
-            <h2 class="logiciel-name">
+            <small>
+              Opentalent
+            </small>
+
+            <h2>
               {{ solution.name }}
             </h2>
-            <hr class="bar" />
-            <p class="description-logiciel">
+
+            <v-divider thickness="2"/>
+
+            <p>
               {{ solution.description }}
             </p>
 
             <nuxt-link :to="solution.link">
               <v-row>
-                <div :class="solution.class" class="image-container">
-                  <v-img :src="solution.image" class="logo" />
-                  <v-btn v-on:mouseover="mouseover" class="view-button"
-                    >Découvrir</v-btn
-                  >
+                <div :class="['image-container', solution.class]" >
+                  <v-img :src="solution.image" />
+                  <v-btn>Découvrir</v-btn>
                 </div>
               </v-row>
             </nuxt-link>
 
             <v-row>
-              <div class="list-container">
+              <div class="details">
                 <v-col cols="6">
-                  <ul class="list-solutions">
+                  <ul>
                     <li
                       v-for="(sol, i) in solution.solutions.slice(0, 4)"
-                      :key="'sol-' + i"
-                      class="details-solution"
+                      :key="i"
                     >
                       {{ sol }}
                     </li>
                   </ul>
                 </v-col>
+
                 <v-col cols="6">
-                  <ul class="list-solutions">
+                  <ul>
                     <li
                       v-for="(sol, i) in solution.solutions.slice(4)"
-                      :key="'sol-' + i"
-                      class="details-solution"
+                      :key="i"
                     >
                       {{ sol }}
                     </li>
@@ -70,32 +79,22 @@
         </v-container>
       </v-col>
     </v-row>
-    <v-container>
+
+    <v-container class="footer">
       <v-row >
         <v-col cols="12">
-          <p style="text-align: right; font-size: 12px;">* en option</p>
+          <p>* en option</p>
         </v-col>
       </v-row>
     </v-container>
   </LayoutContainer>
 </template>
 
-<script setup>
-import { ref, onMounted } from "vue";
-import "vue3-carousel/dist/carousel.css";
-import { useDisplay } from "vuetify";
-const { smAndDown } = useDisplay();
-
-const carousel = ref(null);
+<script setup lang="ts">
 
-const goPrevious = () => {
-  carousel.value.prev();
-};
+import type { SolutionItem } from "~/types/interface";
 
-const goNext = () => {
-  carousel.value.next();
-};
-const solutions = [
+const solutions: Array<SolutionItem> = [
   {
     name: "Artist",
     description: "Orchestres, chorales, compagnies de danse, théâtre et cirque",
@@ -148,300 +147,181 @@ const solutions = [
     ],
   },
 ];
-onMounted(() => {
-  setTimeout(() => goNext(), 0);
-});
 </script>
 
-<style scoped>
-.row-custom {
-  width: 90%;
-  margin-right: auto;
-  margin-left: auto;
-}
-
-.list-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-.image-container {
+<style scoped lang="scss">
+.container {
+  background: var(--primary-color);
+  margin-bottom: 15rem;
+  height: 36rem;
   position: relative;
 }
 
-.view-button {
-  position: absolute;
-  z-index: 100;
-  bottom: 40%;
-  left: 50%;
-  transform: translateX(-50%);
-  display: none;
-  font-size: 0.8rem;
-  border-radius: 6px;
-  background: var(--Vert-60, #64afb7);
-  color: white;
-}
-
-.image-container:hover .view-button {
-  display: block;
-
-}
-
-.solution-subtitle {
+h5 {
   font-size: 1rem;
   line-height: 1rem;
   margin-top: 1rem;
-  color: #c1eff0;
+  color: var(--secondary-color);
   text-align: center;
   letter-spacing: 2.16px;
   text-transform: uppercase;
 }
-.title {
+
+.fa-circle {
+  margin-top: 1rem;
+  color: var(--on-primary-color);
+  margin-right: 1rem;
+}
+
+h3 {
   margin-top: 0.5rem;
   font-size: 2.8rem;
   line-height: 42px;
   text-align: center;
-  color: #ffffff;
+  color: var(--on-primary-color);
   width: 100%;
 }
 
-.logo {
-  position: absolute;
-  bottom: 0;
-  right: 0;
-  width: 200px;
-}
-
-.artist-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-
-.artist-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-
-.manager-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 4rem;
-  height: 4rem;
-  background-color: transparent;
-  border: 2px solid #fff;
-  cursor: pointer;
-  margin-right: 1rem;
-  margin-top: 2rem;
-}
-
-.carousel-button i {
-  color: #fff;
-}
-.manager-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-
-.school-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-
-.school-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-
-.description-logiciel {
-  font-family: "Barlow";
-  font-style: normal;
-  font-size: 0.9rem;
-  line-height: 0.9rem;
-  margin-top: 1rem;
-  color: #eff9fb;
-  width: 20rem;
-}
-
-.icon-title {
-  margin-top: 1rem;
-  color: #ffffff;
-}
-
-.details-solution {
-  font-size: 0.8rem;
-  width: 10rem;
-  margin-left: 1rem;
-  font-family: "Barlow";
-  font-style: normal;
-  line-height: 18px;
-  color: #091d20;
-}
-.list-solutions {
-  margin-top: 0.9rem;
-  font-size: 0.5rem;
-}
-
-.bar {
-  color: #c3e5e7;
-  width: 20rem;
-}
-
-
-.artist-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-
-.artist-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-
-
-.manager-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-
-.manager-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-.artist-image {
-  position: relative;
-  background: url(/images/solutions/artist.jpg);
-  background-size: cover;
-  background-position: center;
-  border-radius: 0px 0px 10px 10px;
-  width: 21rem;
-  height: 300px;
-  margin-top: 2rem;
-  margin-left: 0.9rem;
-  margin-bottom: 1rem;
-}
-
-.school-image{
-  background: url(/images/solutions/school.jpg);
-
-}
-.manager-image {
-  position: relative;
-  background: url(/images/solutions/manager.png);
-  background-size: cover;
-  background-position: center;
-  border-radius: 0px 0px 10px 10px;
-  width: 21rem;
-  height: 300px;
-  margin-top: 2rem;
-  margin-left: 0.9rem;
-  margin-bottom: 1rem;
-
-}
-
-.school-image, .manager-image .artist-image {
-  position: relative;
-  background-size: cover;
-  background-position: center;
-  border-radius: 0px 0px 10px 10px;
-  width: 350px;
-  height: 300px;
-  margin-top: 2rem;
-  margin-left: 0.9rem;
-  margin-bottom: 1rem;
-
-}
-
-.school-image::before {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
-  border-radius: 0px 0px 10px 10px;
-  opacity: 0;
-  transition: opacity 0.3s;
-}
-
-.school-image:hover::before {
-  opacity: 1;
-  cursor: pointer;
-}
-
-.description-logiciel {
-  font-size: 1.3rem;
-  line-height: 1.5rem;
-  margin-top: 1rem;
-  color: #eff9fb;
-}
-
-.logiciel-name {
-  font-weight: 400;
-  font-size: 30px;
-  line-height: 2rem;
-  color: #c3e5e7;
-  margin-bottom: 1rem;
-}
-
-.opentalent-small {
-  font-weight: 600;
-  font-size: 10px;
-  line-height: 15px;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  color: #ffffff;
-}
-
-.container {
-  background: #0e2d32;
-  margin-bottom: 15rem;
-  height: 36rem;
-  position: relative;
+@media (min-width: 600px) {
+  h3 {
+    margin-bottom: 3rem
+  }
+}
+
+.v-row.solutions {
+
+  small {
+    font-weight: 600;
+    font-size: 10px;
+    line-height: 15px;
+    letter-spacing: 0.18em;
+    text-transform: uppercase;
+    color: var(--on-primary-color);
+  }
+
+  h2 {
+    font-weight: 400;
+    font-size: 30px;
+    line-height: 2rem;
+    color: var(--on-primary-color-alt);
+    margin-bottom: 1rem;
+  }
+
+  .v-divider {
+    color: var(--on-primary-color-alt);
+    width: 20rem;
+    opacity: 0.7;
+  }
+
+  p {
+    font-size: 1.3rem;
+    line-height: 1.5rem;
+    margin-top: 1rem;
+    color: var(--on-primary-color);
+    font-style: normal;
+    width: 20rem;
+  }
+
+  .image-container {
+    position: relative;
+    background-size: cover;
+    background-position: center;
+    border-radius: 0 0 10px 10px;
+    width: 350px;
+    height: 300px;
+    margin-top: 2rem;
+    margin-left: 0.9rem;
+    margin-bottom: 1rem;
+
+    .v-img {
+      position: absolute;
+      bottom: 0;
+      right: 0;
+      width: 200px;
+    }
+  }
+
+  .image-container::before {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5));
+    border-radius: 0 0 10px 10px;
+    opacity: 0;
+    transition: opacity 0.3s;
+  }
+
+  .v-btn {
+    position: absolute;
+    z-index: 100;
+    bottom: 40%;
+    left: 50%;
+    transform: translateX(-50%);
+    display: none;
+    font-size: 0.8rem;
+    border-radius: 6px;
+    background: var(--secondary-color);
+    color: var(--on-primary-color);
+  }
+
+  .image-container:hover .v-btn {
+    display: block;
+  }
+
+  .artist-image {
+    background: url(/images/solutions/artist.jpg);
+  }
+
+  .artist-image:hover::before {
+    opacity: 1;
+    cursor: pointer;
+  }
+
+  .school-image{
+    background: url(/images/solutions/school.jpg);
+  }
+
+  .school-image:hover::before {
+    opacity: 1;
+    cursor: pointer;
+  }
+
+  .manager-image {
+    background: url(/images/solutions/manager.png);
+  }
+
+  .manager-image:hover::before {
+    opacity: 1;
+    cursor: pointer;
+  }
+
+  .details {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    ul {
+      margin-top: 0.9rem;
+      font-size: 0.5rem;
+    }
+
+    li {
+      font-size: 0.8rem;
+      width: 10rem;
+      margin-left: 1rem;
+      line-height: 18px;
+      color: var(--primary-color);
+    }
+  }
+}
+
+.footer {
+  p {
+    text-align: right;
+    font-size: 12px;
+  }
 }
 </style>

+ 0 - 56
components/JoinUs/Banner.vue

@@ -1,56 +0,0 @@
-<template>
-  <LayoutContainer>
-    <LayoutUITitlePage title="Nous rejoindre ?" />
-
-    <v-row>
-      <v-col cols="12">
-        <CommonBanner
-          :imageSrc="'/images/join/join.jpg'"
-          imageAlt="'line'"
-        />
-      </v-col>
-    </v-row>
-
-
-    <h3 class="text-center join-title bold mt-6">
-      Opentalent, où l'innovation & la passion se rencontre !
-    </h3>
-    <h4 class="text-center join-title">
-      Découvrez nos opportunités et rejoignez-nous dans cette aventure
-      passionnante.
-    </h4>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-
-:deep().cover-image {
-  object-position: center 50% !important;
-}
-:deep().text-left,
-:deep().text-right,
-:deep().description-square,
-:deep().black-square,
-:deep().blue-square {
-  display: none;
-}
-:deep().text-right {
-  display: none;
-}
-
-.bold {
-  font-weight: 600 !important;
-}
-.join-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.5rem;
-  line-height: 2.5rem;
-  text-align: center;
-}
-
-
-</style>

+ 185 - 0
components/JoinUs/MissionDetail.vue

@@ -0,0 +1,185 @@
+<template>
+  <LayoutContainer>
+    <div class="job-section">
+      <v-row class="mb-6">
+        <v-col class="d-flex align-items-center">
+          <v-btn
+            to="/nous-rejoindre"
+            prepend-icon="fas fa-arrow-left"
+            variant="outlined"
+            class="back-button"
+          >
+            Retour aux annonces
+          </v-btn>
+        </v-col>
+      </v-row>
+
+      <div>
+        <div v-if="pending">
+          <v-row class="justify-center progress">
+            <v-progress-circular
+              indeterminate
+              color="grey"
+            />
+          </v-row>
+        </div>
+
+        <div v-else-if="job !== null">
+          <LayoutUITitlePage>
+            {{ job.title }}
+          </LayoutUITitlePage>
+
+          <v-row class="details blue-content my-6">
+            <v-col cols="6">
+              <v-row>
+                <div>
+                  Type de contrat :
+                  <b>{{ job.contractType }} </b>
+                </div>
+              </v-row>
+
+              <v-row>
+                <div>
+                  Location :
+                  <b>{{ job.postalCode }} {{ job.city }}</b>
+                </div>
+              </v-row>
+            </v-col>
+
+            <v-col cols="6">
+              <v-row>
+                <div>
+                  Secteur d'activité : <b>{{ job.sector.join(', ') }}</b>
+                </div>
+              </v-row>
+
+              <v-row>
+                <div>
+                  Date de parution :
+                  <b>{{ formatDate(job.startPublication) }}</b>
+                </div>
+              </v-row>
+            </v-col>
+          </v-row>
+
+          <v-row>
+            <p
+              v-html="job.content"
+              class="center-90 description mb-12"
+            />
+          </v-row>
+
+          <v-row class="d-flex justify-center align-center">
+            <v-btn
+              prepend-icon="fas fa-info"
+              class="btn-apply mb-12"
+            >
+              Je postule
+            </v-btn>
+          </v-row>
+
+          <v-row class="d-flex justify-space-between center-90">
+            <p>
+              MOTS CLÉS
+            </p>
+            <div>
+              <p>PARTAGER</p>
+            </div>
+          </v-row>
+
+          <v-row class="d-flex justify-space-between mb-8 center-90">
+            <p class="key-word mt-3">
+              <!-- TODO: remplacer par la bonne prop -->
+              ROCK CONCERT FESTIVAL
+            </p>
+
+            <CommonShare />
+          </v-row>
+        </div>
+      </div>
+    </div>
+
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+import "vue3-carousel/dist/carousel.css";
+import { useEntityFetch } from "~/composables/data/useEntityFetch";
+import JobPosting from "~/models/Maestro/JobPosting";
+import DateUtils from "~/services/utils/dateUtils";
+
+const route = useRoute();
+const { fetch } = useEntityFetch()
+const config = useRuntimeConfig()
+
+const jobId: number = parseInt(route.params.id as string)
+if (!jobId || isNaN(jobId)) {
+  throw new Error('Missing or invalid id')
+}
+
+const { data: job, pending } = fetch(JobPosting, jobId)
+
+const formatDate = (date: string) => {
+  return DateUtils.format(new Date(date), "dd/MM/yyyy")
+};
+</script>
+
+<style scoped lang="scss">
+.progress {
+  margin: 32px auto 128px auto;
+}
+
+.job-section {
+  margin: 32px 12%;
+
+  .details {
+    background-color: var(--secondary-color);
+    color: var(--on-secondary-color);
+    height: 10rem;
+
+    .v-row {
+      width: 90%;
+      margin-left: auto;
+      margin-right: auto;
+    }
+
+    div {
+      margin: 12px 0;
+      font-weight: 500;
+      font-size: 25px;
+      line-height: 18px;
+    }
+  }
+
+  .description {
+    color: var(--primary-color);
+    text-align: justify;
+    font-size: 1.875rem;
+    font-weight: 500;
+    line-height: 2.125rem;
+  }
+}
+
+@media (max-width: 600px) {
+  .job-section {
+    margin: 32px 6%;
+  }
+}
+
+.btn-apply {
+  background: var(--secondary-color);
+  color: var(--neutral-color);
+  display: flex;
+  left: 0;
+  padding: 25px 28px;
+  align-items: center;
+  gap: 9px;
+  font-size: 0.9rem;
+  border-radius: 5px;
+  font-weight: 700;
+  line-height: 15px;
+  letter-spacing: 1.3px;
+  text-transform: uppercase;
+  margin-bottom: -1rem;
+}
+</style>

+ 214 - 140
components/JoinUs/Missions.vue

@@ -1,42 +1,62 @@
 <template>
   <LayoutContainer>
-    <div v-for="(job, index) in jobs" :key="index" class="mission-container">
-      <!-- Première ligne avec alignement vertical -->
-      <v-row class="announcement-title ml-6 mr-6 d-flex align-center">
+    <div v-if="pending">
+      <v-row class="justify-center progress">
+        <v-progress-circular
+          indeterminate
+          color="grey"
+        />
+      </v-row>
+    </div>
+
+    <div
+      v-else
+      v-for="(job, index) in jobs"
+      :key="index"
+      class="mission-container"
+    >
+      <v-row class="title-container">
         <NuxtLink
           :to="`/nous-rejoindre/${job.id}`"
-          class="text-decoration-none"
+          class="title"
         >
-          <div class="title-job ml-4">
-            <!-- Icône étoile pour les annonces 'featured' -->
-            {{ job.title }} - {{ job.contractType }}
-            <v-icon
-              v-if="job.featured"
-              class="fas fa-star"
-              style="color: yellow"
-            ></v-icon>
-          </div>
+          {{ job.title }} - {{ job.contractType }}
+
+          <v-icon
+            v-if="job.featured"
+            class="star fas fa-star"
+          />
         </NuxtLink>
-        <NuxtLink
+
+        <v-btn
           :to="`/nous-rejoindre/${job.id}`"
-          class="text-decoration-none d-flex align-center"
+          class="btn-more"
         >
-          <v-icon class="mr-2"> </v-icon>
-          <v-btn class="btn-more mr-4" text> En savoir plus </v-btn>
-        </NuxtLink>
+          En savoir plus
+        </v-btn>
       </v-row>
 
-      <v-row class="announcement-location ml-6 mr-6">
-        <v-icon class="icon-location">
-          <i class="fas fa-map-marker"></i>
-        </v-icon>
+      <v-row class="location-container">
+        <v-icon icon="fas fa-map-marker" />
         <div class="location">
           {{ job.city }}
         </div>
       </v-row>
     </div>
 
-    <v-row class="apply-row ml-6 mb-6">
+    <v-row>
+      <v-col cols="12">
+        <LayoutPagination
+          v-if="jobCollection && jobCollection.pagination"
+          :model-value="page"
+          :pagination="jobCollection.pagination"
+          @update:model-value="onPageUpdated"
+          class="mt-4"
+        />
+      </v-col>
+    </v-row>
+
+    <v-row class="ml-6 mb-6">
       <v-col cols="12">
         <p class="apply-now">
           Nous sommes toujours à la recherche de nouveaux talents. N'hésitez pas
@@ -44,40 +64,81 @@
         </p>
       </v-col>
     </v-row>
+
     <v-row>
       <v-col cols="12">
-        <v-btn class="btn-send" @click="dialog = true">
+        <v-btn
+          class="btn-send"
+          @click="dialog = true"
+        >
           Envoyer ma candidature
         </v-btn>
       </v-col>
     </v-row>
 
-    <v-dialog v-model="dialog" max-width="600px">
+    <!-- Boite de dialogue "soumettre une candidature" -->
+    <v-dialog
+      v-model="dialog"
+      max-width="600px"
+    >
       <v-card>
-        <v-card-title class="text-center" style="font-family: Barlow">
+        <v-card-title
+          class="text-center"
+        >
           Formulaire de Candidature
         </v-card-title>
+
         <v-card-text>
           <v-form>
-            <v-text-field label="Nom*" required></v-text-field>
-            <v-text-field label="Prénom*" required></v-text-field>
-            <v-text-field label="Téléphone*" required></v-text-field>
-            <v-text-field label="Email*" required></v-text-field>
+            <v-text-field
+              label="Nom*"
+              required
+            />
+
+            <v-text-field
+              label="Prénom*"
+              required
+            />
+
+            <v-text-field
+              label="Téléphone*"
+              required
+            />
+
+            <v-text-field
+              label="Email*"
+              required
+            />
+
             <v-file-input
               label="Dépôt de CV*"
               accept=".pdf, .jpeg, .png"
               required
-            ></v-file-input>
+            />
+
             <v-file-input
               label="Dépôt de lettre de motivation"
               accept=".pdf, .jpeg, .png"
-            ></v-file-input>
-            <v-textarea label="Message*" required></v-textarea>
+            />
+
+            <v-textarea
+              label="Message*"
+              required
+            />
           </v-form>
         </v-card-text>
-        <p class="text-right mr-6">* Champs obligatoires</p>
-        <v-card-actions>
-          <v-btn class="btn-more" @click="sendApplication">Envoyer</v-btn>
+
+        <p class="text-right mr-6">
+          * Champs obligatoires
+        </p>
+
+        <v-card-actions class="justify-center">
+          <v-btn
+            class="btn-more mb-4"
+            @click="sendApplication"
+          >
+            Envoyer
+          </v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -85,106 +146,135 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from "vue";
-import { useMaestroRequestService } from "~/composables/useMaestroRequestService";
-const { apiRequestService } = useMaestroRequestService();
+import { useEntityFetch } from "~/composables/data/useEntityFetch";
+import JobPosting from "~/models/Maestro/JobPosting";
+import type { AnyJson } from "~/types/data";
 
-const dialog = ref(false);
+const i18n = useI18n();
+const router = useRouter()
+const { fetchCollection } = useEntityFetch()
 
-const sendApplication = () => {
-  console.log("Formulaire envoyé");
-  dialog.value = false;
-};
+const page: Ref<number> = ref(1);
 
-const query = computed(() => {
-  const queryParams: {
-    page: number;
-    type?: string;
-    [key: string]: number | string;
-  } = {
-    page: page.value,
-    type: "ENTREPRISE",
-  };
+const query: ComputedRef<AnyJson> = computed(() => {
+    return { type: "ENTREPRISE", page: page.value }
+  }
+)
 
-  return queryParams;
-});
+const { data: jobCollection, pending, refresh } = fetchCollection(
+  JobPosting,
+  null,
+  query
+)
 
-const totalItems = ref(0);
-const config = useRuntimeConfig();
-const baseUrl = `${config.public.apiBaseUrl}/api/job-postings`;
+// TODO: voir pourquoi on se retrouve obligé de passer par ce computed pour avoir le type TS correct?
+const jobs: ComputedRef<JobPosting[]> = computed(() => {
+  return jobCollection.value !== null ?
+         jobCollection.value.items as JobPosting[] :
+         []
+})
 
-const page: Ref<number> = ref(1);
-const itemsPerPage: Ref<number> = ref(10);
-const { t } = useI18n();
-
-const {
-  data: jobs = [],
-  pending,
-  refresh,
-} = useLazyAsyncData("files", async () => {
-  const response = await apiRequestService.get(baseUrl, query.value);
-  const collection = response["hydra:member"];
-  const currentDate = new Date();
-
-  // Séparer les annonces 'featured'
-  const featuredJobs = collection.filter(
-    (item) => item.featured && new Date(item.startPublication) <= currentDate
-  );
-
-  // Filtrer et trier les autres annonces
-  const regularJobs = collection.filter((item) => {
-    const startPublicationDate = new Date(item.startPublication);
-    const endPublicationDate = new Date(item.endPublication);
-    return (
-      !item.featured &&
-      startPublicationDate <= currentDate &&
-      endPublicationDate >= currentDate
-    );
-  });
-
-  // Combinez les annonces 'featured' et les autres annonces
-  const combinedJobs = [...featuredJobs, ...regularJobs];
-
-  totalItems.value = combinedJobs.length;
-  console.log(combinedJobs);
-  return combinedJobs;
-});
-</script>
+const onPageUpdated = async (newVal: number): Promise<void> => {
+  page.value = newVal
 
-<style scoped>
-<style scoped>
-.location {
-  font-size: 1.3rem !important;
-  color: #0e2d32;
-}
-.announcement-title {
-  background: #0e2d32;
-  color: white;
-  display: flex;
-  justify-content: space-between;
-  height: 80px;
-  padding: 10px 10px 10px 1;
+  pending.value = true
+  await refresh()
+
+  // TODO: remplacer par un watcher sur pending?
+  setTimeout(
+    async () => await navigateTo({ path: '', hash: '#join-us-anchor' }),
+    200
+  )
 }
 
-.title-job {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 1.5rem;
-  line-height: 39px;
-  color: #ffffff;
+/**
+ * Faut-il afficher la boite de dialogue de candidature
+ */
+const dialog = ref(false);
+
+/**
+ * Soumet le formulaire de candidature (boite de dialogue)
+ */
+const sendApplication = () => {
+  // TODO: implémenter le submit
+  dialog.value = false;
+};
+</script>
+
+<style scoped lang="scss">
+.progress {
+  margin: 32px auto 128px auto;
 }
 
-.btn-more,
-.btn-send {
+.v-btn {
   font-weight: 600;
   height: 50px;
-  background: #64afb7;
+  background: var(--secondary-color);
   border-radius: 6px;
-  color: white;
+  color: var(--on-secondary-color);
   gap: 9px;
 }
 
+.mission-container {
+  margin: 64px 12%;
+
+  .title-container {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: var(--primary-color);
+    color: var(--on-primary-color);
+    height: 80px;
+    padding: 10px 10px 10px 1px;
+
+    .title {
+      font-weight: 600;
+      font-size: 1.5rem;
+      line-height: 39px;
+      color: var(--on-primary-color);
+      text-decoration: none;
+      margin-left: 36px;
+    }
+
+    .star {
+      margin-left: 12px;
+      font-size: 24px;
+      color: yellow;
+      vertical-align: baseline;
+    }
+
+    .btn-more {
+      margin-right: 8px;
+      display: flex;
+      align-items: center;
+    }
+  }
+
+  .location-container {
+    background: var(--secondary-color);
+    display: flex;
+    align-items: center;
+    padding: 10px;
+
+    .v-icon {
+      font-size: 1rem !important;
+      color: var(--primary-color);
+    }
+
+    .location {
+      color: var(--primary-color);
+      margin-left: 10px;
+      font-size: 1.3rem;
+    }
+  }
+}
+
+@media (max-width: 600px) {
+  .mission-container {
+    margin: 64px 6%;
+  }
+}
+
 .btn-send {
   display: flex;
   justify-content: center;
@@ -195,35 +285,19 @@ const {
   font-weight: 700;
 }
 
-.announcement-location {
-  background: #9edbdd;
-  display: flex;
-  align-items: center;
-  padding: 10px;
-}
-
-.icon-location {
-  font-size: 1rem !important;
-  color: #0e2d32;
-}
-
-.location {
-  margin-left: 10px;
-  font-size: 2rem;
-}
-
 .apply-now {
   text-align: center;
   font-style: italic;
   font-weight: 300;
   font-size: 34px;
   line-height: 40px;
-  color: #091d20;
+  color: var(--primary-color);
   margin-bottom: 2rem;
 }
 
-.mission-container {
-  margin-top: 3rem;
-  margin-bottom: 5%;
+.v-dialog {
+  .btn-more {
+    width: 128px;
+  }
 }
 </style>

+ 67 - 0
components/Layout/AnchoredSection.vue

@@ -0,0 +1,67 @@
+<template>
+  <!--suppress VueUnrecognizedDirective -->
+  <div
+    :id="id"
+    ref="section"
+    v-intersect="onIntersect"
+  >
+    <slot/>
+  </div>
+
+</template>
+
+<script setup lang="ts">
+  import { useLayoutStore } from "~/stores/layoutStore";
+
+  const layoutStore = useLayoutStore()
+
+  const props = defineProps({
+    id: {
+      type: String,
+      required: true
+    }
+  })
+
+  if (!props.id) {
+    throw new Error("Anchor's id is missing")
+  }
+
+  const section: Ref<HTMLElement | null> = ref(null)
+
+  layoutStore.setIsAnchoredSectionOnScreen(props.id, false)
+
+  const onIntersect = (e: boolean) => {
+    layoutStore.setIsAnchoredSectionOnScreen(props.id, e)
+  }
+
+  // TODO: supprimer si pas nécessaire, je conserve au cas où il faudrait un
+  //       fonctionnement plus fin qu'un simple intersect
+  // const top: Ref<number | null> = ref(null)
+  // const bottom: Ref<number | null> = ref(null)
+  //
+  // onMounted(() => {
+  //   top.value = section.value!.offsetTop
+  //   bottom.value = section.value!.offsetTop + section.value!.offsetHeight
+  // })
+  //
+  // const onScroll = (e: any) => {
+  //   if (top.value === null || bottom.value === null) {
+  //     return
+  //   }
+  //
+  //   const scroll: number = e.target.scrollingElement.scrollTop
+  //
+  //   const active = scroll > top.value && scroll < bottom.value
+  //
+  //   if (active !== layoutStore.isAnchoredSectionOnScreen[props.id]) {
+  //     layoutStore.setIsAnchoredSectionOnScreen(
+  //       props.id,
+  //       active
+  //     )
+  //   }
+  // }
+</script>
+
+<style scoped>
+
+</style>

+ 77 - 0
components/Layout/Captcha.vue

@@ -0,0 +1,77 @@
+<template>
+  <vue-hcaptcha
+    :sitekey="runtimeConfig.hCaptchaSiteKey"
+    @verify="onVerify"
+    @expired="onExpire"
+    @challenge-expired="onChallengeExpire"
+    @error="onError"
+  />
+  <v-checkbox
+    v-model="honeyPotChecked"
+    :rules="[validateCaptchaState]"
+    class="hidden-ctrl"
+  />
+</template>
+
+<script setup lang="ts">
+import VueHcaptcha from "@hcaptcha/vue3-hcaptcha";
+
+const runtimeConfig = useRuntimeConfig()
+
+const verified: Ref<boolean> = ref(false);
+const expired: Ref<boolean> = ref(false);
+const token: Ref<string> = ref("");
+const eKey: Ref<string> = ref("");
+const error: Ref<string> = ref("");
+
+// La case étant masquée, si elle est cochée, alors on peut en déduire
+// qu'on a affaire un robot (voir mécanisme du honey pot)
+const honeyPotChecked: Ref<boolean> = ref(false)
+
+const emit = defineEmits(['update'])
+
+const validateCaptchaState = () =>
+  verified.value && !honeyPotChecked.value ||
+  "Veuillez procédez à la vérification";
+
+function onVerify(tokenStr: string, ekey: string) {
+  verified.value = true;
+  token.value = tokenStr;
+  eKey.value = ekey;
+  emit('update', true)
+}
+
+function onExpire() {
+  verified.value = false;
+  token.value = '';
+  eKey.value = '';
+  expired.value = true;
+}
+
+function onChallengeExpire() {
+  verified.value = false;
+  token.value = '';
+  eKey.value = '';
+  expired.value = true;
+}
+
+function onError(err: string) {
+  token.value = '';
+  eKey.value = '';
+  error.value = err;
+  console.log(`Error: ${err}`);
+
+  if (process.dev) {
+    console.log('Dev mode: force captcha validation')
+    verified.value = true;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.hidden-ctrl {
+  :deep(.v-input__control) {
+    display: none;
+  }
+}
+</style>

+ 2 - 17
components/Layout/Container.vue

@@ -1,33 +1,18 @@
 <template>
   <v-container class="container">
     <v-row justify="center" align="center">
-      <v-col cols="12" sm="12" md="12">
+      <v-col cols="12">
         <slot />
       </v-col>
     </v-row>
   </v-container>
 </template>
 
-<script setup>
-import { ref } from "vue";
-
-const props = defineProps({
-  overflow: {
-    type: Boolean,
-    default: true,
-  },
-});
-
-const overflow = ref(props.overflow);
-</script>
-
-<style scoped>
+<style scoped lang="scss">
 .container {
   position: relative;
   max-width: 100%;
-  min-width: 100; 
   padding-left: 0 !important;
   padding-right: 0 !important;
 }
-
 </style>

+ 113 - 146
components/Layout/FAQ.vue

@@ -1,183 +1,150 @@
 <template>
-  <div id="Aide">
-    <LayoutContainer>
-      <div class="container-img">
-        <div class="overlay" />
-        <v-row class="mt-12">
-          <v-col cols="6">
-            <div class="container-left">
-              <LayoutUISubTitle
-                class="mt-12 ml-3"
-                title-color="#fff"
-                :iconSize="6"
-                :iconClasses="iconClasses"
-                :titleText="' Vous voulez tirer le meilleur de notre logiciel ?  '"
-              />
-              <h3 class="title-faq mt-6">
-                Quelle que soit votre demande, notre équipe est à vos côtés pour
-                vous guider
-              </h3>
-              <nuxt-link to="https://ressources.opentalent.fr/" target="_blank">
-                <v-btn class="btn-faq"> Consulter notre FAQ </v-btn></nuxt-link
-              >
-            </div>
-          </v-col>
+  <div class="alt-theme main my-2">
+    <div class="d-flex flex-row">
+      <div class="d-flex flex-column">
+        <LayoutUISubTitle class="mt-12 ml-3">
+          Vous voulez tirer le meilleur de notre logiciel ?
+        </LayoutUISubTitle>
 
-          <v-col cols="6">
-            <div class="btn-container">
-              <nuxt-link to="https://ressources.opentalent.fr/pages/viewpage.action?pageId=75170564" target="_blank">
-                <v-btn class="btn-faq-tuto">
-                  <div class="container-button">
-                    <v-img src="/images/icons/tuto.svg" class="icon-button" />
-                    <p class="text-btn">
-                      De nombreux articles tutoriels accessibles 24h/24
-                    </p>
-                  </div>
-                </v-btn>
-              </nuxt-link>
+        <h3 class="mt-6">
+          Quelle que soit votre demande, notre équipe est à vos côtés pour
+          vous guider
+        </h3>
 
-              <nuxt-link
-                to="https://ressources.opentalent.fr/?contact"
-                target="_blank"
-              >
-                <v-btn class="btn-faq-tuto">
-                  <div class="container-button">
-                    <v-img src="/images/icons/faq.svg" class="icon-button" />
-                    <p class="text-btn">
-                      Support accessible du lundi au vendredi via l’outil en
-                      ligne
-                    </p>
-                  </div>
-                </v-btn>
-              </nuxt-link>
-            </div>
-          </v-col>
-        </v-row>
+        <v-btn
+          to="https://ressources.opentalent.fr/"
+          target="_blank"
+          class="btn-faq inv-theme"
+        >
+          Consulter notre FAQ
+        </v-btn>
       </div>
-    </LayoutContainer>
+
+      <div class="d-flex flex-column justify-center links">
+        <v-btn
+          to="https://ressources.opentalent.fr/pages/viewpage.action?pageId=75170564"
+          target="_blank"
+        >
+          <div>
+            <v-img
+              src="/images/icons/tuto.svg"
+            />
+
+            <p>
+              De nombreux articles tutoriels accessibles 24h/24
+            </p>
+          </div>
+        </v-btn>
+
+        <v-btn
+          to="https://ressources.opentalent.fr/?contact"
+          target="_blank"
+        >
+          <div>
+            <v-img
+              src="/images/icons/faq.svg"
+            />
+
+            <p class="text-btn">
+              Support accessible du lundi au vendredi via l’outil en
+              ligne
+            </p>
+          </div>
+        </v-btn>
+      </div>
+    </div>
   </div>
 </template>
 
-<script setup></script>
-
-<style scoped>
-.v-container {
-  padding: 0 !important;
-}
-:deep().subtitle {
-  width: 10rem !important;
-}
-.container-left {
-  margin-left: 6rem;
+<style scoped lang="scss">
+.flex-row {
+  position: relative;
+  z-index: 2;
 }
 
-.text-btn {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 26px;
-  color: #f0e8e4;
-  white-space: normal !important;
-  text-align: left;
-}
-.btn-container {
+.main {
+  min-height: 600px;
+  background-image: url("/images/logiciels/school/faq.jpg");
+  background-size: cover;
+  background-position: center 15%;
+  background-repeat: no-repeat;
+  height: 100%;
   display: flex;
   flex-direction: column;
+  justify-content: center;
   align-items: center;
-  margin-top: 5rem;
-}
-
-.container-button {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  width: 20rem;
-  height: 3.5rem;
+  position: relative;
 }
 
-.icon-button {
-  color: #fff;
-  margin-right: 0.7rem;
-  margin-left: 1rem;
+.main::after {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.6);
   z-index: 1;
-  width: 30px;
 }
-.btn-faq-tuto {
-  z-index: 1;
 
-  width: 23rem;
-  height: 5.5rem;
+h3 {
   margin-left: 3rem;
-  border-radius: 6px;
-  font-family: "Barlow";
-  background: transparent;
-  color: #fff;
-  font-style: normal;
-  font-weight: 500;
-  font-size: 0.8rem;
-  line-height: 1rem;
-  border: 1px white solid;
-  margin-bottom: 2rem;
-  text-transform: none !important;
+  margin-right: 15rem;
+  width: 28rem;
+  margin-bottom: 3rem;
+  font-size: 30px;
+  font-weight: 400;
 }
 
 .btn-faq {
   width: 14rem;
   height: 3.5rem;
   margin-left: 3rem;
-  background: #ffffff;
   border-radius: 6px;
-  font-family: "Barlow";
-  font-style: normal;
   font-weight: 500;
   font-size: 0.8rem;
   z-index: 1;
-
   text-transform: none !important;
   line-height: 1rem;
 }
-.title-faq {
-  color: #fff;
-  font-family: "Barlow";
-  margin-left: 3rem;
-  margin-right: 15rem;
-  width: 28rem;
-  margin-bottom: 3rem;
 
-  color: var(--NEUTRAL---BLANC, #fff);
+.links {
+  .v-btn {
+    z-index: 1;
+    width: 23rem;
+    height: 5.5rem;
+    margin-left: 3rem;
+    border-radius: 6px;
+    background: transparent;
+    font-weight: 500;
+    font-size: 0.8rem;
+    line-height: 1rem;
+    border: 1px var(--on-alt-theme) solid;
+    margin-bottom: 2rem;
+    text-transform: none !important;
 
-  font-size: 30px;
-  font-style: normal;
-  font-weight: 400;
-}
-
-.container-img {
-  background-image: url("/images/logiciels/school/faq.jpg");
-  background-size: cover;
-  background-position: center 15%;
-  background-repeat: no-repeat;
-  height: 37rem;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  position: relative;
-}
+    .v-btn__content>div {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+    }
 
-.container-img::after {
-  content: "";
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  background: rgba(0, 0, 0, 0.6);
-  z-index: 1;
-}
+    .v-img {
+      color: var(--on-alt-theme);
+      margin-right: 0.7rem;
+      margin-left: 1rem;
+      z-index: 1;
+      width: 30px;
+    }
 
-.v-row {
-  position: relative;
-  z-index: 2;
+    p {
+      font-weight: 500;
+      font-size: 16px;
+      line-height: 26px;
+      color: var(--on-alt-theme);
+      white-space: normal !important;
+      text-align: left;
+    }
+  }
 }
 </style>

+ 216 - 283
components/Layout/Footer/Footer.vue

@@ -1,209 +1,227 @@
 <template>
-  <footer ref="footerElement">
+  <!--suppress VueUnrecognizedDirective -->
+  <footer v-intersect="onIntersect">
     <LayoutContainer>
-      <div >
+      <div>
         <v-row>
-          <v-col
-            :cols="mdAndDown ? 12 : 3"
-            :class="mdAndDown ? 'logo-container' : 'flex-container'"
-          >
+          <!-- Première section : Logo Opentalent -->
+          <v-col cols="12" lg="3" class="logo">
             <nuxt-link to="/">
-              <v-img
-                :class="mdAndDown ? 'logo-md' : 'logo'"
-                src="/images/logo/footer-logo.png"
-              />
+              <v-img src="/images/logo/footer-logo.png" />
             </nuxt-link>
           </v-col>
 
-          <v-col cols=" 2" v-if="!mdAndDown">
-            <v-row class="title-link">
-              <h5 class="ml-12 mt-10 h5-title">Agenda culturel</h5>
+          <!-- Deuxième section : liens agenda culturel (écrans larges seulement) -->
+          <v-col v-if="mdAndUp" cols="2" >
+            <v-row>
+              <h5>
+                Agenda culturel
+              </h5>
             </v-row>
             <v-row>
-              <router-link to="/annuaire" class="small-link ml-12"
-                >Annuaire</router-link
-              >
+              <nuxt-link to="/annuaire">
+                Annuaire
+              </nuxt-link>
             </v-row>
             <v-row>
-              <router-link to="/actualites" class="small-link ml-12"
-                >Actualités</router-link
-              >
+              <nuxt-link to="/actualites">
+                Actualités
+              </nuxt-link>
             </v-row>
             <v-row>
-              <router-link to="/annonces" class="small-link ml-12"
-                >Annonces</router-link
-              >
+              <nuxt-link to="/annonces">
+                Annonces
+              </nuxt-link>
             </v-row>
           </v-col>
 
-          <v-col cols="2" v-if="!mdAndDown">
-            <v-row class="title-link">
-              <h5 class="ml-12 mt-10 h5-title">Logiciels culturels</h5>
+          <!-- Troisième section : liens logiciels culturels (écrans larges seulement) -->
+          <v-col v-if="mdAndUp" cols="2">
+            <v-row>
+              <h5>
+                Logiciels culturels
+              </h5>
             </v-row>
             <v-row>
-              <router-link to="/opentalent_artist" class="small-link ml-12"
-                >Opentalent Artist</router-link
-              >
+              <nuxt-link to="/opentalent_artist">
+                Opentalent Artist
+              </nuxt-link>
             </v-row>
             <v-row>
-              <router-link to="/opentalent_school" class="small-link ml-12"
-                >Opentalent School</router-link
+              <nuxt-link to="/opentalent_school">
+                Opentalent School
+              </nuxt-link
               >
             </v-row>
             <v-row>
-              <router-link to="/opentalent_manager" class="small-link ml-12"
-                >Opentalent Manager</router-link
-              >
+              <nuxt-link to="/opentalent_manager">
+                Opentalent Manager
+              </nuxt-link>
             </v-row>
           </v-col>
 
-          <v-col cols="2" v-if="!mdAndDown">
-            <v-row class="title-link">
-              <h5 class="ml-12 mt-8 h5-title">Espace client</h5>
+          <!-- Quatrième section : liens espace client (écrans larges seulement) -->
+          <v-col v-if="mdAndUp" cols="2">
+            <v-row>
+              <h5>
+                Espace client
+              </h5>
             </v-row>
             <v-row>
-              <NuxtLink
-                to="https://ressources.opentalent.fr/display/FAQ/Accueil"
-                class="small-link ml-12"
-                >Foire Aux Questions</NuxtLink
-              >
+              <nuxt-link href="https://ressources.opentalent.fr/display/FAQ/Accueil">
+                Foire Aux Questions
+              </nuxt-link>
             </v-row>
             <v-row>
-              <NuxtLink
-                to="https://ressources.opentalent.fr/"
-                class="small-link ml-12"
-                target="_blank"
-                >Support en ligne</NuxtLink
-              >
+              <nuxt-link href="https://ressources.opentalent.fr/" target="_blank">
+                Support en ligne
+              </nuxt-link>
             </v-row>
             <v-row>
-              <NuxtLink
-                to="/nous-contacter"
-                class="small-link ml-12"
-                target="_blank"
-                >Nous contacter</NuxtLink
-              >
+              <nuxt-link to="/nous-contacter" target="_blank" >
+                Nous contacter
+              </nuxt-link>
             </v-row>
           </v-col>
 
-          <v-col cols="3" v-if="!mdAndDown">
-            <v-row class="title-link">
-              <h5 class="ml-12 mt-10 h5-title">Suivez-nous</h5>
+          <!-- Cinquième section : liens réseaux sociaux (écrans larges seulement) -->
+          <v-col v-if="mdAndUp" cols="3">
+            <v-row>
+              <h5>
+                Suivez-nous
+              </h5>
             </v-row>
 
-            <v-row class="ml-5" no-gutters>
+            <v-row class="social-networks">
               <v-col cols="2">
-                <a
+                <nuxt-link
                   href="https://www.facebook.com/opentalent"
                   target="_blank"
-                  class="fab fa-facebook brand"
+                  class="fab fa-facebook"
                 />
               </v-col>
               <v-col cols="2">
-                <a
+                <nuxt-link
                   href="https://twitter.com/Opentalent_FRA"
                   target="_blank"
-                  class="fa-brands fa-square-twitter brand"
+                  class="fa-brands fa-square-twitter"
                 />
               </v-col>
               <v-col cols="2">
-                <a
+                <nuxt-link
                   href="https://www.linkedin.com/company/2iopenservice"
                   target="_blank"
-                  class="fab fa-linkedin brand"
+                  class="fab fa-linkedin"
                 />
               </v-col>
 
               <v-col cols="2">
-                <a
+                <nuxt-link
                   href="https://www.youtube.com/@Opentalent74300"
                   target="_blank"
-                  class="fab fa-youtube brand"
+                  class="fab fa-youtube"
                 />
               </v-col>
             </v-row>
           </v-col>
         </v-row>
 
-        <v-row class="justify-center" v-if="mdAndDown">
+        <!-- Deuxième section alt : version petits écrans -->
+        <v-row
+          v-if="mdAndDown"
+          class="justify-center social-networks"
+        >
+          <!-- TODO: voir si faisable de fusionner avec la section précédente -->
           <v-col cols="12" class="text-center">
-            <a
+            <nuxt-link
               href="https://www.facebook.com/opentalent"
               target="_blank"
-              class="fab fa-facebook brand-md"
+              class="fab fa-facebook"
             />
-            <a
+            <nuxt-link
               href="https://twitter.com/Opentalent_FRA"
               target="_blank"
-              class="fa-brands fa-square-twitter brand-md"
+              class="fa-brands fa-square-twitter"
             />
-            <a
+            <nuxt-link
               href="https://www.linkedin.com/company/2iopenservice"
               target="_blank"
-              class="fab fa-linkedin brand-md"
+              class="fab fa-linkedin"
             />
-            <a
+            <nuxt-link
               href="https://www.youtube.com/@Opentalent74300"
               target="_blank"
-              class="fab fa-youtube brand-md"
+              class="fab fa-youtube"
             />
           </v-col>
         </v-row>
       </div>
+
+      <!-- Troisième section alt : version petits écrans -->
       <v-row v-if="mdAndDown">
         <v-col cols="12" >
           <div v-for="(item, index) in footerLinks" :key="index">
             <v-container>
-              <div  class="link-md d-flex justify-space-between align-left" @click="toggle(index)">
-              {{ item.label }}
-              <v-icon>
-                {{
-                  isActive(index) ? "fas fa-chevron-up" : "fas fa-chevron-down"
-                }}
-              </v-icon>
-            </div>
-              <div class="answer" v-if="isActive(index)">
-              <div
-                v-for="(sublink, sublinkIndex) in item.sublink"
-                :key="sublinkIndex"
-                class="mt-3"
-              >
-                <NuxtLink class="small-link-sm" :to="sublink.link">{{ sublink.label }}</NuxtLink>
+              <div class="section" @click="toggleSection(index)">
+                <div class="d-flex flex-row justify-space-between">
+                  {{ item.label }}
+
+                  <v-icon
+                    :icon="isActive(index) ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"
+                  />
+                </div>
+
+                <div
+                  v-show="isActive(index)"
+                  v-for="(sublink, sublinkIndex) in item.sublink"
+                  :key="sublinkIndex"
+                  class="mt-3"
+                >
+                  <nuxt-link :to="sublink.link">
+                    {{ sublink.label }}
+                  </nuxt-link>
+                </div>
               </div>
-            </div>
             </v-container>
-  
+
           </div>
         </v-col>
       </v-row>
-      <v-row :class="mdAndDown ? '' : 'footer'" justify="center">
-        <p class="mt-6">
-          <a class="mention" href="/mentions-legales" target="_blank"
-            >Mentions légales</a
-          >
-          -
-          <a class="mention" href="/politiques-de-cookies" target="_blank"
-            >Politiques de cookies</a
-          >
-          -
-          <a class="mention" href="/CGV" target="_blank"
-            >Conditions Générales de Ventes</a
-          >
-        </p>
-      </v-row>
 
-      <v-row justify="center" class="mb-6">
-        <p class="mention">2024 &copy; Tous droits réservés par Opentalent</p>
-      </v-row>
+      <div class="footnotes">
+        <v-row justify="center">
+          <p class="mt-6">
+            <a href="/mentions-legales" target="_blank">
+              Mentions légales
+            </a>
+            -
+            <a href="/politiques-de-cookies" target="_blank">
+              Politiques de cookies
+            </a>
+            -
+            <a href="/CGV" target="_blank">
+              Conditions Générales de Ventes
+            </a>
+          </p>
+        </v-row>
+
+        <v-row class="mb-6" justify="center">
+          <p>
+            2024 &copy; Tous droits réservés par Opentalent
+          </p>
+        </v-row>
+      </div>
     </LayoutContainer>
   </footer>
 </template>
 
 <script setup>
 import { useDisplay } from "vuetify";
-import { ref, provide } from "vue";
+import { useLayoutStore } from "~/stores/layoutStore";
+
+
+const { mdAndDown, mdAndUp } = useDisplay();
 
-const footerElement = ref(null);
 const footerLinks = ref([
   {
     label: "AGENDA CULTUREL",
@@ -274,213 +292,128 @@ const footerLinks = ref([
     ],
   },
 ]);
-const activeIndex = ref(-1);
 
-function toggle(index) {
+const activeIndex = ref(-1);
+function toggleSection(index) {
   activeIndex.value = activeIndex.value === index ? -1 : index;
 }
 
 function isActive(index) {
   return activeIndex.value === index;
 }
-provide("footerElement", footerElement);
-const { mdAndDown } = useDisplay();
-</script>
-
-<style scoped>
-
 
-.jusitfy-center {
-  justify-content: center;
-}
-.logo-md {
-  width: 18rem;
-}
-.logo-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
+const layoutStore = useLayoutStore()
+const onIntersect = (isIntersecting) => {
+  layoutStore.setIsFooterVisible(isIntersecting)
 }
 
-.mention {
-  text-decoration: none;
-  color: #ffffff;
-  font-size: 0.8rem;
-}
+</script>
 
-.brand {
-  color: #ecfbfc;
-  font-size: 1.9rem;
-  text-decoration: none !important;
-}
+<style scoped lang="scss">
 
-.brand-md {
-  color: #ecfbfc;
-  font-size: 3rem;
-  text-decoration: none !important;
-  margin: 0 1rem;
-}
-/* .flex-container {
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
-} */
-
-.vertical-bar {
-  height: 4rem;
-  border: 0.1rem solid #ecfbfc;
-  margin-left: 10px;
-  margin-top: 3rem;
+.container {
+  background: var(--primary-color);
+  color: var(--on-primary-color);
 }
 
-.right-reserved {
-  color: rgba(255, 255, 255, 0.6);
-  font-family: Space Grotesk;
-  font-size: 0.6rem;
-  letter-spacing: 1px;
-}
-.h5-title {
-  font-size: 1.1rem;
-  font-style: normal;
-  letter-spacing: 1.2px;
-  text-transform: uppercase;
+.logo .v-img {
+  margin-bottom: 3rem;
+  width: 25rem;
 }
-.link-md {
-  display: flex;
-  flex-direction: row;
-  text-align: left;
-  text-transform: uppercase;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 700;
-  font-size: 1.5rem;
-  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
 
-  
+.v-col {
+  padding: 12px;
 }
 
-.logo-opentalent-md {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-}
-.icon:nth-child(2) {
-  margin-left: 10px;
+.container {
+  padding-top: 32px;
 }
-.title-link,
-.title-link-sm {
-  font-family: "Barlow";
-  font-style: normal;
+
+h5 {
   font-weight: 500;
-  font-size: 1rem;
   line-height: 20px;
+  margin-top: 20px;
   margin-bottom: 1rem;
+  font-size: 1.1rem;
+  letter-spacing: 1.2px;
+  text-transform: uppercase;
 }
 
-.title-link-sm {
-  margin-bottom: 0.1rem;
-}
-.small-link-sm {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.3rem;
-  line-height: 20px;
-  color: #ffffff;
-  text-decoration: none !important;
-  text-align: left;
-}
-.small-link {
-  font-family: "Barlow";
-  font-style: normal;
+a {
   font-weight: 300;
   font-size: 0.9rem;
   line-height: 20px;
-  color: #ffffff;
+  color: var(--on-primary-color);
   text-decoration: none !important;
   margin-bottom: 0.5rem;
 }
-.container {
-  background: #091d20;
-  color: aliceblue;
-}
 
-.activities {
-  height: 12rem;
-  background: #091d20;
-  border-bottom: 0.4px solid rgba(255, 255, 255, 0.3);
-  box-shadow: 0px 3px 24px rgba(0, 0, 0, 0.07);
+.social-networks {
+  a {
+    color: var(--on-primary-color);
+    font-size: 1.9rem;
+    text-decoration: none !important;
+  }
 }
 
-.footer {
+.footnotes {
   margin-top: 2rem;
-  border-top: 0.4px solid rgba(255, 255, 255, 0.3);
-  box-shadow: 0px 3px 24px rgba(0, 0, 0, 0.07);
+  border-top: 0.4px solid var(--neutral-color-alt-strong);
+  box-shadow: 0 3px 24px rgba(0, 0, 0, 0.07);
+
+  a, p {
+    text-decoration: none;
+    color: var(--on-primary-color);
+    font-size: 0.8rem;
+  }
 }
 
-.logo {
-  margin-bottom: 3rem;
-  width: 25rem;
-}
-
-.logo-jaune {
-  margin-left: 307.74px;
-}
-
-.logo-rouge {
-  margin-left: 117px;
-}
-
-.logo-bleu {
-  margin-left: 91.74px;
-}
-
-.text-logo-jaune {
-  margin-left: 10rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 18px;
-  display: flex;
-  align-items: center;
-
-  color: #ecfbfc;
-
-  text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25),
-    0px 4px 4px rgba(0, 0, 0, 0.25);
-}
-
-.text-logo-rouge {
-  margin-left: 37.74px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 18px;
-  display: flex;
-  align-items: center;
-
-  color: #ecfbfc;
-
-  text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25),
-    0px 4px 4px rgba(0, 0, 0, 0.25);
-}
-
-.text-logo-bleu {
-  height: 24px;
-  left: 897px;
-  top: 7858px;
-  margin-left: 25.74px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 18px;
-  display: flex;
-  align-items: center;
-  color: #ecfbfc;
-  text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25),
-    0px 4px 4px rgba(0, 0, 0, 0.25);
+@media (max-width: 960px) {
+  .logo {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 140px;
+  }
+
+  .logo .v-img {
+    width: 18rem;
+  }
+
+  .social-networks {
+    a {
+      font-size: 3rem;
+      margin: 0 1rem;
+    }
+  }
+
+  .section {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    text-align: left;
+    font-weight: 700;
+    font-size: 1.5rem;
+    cursor: pointer;
+
+    >div:first-child {
+      border-bottom: 1px solid var(--on-secondary-color);
+      padding-bottom: 6px;
+      text-transform: uppercase;
+    }
+
+    a {
+      font-weight: 300;
+      font-size: 1.3rem;
+      line-height: 20px;
+      color: var(--on-primary-color);
+      text-decoration: none !important;
+      text-align: left;
+    }
+  }
+
+  .footnotes {
+    border: none;
+  }
 }
 </style>

+ 49 - 66
components/Layout/Footer/Prefooter.vue

@@ -1,87 +1,70 @@
+<!--
+Première section du footer (galerie des logiciels)
+-->
+
 <template>
-  <footer ref="footerElement">
+  <footer>
     <LayoutContainer>
-      <div v-if="lgAndUp" class="activities">
-        <v-row class="custom-row">
-          <v-col cols="4" class="text-center">
-            <a href="/opentalent_artist">
-              <v-img
-                class="logo logo-jaune"
-                src="/images/logo/logiciels/Artist-noir.png"
-              />
-            </a>
-            <small class="text-logo"
-              >Orchestres, chorales, danse, théâtre, cirque</small
-            >
-          </v-col>
+      <v-row>
+
+        <v-col cols="4" class="text-center">
+          <nuxt-link href="/opentalent_artist">
+            <v-img src="/images/logo/logiciels/Artist-noir.png"/>
+          </nuxt-link>
+
+          <small class="text-logo">
+            Orchestres, chorales, danse, théâtre, cirque
+          </small>
+        </v-col>
+
+        <v-divider :vertical="true" />
+
+        <v-col cols="4" class="text-center">
+          <nuxt-link href="/opentalent_school">
+            <v-img src="/images/logo/logiciels/School-noir.png"/>
+          </nuxt-link>
 
-          <div class="vertical-bar" />
-          <v-col cols="4" class="text-center">
-            <a href="/opentalent_school">
-              <v-img
-                class="logo logo-bleu"
-                src="/images/logo/logiciels/School-noir.png"
-              />
-            </a>
-            <small class="text-logo"
-              >Tous les établissements d'enseignement artistique</small
-            >
-          </v-col>
+          <small class="text-logo">
+            Tous les établissements d'enseignement artistique
+          </small>
+        </v-col>
 
-          <div class="vertical-bar" />
+        <v-divider :vertical="true" />
 
-          <v-col cols="3" class="text-center">
-            <a href="/opentalent_manager">
-              <v-img
-                class="logo logo-rouge"
-                src="/images/logo/logiciels/Manager-noir.png"
-              />
-            </a>
-            <small class="text-logo"
-              >Fédérations, confédérations, collectivités</small
-            >
-          </v-col>
-        </v-row>
-      </div>
+        <v-col cols="3" class="text-center">
+          <nuxt-link href="/opentalent_manager">
+            <v-img src="/images/logo/logiciels/Manager-noir.png"/>
+          </nuxt-link>
+
+          <small class="text-logo">
+            Fédérations, confédérations, collectivités
+          </small>
+        </v-col>
+      </v-row>
     </LayoutContainer>
   </footer>
 </template>
 
 <script setup>
-import { useDisplay } from "vuetify";
-import { ref, provide } from "vue";
-
-const footerElement = ref(null);
-
-provide("footerElement", footerElement);
-const { smAndDown, lgAndUp } = useDisplay();
 </script>
 
-<style scoped>
-.custom-row {
+<style scoped lang="scss">
+.container {
+  height: 172px;
   width: 90%;
-  margin-left: auto;
-  margin-right: auto;
+  margin: 0 auto;
+  border-bottom: 0.4px solid rgba(255, 255, 255, 0.3);
 }
-.flex-container {
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
+
+.v-img {
+  margin-top: 2rem;
+  height: 70px;
 }
 
-.vertical-bar {
+.v-divider {
   height: 4rem;
   border: 0.1rem solid rgb(205, 205, 205);
   margin-top: 3rem;
-}
-
-.activities {
-  height: 10rem;
-  border-bottom: 0.4px solid rgba(255, 255, 255, 0.3);
-}
-
-.logo {
-  margin-top: 2rem;
-  height: 70px;
+  opacity: 80%;
 }
 </style>

+ 41 - 53
components/Layout/Footer/SolutionsFooter.vue → components/Layout/Footer/Solutions.vue

@@ -4,22 +4,21 @@
       <v-row>
         <v-col cols="12">
           <h4 class="solution-title text-center">
-            Ces solutions peuvent vous intéresser
+            Ces solutions peuvent aussi vous intéresser
           </h4>
         </v-col>
       </v-row>
 
-      <v-row v-if="!hideArtistRow" class="row-artist">
+      <v-row
+        v-if="showArtist"
+        class="row-artist"
+      >
         <v-col cols="2">
           <NuxtLink to="/opentalent_artist">
             <v-img src="/images/logo/logiciels/Artist-noir.png" class="logo" />
           </NuxtLink>
         </v-col>
 
-        <!-- <v-col cols="2">
-          <h5 class="solution-name">Opentalent Artist</h5>
-        </v-col> -->
-
         <v-col cols="10">
           <!-- list v-chip-->
           <v-chip-group active-class="primary--text" column>
@@ -42,17 +41,16 @@
         </v-col>
       </v-row>
 
-      <v-row v-if="!hideManagerRow" class="row-manager">
+      <v-row
+        v-if="showManager"
+        class="row-manager"
+      >
         <v-col cols="2">
           <NuxtLink to="/opentalent_manager">
           <v-img src="/images/logo/logiciels/Manager-noir.png" class="logo" />
         </NuxtLink>
         </v-col>
 
-        <!-- <v-col cols="2">
-          <h5 class="solution-name">Opentalent Manager</h5>
-        </v-col> -->
-
         <v-col cols="10">
           <!-- list v-chip-->
           <v-chip-group active-class="primary--text" column>
@@ -72,17 +70,16 @@
         </v-col>
       </v-row>
 
-      <v-row v-if="!hideSchoolRow" class="row-school">
+      <v-row
+        v-if="showSchool"
+        class="row-school"
+      >
         <v-col cols="2">
           <NuxtLink to="/opentalent_school">
-          <v-img src="/images/logo/logiciels/School-noir.png" class="logo" />
-        </NuxtLink>
+            <v-img src="/images/logo/logiciels/School-noir.png" class="logo" />
+          </NuxtLink>
         </v-col>
 
-        <!-- <v-col cols="2">
-          <h5 class="solution-name">Opentalent Artist</h5>
-        </v-col> -->
-
         <v-col cols="10">
           <!-- list v-chip-->
           <v-chip-group active-class="primary--text" column>
@@ -114,68 +111,59 @@
   </div>
 </template>
 
-<script setup>
-import { useRoute } from "vue-router";
-
-const route = useRoute();
-
-const hideManagerRow = route.path.includes("opentalent_manager");
-const hideArtistRow = route.path.includes("opentalent_artist") || route.path.includes("formations");
-const hideSchoolRow = route.path.includes("opentalent_school") ;
+<script setup lang="ts">
+const props = defineProps({
+  showArtist: {
+    type: Boolean,
+    required: false,
+    default: true
+  },
+  showSchool: {
+    type: Boolean,
+    required: false,
+    default: true
+  },
+  showManager: {
+    type: Boolean,
+    required: false,
+    default: true
+  },
+})
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .chip-detail {
-  color: #000000;
+  color: var(--on-neutral-color);
 }
+
 .chip-custom {
-  color: white;
-  border: 1px solid #0e2d32;
+  color: var(--on-primary-color);
+  border: 1px solid var(--primary-color);
   border-radius: 3rem;
   text-transform: uppercase;
-
-  font-family: "Barlow";
-  font-style: normal;
   font-weight: 500;
   font-size: 10px;
   line-height: 16px;
-
   display: flex;
   align-items: center;
   text-align: center;
   letter-spacing: 0.2em;
 }
 
-.row-artist,
-.row-school,
-.row-manager {
-  border-top: 1px solid #d1cdc7;
-
-}
-
-.solution-name {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.5rem;
-  line-height: 1.5rem;
-  color: #0e2d32;
-}
-
 .row-artist,
 .row-school,
 .row-manager {
   display: flex;
   flex-direction: row;
   align-items: center;
+  border-top: 1px solid var(--on-primary-color-alt);
 }
+
 .solution-title {
-  font-family: "Barlow";
-  font-style: normal;
   font-weight: 500;
   font-size: 1.5rem;
   line-height: 1.5rem;
-  color: #000000;
+  color: var(--on-neutral-color);
   margin-top: 2rem;
   margin-bottom: 2rem;
   text-align: center;

+ 194 - 259
components/Layout/Navigation.vue

@@ -1,100 +1,65 @@
+<!--
+Menu Navigation
+-->
 <template>
-  <div class="container-grey" v-if="!mdAndDown">
-    <v-row>
-      <v-col cols="12" class="buttons-col">
-        <nuxt-link
-          to="https://admin.opentalent.fr/#/login/"
-          style="text-decoration: none"
-        >
-          <v-btn class="btn btn-common btn-login" text>
-            <v-icon left class="fas fa-user mr-4"></v-icon> Se connecter<br />aux
-            logiciels
-          </v-btn>
+
+  <!-- Navigation (écran large) -->
+  <div v-if="mdAndUp">
+    <LayoutNavigationTopbar />
+
+    <v-row class="navigation-lg" style="margin-top: 0 !important;">
+      <!-- Logo Opentalent -->
+      <v-col cols="3">
+        <nuxt-link to="/">
+          <v-img class="logo" src="/images/logo/navigation-logo.png" />
         </nuxt-link>
+      </v-col>
+
+      <!-- Menu principal -->
+      <v-col cols="9">
+        <v-menu
+          v-for="item in menu"
+          :key="item.label"
+          open-on-hover
+        >
+          <template v-slot:activator="{ props }">
+            <nuxt-link
+              v-bind="props"
+              class="menuItem first-level"
+              :to="item.to"
+            >
+              {{ item.label }}
+            </nuxt-link>
+          </template>
 
-        <div class="vertical-bar" />
-        <NuxtLink to="/agenda-culturel" style="text-decoration: none">
-          <v-btn class="btn btn-common btn-subscribe ml-4 mr-2" text>
-            <v-icon left class="fas fa-calendar mr-4"></v-icon>Agenda Culturel
-          </v-btn>
-        </NuxtLink>
+          <v-list
+            v-if="item.children?.length > 0"
+            class="menu-list"
+          >
+            <v-list-item
+              v-for="child in item.children"
+              :key="child.label"
+              :to="child.to"
+              class="menuItem"
+            >
+              <v-list-item-title>{{ child.label }}</v-list-item-title>
+            </v-list-item>
+          </v-list>
+        </v-menu>
       </v-col>
     </v-row>
   </div>
-  <v-row class="menu" v-if="!mdAndDown">
-    <v-col cols="3">
-      <nuxt-link to="/">
-        <v-img class="logo" src="/images/logo/navigation-logo.png" />
-      </nuxt-link>
-    </v-col>
-
-    <v-col cols="9">
-      <v-menu open-on-hover>
-        <template v-slot:activator="{ props }">
-          <nuxt-link v-bind="props" class="link-style"
-            >Nos logiciels
-          </nuxt-link>
-        </template>
-
-        <v-list class="menu-list">
-          <nuxt-link
-            v-for="software in softwareLinks"
-            :key="software.name"
-            :to="software.href"
-            class="link-styles"
-          >
-            <v-list-item>
-              <v-list-item-title>{{ software.name }}</v-list-item-title>
-            </v-list-item>
-          </nuxt-link>
-        </v-list>
-      </v-menu>
-
-      <v-menu open-on-hover>
-        <template v-slot:activator="{ props }">
-          <nuxt-link v-bind="props" class="link-style">Nos services </nuxt-link>
-        </template>
-
-        <v-list>
-          <nuxt-link
-            v-for="service in serviceLinks"
-            :key="service.name"
-            :to="service.href"
-            class="link-styles"
-          >
-            <v-list-item>
-              <v-list-item-title>{{ service.name }}</v-list-item-title>
-            </v-list-item>
-          </nuxt-link>
-        </v-list>
-      </v-menu>
-
-      <v-menu open-on-hover>
-        <template v-slot:activator="{ props }">
-          <nuxt-link v-bind="props" class="link-style">à propos</nuxt-link>
-        </template>
-
-        <v-list>
-          <nuxt-link
-            v-for="info in aboutLinks"
-            :key="info.name"
-            :to="info.href"
-            class="link-styles"
-          >
-            <v-list-item>
-              <v-list-item-title>{{ info.name }}</v-list-item-title>
-            </v-list-item>
-          </nuxt-link>
-        </v-list>
-      </v-menu>
-
-      <nuxt-link class="link-style" to="/actualites">Actualités</nuxt-link>
-      <nuxt-link class="link-style" to="/nous-contacter">Contact</nuxt-link>
-    </v-col>
-  </v-row>
-  <v-app v-if="mdAndDown" class="navigation-sm">
+
+  <!-- Navigation (petit écran) -->
+  <v-app
+    v-else
+    class="navigation-sm"
+  >
+    <!-- Top bar -->
     <v-app-bar app>
-      <v-app-bar-nav-icon @click="toggleDrawer"></v-app-bar-nav-icon>
+      <v-app-bar-nav-icon
+        @click="toggleMenu"
+      />
 
       <nuxt-link to="/">
         <v-img class="logo-md" src="/images/logo/navigation-logo.png" />
@@ -121,214 +86,184 @@
     </v-app-bar>
 
     <!-- Tiroir de navigation principal -->
-    <v-navigation-drawer v-model="drawer" app>
+    <v-navigation-drawer
+      v-model="isMenuOpen"
+      app
+      temporary
+    >
       <v-list nav dense>
         <v-list-item
-          v-for="(item, index) in menuItems"
-          :key="item.id"
-          @click="selectMenu(item.id)"
+          v-if="isSubMenu"
+          class="menuItem back-item"
+          @click="onBackItemClick"
         >
           <v-list-item-title>
-            {{ item.label }}
+            <v-icon icon="fas fa-caret-left" class="mr-1"/> Retour
           </v-list-item-title>
         </v-list-item>
-      </v-list>
-    </v-navigation-drawer>
 
-    <!-- Tiroir de sous-menu -->
-    <v-navigation-drawer v-model="subMenuDrawer" app right temporary>
-      <v-list nav dense>
-        <v-list-item>
-          <v-list-item-title @click="closeSubMenu">Retour</v-list-item-title>
-        </v-list-item>
-        <nuxt-link
-          v-for="(subItem, subIndex) in subMenus[currentMenu]"
-          :key="subIndex"
-          :to="subItem.href"
-          style="text-decoration: none !important; color: black"
+        <v-list-item
+          v-for="(item, index) in activeMenu"
+          :key="item.label"
+          :to="item.to"
+          class="menuItem"
+          @click="onMenuItemClick(index, item)"
         >
-          <v-list-item>
-            <v-list-item-title>{{ subItem.name }}</v-list-item-title>
-          </v-list-item>
-        </nuxt-link>
+          <v-list-item-title>
+            {{ item.label }}
+          </v-list-item-title>
+        </v-list-item>
       </v-list>
     </v-navigation-drawer>
   </v-app>
 </template>
 
-<script setup>
+<script setup lang="ts">
 import { useDisplay } from "vuetify";
-const { mdAndDown } = useDisplay();
-
-const softwareLinks = ref([
-  { name: "Opentalent Artist", href: "/opentalent_artist" },
-  { name: "Opentalent School", href: "/opentalent_school" },
-  { name: "Opentalent Manager", href: "/opentalent_manager" },
-]);
-
-const serviceLinks = ref([
-  { name: "Formations", href: "/formations" },
-  { name: "Webinaires", href: "/webinaires" },
-]);
-
-const aboutLinks = ref([
-  { name: "Qui sommes-nous", href: "/qui-sommes-nous" },
-  { name: "Nous rejoindre", href: "/nous-rejoindre" },
-]);
-
-const drawer = ref(false);
-const subMenuDrawer = ref(false);
-const currentMenu = ref("");
-const menuItems = ref([
-  { id: "logiciels", label: "Nos logiciels" },
-  { id: "services", label: "Nos services" },
-  { id: "about", label: "À propos" },
-  { id: "actualites", label: "Actualités" },
-  { id: "contact", label: "Contact" },
-]);
-
-const subMenus = ref({
-  logiciels: [
-    { name: "Opentalent Artist", href: "/opentalent_artist" },
-    { name: "Opentalent School", href: "/opentalent_school" },
-    { name: "Opentalent Manager", href: "/opentalent_manager" },
-  ],
-  services: [
-    { name: "Formations", href: "/formations" },
-    { name: "Webinaires", href: "/webinaires" },
-  ],
-  propos: [
-    { name: "Qui sommes-nous", href: "/qui-sommes-nous" },
-    { name: "Nous rejoindre", href: "/nous-rejoindre" },
-  ],
-});
-
-const toggleDrawer = () => {
-  drawer.value = !drawer.value;
-};
+import type { MainMenuItem } from "~/types/interface";
+const { mdAndUp } = useDisplay();
 
-const selectMenu = (id) => {
-  if (subMenus.value[id]) {
-    currentMenu.value = id;
-    subMenuDrawer.value = true;
-    drawer.value = false;
-  } else {
-    switch (id) {
-      case "actualites":
-        window.location.href = "/actualites";
-        break;
-      case "contact":
-        window.location.href = "/nous-contacter";
-        break;
-    }
-  }
-};
+const menu: Array<MainMenuItem> = [
+  {
+    label: "Nos logiciels",
+    children: [
+      { label: "Opentalent Artist", to: "/opentalent_artist" },
+      { label: "Opentalent School", to: "/opentalent_school" },
+      { label: "Opentalent Manager", to: "/opentalent_manager" },
+    ]
+  },
+  {
+    label: "Nos services",
+    children: [
+      { label: "Formations", to: "/formations" },
+      { label: "Webinaires", to: "/webinaires" },
+    ]
+  },
+  {
+    label: "À propos",
+    children: [
+      { label: "Qui sommes-nous", to: "/qui-sommes-nous" },
+      { label: "Nous rejoindre", to: "/nous-rejoindre" },
+    ]
+  },
+  { label: "Actualités", to: "/actualites" },
+  { label: "Contact", to: "/nous-contacter" },
+]
 
-const closeSubMenu = () => {
-  subMenuDrawer.value = false;
-  drawer.value = true;
+// Menu dépliant (petit écran)
+const isMenuOpen: Ref<boolean> = ref(false);
+const toggleMenu = () => {
+  isMenuOpen.value = !isMenuOpen.value;
 };
-</script>
 
-<style scoped>
-.navigation-sm {
-  background-color: #ffffff;
-  position: fixed;
-  top: 0;
-}
-/* =============== CONTAINER BUTTON =============== */
-.container-grey {
-  background-color: #dbdbdb;
-}
-/* =============== Button Styles =============== */
+const activeMenuIndex: Ref<number | null> = ref(null)
 
-.buttons-col {
-  display: flex;
-  align-items: center;
-  justify-content: flex-end;
+const activeMenu = computed(() =>
+  activeMenuIndex.value !== null ? menu[activeMenuIndex.value].children : menu
+)
+
+/**
+ * Determines if the is active menu is a sub-menu .
+ *
+ * @function isSubMenu
+ * @returns {boolean} - True if a sub-menu is active, otherwise false.
+ */
+const isSubMenu = computed(() => activeMenuIndex.value !== null)
+
+/**
+ * Handles the click event on a menu item.
+ *
+ * @param {number} index - The index of the clicked menu item.
+ * @param {MainMenuItem} item - The clicked menu item.
+ * @returns {void}
+ */
+const onMenuItemClick = (index: number, item: MainMenuItem): void => {
+  if (!item.children) {
+    return
+  }
+  withAnimation(() => activeMenuIndex.value = index)
 }
 
-.btn-common {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  border-radius: 6px;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 700;
-  font-size: 0.7rem;
+/**
+ * Function to handle back button click event.
+ */
+const onBackItemClick = (): void => {
+  withAnimation(() => activeMenuIndex.value = null)
 }
 
-.btn-login {
-  background: #091d20;
-  color: white;
+/**
+ * Déclenche une animation de changement de menu en fermant et rouvrant le drawer
+ * @param callback
+ */
+const withAnimation = (callback: () => void) => {
+  isMenuOpen.value = false
+  callback()
+  setTimeout(() => {isMenuOpen.value = true}, 85)
 }
-.vertical-bar {
-  width: 0px;
-  height: 3rem;
-  border: 0.5px solid rgba(14, 45, 50, 0.4);
-  margin-left: 10px;
-  margin-top: 0.2rem;
+
+</script>
+
+<style scoped>
+
+.logo {
+  height: 8rem;
 }
 
-.btn-subscribe {
-  background: #9edbdd;
+.logo-md {
+  width: 150px;
+  height: 300px;
 }
-/* =============== menu Styles =============== */
 
-.menu {
-  display: flex;
-  align-items: center;
-  background-color: #ffffff;
+.icon {
+  color: var(--on-neutral-color);
 }
-.v-list-item-title {
-  font-family: "Barlow";
-  font-style: normal;
+
+.menuItem, .menuItem .v-list-item-title {
   font-weight: 500;
   font-size: 0.9rem;
   letter-spacing: 0.1em;
   text-transform: uppercase;
-  color: #0e2d32;
-}
-.common-styles {
-  font-family: "Barlow";
-  font-style: normal;
-  font-size: 1.1rem;
-  padding: 0.1rem;
-  font-weight: 700;
-  letter-spacing: 0.1em;
-  text-transform: uppercase;
-  color: #0e2d32;
-  text-decoration: none !important;
-}
-.link-style {
-  font-family: "Barlow";
-  font-style: normal;
-  font-size: 1rem;
-  margin-right: 3rem;
-  font-weight: 700;
-  letter-spacing: 0.05em;
-  text-transform: uppercase;
-  color: #0e2d32;
-  text-decoration: none !important;
+  color: var(--primary-color);
   cursor: pointer;
-}
-.link-styles {
-  font-family: "Barlow";
-  font-style: normal;
   text-decoration: none !important;
-  color: #0e2d32;
 }
-.logo {
-  height: 8rem;
+
+/**
+  Navigation grands écrans
+ */
+.navigation-lg {
+  display: flex;
+  align-items: center;
+  background-color: var(--neutral-color);
+
+  .menuItem  {
+    padding: 18px;
+  }
+
+  .menuItem.first-level {
+    font-size: 1rem;
+    margin-right: 1rem;
+    font-weight: 700;
+    letter-spacing: 0.05em;
+  }
 }
 
-.logo-md {
-  width: 150px;
-  height: 300px;
+/**
+  Navigation petits écrans
+ */
+.navigation-sm {
+  background-color: var(--neutral-color);
+  position: fixed;
+  top: 0;
 }
 
-.icon {
-  color: #000000;
+.back-item {
+  border-bottom: solid 1px var(--on-neutral-color-light);
+  border-radius: 0;
+
+  .v-list-item-title {
+    display: flex;
+    align-items: center;
+  }
 }
 </style>

+ 63 - 0
components/Layout/Navigation/Topbar.vue

@@ -0,0 +1,63 @@
+<template>
+  <div class="top-bar" >
+      <v-btn
+        href="https://admin.opentalent.fr/#/login/"
+        prepend-icon="fas fa-user"
+        class="btn-login"
+      >
+        Se connecter<br />aux logiciels
+      </v-btn>
+
+      <v-btn
+        to="/agenda-culturel"
+        prepend-icon="fas fa-calendar"
+        class="btn-agenda"
+      >
+          Agenda Culturel
+      </v-btn>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useDisplay } from "vuetify";
+
+const { mdAndDown } = useDisplay();
+</script>
+
+<style scoped lang="scss">
+.top-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  height: 54px;
+  background-color: var(--neutral-color-alt);
+  font-weight: 700;
+  font-size: 0.7rem;
+
+  .v-btn {
+    margin: 4px 8px;
+    border-radius: 6px;
+    height: 44px;
+  }
+}
+
+.btn-login {
+  background: var(--primary-color);
+  color: var(--on-primary-color);
+}
+
+.btn-agenda {
+  background: var(--secondary-color);
+}
+
+/**
+.vertical-bar {
+  width: 0px;
+  height: 3rem;
+  border: 0.5px solid rgba(14, 45, 50, 0.4);
+  margin-left: 10px;
+  margin-top: 0.2rem;
+}
+*/
+</style>

+ 35 - 0
components/Layout/Pagination.vue

@@ -0,0 +1,35 @@
+<template>
+  <v-pagination
+    v-if="pagination.last"
+    :model-value="modelValue"
+    :length="pagination.last"
+    rounded="circle"
+    @update:model-value="onPageUpdated"
+  />
+</template>
+
+<script setup lang="ts">
+import { defineProps, defineEmits, ComputedRef } from "vue";
+import { PropType } from "@vue/runtime-core";
+import { Pagination } from "~/types/data";
+
+const props = defineProps({
+  modelValue: {
+    type: Number,
+    required: true
+  },
+  pagination: {
+    type: Object as PropType<Pagination>,
+    required: true
+  }
+});
+
+const emit = defineEmits(['update:modelValue']);
+
+const onPageUpdated = (newPage: number) => {
+  emit('update:modelValue', newPage);
+};
+</script>
+
+<style scoped lang="scss">
+</style>

+ 23 - 52
components/Layout/UI/SubTitle.vue

@@ -1,75 +1,42 @@
+<!--
+Titre H4 précédé d'une puce
+-->
 <template>
   <LayoutContainer>
-    <div class="title-container">
+    <div class="container">
       <v-icon
+        :icon="icon"
         :size="iconSize"
-        :style="{ color: iconColor }"
-        :class="iconClasses"
       />
-      <h4 class="presentation-title" :style="{ color: titleColor }">
-        {{ titleText }}
-      </h4>
+      <h2>
+        <slot />
+      </h2>
     </div>
   </LayoutContainer>
 </template>
 
-<script setup>
+<script setup lang="ts">
 const router = useRouter();
 
-const iconColor = ref("#2093BE4D");
-
-const updateIconColor = computed(() => {
-  const path = router.currentRoute.value.path;
-
-  if (/^\/opentalent_school\/?$/.test(path)) {
-    return "#2093BE4D";
-  } else if (/^\/opentalent_artist\/?$/.test(path)) {
-    return "#FAC20A";
-  } else if (/^\/opentalent_manager\/?$/.test(path)) {
-    return "#D8050B";
-  } else {
-    return "#9edbdd";
-  }
-});
-
-watch(
-  () => router.currentRoute.value,
-  () => {
-    iconColor.value = updateIconColor.value;
-  },
-  { immediate: true }
-);
-
 const props = defineProps({
+  icon: {
+    type: String,
+    default: "fas fa-circle",
+  },
   iconSize: {
     type: [String, Number],
     default: 5,
   },
-  iconClasses: {
-    type: String,
-    default: "fa-solid fa-circle icon-title",
-  },
-  titleText: {
-    type: String,
-    default: "default title",
-  },
-  iconColor: {
-    type: String,
-  },
-  titleColor: {
-    type: String,
-    default: "#071b1f",
-  },
 });
 </script>
 
-<style scoped>
-.title-container {
+<style scoped lang="scss">
+.container {
   display: flex;
   align-items: center;
   gap: 0.5rem;
   margin-left: 1rem;
-  color: #071b1f;
+  color: var(--primary-color);
   font-size: 10px;
   font-weight: 600;
   line-height: 15px;
@@ -77,13 +44,17 @@ const props = defineProps({
   text-transform: uppercase;
 }
 
-.presentation-title {
-  font-weight: 500;
-  color: var(--Vert-90, #0E2D32); 
+.v-icon {
+  color: var(--on-primary-color-alt);
+}
 
+h2 {
+  color: var(--on-neutral-color);
+  font-weight: 500;
   font-size: 1rem;
   line-height: 15px;
   letter-spacing: 1px;
   text-transform: uppercase;
 }
+
 </style>

+ 17 - 23
components/Layout/UI/Title.vue

@@ -1,31 +1,25 @@
+<!-- Titre H2 -->
 <template>
   <LayoutContainer>
-    <div>
-      <h2 class="title" :style="{ color: titleColor }">{{ title }}</h2>
-    </div>
+    <!--
+    TODO: dans les faits c'est plutôt le sous-titre (même s'il apparait en plus gros)
+    voir à passer en H3, ou même en autre chose qu'un titre
+    -->
+    <h2>
+      <slot />
+    </h2>
   </LayoutContainer>
 </template>
 
-<script setup>
-import { defineProps } from "vue";
-
-const props = defineProps({
-  title: String,
-  titleColor: {
-    type: String,
-    default: "#0E2D32", 
-  },
-});
+<script setup lang="ts">
 </script>
 
-<style scoped>
-.title {
-  font-weight: 600;
-  font-size: 3rem;
-  line-height: 3rem;
-  color: inherit;
-  margin-left: 1rem;
-  color: var(--Vert-90, #0E2D32); 
-  width: 35rem;
-}
+<style scoped lang="scss">
+  h2 {
+    color: var(--on-neutral-color);
+    font-weight: 600;
+    font-size: 3rem;
+    line-height: 3rem;
+    margin-left: 1rem;
+  }
 </style>

+ 22 - 43
components/Layout/UI/TitlePage.vue

@@ -1,67 +1,46 @@
 <template>
-  <div>
-    <h1 style="text-align: center" :class="mdAndDown ? 'title-md ' : 'title '">
-      {{ title }}
+  <div class="mb-4">
+    <h1>
+      <slot />
     </h1>
-    <h2
-      style="text-align: center"
-      :class="mdAndDown ? 'subtitle-md ' : 'subtitle '"
-    >
-      {{ subtitle }}
+    <h2>
+      <slot name="subtitle" />
     </h2>
   </div>
 </template>
 
-<script setup>
-import { useDisplay } from "vuetify";
-const { mdAndDown } = useDisplay();
-import { defineProps } from "vue";
-
-const props = defineProps({
-  title: String,
-  subtitle: String,
-});
-</script>
-
-<style scoped>
-.text-center {
+<style scoped lang="scss">
+h1, h2 {
   text-align: center;
+  text-transform: uppercase;
 }
 
-.title {
+h1 {
   font-size: 4rem;
   line-height: 3.5rem;
   letter-spacing: 0.3rem;
   margin-top: 2rem;
   margin-bottom: 2rem;
-  text-transform: uppercase;
 }
 
-.title-md {
-  font-size: 2rem;
-  line-height: 2.5rem;
-  letter-spacing: 0.2rem;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-  
-  text-transform: uppercase;
-}
-
-.subtitle {
+h2 {
   font-size: 1.5rem;
   line-height: 2rem;
-  letter-spacing: 0.5rem;
-  margin-bottom: 8rem;
-  text-transform: uppercase;
+  letter-spacing: 0.2rem;
   margin-left: 1rem;
   margin-right: 1rem;
 }
 
-.subtitle-md {
-  font-size: 1.5rem;
-  line-height: 2rem;
-  letter-spacing: 0.1rem;
-  text-transform: uppercase;
-  width: 100%;
+@media (max-width: 960px) {
+  h1 {
+    font-size: 2rem;
+    line-height: 2.5rem;
+  }
+
+  h2 {
+    letter-spacing: 0.1rem;
+    width: 100%;
+  }
 }
+
 </style>

+ 62 - 84
components/Logiciels/Artist/Abonnement.vue

@@ -1,19 +1,14 @@
 <template>
-  <div id="Abonnement">
+  <AnchoredSection id="subscription">
     <LayoutContainer>
-      <v-row class="mt-12">
+      <v-row class="mt-12 center-90">
         <v-col cols="4">
-          <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'S\'abonner dès maintenant'"
-            :iconColor="'#fac20a'"
-          />
+          <LayoutUISubTitle>
+            S'abonner dès maintenant
+          </LayoutUISubTitle>
+
           <div class="profile-circle">
-            <v-img
-              src="/images/logo/logiciels/OT_Artist-BLANC.png"
-              style="top: 0.5rem"
-            ></v-img>
+            <v-img src="/images/logo/logiciels/OT_Artist-BLANC.png" />
           </div>
 
           <div class="subscription-info">
@@ -25,21 +20,27 @@
               href="https://www.opentalent.fr/fileadmin/stockage/commercial/contrats/BDC_Artist_Public-23.pdf"
               target="_blank"
               class="download-button"
-              >Télécharger le formulaire d'abonnement</a
-            >
+              >
+              Télécharger le formulaire d'abonnement
+            </a>
           </div>
+
           <div class="subscription-steps">
             <ol>
-              <li class="mt-6">Téléchargez le formulaire</li>
-              <li>Complétez le formulaire</li>
+              <li class="mt-6">
+                Téléchargez le formulaire
+              </li>
+              <li>
+                Complétez le formulaire
+              </li>
               <li>
                 Joignez le règlement par chèque avec le formulaire à <br />
-                <br />
-                2iOPENservice <br />
-                217 rue Raoul Follereau <br />
-                74300 CLUSES
+                <p class="pa-3">
+                  2iOPENService <br />
+                  217 rue Raoul Follereau <br />
+                  74300 CLUSES
+                </p>
               </li>
-              <br />
               <li>
                 Après réception de votre formulaire d'adhésion et de votre
                 règlement, nous vous ouvrons le service choisi. Vous recevrez
@@ -51,25 +52,27 @@
         </v-col>
 
         <v-col cols="8">
-          <h5 class="title">
+          <h5>
             Opentalent Artist, <br> la solution que vous attendiez...
           </h5>
-          <p class="solution" style="text-align: justify">
+
+          <p class="solution">
             Conçu pour les structures artistiques telles que chorales,
             orchestres (fanfares, orchestres d'harmonie, symphoniques, musiques
             actuelles, petites formations musicales...), compagnies de danse,
             troupes de théâtre, cirque, arts de la rue… Le logiciel s'adapte à
             vos besoins d'évolution !
           </p>
-          <h3 class="cmf">
+
+          <p class="cmf">
             Adhérents CMF ? <br> Et si on vous disait que vous l’aviez déjà ...
-          </h3>
-          <div class="border-row">
+          </p>
 
+          <div class="border-row">
+            <v-img src="/images/logiciels/school/cmf_logo_orange.png" class="logo-cmf" />
 
-            <div class="logo-cmf"></div>
             <div class="cmf-container">
-              <p class="cmf-text">
+              <p>
                 Attention si vous êtes adhérent à la Confédération Musicale de
                 France (CMF), vous bénéficiez gratuitement, dans le cadre de
                 votre adhésion, de la version Opentalent Artist Standard, et de
@@ -82,41 +85,38 @@
         </v-col>
       </v-row>
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup></script>
+<script setup>
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
 
-<style scoped>
-.v-container {
-  max-width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
+<style scoped lang="scss">
 .subscription-steps ol {
   list-style-type: decimal;
   padding-left: 2rem;
-  color: #000;
-  font-family: Barlow;
+  color: var(--on-neutral-color);
   font-size: 16px;
-  font-style: normal;
   font-weight: 300;
   line-height: 20px;
   margin-left: 3rem;
   width: 20rem;
 }
+
 .profile-circle {
+  top: 0.5rem;
   width: 100px;
   height: 100px;
   position: relative;
-  background-color: #000;
+  background-color: var(--on-neutral-color);
   border-radius: 50%;
   margin-left: 11rem;
-  top: 3rem;
 }
+
 .subscription-info {
   margin-left: 4rem;
-  background: var(--Jaune-Artist-20, rgba(250, 194, 10, 0.2));
+  background: var(--secondary-color);
   border-radius: 10px;
   height: 15rem;
   width: 20rem;
@@ -125,56 +125,52 @@
   display: flex;
   flex-direction: column;
   justify-content: center;
-  color: var(--Vert-100, #091d20);
-
+  color: var(--on-secondary-color);
   text-align: center;
-  font-family: "Barlow";
   font-size: 1rem;
-  font-style: normal;
   font-weight: 300;
   line-height: 18px;
 }
 
 .download-button {
   font-weight: 700;
-  background-color: #000;
-  color: #fff;
+  background-color: var(--on-neutral-color);
+  color: var(--neutral-color);
   padding: 10px 20px;
   border-radius: 5px;
   text-decoration: none;
   display: inline-block;
 }
 
-.black-circle {
-  width: 90px;
-  height: 90px;
-  background-color: #000;
-  border-radius: 50%;
-  flex-shrink: 0;
-  margin-top: -1.5rem;
-  margin-left: -2rem;
-}
 .solution {
   width: 45rem;
+  text-align: justify
 }
 
-.title {
-  font-family: "Barlow";
-  font-weight: 600;
-  font-size: 1.5rem;
-  line-height: 18px;
-  color: #091d20;
+h5 {
+  color: var(--primary-color);
   margin-bottom: 4rem;
+  font-size: 42px;
+  font-weight: 600;
+  line-height: 42px;
 }
 
 .cmf-container {
   margin-top: 4rem;
   margin-bottom: 4rem;
+
+  p {
+    color: var(--primary-color);
+    width: 25rem;
+    font-weight: 300;
+    font-size: 16px;
+    line-height: 20px;
+    margin-left: 2rem;
+  }
 }
 
 .logo-cmf {
-  border-right: 1px solid #e5e5e5;
-  background-image: url("/images/logiciels/school/cmf_logo_orange.png");
+  border-right: 1px solid var(--neutral-color);
   background-repeat: no-repeat;
   background-position: center;
   background-size: contain;
@@ -182,31 +178,13 @@
   height: 10rem;
 }
 
-.cmf-text {
-  color: #091d20;
-  width: 25rem;
-  font-weight: 300;
-  font-size: 16px;
-  line-height: 20px;
-  margin-left: 2rem;
-}
 .cmf {
   margin-top: 3rem;
   margin-bottom: 2rem;
-  color: #071b1f;
+  color: var(--primary-color);
   width: 40rem;
-  font-family: Barlow;
   font-size: 34px;
-  font-style: normal;
   font-weight: 400;
   line-height: 38px;
 }
-.title {
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  color: #071b1f;
-  font-family: "Barlow";
-  font-style: normal;
-}
 </style>

+ 14 - 56
components/Logiciels/Artist/Avantages.vue

@@ -1,46 +1,17 @@
-
-  <template>
-    <div id="Avantages">
-      <LayoutContainer>
-        <v-row class="row-custom">
-          <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'Découvrez les avantages de la solution'"
-            :iconColor="'#fac20a'"
-
-          />
-          <LayoutUITitle title="Des avantages concrets" />
-        </v-row>
-
-        <v-row class="row-custom">
-          <v-col
-            cols="12"
-            md="4"
-            offset-md="1"
-            v-for="(card, index) in cards"
-            :key="index"
-          >
-            <CommonCardAvantageCard
-              :title="card.title"
-              :number="card.number"
-              :description="card.description"
-              :image="card.image"
-              :isMemberCMF="card.isMemberCMF"
-              :numberColor="card.numberColor"
-              :dynamicNumberColor="'#fac20a'"
-
-            />
-          </v-col>
-        </v-row>
-      </LayoutContainer>
-    </div>
-  </template>
-
-<script setup>
-import { ref } from "vue";
-
-const cards = ref([
+<!--
+Section "Avantages" de la page du logiciel Artist
+-->
+<template>
+  <AnchoredSection id="benefits">
+    <CommonAvantages :benefits="benefits" />
+  </AnchoredSection>
+</template>
+
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Benefit } from "~/types/interface";
+
+const benefits: Ref<Array<Benefit>> = ref([
   {
     title: "Un gain de temps",
     number: "01",
@@ -67,16 +38,3 @@ const cards = ref([
   },
 ]);
 </script>
-<style scoped>
-
-.row-custom{
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-</style>

+ 0 - 29
components/Logiciels/Artist/Banner.vue

@@ -1,29 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <CommonBannerTitle
-        :leftText="'School'"
-        :centerText="'Opentalent Artist'"
-        :rightText="'Manager'"
-      />
-    </v-row>
-
-    <v-row>
-      <v-col cols="12">
-        <CommonBanner
-          :imageSrc="'/images/logiciels/artist/banner.jpg'"
-          imageAlt="'line'"
-          :squareText="'Orchestres, chorales, compagnies de danse, de cirque et de théâtre  '"
-          :logoSrc="'/images/logo/logiciels/Artist-noir.png'"
-          :squareColor="'#fac20a'"
-          :blueSquareColor="'#FFF'"
-        />
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-</style>

+ 58 - 71
components/Logiciels/Artist/Comparatif.vue

@@ -1,105 +1,92 @@
 <template>
-  <div id="Comparatif">
+  <AnchoredSection id="comparative">
     <LayoutContainer>
-      <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Comparatif de nos solutions'"
-          :iconColor="'#fac20a'"
-        />
-        <LayoutUITitle
-          title="Choisissez la version qui vous convient !"
-        />
-        <CommonTableComparatif
-        :standardPrice="'14€'"
-        :premiumPrice="'18€'"
-        :color="'#0e2d32'"
-        :stripeColor="'#fac20a33'"
-        :tableData="tableData"
+      <LayoutUISubTitle>
+        Comparatif de nos solutions
+      </LayoutUISubTitle>
+
+      <LayoutUITitle>
+        Choisissez la version qui vous convient !
+      </LayoutUITitle>
+
+      <CommonTableComparatif
+        standardPrice="14€"
+        premiumPrice="18€"
+        :items="comparisonItems"
       />
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const tableData = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { ComparisonItem } from "~/types/interface";
+
+const comparisonItems: Array<ComparisonItem> = [
   {
-    id: 1,
-    column1: "GESTION DU RÉPERTOIRE",
-    column2: "check",
-    column3: "check",
+    label: "GESTION DU RÉPERTOIRE",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 2,
-    column1: "AGENDA",
-    column2: "check",
-    column3: "check",
+    label: "AGENDA",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 4,
-    column1: "GESTION DU PARC MATÉRIEL",
-    column2: "check",
-    column3: "check",
+    label: "GESTION DU PARC MATÉRIEL",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 5,
-    column1: "COMMUNICATION",
-    column2: "cross",
-    column3: "check",
+    label: "COMMUNICATION",
+    includedInStandard: false,
+    includedInPremium: true,
   },
   {
-    id: 6,
-    column1: "SMS",
-    column2: "Option",
-    column3: "Option",
+    label: "SMS",
+    includedInStandard: "Option",
+    includedInPremium: "Option",
   },
   {
-    id: 6,
-    column1: "NOM DE DOMAINE",
-    column2: "Option",
-    column3: "Option",
+    label: "NOM DE DOMAINE",
+    includedInStandard: "Option",
+    includedInPremium: "Option",
   },
   {
-    id: 7,
-    column1: "SITE INTERNET",
-    column2: "check",
-    column3: "check",
+    label: "SITE INTERNET",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 8,
-    column1: "STATISTIQUES",
-    column2: "check",
-    column3: "check",
+    label: "STATISTIQUES",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 9,
-    column1: "FONCTIONNALITÉ DU RÉSEAU CMF",
-    column2: "check",
-    column3: "check",
+    label: "FONCTIONNALITÉ DU RÉSEAU CMF",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 10,
-    column1: "SAUVEGARDE",
-    column2: "check",
-    column3: "check",
+    label: "SAUVEGARDE",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 11,
-    column1: "EXTRANET UTILISATEURS",
-    column2: "75 comptes",
-    column3: "150 comptes",
+    label: "EXTRANET UTILISATEURS",
+    includedInStandard: "75 comptes",
+    includedInPremium: "150 comptes",
   },
   {
-    id: 15,
-    column1: "ESPACE DE STOCKAGE",
-    column2: "100 Mo",
-    column3: "1 Go",
+    label: "ESPACE DE STOCKAGE",
+    includedInStandard: "100 Mo",
+    includedInPremium: "1 Go",
   },
   {
-    id: 16,
-    column1: "PAGE DU SITE INTERNET",
-    column2: "Restreint",
-    column3: "Illimités",
+    label: "PAGE DU SITE INTERNET",
+    includedInStandard: "Restreint",
+    includedInPremium: "Illimités",
   },
 ];
 </script>

+ 17 - 26
components/Logiciels/Artist/Fonctionnalites.vue

@@ -1,29 +1,25 @@
 <template>
-  <div id="Fonctionnalites">
-    <LayoutContainer>
-      <div class="container-green">
-          <v-row>
-            <v-col cols="12">
-              <CommonCarouselFonctionnalite
-                :cards="cards"
-                :functionCarousel="functionCarousel"
-                :itemsToShow="itemsToShow"
-                pricingFromText="à partir de" 
-              />
-            </v-col>
-          </v-row>
-      </div>
-    </LayoutContainer>
-  </div>
+  <AnchoredSection id="functionalities">
+    <div>
+      <LayoutContainer>
+        <v-row>
+          <v-col cols="12">
+            <CommonCarouselFonctionnalite
+              :cards="cards"
+            />
+          </v-col>
+        </v-row>
+      </LayoutContainer>
+    </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
 import "vue3-carousel/dist/carousel.css";
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Functionality } from "~/types/interface";
 
-const functionCarousel = ref(null);
-
-const cards = [
+const cards: Array<Functionality> = [
   {
     logo: "/images/logiciels/artist/fonctionnalites/Espaces_dedies.svg",
     title: "ESPACES DÉDIÉS *",
@@ -110,8 +106,3 @@ const cards = [
   },
 ];
 </script>
-<style scoped>
-.container-green {
-  background-color: #0e2d32;
-}
-</style>

+ 61 - 132
components/Logiciels/Artist/Formations.vue

@@ -1,32 +1,25 @@
 <template>
-  <div id="Webinaires">
+  <AnchoredSection id="webinars">
     <LayoutContainer>
-      <div class="container-green 2">
+      <div class="alt-theme">
         <v-container>
-          <v-row class="custom-row">
-            <LayoutUISubTitle
-              class="mt-12"
-              title-color="#fff"
-              :iconSize="6"
-              :iconClasses="iconClasses"
-              :titleText="'Pour aller plus loin'"
-              :iconColor="'#fac20a'"
-            />
+          <v-row class="center-90">
+            <LayoutUISubTitle class="mt-12" >
+              Pour aller plus loin
+            </LayoutUISubTitle>
           </v-row>
 
-          <v-row class="mt-12 align-center" no-gutters>
-            <v-col cols="12" lg="6" md="6" sm="6">
-              <div class="reunion-img mb-12"></div>
+          <v-row class="formation py-12 align-center mb-12" no-gutters>
+            <v-col cols="12" lg="6">
+              <v-img src="/images/logiciels/artist/webinaire.jpg" class="meeting-img" />
             </v-col>
 
             <v-col cols="12" lg="6" md="6" sm="6">
-              <h3 class="formation-title ml-6 mr-12">
+              <h3 class="ml-6 mr-12">
                 Webinaire - Partez à la découverte du logiciel Opentalent Artist
               </h3>
-              <p
-                class="formation-details ml-6 mr-12"
-                style="text-align: justify"
-              >
+
+              <p class="details ml-6 mr-12" >
                 Rejoignez notre webinaire, spécialement conçu pour les
                 professionnels du secteur culturel, orchestres, chorales,
                 compagnies de danse, ainsi que les troupes de théâtre et de
@@ -37,136 +30,72 @@
                 votre gestion et de faire évoluer votre pratique artistique avec
                 nos solutions technologiques innovantes !
               </p>
+
               <nuxt-link to="/webinaires">
-                <v-btn class="formation-btn mt-12 ml-6">
-                  S'inscrire à nos webinaires</v-btn
-                >
+                <v-btn class="mt-12 ml-6">
+                  S'inscrire à nos webinaires
+                </v-btn>
               </nuxt-link>
             </v-col>
           </v-row>
         </v-container>
       </div>
-      <v-row class="custom-row">
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="' Quelques chiffres'"
-          class="mb-12"
-        />
-      </v-row>
-      <v-container>
-        <v-row class="card-container mb-12">
-          <v-col
-            cols="3"
-            class="d-flex justify-center align-center small-padding"
-          >
-            <CommonCardStat
-              :chiffre="'184 634'"
-              text="Utilisateurs"
-              backgroundColor="#fac20a"
-            />
-          </v-col>
-          <v-col cols="3" class="d-flex justify-center align-center">
-            <CommonCardStat
-              :chiffre="'3 424'"
-              text="Structures"
-              backgroundColor="#fac20a"
-            />
-          </v-col>
-          <v-col cols="3" class="d-flex justify-center align-center">
-            <CommonCardStat
-              :chiffre="13"
-              text="Années d'expérience"
-              backgroundColor="#fac20a"
-            />
-          </v-col>
-        </v-row>
-      </v-container>
-      <v-row />
-
-      <v-row />
-      <CommonCarouselTrustCompanie
-        :items="items"
-        :trustMessage="'nous ont déjà adoptées'"
-        :structureCount="'3400 structures'"
-        :structureCountColor="'#fac20a'"
-      />
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const items = ref([
-  { src: "/images/reviews/artist/review1.jpeg" },
-  { src: "/images/reviews/artist/review2.jpg" },
-  { src: "/images/reviews/artist/review3.jpeg" },
-  { src: "/images/reviews/artist/review4.jpg" },
-  { src: "/images/reviews/artist/review5.png" },
-  { src: "/images/reviews/artist/review6.jpeg" },
-]);
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .v-container {
   padding: 0 !important;
 }
 
-@media (min-width: 1000px) {
-  .custom-row {
-    margin-right: auto;
-    margin-left: auto;
-  }
-}
-.custom-row {
-  width: 90%;
-  margin-right: auto;
-  margin-left: auto;
+.alt-color {
+  color: var(--on-primary-color-alt);
 }
 
-.formation-btn {
-  font-weight: 500;
-  font-size: 1rem;
-  line-height: 18px;
-  background: transparent;
-  color: #eff9fb;
-  border: 1px solid #eff9fb;
-  border-radius: 0.5rem;
-  width: 90%;
-}
-.formation-details {
-  font-weight: 300;
-  font-size: 1rem;
-  line-height: 1.5rem;
-  color: #eff9fb;
-}
-.formation-title {
-  font-weight: 500;
-  font-size: 1.8rem;
-  line-height: 35px;
-  color: #ffffff;
-  margin-bottom: 1rem;
-}
-.reunion-img {
-  width: 600px;
-  height: 500px;
-  background-position: center;
-  background-size: cover;
-  border-radius: 10%;
-  background-image: url("/images/logiciels/artist/webinaire.jpg");
-}
-.container-green {
-  background-color: #0e2d32;
-  padding: 20px;
-  height: auto;
-  margin-bottom: 2rem;
-  color: white;
-}
+.formation {
+  .v-img {
+    width: 600px;
+    height: 500px;
+    background-position: center;
+    background-size: cover;
+    border-radius: 10%;
+  }
 
-.card-container {
-  margin-left: auto;
-  margin-right: auto;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+  :deep(.v-img img) {
+    object-fit: cover;
+  }
+
+  h3 {
+    font-weight: 500;
+    font-size: 1.8rem;
+    line-height: 35px;
+    color: var(--on-primary-color);
+    margin-bottom: 1rem;
+  }
+
+  .details {
+    font-weight: 300;
+    font-size: 1rem;
+    line-height: 1.5rem;
+    color: var(--on-primary-color);
+    text-align: justify
+  }
+
+  .v-btn {
+    font-weight: 500;
+    font-size: 1rem;
+    line-height: 18px;
+    background: transparent;
+    color: var(--on-primary-color);
+    border: 1px solid;
+    border-color: var(--on-primary-color);
+    border-radius: 0.5rem;
+    width: 90%;
+  }
 }
 </style>

+ 24 - 21
components/Logiciels/Artist/Presentation.vue

@@ -1,19 +1,33 @@
 <template>
-  <div id="Presentation">
+  <AnchoredSection id="presentation">
     <CommonPresentation
-      :pictoImages="pictoData"
-      :presentationText="presentationData"
-      :backgroundColor="'rgba(250, 194, 10, 0.2)'"
-      pricingPeriodText="/mois"
-      pricingAnnouncementText="payable annuellement"
+      title="Présentation d'Opentalent Artist"
+      :features="features"
+      :pictos="pictos"
+      logo-src="/images/logo/logiciels/OT_Artist-BLANC.png"
+      pricingAmount="14€"
     />
-  </div>
 
-  <CommonContainerVideo image-url="/images/logiciels/school/screen2.png" />
+    <CommonContainerVideo
+      title="Logiciel OpenTalent Artist"
+      quote="Le logiciel de gestion et communication au service de votre passion"
+      image-url="/images/logiciels/school/screen2.png"
+    />
+  </AnchoredSection>
 </template>
 
-<script setup>
-const pictoData = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { FeaturePicto } from "~/types/interface";
+
+const features = [
+  "Logiciel de gestion et communication en ligne",
+  "Destiné aux structures culturelles (tout statut juridique)",
+  "Gestion complète (membres, événements, planning, matériel,...)",
+  "Une solution simple d'utilisation, intuitive et collaborative"
+]
+
+const pictos: Array<FeaturePicto> = [
   {
     src: "/images/logiciels/artist/picto1.png",
     text: "Logiciel de gestion et communication full web",
@@ -28,15 +42,4 @@ const pictoData = [
   },
   { src: "/images/logiciels/artist/picto4.png", text: "Communiquez en réseau" },
 ];
-
-const presentationData = {
-  toolTitle: "Un outil complet en ligne",
-  toolList: [
-    "Logiciel de gestion et communication en ligne",
-    "Destiné aux structures culturelles (tout statut juridique)",
-    "Gestion complète (membres, événements, planning, matériel,...)",
-    "Une solution simple d'utilisation, intuitive et collaborative",
-  ],
-  characteristicsTitle: "Des caractéristiques uniques & dédiées",
-};
 </script>

+ 18 - 11
components/Logiciels/Artist/Reviews.vue

@@ -1,22 +1,29 @@
 <template>
-  <div id="Temoignages">
-    <LayoutContainer>
-      <CommonReviewCard :cards="cards" />
-    </LayoutContainer>
-  </div>
+  <AnchoredSection id="testimonials">
+    <div>
+      <LayoutContainer>
+        <LogicielsArtistSomeNumbers />
+
+        <CommonReviewSection :cards="cards" class="alt-theme" />
+      </LayoutContainer>
+    </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const cards = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Review } from "~/types/interface";
+
+const cards: Array<Review> = [
   {
-    description:
+    review:
       "L'outil répond à toutes les demandes d'une structure de notre taille et la connexion avec le site internet est très pratique.",
     name: "Patrice MONTESSUIT",
     status: "Directeur musical ",
     structure: "Orchestre d'Harmonie de Cluses (74)",
   },
   {
-    description:
+    review:
       "C'est un outil de travail très intéressant, complet et intuitif quand on comprend certaines subtilités. Il a très bien évolué aussi bien pour les chorales que les harmonie. Mes remarques ont toujours été prises en compte.",
     name: "Gérard LEFÈBVRE ",
     status: "Président",
@@ -25,12 +32,12 @@ const cards = [
 ];
 </script>
 
-<style scoped>
+<style scoped lang="scss">
 .v-container {
   padding: 0 !important;
 }
 
-:deep().reviewer-name {
+:deep(.reviewer-name) {
   color: rgb(250, 194, 10) !important;
 }
 </style>

+ 74 - 0
components/Logiciels/Artist/SomeNumbers.vue

@@ -0,0 +1,74 @@
+<template>
+  <LayoutContainer>
+    <v-row class="custom-row">
+      <LayoutUISubTitle class="mb-12">
+        Quelques chiffres
+      </LayoutUISubTitle>
+    </v-row>
+
+    <v-container>
+      <v-row class="card-container mb-12">
+        <v-col
+          cols="3"
+          class="d-flex justify-center align-center small-padding"
+        >
+          <CommonCardStat
+            number="184 634"
+            text="Utilisateurs"
+          />
+        </v-col>
+
+        <v-col cols="3" class="d-flex justify-center align-center">
+          <CommonCardStat
+            number="3 424"
+            text="Structures"
+          />
+        </v-col>
+
+        <v-col cols="3" class="d-flex justify-center align-center">
+          <CommonCardStat
+            number="13"
+            text="Années d'expérience"
+          />
+        </v-col>
+      </v-row>
+    </v-container>
+
+    <CommonCarouselClients :items="items" >
+      <template v-slot:title>
+        Plus de <span class="alt-color">3400 structures</span> nous ont déjà adoptées
+      </template>
+    </CommonCarouselClients>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+const items: Ref<Array<{ src: string }>> = ref([
+  { src: "/images/reviews/artist/review1.jpeg" },
+  { src: "/images/reviews/artist/review2.jpg" },
+  { src: "/images/reviews/artist/review3.jpeg" },
+  { src: "/images/reviews/artist/review4.jpg" },
+  { src: "/images/reviews/artist/review5.png" },
+  { src: "/images/reviews/artist/review6.jpeg" },
+]);
+</script>
+
+<style scoped lang="scss">
+.custom-row {
+  width: 90%;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.card-container {
+  margin-left: auto;
+  margin-right: auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.alt-color {
+  color: var(--on-primary-color-alt);
+}
+</style>

+ 0 - 61
components/Logiciels/Manager/Agenda.vue

@@ -1,61 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <v-col cols="4">
-        <h3>L'agenda Opentalent</h3>
-      </v-col>
-
-      <v-col cols="4" />
-
-      <v-col cols="4">
-        <v-btn>Tous les évèvenements</v-btn>
-      </v-col>
-    </v-row>
-
-    <v-row>
-      <!-- slide card-->
-      <v-col cols="4">
-        <v-card>
-          <v-img
-            src="/images/logiciels/school/enseignement.jpg"
-            class="enseignement"
-          >
-            <v-card-title class="title">
-              Enseignement
-            </v-card-title>
-          </v-img>
-        </v-card>
-      </v-col>
-
-      <v-col cols="4">
-        <v-card>
-          <v-img
-            src="/images/logiciels/school/enseignement.jpg"
-            class="enseignement"
-          >
-            <v-card-title class="title">
-              Enseignement
-            </v-card-title>
-          </v-img>
-        </v-card>
-      </v-col>
-
-      <v-col cols="4">
-        <v-card>
-          <v-img
-            src="/images/logiciels/school/enseignement.jpg"
-            class="enseignement"
-          >
-            <v-card-title class="title">
-              Enseignement
-            </v-card-title>
-          </v-img>
-        </v-card>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped></style>

+ 14 - 67
components/Logiciels/Manager/Avantages.vue

@@ -1,52 +1,25 @@
 
 
-  <template>
-  <div id="Avantages">
-    <LayoutContainer>
-      <v-row class=" row-custom" >
-     
-
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Découvrez les avantages de la solution'"
-          :iconColor="'#E34461'"
-        />
-        <LayoutUITitle title="Des avantages concrets pour un outil..." />
-
-      </v-row>
-
-      <v-row class="row-custom"  >
-
-        <v-col cols="12" md="4" offset-md="1"  v-for="(card, index) in cards" :key="index">
-          <CommonCardAvantageCard
-            :title="card.title"
-            :number="card.number"
-            :description="card.description"
-            :image="card.image"
-            :isMemberCMF="card.isMemberCMF"
-            :numberColor="card.numberColor"
-            :dynamicNumberColor="'#E34461'"
-
-          />
-        </v-col>
-
-      </v-row>
-    </LayoutContainer>
-  </div>
+<template>
+  <AnchoredSection id="benefits">
+    <CommonAvantages
+      :benefits="benefits"
+      title="Des avantages concrets pour un outil..."
+    />
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Benefit } from "~/types/interface";
 
-const cards = ref([
+const benefits: Array<Benefit> = [
   {
     title: "Sur-mesure",
     number: "01",
     description:
       "S'adapte à tous les réseaux de type pyramidal, quelque soit le nombre de niveaux :",
-    numberColor: "#f9d648",
-    listItems: ["Fédérations", "Institutions publiques"],
+    list: ["Fédérations", "Institutions publiques"],
     image: "/images/avantages/manager/Sur-mesure.jpg",
   },
   {
@@ -54,62 +27,36 @@ const cards = ref([
     number: "02",
     description:
       "Chaque structure du réseau dispose de sa propre solution indépendante et connectée au réseau :",
-    numberColor: "#f9d648",
-    listItems: ["Opentalent manager", "Opentalent school", "Opentalent artist"],
+    list: ["Opentalent manager", "Opentalent school", "Opentalent artist"],
     image: "/images/avantages/manager/Adapte.jpg",
-
   },
   {
     title: "Économique",
     number: "03",
     description:
       "Une solution éprouvée au niveau national, sans avoir à supporter de coûts de développement importants pour ce type de logiciel.",
-    numberColor: "#f9d648",
     image: "/images/avantages/manager/Economique.jpg",
-
   },
   {
     title: "De pilotage",
     number: "04",
     description:
       "Pilotez votre réseau de manière quotidienne et en temps réel. Gagnez du temps avec notre solution qui génère automatiquement un rapport d'activité complet.",
-    numberColor: "#f9d648",
     image: "/images/avantages/manager/Pilotage.jpg",
-
   },
   {
     title: "En réseau",
     number: "05",
     description:
       "Mise à jour automatique des coordonnées publiques entre les membres du réseau.",
-    numberColor: "#f9d648",
     image: "/images/avantages/manager/En-reseau.jpg",
-
   },
   {
     title: "Confidentiel",
     number: "06",
     description:
       "Chaque structure garde son indépendance et reste entièrement maître des informations et des données qu'elle saisit.",
-    numberColor: "#f9d648",
     image: "/images/avantages/manager/Confidentiel-les-donnees-appartiennent-aux-structures.jpg",
-
   },
-]);
+];
 </script>
-
-<style>
-:deep().description-container {
-  height: 15rem;
-}
-
-.row-custom{
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-</style>

+ 0 - 33
components/Logiciels/Manager/Banner.vue

@@ -1,33 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <CommonBannerTitle
-        :leftText="'School'"
-        :centerText="'Opentalent Manager'"
-        :rightText="'Artist'"
-      />
-    </v-row>
-
-    <v-row>
-      <v-col cols="12">
-        <CommonBanner
-          :imageSrc="'/images/logiciels/manager/banner-manager.png'"
-          imageAlt="'line'"
-          :squareText="'Fédérations, confédérations et collectivités'"
-          :logoSrc="'/images/logo/logiciels/Manager-noir.png'"
-          :squareColor="'#d8050b'"
-          :blueSquareColor="'#FFF'"
-          :textColor="'#FFF'"
-        />
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<style scoped>
-
-
-:deep().cover-image {
-  object-position: center 40% !important;
-}
-</style>

+ 11 - 21
components/Logiciels/Manager/Fonctionnalites.vue

@@ -1,29 +1,25 @@
 <template>
-  <div id="Fonctionnalites">
-    <LayoutContainer>
-      
+  <AnchoredSection id="functionalities">
+    <div>
+      <LayoutContainer>
         <v-row>
           <v-col cols="12">
             <CommonCarouselFonctionnalite
               :cards="cards"
-              :functionCarousel="functionCarousel"
-              :itemsToShow="itemsToShow"
             />
           </v-col>
         </v-row>
- 
-    </LayoutContainer>
-  </div>
+      </LayoutContainer>
+    </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from "vue";
+<script setup lang="ts">
 import "vue3-carousel/dist/carousel.css";
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Functionality } from "~/types/interface";
 
-
-const functionCarousel = ref(null);
-
-const cards = [
+const cards: Array<Functionality> = [
   {
     logo:"images/logiciels/manager/fonctionnalites/Espaces_dedies.svg",
     title: "ESPACES DÉDIÉS *",
@@ -67,7 +63,7 @@ const cards = [
       "Création de modèles de courriers, mails ou SMS",
       "Outil de publipostage intégré pour un envoi personnalisé",
     ],
-    option: "* en option",
+    options: ["* en option"]
   },
   {
     logo: "images/logiciels/manager/fonctionnalites/Site_internet.svg",
@@ -107,9 +103,3 @@ const cards = [
   },
 ];
 </script>
-
-<style scoped>
-.container-green {
-  background-color: #0e2d32;
-}
-</style>

+ 73 - 156
components/Logiciels/Manager/Formation.vue

@@ -1,96 +1,53 @@
 <template>
-  <div id="Formations">
+  <AnchoredSection id="webinars">
     <LayoutContainer>
-      <div class="container-green mt-12">
+      <div class="alt-theme pt-6 mt-12">
         <v-row>
-          <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'Nos accompagnements pour aller plus loin '"
-            title-color="#fff"
-            class="mb-6 mt-6"
-          />
+          <LayoutUISubTitle class="mb-6 mt-6">
+            Nos accompagnements pour aller plus loin
+          </LayoutUISubTitle>
         </v-row>
-        <v-row class="mb-6">
-          <v-col cols="6" v-for="(formation, index) in formations" :key="index">
-            <div class="image-wrapper mb-6">
-              <div :class="formation.overlayClass"></div>
-              <div
-                :style="{ backgroundImage: 'url(' + formation.image + ')' }"
+
+        <v-row class="formation pb-6 align-center">
+          <v-col
+            cols="6"
+            v-for="(formation, index) in formations"
+            :key="index"
+          >
+            <div class="mb-6">
+              <v-img
+                :src="formation.image"
                 class="background-img"
-              ></div>
+              />
             </div>
-            <div class="col-details">
-              <h4 class="session-title">
+
+            <div>
+              <h4>
                 {{ formation.sessions }}
               </h4>
-              <h3 class="formation-title">{{ formation.title }}</h3>
-              <p class="formation-details">{{ formation.description }}</p>
-              <br />
+
+              <h3>
+                {{ formation.title }}
+              </h3>
+
+              <p class="details mb-5">
+                {{ formation.description }}
+              </p>
+
+              <v-btn :to="formation.link">
+                {{ formation.buttonText }}
+              </v-btn>
             </div>
-            <nuxt-link :to="formation.link">
-              <v-btn class="formation-btn mt-6">{{
-                formation.buttonText
-              }}</v-btn>
-            </nuxt-link>
           </v-col>
         </v-row>
       </div>
-      <v-row>
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="' Quelques chiffres'"
-          class="mt-6 mb-12"
-        />
-      </v-row>
-
-      <v-container>
-        <v-row class="card-container mb-12">
-          <v-col
-            cols="3"
-            class="d-flex justify-center align-center small-padding"
-          >
-            <CommonCardStat
-              :chiffre="140"
-              text="Structures en réseau"
-              backgroundColor="#d8050b"
-            />
-          </v-col>
-          <v-col cols="3" class="d-flex justify-center align-center">
-            <CommonCardStat
-              :chiffre="'300 000'"
-              text="Utilisateurs"
-              backgroundColor="#d8050b"
-            />
-          </v-col>
-          <v-col cols="3" class="d-flex justify-center align-center">
-            <CommonCardStat
-              :chiffre="12"
-              text="Années de collaboration"
-              backgroundColor="#d8050b"
-            />
-          </v-col>
-        </v-row>
-      </v-container>
-
-      <v-row>
-        <v-col cols="12">
-          <h2 class="text-center" style="font-size: 2rem">
-            La plus grande Confédération Musicale de France nous fait confiance
-          </h2>
-        </v-col>
-      </v-row>
-
-      <!-- <h4 class="text-center title-cmf">
-        La plus grande Confédération Musicale de France nous fait confiance
-      </h4> -->
-      <v-img src="/images/logiciels/manager/cmf.jpg" class="cmf-img mb-6" />
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
 <script setup>
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+
 const formations = ref([
   {
     id: 1,
@@ -115,101 +72,61 @@ const formations = ref([
     link: "/webinaires",
   },
 ]);
-const items = ref([
-  { src: "/images/reviews/school/review1.svg" },
-  { src: "/images/reviews/school/review2.png" },
-  { src: "/images/reviews/school/review3.png" },
-  { src: "/images/reviews/school/review4.jpeg" },
-  { src: "/images/reviews/school/review5.jpeg" },
-  { src: "/images/reviews/school/review6.jpeg" },
-]);
 </script>
 
 <style scoped>
-:deep(.card) {
-  color: white;
-}
-
-:deep(.chiffre) {
-  color: white;
-}
-.v-container {
-  padding: 0 !important;
-}
 .v-row {
   max-width: 1600px;
-  margin-right: auto;
-  margin-left: auto;
+  margin: 0 auto;
 }
-.cmf-img {
-  width: 30rem;
-  height: 18rem;
-  margin-top: 2rem;
-  margin-right: auto;
-  margin-left: auto;
-}
-.image-wrapper {
-  position: relative;
+
+:deep(h2) {
+  width: 60rem;
 }
+
 .background-img {
   width: 600px;
-  margin-left: 5rem;
   height: 400px;
   background-size: cover;
   background-position: center;
 }
 
-.col-details {
-  margin-right: 6rem;
-  margin-left: 5rem;
-  height: 15rem;
-}
-
-.formation-btn {
-  margin-left: 5rem;
-  font-family: "Barlow";
-  font-style: normal;
-  width: 30rem;
-  height: 4rem;
-  font-weight: 500;
-  font-size: 1.5rem;
-  line-height: 18px;
-  background: transparent;
-  color: #eff9fb;
-  border: 1px solid #eff9fb;
-  border-radius: 0.5rem;
-  text-transform: none;
-}
-.formation-details {
-}
-.formation-title {
-  font-weight: 500;
-  font-size: 1.8rem;
-  line-height: 26px;
-  color: #ffffff;
-  margin-bottom: 3rem;
-}
+.formation {
+  .v-btn {
+    width: 30rem;
+    height: 4rem;
+    font-weight: 500;
+    font-size: 1.5rem;
+    line-height: 18px;
+    background: transparent;
+    color: var(--on-primary-color);
+    border: 1px solid;
+    border-color: var(--on-primary-color);
+    border-radius: 0.5rem;
+    text-transform: none;
+  }
 
-.session-title {
-  font-weight: 500;
-  font-size: 1.8rem;
-  line-height: 26px;
-  color: #ffffff;
-  margin-bottom: 3rem;
-}
+  h3 {
+    font-weight: 500;
+    font-size: 1.8rem;
+    line-height: 26px;
+    color: var(--on-primary-color);
+    margin-bottom: 3rem;
+  }
 
-.container-green {
-  background-color: #0e2d32;
-  padding: 20px;
-  margin-bottom: 20px;
-  color: white;
-}
+  h4 {
+    font-weight: 500;
+    font-size: 1.8rem;
+    line-height: 26px;
+    color: var(--on-primary-color);
+    margin-bottom: 3rem;
+  }
 
-.card-container {
-  margin-left: auto;
-  margin-right: auto;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+  .details {
+    font-weight: 300;
+    font-size: 1.2rem;
+    line-height: 1.5rem;
+    color: var(--on-primary-color);
+  }
 }
 </style>

+ 49 - 0
components/Logiciels/Manager/Network.vue

@@ -0,0 +1,49 @@
+<template>
+  <AnchoredSection id="network">
+    <LayoutContainer>
+      <v-row class="mt-12  center-90">
+        <LayoutUISubTitle>
+          Un réseau pyramidal
+        </LayoutUISubTitle>
+      </v-row>
+
+      <v-row class="center-90">
+        <v-col cols="12" lg="6" md="6">
+          <LayoutUITitle>
+            Opentalent Manager, un logiciel adapté à chacun
+          </LayoutUITitle>
+
+          <p class="pyramide-details ml-3 mt-6">
+            Notre système s'adapte à toutes les structures de réseau pyramidal, quel que soit le nombre de niveau.
+          </p>
+        </v-col>
+
+        <v-col cols="12" lg="6" md="6">
+          <v-img
+            src="/images/logiciels/manager/reseau.png"
+            class="schema-manager"
+          />
+        </v-col>
+      </v-row>
+    </LayoutContainer>
+  </AnchoredSection>
+</template>
+
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+</script>
+
+<style scoped lang="scss">
+@media (min-width: 2000px) {
+  .v-row {
+    width: 70%;
+  }
+}
+
+.pyramide-details {
+  font-size: 2.125rem;
+  font-weight: 400;
+  line-height: 2.375rem;
+  width: 40rem;
+}
+</style>

+ 34 - 44
components/Logiciels/Manager/Presentation.vue

@@ -1,19 +1,41 @@
 <template>
-  <LayoutContainer>
-    <div id="Presentation">
-      <CommonPresentation
-        :pictoImages="pictoData"
-        :presentationText="presentationData"
-        :backgroundColor="'rgba(216, 5, 11, 0.2)'"
-      />
-    </div>
+  <AnchoredSection id="presentation">
+    <LayoutContainer>
+      <div>
+        <CommonPresentation
+          title="Présentation d'Opentalent Manager"
+          section1title="La solution de mise en réseau des organisations culturelles"
+          :features="features"
+          :pictos="pictos"
+          logo-src="/images/logo/logiciels/OT_Manager-BLANC.png"
+          pricing-alt-text="Sur devis"
+          pricing-announcement-text=""
+          pricing-from-text=""
+          pricing-period-text=""
+        />
+      </div>
 
-    <CommonContainerVideo image-url="/images/logiciels/school/screen2.png" />
-  </LayoutContainer>
+      <CommonContainerVideo
+        title="Logiciel OpenTalent Manager"
+        quote="Une solution unique, collaborative et innovante pour une gestion optimale de votre réseau culturel"
+        image-url="/images/logiciels/school/screen2.png"
+      />
+    </LayoutContainer>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const pictoData = [
+<script setup lang="ts">
+import type { FeaturePicto } from "~/types/interface";
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+
+const features: Array<string> = [
+  "Logiciel de gestion et communication en ligne ",
+  "Répond aux besoins globaux des réseaux culturels ",
+  "Gestion collaborative ",
+  "Mise en valeur des activités des membres du réseau ",
+]
+
+const pictos: Array<FeaturePicto> = [
   {
     src: "/images/logiciels/manager/picto1.png",
     text: "Logiciel de gestion et communication full web",
@@ -39,36 +61,4 @@ const pictoData = [
     text: "Pout tout type de réseau pyramidal",
   },
 ];
-
-const presentationData = {
-  toolTitle: "La solution de mise en réseau des organisations culturelles ",
-  toolList: [
-    "Logiciel de gestion et communication en ligne ",
-    "Répond aux besoins globaux des réseaux culturels ",
-    "Gestion collaborative ",
-    "Mise en valeur des activités des membres du réseau ",
-  ],
-  characteristicsTitle: "Des caractéristiques uniques & dédiées",
-};
 </script>
-
-<style scoped>
-:deep().pricing-big-text {
-  font-size: 1.5rem;
-  font-weight: normal;
-  line-height: 1.5rem;
-  margin-top: 1.5rem;
-}
-
-:deep().picto-group {
-  display: flex;
-  flex-direction: column;
-  margin-left: -4rem;
-}
-
-:deep().picto-container {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-}
-</style>

+ 0 - 98
components/Logiciels/Manager/Projet.vue

@@ -1,98 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <v-col cols="4">
-        <h5>Contactez-nous</h5>
-        <v-img
-          src="/images/logiciels/school/femme-casque.jpg"
-          class="femme-casque"
-        />
-      </v-col>
-      <v-col cols="8">
-        <h5>Vous avez un projet ?</h5>
-        <h6>N'attendez plus, appelez-nous</h6>
-        <p>
-          Vous avez une identité, des besoins, des projets... On est là pour
-          vous écouter et vous offrir une offre personnalisée ! Que vous soyez
-          une petite ou une structure plus conséquente, notre offre s'adapte à
-          toutes les tailles : le prix de l’abonnement au logiciel varie en
-          fonction du nombre d'élèves, tout en conservant l'intégralité des
-          fonctionnalités.
-        </p>
-
-        <v-btn> Nous contacter</v-btn>
-      </v-col>
-    </v-row>
-
-    <v-row>
-      <v-col cols="2">
-        <v-img src="/images/logiciels/school/cmf_logo_orange.png" />
-      </v-col>
-      <v-col cols="10">
-        <h5>Adhérents CMF : bénéficiez de conditions privilégiées</h5>
-        <p>
-          Si votre établissement d’enseignement artistique est adhérent à la
-          Confédération Musicale de France (CMF), vous bénéficiez gratuitement,
-          dans le cadre de votre adhésion, de la version Opentalent Artist
-          standard et de conditions priviliégiés pour la version Opentalent
-          School. Contactez nous direcetement ou contactez votre fédération pour
-          obtenir vos codes d’accès.
-        </p>
-      </v-col>
-    </v-row>
-
-    <v-row>
-      <v-col
-        cols="4"
-        class="border"
-      >
-        <div class="d-flex justify-center align-center">
-          <v-icon class="fa-brands fa-react icon" />
-        </div>
-        <p class="d-flex justify-center align-center">
-          Paiement Sécurisé
-        </p>
-      </v-col>
-      <v-col
-        cols="4"
-        class="border"
-      >
-        <div class="d-flex justify-center align-center">
-          <v-icon class="fa-brands fa-react icon" />
-        </div>
-        <p class="d-flex justify-center align-center">
-          Paiement Sécurisé
-        </p>
-      </v-col>
-
-      <v-col
-        cols="4"
-        class="border"
-      >
-        <div class="d-flex justify-center align-center">
-          <v-icon class="fa-brands fa-react icon" />
-        </div>
-        <p class="d-flex justify-center align-center">
-          Paiement Sécurisé
-        </p>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-.border {
-  border-top: 1px solid #000; 
-  border-right: 1px solid #000;
-}
-
-.icon {
-  font-size: 3rem;
-  color: #0e2d32;
-}
-.femme-casque {
-  width: 20rem;
-}
-</style>

+ 0 - 67
components/Logiciels/Manager/Pyramide.vue

@@ -1,67 +0,0 @@
-<template>
-  <div id="détails">
-    <LayoutContainer>
-        <v-row class="mt-12 custom-row">
-        <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="'Un réseau pyramidal '"
-          :iconColor="'#E34461'"
-        />
-      </v-row>
-
-      <v-row class="custom-row">
-        <v-col cols="12" lg="6" md="6">
-          <LayoutUITitle
-          title="Opentalent Manager, un logiciel adapté à chacun "
-        />
-        <p class="pyramide-details ml-3 mt-6">Notre système s'adapte à toutes les structures de réseau pyramidal, quel que soit le nombre de niveau.</p>
-        </v-col>
-
-        <v-col cols="12" lg="6" md="6">
-          <v-img
-            src="/images/logiciels/manager/reseau.png"
-            class="schema-manager"
-          />
-        </v-col>
-      </v-row>
-
-
-    </LayoutContainer>
-  </div>
-</template>
-
-<script setup></script>
-
-<style scoped>
-
-.custom-row {
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-@media (min-width: 2000px) {
-  .custom-row {
-    width: 70%;
-  }
-}
-
-.pyramide-details {
-  color: #071B1F;
-font-size: 2.125rem;
-font-style: normal;
-font-weight: 400;
-line-height: 2.375rem; 
-width: 40rem;
-}
-
-.v-row {
-  margin-top: 0px !important;
-  margin-left: auto;
-  margin-right: auto;
-}
-.schema-manager {
-}
-
-</style>

+ 20 - 17
components/Logiciels/Manager/Reviews.vue

@@ -1,42 +1,51 @@
 <template>
-  <LayoutContainer id="Temoignages">
-    <CommonReviewCard :cards="cards" />
-  </LayoutContainer>
+  <AnchoredSection id="testimonials">
+    <div>
+      <LayoutContainer>
+        <LogicielsManagerSomeNumbers />
+
+        <CommonReviewSection :cards="cards" class="alt-theme" />
+      </LayoutContainer>
+    </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
+<script setup lang="ts">
+
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Review } from "~/types/interface";
 
-const cards = [
+const cards: Array<Review> = [
   {
-    description:
+    review:
       "L'outil répond à toutes les demandes d'une structure de notre taille et la connexion avec le site internet est très pratique.",
     name: "Christophe MORIZOT",
     status: "Président ",
     structure: "Confédération Musicale de France (92)",
   },
   {
-    description:
+    review:
       "Lorem ipsum dolor sit amet consectetur adipisicing elit.Provident porro fuga incidunt quae, doloremque tenetur aliquam  exercitationem deleniti aspernatur illo rem deserunt sapiente empore dolorem ipsa aliquid vel nihil eius.",
     name: "Eric TAUVRON ",
     status: "Vice-président",
     structure: "CMF Rhône - Grand Lyon (69)",
   },
   {
-    description:
+    review:
       "C'est un outil de travail très intéressant, complet et intuitif quand on comprend certaines subtilités. Il a très bien évolué aussi bien pour les chorales que les harmonie. Mes remarques ont toujours été prises en compte.",
     name: "Noëlle ROBERT",
     status: "Président",
     structure: "CMF Côte d'or (21)",
   },
   {
-    description:
+    review:
       "Lorem ipsum dolor sit amet consectetur adipisicing elit.Provident porro fuga incidunt quae, doloremque tenetur aliquam  exercitationem deleniti aspernatur illo rem deserunt sapiente empore dolorem ipsa aliquid vel nihil eius.",
     name: "Laurent Lebon",
     status: "Chef d'orchestre",
     structure: "Conservatoire de Lyon",
   },
   {
-    description:
+    review:
       "Lorem ipsum dolor sit amet consectetur adipisicing elit.Provident porro fuga incidunt quae, doloremque tenetur aliquam  exercitationem deleniti aspernatur illo rem deserunt sapiente empore dolorem ipsa aliquid vel nihil eius.",
     name: "Laurent Lebon",
     status: "Chef d'orchestre",
@@ -47,13 +56,7 @@ const cards = [
 
 
 <style scoped>
-
-
-.v-container{
+.v-container {
   padding: 0 !important;
 }
-:deep().reviewer-name {
-  color: #e34461;
-}
-
 </style>

+ 0 - 181
components/Logiciels/Manager/Solutions.vue

@@ -1,181 +0,0 @@
-<template>
-  <div id="solutions">
-    <LayoutContainer>
-      <v-row>
-        <v-col cols="12">
-          <h4 class="solution-title text-center">
-            Ces solutions peuvent vous intéresser
-          </h4>
-        </v-col>
-      </v-row>
-
-      <v-row v-if="!hideArtistRow"  class="row-artist">
-        <v-col cols="3">
-          <v-img src="/images/logo/logiciels/Artist-noir.png" class="logo" />
-        </v-col>
-
-        <v-col cols="2">
-          <h5 class="solution-name">Opentalent Artist</h5>
-        </v-col>
-
-        <v-col cols="7">
-          <!-- list v-chip-->
-          <v-chip-group active-class="primary--text" column>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Agenda</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Facturation</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Comptabilité</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Communication</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Site internet</span>
-            </v-chip>
-          </v-chip-group>
-        </v-col>
-      </v-row>
-
-      <v-row v-if="!hideManagerRow" class="row-manager">
-        <v-col cols="3">
-          <v-img src="/images/logo/logiciels/Manager-noir.png" class="logo" />
-        </v-col>
-
-        <v-col cols="2">
-          <h5 class="solution-name">Opentalent Manager</h5>
-        </v-col>
-
-        <v-col cols="7">
-          <!-- list v-chip-->
-          <v-chip-group active-class="primary--text" column>
-            <v-chip class="ma-2 chip-custom" color="primary" label>
-              <span class="chip-detail">Agenda</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" color="primary" label>
-              <span class="chip-detail">Facturation</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" color="primary" label>
-              <span class="chip-detail">Comptabilité</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" color="primary" label>
-              <span class="chip-detail">Communication</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" color="primary" label>
-              <span class="chip-detail">Site internet</span>
-            </v-chip>
-          </v-chip-group>
-        </v-col>
-      </v-row>
-
-      <v-row v-if="!hideSchoolRow" class="row-school">
-        <v-col cols="3">
-          <v-img src="/images/logo/logiciels/School-noir.png" class="logo" />
-        </v-col>
-
-        <v-col cols="2">
-          <h5 class="solution-name">Opentalent Artist</h5>
-        </v-col>
-
-        <v-col cols="7">
-          <!-- list v-chip-->
-          <v-chip-group active-class="primary--text" column>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Agenda</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Facturation</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Comptabilité</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Communication</span>
-            </v-chip>
-            <v-chip class="ma-2 chip-custom" label>
-              <span class="chip-detail">Site internet</span>
-            </v-chip>
-          </v-chip-group>
-        </v-col>
-      </v-row>
-    </LayoutContainer>
-  </div>
-</template>
-
-<script setup>
-import { useRoute } from "vue-router";
-
-const route = useRoute();
-
-// Check the URL and set variables to determine which rows to hide
-const hideManagerRow = route.path.includes("opentalent_manager");
-const hideArtistRow = route.path.includes("opentalent_artist");
-const hideSchoolRow = route.path.includes("opentalent_school");
-</script>
-
-<style scoped>
-.chip-detail {
-  color: #000000;
-}
-.chip-custom {
-  color: white;
-  border: 1px solid #0e2d32;
-  border-radius: 3rem;
-  text-transform: uppercase;
-
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 16px;
-
-  display: flex;
-  align-items: center;
-  text-align: center;
-  letter-spacing: 0.2em;
-}
-
-.row-artist,
-.row-school,
-.row-manager {
-  border-top: 1px solid #d1cdc7;
-  margin-left: 2rem;
-  margin-right: 2rem;
-}
-
-.solution-name {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 1.5rem;
-  line-height: 1.5rem;
-  color: #0e2d32;
-}
-
-.row-artist, .row-school, .row-manager {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-}
-.solution-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 1.5rem;
-  line-height: 1.5rem;
-  color: #000000;
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-  text-align: center;
-}
-
-.logo {
-  width: 17rem;
-  height: 10rem;
-  margin-left: 2rem;
-  margin-right: 2rem;
-}
-</style>

+ 106 - 0
components/Logiciels/Manager/SomeNumbers.vue

@@ -0,0 +1,106 @@
+<template>
+  <LayoutContainer>
+    <v-row class="align-center">
+      <LayoutUISubTitle>
+        Quelques chiffres
+      </LayoutUISubTitle>
+    </v-row>
+
+    <v-container>
+      <v-row class="card-container justify-center mb-12">
+        <v-col
+          cols="3"
+          class="d-flex justify-center align-center small-padding"
+        >
+          <CommonCardStat
+            number="140"
+            text="Structures en réseau"
+          />
+        </v-col>
+        <v-col cols="3" class="d-flex justify-center align-center">
+          <CommonCardStat
+            number="300 000"
+            text="Utilisateurs"
+          />
+        </v-col>
+        <v-col cols="3" class="d-flex justify-center align-center">
+          <CommonCardStat
+            number="12"
+            text="Années de collaboration"
+          />
+        </v-col>
+      </v-row>
+    </v-container>
+
+    <v-row>
+      <v-col cols="12" class="justify-center">
+        <span class="cmf-trust-statement">
+          La plus grande Confédération Musicale de France nous fait confiance
+        </span>
+
+        <v-img
+          src="/images/logiciels/manager/cmf.jpg"
+          class="cmf-img mb-6"
+        />
+      </v-col>
+    </v-row>
+  </LayoutContainer>
+</template>
+
+<script setup lang="ts">
+
+</script>
+
+<style scoped lang="scss">
+.custom-row {
+  width: 90%;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.v-row {
+  max-width: 1600px;
+  margin: 0 auto;
+}
+
+:deep(h2) {
+  width: 60rem;
+}
+
+.card-container {
+  --primary-color-alt: white;
+
+  margin-left: auto;
+  margin-right: auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.alt-color {
+  color: var(--on-primary-color-alt);
+}
+
+.background-img {
+  width: 600px;
+  height: 400px;
+  background-size: cover;
+  background-position: center;
+}
+
+.cmf-img {
+  width: 30rem;
+  height: 18rem;
+  margin-top: 2rem;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.cmf-trust-statement {
+  font-size: 2rem;
+  text-align: center;
+  width: 100%;
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 0 - 324
components/Logiciels/School/Agenda.vue

@@ -1,324 +0,0 @@
-<template>
-  <LayoutContainer :overflow="false">
-    <v-row>
-      <v-col cols="4">
-        <h2 class="title">
-          L'agenda Opentalent
-        </h2>
-      </v-col>
-
-      <v-col cols="4">
-        <div class="d-flex justify-center align-center">
-          <div
-            class="carousel-button"
-            @click="goPrevious"
-          >
-            <i class="fas fa-chevron-left" />
-          </div>
-          <div
-            class="carousel-button"
-            @click="goNext"
-          >
-            <i class="fas fa-chevron-right" />
-          </div>
-        </div>
-      </v-col>
-
-      <v-col cols="4">
-        <v-btn
-          class="btn-news"
-          text
-        >
-          VOIR TOUTES LES ACTUALITÉS
-        </v-btn>
-      </v-col>
-    </v-row>
-
-    <p class="agenda-details">
-      Retrouvez tous les évènements culturels autour de chez vous.
-    </p>
-
-    <v-row>
-      <v-col cols="12">
-        <Carousel
-          ref="carousel"
-          :items-to-show="3"
-          :items-to-scroll="2"
-        >
-          <Slide
-            v-for="(event, eventIndex) in events"
-            :key="eventIndex"
-            class="slide-card"
-          >
-            <div class="card">
-              <img
-                class="card-img-top"
-                :src="event.img"
-                alt="Card image cap"
-              >
-              <div class="card-body">
-                <small class="card-rdv">{{ event.rdv }}</small>
-                <h5 class="card-title">
-                  {{ event.title }}
-                </h5>
-                <p class="card-localisation">
-                  {{ event.localisation }}
-                </p>
-              </div>
-
-              <div class="card-footer">
-                <v-chip-group
-                  active-class="primary--text"
-                  column
-                >
-                  <v-chip
-                    v-for="(tag, tagIndex) in event.tags"
-                    :key="tagIndex"
-                    class="ma-2 chip-custom"
-                    :color="tagColor(tag)"
-                    label
-                  >
-                    <span :class="tagTextColor(tag)">{{ tag }}</span>
-                  </v-chip>
-                </v-chip-group>
-              </div>
-            </div>
-          </Slide>
-        </Carousel>
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup>
-import { ref } from "vue";
-import { Carousel, Slide } from "vue3-carousel";
-import "vue3-carousel/dist/carousel.css";
-const tagColor = (tag) => {
-  switch (tag) {
-    case "Payant":
-      return "red";
-    case "Gratuit":
-      return "green";
-    default:
-      return "primary";
-  }
-};
-
-const tagTextColor = (tag) => {
-  switch (tag) {
-    case "Payant":
-      return "red--text";
-    case "Gratuit":
-      return "green--text";
-    default:
-      return "black--text";
-  }
-};
-const events = ref([
-  {
-    rdv: "20h00",
-    title: "LA NUIT DES RÊVES  ",
-    localisation: "FESTIVALDE musique - LONGCHAMP",
-    date: "21/06/2023",
-    img: "/images/agenda/agenda2.jpg",
-    tags: ["Festival", "Musique", "Tout public", "Payant"],
-  },
-  {
-    rdv: "20h00",
-    title: "LE LAC DES CYGNES",
-    localisation: "SPECTACLE DE DANSE - PARIS 1",
-    date: "22/06/2023",
-    img: "/images/agenda/agenda3.jpg",
-    tags: ["Festival", "Musique", "Tout public", "Gratuit"],
-  },
-  {
-    rdv: "20h00",
-    title: "SOLIDAYS 2023  : 23 > 25 juin",
-    localisation: "ORCHESTRE DE PARIS - PARIS 12",
-    date: "23/06/2023",
-    img: "/images/agenda/agenda4.jpg",
-    tags: ["Festival", "Musique", "Tout public", "Payant"],
-  },
-  {
-    rdv: "20h00",
-    title: "LE LAC DES CYGNES",
-    localisation: "FESTIVALDE musique - LONGCHAMP",
-    date: "24/06/2023",
-    img: "/images/agenda/agenda5.jpg",
-    tags: ["Festival", "Musique", "Tout public", "Payant"],
-  },
-  {
-    rdv: "20h00",
-    title: "SOLIDAYS 2023  : 23 > 25 juin ",
-    localisation: "SPECTACLE DE DANSE - PARIS 1",
-    date: "20/06/2023",
-    img: "/images/agenda/agenda1.jpg",
-    tags: ["Festival", "Musique", "Tout public", "Payant"],
-  },
-]);
-
-let carousel;
-
-const goPrevious = () => carousel.prev();
-const goNext = () => carousel.next();
-</script>
-
-<style scoped>
-.green--text {
-  color: green;
-}
-
-.red--text {
-  color: red;
-}
-.black--text {
-  color: black;
-}
-.btn-news {
-  color: #9edbdd;
-  border-radius: 2rem;
-  font-family: "Barlow";
-  background: transparent;
-  border: 1px solid #9edbdd;
-  border-radius: 6px;
-  font-style: normal;
-  font-weight: 600;
-  text-transform: uppercase;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  padding: 25px;
-  font-size: 10px;
-  line-height: 15px;
-}
-.chip-detail {
-  color: #000000;
-}
-.chip-custom {
-  color: white;
-  border: 1px solid #0e2d32;
-  border-radius: 3rem;
-  text-transform: uppercase;
-  font-family: "Barlow";
-  font-style: normal;
-  display: flex;
-  align-items: center;
-  text-align: center;
-}
-
-.card-localisation {
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-  font-size: 10px;
-  color: #112528;
-}
-.card {
-  border-radius: 15px 15px 0 0;
-  margin-bottom: 2rem;
-  width: 90%;
-}
-
-.icon-title {
-  color: #64afb7;
-  margin-top: 4.5rem;
-}
-.container-title {
-  display: flex;
-  align-items: center;
-  margin-left: 2rem;
-  margin-top: 4.5rem;
-}
-
-.carousel-button i {
-  color: #000000;
-}
-.card-text {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 16px;
-  line-height: 18px;
-  margin-bottom: 1rem;
-  color: #091d20;
-}
-.card-title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  font-size: 20px;
-  line-height: 24px;
-  display: flex;
-  align-items: center;
-  letter-spacing: 0.18em;
-  text-transform: uppercase;
-}
-.card-date {
-  font-size: 0.8em;
-  color: #888;
-  margin-left: 1rem;
-}
-
-.card-footer {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.card-body {
-  text-align: left;
-  margin-bottom: 1rem;
-  margin-left: 1rem;
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 500;
-  line-height: 24px;
-  color: #112528;
-}
-
-.card-img-top {
-  border-radius: 9px 9px 0 0;
-  width: 100%;
-  object-fit: cover;
-  object-position: center;
-}
-
-.title,
-.carousel-button,
-.btn-news {
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-}
-.agenda-details {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 300;
-  font-size: 16px;
-  line-height: 20px;
-  margin-left: 2rem;
-  color: #091d20;
-  margin-bottom: 3rem;
-  width: 15rem;
-}
-.title {
-  font-family: "Barlow";
-  font-style: normal;
-  font-weight: 600;
-  font-size: 42px;
-  line-height: 42px;
-  margin-left: 2rem;
-  color: #071b1f;
-}
-
-.carousel-button {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 40px;
-  height: 40px;
-  background-color: transparent;
-  border: 2px solid #000000;
-  cursor: pointer;
-  margin-right: 1rem;
-}
-</style>

+ 10 - 48
components/Logiciels/School/Avantages.vue

@@ -1,48 +1,24 @@
+<!--
+Section "Avantages" de la page du logiciel School
+-->
 <template>
-  <div id="Avantages">
-    <LayoutContainer>
-      <v-row class=" row-custom" >
-     
-
-        <LayoutUISubTitle
-            :iconSize="6"
-            :iconClasses="iconClasses"
-            :titleText="'Découvrez les avantages de la solution'"
-          />
-          <LayoutUITitle title="Des avantages concrets" />
-
-      </v-row>
-
-      <v-row class="row-custom"  >
-
-        <v-col cols="12" md="4" offset-md="1"  v-for="(card, index) in cards" :key="index">
-          <CommonCardAvantageCard
-            :title="card.title"
-            :number="card.number"
-            :description="card.description"
-            :image="card.image"
-            :isMemberCMF="card.isMemberCMF"
-            :numberColor="card.numberColor"
-          />
-        </v-col>
-
-      </v-row>
-    </LayoutContainer>
-  </div>
+  <AnchoredSection id="benefits">
+    <CommonAvantages :benefits="benefits" />
+  </AnchoredSection>
 </template>
 
-<script setup>
-import { ref } from 'vue';
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { Benefit } from "~/types/interface";
 
 // Exemple de données pour les cartes
-const cards = ref([
+const benefits: Ref<Array<Benefit>> = ref([
   {
     title: 'Un gain de temps',
     number: '01',
     description: 'Centralisez toutes vos informations sur un seul et même outil et ne perdez plus de temps avec des fichiers sur diverses applications.',
     image: '/images/avantages/school/temps.jpg',
     isMemberCMF: true,
-    
   },
   {
     title: 'Une activité structurée',
@@ -61,17 +37,3 @@ const cards = ref([
 ]);
 
 </script>
-
-<style scoped>
-
-.row-custom{
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  width: 90%;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-</style>

+ 0 - 37
components/Logiciels/School/Banner.vue

@@ -1,37 +0,0 @@
-<template>
-  <LayoutContainer>
-    <v-row>
-      <CommonBannerTitle
-        :leftText="'Artist'"
-        :centerText="'Opentalent School'"
-        :rightText="'Manager'"
-      />
-    </v-row>
-
-    <v-row>
-      <v-col cols="12">
-        <CommonBanner
-          :imageSrc="'/images/solutions/school.jpg'"
-          imageAlt="'line'"
-          :squareText="'École de musique, d\'art, de danse, de cirque, conservatoires et MJC'"
-          :logoSrc="'/images/logo/logiciels/School-Blanc.png'"
-        />
-      </v-col>
-    </v-row>
-  </LayoutContainer>
-</template>
-
-<script setup></script>
-
-<style scoped>
-
-.v-container{
-  padding-left: 0;
-  padding-right: 0;
-}
-
-:deep().cover-image {
-  object-position: center 40% !important;
-}
-
-</style>

+ 70 - 87
components/Logiciels/School/Comparatif.vue

@@ -1,129 +1,112 @@
 <template>
-  <div id="Comparatif">
-    <LayoutContainer class="mt-6">
-      <LayoutUISubTitle
-          :iconSize="6"
-          :iconClasses="iconClasses"
-          :titleText="' Comparatif de nos solutions'"
-        />
-        <LayoutUITitle
-          title="Choisissez la version qui vous convient ! "
-        />
+  <AnchoredSection id="comparative">
+    <LayoutContainer>
+      <LayoutUISubTitle>
+        Comparatif de nos solutions
+      </LayoutUISubTitle>
 
-        <CommonTableComparatif
-        :standardPrice="'32,90€'"
-        :premiumPrice="'46,20€'"
-        :color="'#0e2d32'"
-        :stripeColor="'rgba(32, 147, 190, 0.2)'"
-        :tableData="tableData"
+      <LayoutUITitle>
+        Choisissez la version qui vous convient !
+      </LayoutUITitle>
+
+      <CommonTableComparatif
+        standardPrice="32,90€"
+        premiumPrice="46,20€"
+        :items="comparisonItems"
       />
     </LayoutContainer>
-  </div>
+  </AnchoredSection>
 </template>
 
-<script setup>
-const tableData = [
+<script setup lang="ts">
+import AnchoredSection from "~/components/Layout/AnchoredSection.vue";
+import type { ComparisonItem } from "~/types/interface";
+
+const comparisonItems: Array<ComparisonItem> = [
   {
-    id: 1,
-    column1: "GESTION DU RÉPERTOIRE",
-    column2: "check",
-    column3: "check",
+    label: "GESTION DU RÉPERTOIRE",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 2,
-    column1: "AGENDA",
-    column2: "check",
-    column3: "check",
+    label: "AGENDA",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 3,
-    column1: "SUIVI PÉDAGOGIQUE",
-    column2: "check",
-    column3: "check",
+    label: "SUIVI PÉDAGOGIQUE",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 4,
-    column1: "GESTION DU PARC MATÉRIEL",
-    column2: "check",
-    column3: "check",
+    label: "GESTION DU PARC MATÉRIEL",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 5,
-    column1: "COMMUNICATION",
-    column2: "check",
-    column3: "check",
+    label: "COMMUNICATION",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 6,
-    column1: "SMS",
-    column2: "Option",
-    column3: "Option",
+    label: "SMS",
+    includedInStandard: "Option",
+    includedInPremium: "Option",
   },
   {
-    id: 6,
-    column1: "NOM DE DOMAINE",
-    column2: "Option",
-    column3: "Option",
+    label: "NOM DE DOMAINE",
+    includedInStandard: "Option",
+    includedInPremium: "Option",
   },
   {
-    id: 7,
-    column1: "SITE INTERNET",
-    column2: "check",
-    column3: "check",
+    label: "SITE INTERNET",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 8,
-    column1: "STATISTIQUES",
-    column2: "check",
-    column3: "check",
+    label: "STATISTIQUES",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 9,
-    column1: "FONCTIONNALITÉ DU RÉSEAU CMF",
-    column2: "check",
-    column3: "check",
+    label: "FONCTIONNALITÉ DU RÉSEAU CMF",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 10,
-    column1: "SAUVEGARDE",
-    column2: "check",
-    column3: "check",
+    label: "SAUVEGARDE",
+    includedInStandard: true,
+    includedInPremium: true,
   },
   {
-    id: 11,
-    column1: "EXTRANET UTILISATEURS",
-    column2: "cross",
-    column3: "Option",
+    label: "EXTRANET UTILISATEURS",
+    includedInStandard: false,
+    includedInPremium: "Option",
   },
   {
-    id: 12,
-    column1: "PRÉINSCRIPTION EN LIGNE",
-    column2: "cross",
-    column3: "Option",
+    label: "PRÉINSCRIPTION EN LIGNE",
+    includedInStandard: false,
+    includedInPremium: "Option",
   },
   {
-    id: 13,
-    column1: "GRILLES D'ÉVALUATION",
-    column2: "check",
-    column3: "Option",
+    label: "GRILLES D'ÉVALUATION",
+    includedInStandard: true,
+    includedInPremium: "Option",
   },
   {
-    id: 14,
-    column1: "GESTION DES RÈGLEMENTS",
-    column2: "Option",
-    column3: "Option",
+    label: "GESTION DES RÈGLEMENTS",
+    includedInStandard: "Option",
+    includedInPremium: "Option",
   },
   {
-    id: 15,
-    column1: "ESPACE DE STOCKAGE",
-    column2: "500 Mo",
-    column3: "1 Go",
+    label: "ESPACE DE STOCKAGE",
+    includedInStandard: "500 Mo",
+    includedInPremium: "1 Go",
   },
   {
-    id: 16,
-    column1: "PAGE DU SITE INTERNET",
-    column2: "restreint",
-    column3: "illimités",
+    label: "PAGE DU SITE INTERNET",
+    includedInStandard: "restreint",
+    includedInPremium: "illimités",
   },
 ];
 </script>

部分文件因为文件数量过多而无法显示