From 72cb11d797ce81cfa486447f46a7bb47f19becab Mon Sep 17 00:00:00 2001
From: Bastien DUMONT <bdumont@grandlyon.com>
Date: Wed, 28 Sep 2022 12:34:33 +0000
Subject: [PATCH] Feat/us827 custom alert

---
 template.env => .env.template                 |  10 +-
 .gitlab-ci.yml                                |  28 +-
 .vscode/settings.json                         |   6 +-
 README.md                                     |   3 +-
 docker-compose.local.yml                      |   3 +-
 src/axios.config.ts                           |   7 +
 src/components/Consents/Consents.tsx          |  13 +-
 src/components/Consents/consents.module.scss  |   5 -
 src/components/DateSelector/dateSelector.scss |   4 +-
 src/components/Editing/CustomEditor.tsx       |   5 +-
 src/components/Editing/CustomLink.tsx         |   5 +-
 src/components/Editing/Editing.tsx            |  55 +++-
 src/components/Editing/editing.scss           |   8 +-
 src/components/ImagePicker/ImagePicker.tsx    |   3 +-
 src/components/ImagePicker/SingleImage.tsx    |   4 +-
 src/components/ImagePicker/imagePicker.scss   |   2 +-
 src/components/Layout/Layout.tsx              |   4 +-
 src/components/Layout/layout.module.scss      |   4 +-
 src/components/MailSuject/mailSubject.scss    |   1 -
 src/components/Menu/Menu.tsx                  |   3 +-
 src/components/Menu/menu.scss                 |  14 +-
 src/components/Navbar/Navbar.tsx              |  21 +-
 src/components/PartnersInfo/PartnersInfo.tsx  | 187 ------------
 src/components/PartnersInfo/partnersInfo.scss |  59 ----
 src/components/Prices/PriceSection.tsx        |   6 +-
 src/components/Routes/Routes.tsx              |   8 +-
 src/components/Settings/Settings.tsx          | 287 ++++++++++++++++--
 src/components/Settings/settings.scss         | 115 +++++++
 src/constants/routes.json                     |  12 +-
 src/enum/checkboxType.enum.ts                 |   8 +-
 src/models/cutomPopup.model.ts                |   5 +
 src/models/route.model.ts                     |   6 +
 src/services/consent.service.ts               |  25 +-
 src/services/customPopup.service.ts           |  42 +++
 src/services/newsletter.service.ts            | 137 +++------
 src/services/partnersInfo.service.ts          |  14 +-
 src/services/prices.service.ts                |  15 +-
 src/styles/config/_colors.scss                |   2 +
 src/styles/config/_typography.scss            |   2 +-
 src/utils/editorStateManagment.ts             |   3 +-
 40 files changed, 649 insertions(+), 492 deletions(-)
 rename template.env => .env.template (79%)
 create mode 100644 src/axios.config.ts
 delete mode 100644 src/components/PartnersInfo/PartnersInfo.tsx
 delete mode 100644 src/components/PartnersInfo/partnersInfo.scss
 create mode 100644 src/components/Settings/settings.scss
 create mode 100644 src/models/cutomPopup.model.ts
 create mode 100644 src/models/route.model.ts
 create mode 100644 src/services/customPopup.service.ts

diff --git a/template.env b/.env.template
similarity index 79%
rename from template.env
rename to .env.template
index bd65fa3b..ea19ce6a 100644
--- a/template.env
+++ b/.env.template
@@ -2,8 +2,9 @@ NODE_TLS_REJECT_UNAUTHORIZED = '0'
 HTTPS=true
 SSL_CRT_FILE=cert.pem
 SSL_KEY_FILE=key.pem
-# Common 
-HOSTNAME=
+
+# Common settings
+HOSTNAME=localhost
 ADMIN_ROLE=
 DEBUG_MODE=
 MOCK_OAUTH2=
@@ -22,4 +23,7 @@ LOGOUT_URL=
 # Access to the database
 DATABASE_USER=
 DATABASE_PASSWORD=
-DATABASE_NAME=
\ No newline at end of file
+DATABASE_NAME=
+
+SGE_API_TOKEN=
+MEILI_MASTER_KEY=
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 173b5115..d8f2bbe9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,15 +1,15 @@
-image: docker:git
-
-services:
-  - docker:dind
+default:
+  image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:14.19.3-alpine
+  services:
+    - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:20.10.9-dind
+      alias: docker
 
 variables:
-  DOCKER_DRIVER: overlay2
-  DOCKER_TLS_CERTDIR: ''
+  DEPENDENCY_PROXY: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/
 
 stages:
-  - build
   - quality
+  - build
 
 build-test:
   stage: build
@@ -40,13 +40,15 @@ build:
 sonarqube:
   stage: quality
   only:
-    - dev
     - merge_requests
-  when: manual
-  image: registry.forge.grandlyon.com/apoyen2/sonnar-scanner-gl:master
-  before_script:
-    - export NODE_PATH=$NODE_PATH:`npm root -g`
-    - npm install -g typescript
+  image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/sonarsource/sonar-scanner-cli:4
+  variables:
+    SONAR_USER_HOME: '${CI_PROJECT_DIR}/.sonar' # Defines the location of the analysis task cache
+    GIT_DEPTH: '0' # T
+  cache:
+    key: '${CI_JOB_NAME}'
+    paths:
+      - .sonar/cache
   script:
     - >
       sonar-scanner
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 2a18744c..1adc76b2 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -24,5 +24,9 @@
     "source.fixAll.eslint": true
   },
   "editor.defaultFormatter": "esbenp.prettier-vscode",
-  "peacock.color": "#2aa63d"
+  "peacock.color": "#2aa63d",
+  "sonarlint.connectedMode.project": {
+    "connectionId": "sonarqube-forge-grandlyon",
+    "projectKey": "web-et-numerique-llle-project-backoffice-client"
+  }
 }
diff --git a/README.md b/README.md
index 5546d2b2..c587f93a 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,12 @@ You can then clone the app repository and install dependencies:
 ```sh
 $ git clone https://forge.grandlyon.com/web-et-numerique/llle_project/backoffice-client.git
 $ cd backoffice-client
+yarn
 ```
 
 ## Local usage
 
-Before launching the application, ensure you've properly filled the .env file according to the template. If needed please refer to a team member.
+Before launching the application, ensure you've properly filled the **.env** file according to the .env.template. If needed please refer to a team member.
 
 In order to launch the projet in local with the backend working launch the following command
 
diff --git a/docker-compose.local.yml b/docker-compose.local.yml
index d8cbe45f..eb54fa96 100644
--- a/docker-compose.local.yml
+++ b/docker-compose.local.yml
@@ -52,7 +52,8 @@ services:
       PMA_HOST: database-agent
 
   backend:
-    image: registry.forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server:test-US821
+    # --When using yarn local-up build backoffice service image with: docker build . -t backoffice-server
+    image: backoffice-server
     depends_on:
       database-agent:
         condition: service_healthy
diff --git a/src/axios.config.ts b/src/axios.config.ts
new file mode 100644
index 00000000..15a9dfbb
--- /dev/null
+++ b/src/axios.config.ts
@@ -0,0 +1,7 @@
+import { AxiosRequestConfig } from 'axios'
+
+export const getAxiosXSRFHeader = (token: string): AxiosRequestConfig => ({
+  headers: {
+    'XSRF-TOKEN': token,
+  },
+})
diff --git a/src/components/Consents/Consents.tsx b/src/components/Consents/Consents.tsx
index 5d06fdfb..4b7eb3cb 100644
--- a/src/components/Consents/Consents.tsx
+++ b/src/components/Consents/Consents.tsx
@@ -25,6 +25,7 @@ import DowloadModal from './DowloadModal'
 import { ConsentService } from '../../services/consent.service'
 import { UserContextProps, UserContext } from '../../hooks/userContext'
 import { IConsent } from '../../models/consent.model'
+import { getAxiosXSRFHeader } from '../../axios.config'
 
 const Consents: React.FC = () => {
   const [gridApi, setGridApi] = useState<GridApi | null>(null)
@@ -87,12 +88,14 @@ const Consents: React.FC = () => {
       headerName: 'Nom',
       initialWidth: 200,
       filter: true,
+      cellStyle: { 'text-transform': 'uppercase' },
     },
     {
       field: 'firstname',
       headerName: 'Prénom',
       initialWidth: 200,
       filter: true,
+      cellStyle: { 'text-transform': 'capitalize' },
     },
   ])
   const handleChangePage = useCallback(
@@ -131,13 +134,13 @@ const Consents: React.FC = () => {
         if (newSearch) {
           consentsData = await consentService.searchConsent(
             newSearch,
-            user.xsrftoken
+            getAxiosXSRFHeader(user.xsrftoken)
           )
         } else {
           const consentPagination = await consentService.getConsents(
             rowsPerPage,
             page,
-            user.xsrftoken
+            getAxiosXSRFHeader(user.xsrftoken)
           )
           consentsData = consentPagination && consentPagination.rows
         }
@@ -235,7 +238,7 @@ const Consents: React.FC = () => {
         const consentsPaginationData = await consentService.getConsents(
           rowsPerPage,
           page,
-          user.xsrftoken
+          getAxiosXSRFHeader(user.xsrftoken)
         )
         if (consentsPaginationData) {
           setConsents(consentsPaginationData.rows)
@@ -257,12 +260,12 @@ const Consents: React.FC = () => {
       <div className={styles.content + ' content'}>
         <div className={styles.searchField}>
           <div className={styles.inputGroup}>
-            <label htmlFor="search">N° PDL / Nom: </label>
+            <label htmlFor="search">Recherche</label>
             <input
               value={search}
               name="search"
               type="text"
-              placeholder="N° PDL / Nom"
+              placeholder="N°PDL, Nom, Prénom..."
               onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                 handleSearchChange(e.target.value)
               }
diff --git a/src/components/Consents/consents.module.scss b/src/components/Consents/consents.module.scss
index b2787aa8..2a5ef405 100644
--- a/src/components/Consents/consents.module.scss
+++ b/src/components/Consents/consents.module.scss
@@ -7,12 +7,7 @@
   height: $small-nav-height !important;
 }
 .content {
-  padding-top: $small-nav-height !important;
-  margin-top: 1rem !important;
-  background: #121212;
-  min-height: 100vh;
   background: $dark-bg;
-  min-height: 100vh;
 }
 .searchField {
   max-width: 750px;
diff --git a/src/components/DateSelector/dateSelector.scss b/src/components/DateSelector/dateSelector.scss
index 8154e6a4..5d079413 100644
--- a/src/components/DateSelector/dateSelector.scss
+++ b/src/components/DateSelector/dateSelector.scss
@@ -8,7 +8,7 @@
   height: 3rem;
   margin: auto;
   max-width: 250px;
-  @media screen and(min-width: $width-desktop) {
+  @media screen and (min-width: $width-desktop) {
     position: relative;
     left: -2rem;
   }
@@ -16,10 +16,8 @@
     @include text-large();
     color: white;
     font-weight: 600;
-    margin: 0 0.4rem;
     min-width: 150px;
     text-align: center;
-    margin: auto;
   }
   .arrow {
     cursor: pointer;
diff --git a/src/components/Editing/CustomEditor.tsx b/src/components/Editing/CustomEditor.tsx
index fe837c1b..3fae4902 100644
--- a/src/components/Editing/CustomEditor.tsx
+++ b/src/components/Editing/CustomEditor.tsx
@@ -1,9 +1,8 @@
-import React from 'react'
 import { stateToHTML } from 'draft-js-export-html'
-import { useCallback, useMemo, useState } from 'react'
+import React, { useCallback, useMemo, useState } from 'react'
 import { Editor, EditorState } from 'react-draft-wysiwyg'
-import CustomLink from './CustomLink'
 import './customEditor.scss'
+import CustomLink from './CustomLink'
 
 interface CustomEditorProps {
   baseState: EditorState
diff --git a/src/components/Editing/CustomLink.tsx b/src/components/Editing/CustomLink.tsx
index aeb17571..46bb1d97 100644
--- a/src/components/Editing/CustomLink.tsx
+++ b/src/components/Editing/CustomLink.tsx
@@ -1,7 +1,6 @@
-import React from 'react'
-import { EditorState, Modifier, ContentState } from 'draft-js'
+import { ContentState, EditorState, Modifier } from 'draft-js'
 import htmlToDraft from 'html-to-draftjs'
-import { useState } from 'react'
+import React, { useState } from 'react'
 
 interface EcolyoLinkProps {
   onChange?: (editorState: EditorState) => void
diff --git a/src/components/Editing/Editing.tsx b/src/components/Editing/Editing.tsx
index 30637e61..4de59e72 100644
--- a/src/components/Editing/Editing.tsx
+++ b/src/components/Editing/Editing.tsx
@@ -19,6 +19,7 @@ import MonthlyNews from '../MonthlyNews/MonthlyNews'
 import Loader from '../Loader/Loader'
 import Modal from '../Modal/Modal'
 import './editing.scss'
+import { getAxiosXSRFHeader } from '../../axios.config'
 
 export type ContentItems =
   | 'monthlyInfo'
@@ -58,7 +59,11 @@ const Editing: React.FC = () => {
 
   const handleSaveSubject = async (): Promise<void> => {
     if (user) {
-      await newsletterService.saveMailSubject(date, subject, user.xsrftoken)
+      await newsletterService.saveMailSubject(
+        date,
+        subject,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setIsTouched(false)
     }
   }
@@ -69,7 +74,7 @@ const Editing: React.FC = () => {
         date,
         info,
         imageURL,
-        user.xsrftoken
+        getAxiosXSRFHeader(user.xsrftoken)
       )
       setIsTouched(false)
     }
@@ -81,14 +86,19 @@ const Editing: React.FC = () => {
         date,
         title,
         content,
-        user.xsrftoken
+        getAxiosXSRFHeader(user.xsrftoken)
       )
       setIsTouched(false)
     }
   }
   const handleSavePoll = async (): Promise<void> => {
     if (user) {
-      await newsletterService.savePoll(date, question, link, user.xsrftoken)
+      await newsletterService.savePoll(
+        date,
+        question,
+        link,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setIsTouched(false)
     }
   }
@@ -98,25 +108,37 @@ const Editing: React.FC = () => {
 
   const handleDeleteMailSubject = async (): Promise<void> => {
     if (user) {
-      await newsletterService.deleteMailSubject(date, user.xsrftoken)
+      await newsletterService.deleteMailSubject(
+        date,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setRefreshData(true)
     }
   }
   const handleDeleteMonthlyInfo = async (): Promise<void> => {
     if (user) {
-      await newsletterService.deleteMonthlyInfo(date, user.xsrftoken)
+      await newsletterService.deleteMonthlyInfo(
+        date,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setRefreshData(true)
     }
   }
   const handleDeleteMonthlyNews = async (): Promise<void> => {
     if (user) {
-      await newsletterService.deleteMonthlyNews(date, user.xsrftoken)
+      await newsletterService.deleteMonthlyNews(
+        date,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setRefreshData(true)
     }
   }
   const handleDeletePoll = async (): Promise<void> => {
     if (user) {
-      await newsletterService.deletePoll(date, user.xsrftoken)
+      await newsletterService.deletePoll(
+        date,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setRefreshData(true)
     }
   }
@@ -213,14 +235,23 @@ const Editing: React.FC = () => {
     async function getCurrentMonthlyNews() {
       if (user) {
         const mailSubject: IMailSubject | null =
-          await newsletterService.getSingleMailSubject(date, user.xsrftoken)
+          await newsletterService.getSingleMailSubject(
+            date,
+            getAxiosXSRFHeader(user.xsrftoken)
+          )
         const montlhyInfo: IMonthlyInfo | null =
-          await newsletterService.getSingleMonthlyInfo(date, user.xsrftoken)
+          await newsletterService.getSingleMonthlyInfo(
+            date,
+            getAxiosXSRFHeader(user.xsrftoken)
+          )
         const montlhyNews: IMonthlyNews | null =
-          await newsletterService.getSingleMonthlyNews(date, user.xsrftoken)
+          await newsletterService.getSingleMonthlyNews(
+            date,
+            getAxiosXSRFHeader(user.xsrftoken)
+          )
         const poll: IPoll | null = await newsletterService.getSinglePoll(
           date,
-          user.xsrftoken
+          getAxiosXSRFHeader(user.xsrftoken)
         )
         if (mailSubject) {
           setSubject(mailSubject.subject)
diff --git a/src/components/Editing/editing.scss b/src/components/Editing/editing.scss
index 82c9a2f6..e2c8832d 100644
--- a/src/components/Editing/editing.scss
+++ b/src/components/Editing/editing.scss
@@ -3,22 +3,18 @@
 @import '../../styles/config/breakpoints';
 
 .header {
-  position: fixed;
-  z-index: 1500;
+  padding: 1.5rem;
   width: inherit;
   background: radial-gradient(
     74.83% 76.97% at 50% 13.64%,
     #343641 0%,
     #1b1c22 100%
   );
-  height: $navigator-height;
   box-shadow: 0px 5px 5px rgb(0 0 0 / 0%), 0px 3px 14px rgb(0 0 0 / 0%),
     0px 8px 10px rgb(0 0 0 / 15%);
-  padding: 1.7rem;
 }
 .content {
   padding: 1rem;
-  margin-top: $navigator-height;
 }
 .subtitle {
   margin: 1rem 0;
@@ -28,7 +24,7 @@ hr {
 }
 .buttons {
   display: flex;
-  @media screen and(max-width: $width-tablet) {
+  @media screen and (max-width: $width-tablet) {
     flex-direction: column;
     button {
       width: 100%;
diff --git a/src/components/ImagePicker/ImagePicker.tsx b/src/components/ImagePicker/ImagePicker.tsx
index c3625b96..cce9b48a 100644
--- a/src/components/ImagePicker/ImagePicker.tsx
+++ b/src/components/ImagePicker/ImagePicker.tsx
@@ -4,6 +4,7 @@ import Modal from '../Modal/Modal'
 import Pagination from '@material-ui/lab/Pagination'
 import SingleImage from './SingleImage'
 import { UserContext, UserContextProps } from '../../hooks/userContext'
+import { getAxiosXSRFHeader } from '../../axios.config'
 
 interface ImagePickerProps {
   imageURL: string
@@ -53,7 +54,7 @@ const ImagePicker: React.FC<ImagePickerProps> = ({
       if (user) {
         const newsletterService = new NewsletterService()
         const images = await newsletterService.getEcogestureImages(
-          user.xsrftoken
+          getAxiosXSRFHeader(user.xsrftoken)
         )
         //Split array depending on page numbers
         setpageCount(Math.ceil(images.length / imagePerPage))
diff --git a/src/components/ImagePicker/SingleImage.tsx b/src/components/ImagePicker/SingleImage.tsx
index b217b1b1..94d2f5c6 100644
--- a/src/components/ImagePicker/SingleImage.tsx
+++ b/src/components/ImagePicker/SingleImage.tsx
@@ -11,8 +11,8 @@ const SingleImage: React.FC<SingleImageProps> = ({
   selectedImage,
   setSelectedImageURL,
 }: SingleImageProps) => {
-  const selectImage = (imageURL: string) => {
-    setSelectedImageURL(imageURL)
+  const selectImage = (targetImage: string) => {
+    setSelectedImageURL(targetImage)
   }
   return (
     <img
diff --git a/src/components/ImagePicker/imagePicker.scss b/src/components/ImagePicker/imagePicker.scss
index 2d1b5855..249a9917 100644
--- a/src/components/ImagePicker/imagePicker.scss
+++ b/src/components/ImagePicker/imagePicker.scss
@@ -5,7 +5,7 @@
   display: flex;
   flex-wrap: wrap;
   justify-content: center;
-  @media screen and(max-width: $width-tablet) {
+  @media screen and (max-width: $width-tablet) {
     .ecogesture-image {
       max-width: 80px;
       max-height: 80px;
diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx
index 9dd09a7d..440e00c2 100644
--- a/src/components/Layout/Layout.tsx
+++ b/src/components/Layout/Layout.tsx
@@ -14,9 +14,7 @@ const Layout: React.FC<LayoutProps> = ({ children }: LayoutProps) => {
       const test: boolean =
         /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
           navigator.userAgent
-        )
-          ? true
-          : window.innerWidth < 768
+        ) || window.innerWidth < 768
           ? true
           : false
       setisMobile(test)
diff --git a/src/components/Layout/layout.module.scss b/src/components/Layout/layout.module.scss
index 3ca31348..c6214223 100644
--- a/src/components/Layout/layout.module.scss
+++ b/src/components/Layout/layout.module.scss
@@ -14,7 +14,7 @@
   height: 100vh;
   z-index: 1501;
 
-  @media screen and(max-width: $width-tablet) {
+  @media screen and (max-width: $width-tablet) {
     width: 0;
     display: none;
   }
@@ -35,7 +35,7 @@
   box-shadow: 0px 5px 5px rgb(0 0 0 / 20%), 0px 3px 14px rgb(0 0 0 / 12%),
     0px 8px 10px rgb(0 0 0 / 14%);
   background: $dark-bg;
-  @media screen and(max-width: $width-tablet) {
+  @media screen and (max-width: $width-tablet) {
     margin-left: 0;
     padding-bottom: $navbar-height;
   }
diff --git a/src/components/MailSuject/mailSubject.scss b/src/components/MailSuject/mailSubject.scss
index 87f0d6d6..de327758 100644
--- a/src/components/MailSuject/mailSubject.scss
+++ b/src/components/MailSuject/mailSubject.scss
@@ -1,5 +1,4 @@
 .mailSubject {
-  margin: 2rem 0;
   .title {
     margin: 1rem 0;
   }
diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx
index 10b2d90f..05b3b168 100644
--- a/src/components/Menu/Menu.tsx
+++ b/src/components/Menu/Menu.tsx
@@ -5,6 +5,7 @@ import './menu.scss'
 import { NavLink } from 'react-router-dom'
 import { UserContext } from '../../hooks/userContext'
 import { useAuth } from '../../hooks/useAuth'
+import { Route } from '../../models/route.model'
 
 const Menu: React.FC = () => {
   const { user } = useContext(UserContext)
@@ -15,7 +16,7 @@ const Menu: React.FC = () => {
         <img src={logo} alt="Ecolyo logo" className="logo" />
       </div>
       <div className="menu-list">
-        {routes.map((route: any, index: number) => {
+        {routes.map((route: Route, index: number) => {
           return (
             <NavLink key={index} to={route.path} activeClassName="active">
               {route.label}
diff --git a/src/components/Menu/menu.scss b/src/components/Menu/menu.scss
index 4520ef89..e6917fe4 100644
--- a/src/components/Menu/menu.scss
+++ b/src/components/Menu/menu.scss
@@ -8,11 +8,7 @@
   padding: 1.875rem;
   box-shadow: 0px 5px 5px rgb(0 0 0 / 20%), 0px 3px 14px rgb(0 0 0 / 12%),
     0px 8px 10px rgb(0 0 0 / 14%);
-  border-top: unset;
-  border-right: unset;
-  background-color: $grey-dark;
-  position: relative;
-  z-index: 1501;
+  background-color: $grey-light;
 
   .logo-container {
     display: flex;
@@ -28,13 +24,15 @@
     color: $text-grey;
     font-size: 1rem;
 
+    &.active {
+      color: $gold;
+      font-weight: 700;
+    }
+
     &:hover {
       color: $gold;
     }
   }
-  .active {
-    color: $gold;
-  }
   .menu-list {
     margin-top: 1.5rem;
   }
diff --git a/src/components/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx
index a41458c3..ad45dd3f 100644
--- a/src/components/Navbar/Navbar.tsx
+++ b/src/components/Navbar/Navbar.tsx
@@ -1,10 +1,10 @@
 import React, { useContext } from 'react'
 import { NavLink } from 'react-router-dom'
-import editing from '../../assets/icons/editing.svg'
-import settings from '../../assets/icons/settings.svg'
-import './navbar.scss'
-import { UserContext } from '../../hooks/userContext'
+import routes from '../../constants/routes.json'
 import { useAuth } from '../../hooks/useAuth'
+import { UserContext } from '../../hooks/userContext'
+import { Route } from '../../models/route.model'
+import './navbar.scss'
 
 const Navbar: React.FC = () => {
   const { user } = useContext(UserContext)
@@ -12,14 +12,11 @@ const Navbar: React.FC = () => {
   return (
     <div className="navbar">
       <div className="menu-list">
-        <NavLink to={'/editing'} activeClassName="active">
-          <img src={editing} className="navbar-icon" alt="Editing icon" />
-          Edition
-        </NavLink>
-        <NavLink to={'/settings'} activeClassName="active">
-          <img src={settings} className="navbar-icon" alt="Settings icon" />
-          Paramètres
-        </NavLink>
+        {routes.map((route: Route, index: number) => (
+          <NavLink key={index} to={route.path} activeClassName="active">
+            {route.label}
+          </NavLink>
+        ))}
       </div>
       {user && (
         <button className="btnValid logButton" onClick={logoutUser}>
diff --git a/src/components/PartnersInfo/PartnersInfo.tsx b/src/components/PartnersInfo/PartnersInfo.tsx
deleted file mode 100644
index 0988b3d7..00000000
--- a/src/components/PartnersInfo/PartnersInfo.tsx
+++ /dev/null
@@ -1,187 +0,0 @@
-import React, { useCallback, useContext, useEffect, useState } from 'react'
-import { IPartnersInfo } from '../../models/partnersInfo.model'
-import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
-import './partnersInfo.scss'
-import { PartnersInfoService } from '../../services/partnersInfo.service'
-import { UserContext, UserContextProps } from '../../hooks/userContext'
-import Loader from '../Loader/Loader'
-import { CheckboxType } from '../../enum/checkboxType.enum'
-
-const PartnersInfo: React.FC = () => {
-  const [refreshData, setRefreshData] = useState(false)
-  const [isLoading, setIsLoading] = useState<boolean>(false)
-  const [partnersInfo, setPartnersInfo] = useState<IPartnersInfo>({
-    grdf_failure: false,
-    enedis_failure: false,
-    egl_failure: false,
-    notification_activated: false,
-  })
-  const { user }: Partial<UserContextProps> = useContext(UserContext)
-
-  const handleCheckboxChange = (value: boolean, type: CheckboxType): void => {
-    switch (type) {
-      case CheckboxType.GRDF:
-        setPartnersInfo((prevPartnersInfo) => ({
-          ...prevPartnersInfo,
-          grdf_failure: value,
-        }))
-        break
-      case CheckboxType.ENEDIS:
-        setPartnersInfo((prevPartnersInfo) => ({
-          ...prevPartnersInfo,
-          enedis_failure: value,
-        }))
-        break
-      case CheckboxType.EGL:
-        setPartnersInfo((prevPartnersInfo) => ({
-          ...prevPartnersInfo,
-          egl_failure: value,
-        }))
-        break
-      case CheckboxType.NOTIFICATION:
-        setPartnersInfo((prevPartnersInfo) => ({
-          ...prevPartnersInfo,
-          notification_activated: value,
-        }))
-        break
-      default:
-        throw new Error('Unknown checkbox type')
-    }
-  }
-
-  const handleCancel = useCallback(() => {
-    setRefreshData(true)
-  }, [setRefreshData])
-
-  const resetFields = useCallback(() => {
-    setPartnersInfo({
-      grdf_failure: false,
-      enedis_failure: false,
-      egl_failure: false,
-      notification_activated: false,
-    })
-  }, [setPartnersInfo])
-
-  useEffect(() => {
-    let subscribed = true
-    resetFields()
-    setIsLoading(true)
-
-    async function getPartnersInfo() {
-      if (user) {
-        const partnersInfoService = new PartnersInfoService()
-        const partnersInfoResp: IPartnersInfo | null =
-          await partnersInfoService.getPartnersInfo()
-        if (partnersInfoResp) {
-          setPartnersInfo({
-            grdf_failure: partnersInfoResp.grdf_failure,
-            enedis_failure: partnersInfoResp.enedis_failure,
-            egl_failure: partnersInfoResp.egl_failure,
-            notification_activated: partnersInfoResp.notification_activated,
-          })
-        }
-      }
-      setIsLoading(false)
-    }
-    if (subscribed) {
-      getPartnersInfo()
-    }
-    return () => {
-      subscribed = false
-      setRefreshData(false)
-    }
-  }, [user, refreshData, setPartnersInfo, resetFields])
-
-  const handleSave = async (): Promise<void> => {
-    if (user) {
-      const partnersInfoService = new PartnersInfoService()
-      await partnersInfoService.savePartnersInfo(partnersInfo, user.xsrftoken)
-    }
-  }
-
-  return (
-    <>
-      {isLoading ? (
-        <Loader />
-      ) : (
-        <div className="partnersInfo">
-          <h2>État des services des partenaires</h2>
-          <div>
-            <p className="title">Affichage de la pop-up dans Ecolyo</p>
-            <div className="switch_div">
-              Pop-up active
-              <input
-                type="checkbox"
-                id="switch_notification"
-                onChange={(event) => {
-                  handleCheckboxChange(
-                    event.currentTarget.checked,
-                    CheckboxType.NOTIFICATION
-                  )
-                }}
-                checked={partnersInfo.notification_activated}
-              />
-              <label htmlFor="switch_notification"></label>
-            </div>
-            <p className="title">Services concernés</p>
-            <div className="switch_div">
-              Panne Enedis
-              <input
-                type="checkbox"
-                id="switch_enedis"
-                onChange={(event) => {
-                  handleCheckboxChange(
-                    event.currentTarget.checked,
-                    CheckboxType.ENEDIS
-                  )
-                }}
-                checked={partnersInfo.enedis_failure}
-              />
-              <label htmlFor="switch_enedis"></label>
-            </div>
-            <div className="switch_div">
-              Panne EGL
-              <input
-                type="checkbox"
-                id="switch_egl"
-                onChange={(event) => {
-                  handleCheckboxChange(
-                    event.currentTarget.checked,
-                    CheckboxType.EGL
-                  )
-                }}
-                checked={partnersInfo.egl_failure}
-              />
-              <label htmlFor="switch_egl"></label>
-            </div>
-            <div className="switch_div">
-              Panne GRDF
-              <input
-                type="checkbox"
-                id="switch_grdf"
-                onChange={(event) => {
-                  handleCheckboxChange(
-                    event.currentTarget.checked,
-                    CheckboxType.GRDF
-                  )
-                }}
-                checked={partnersInfo.grdf_failure}
-              />
-              <label htmlFor="switch_grdf"></label>
-            </div>
-            <div className="buttons">
-              <button className="btnCancel" onClick={handleCancel}>
-                Annuler
-              </button>
-              <button className="btnValid" onClick={handleSave}>
-                Sauvegarder
-              </button>
-            </div>
-          </div>
-        </div>
-      )}
-    </>
-  )
-}
-
-export default PartnersInfo
diff --git a/src/components/PartnersInfo/partnersInfo.scss b/src/components/PartnersInfo/partnersInfo.scss
deleted file mode 100644
index 27de6e11..00000000
--- a/src/components/PartnersInfo/partnersInfo.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-.partnersInfo {
-  margin: 2rem 0;
-  .title {
-    margin: 1rem 0;
-  }
-  h2 {
-    margin-bottom: 1rem;
-  }
-
-  .switch_div {
-    display: inline-block;
-    padding: 1rem 1rem;
-    min-width: 135px;
-  }
-
-  input[type='checkbox'] {
-    width: 0;
-    height: 0;
-    visibility: hidden;
-    margin-bottom: 15px;
-  }
-
-  label {
-    display: block;
-    width: 50px;
-    height: 20px;
-    background-color: grey;
-    border-radius: 15px;
-    position: relative;
-    cursor: pointer;
-    transition: 0.5s;
-    box-shadow: 0 0 20px #80808050;
-  }
-
-  label::after {
-    content: '';
-    width: 17px;
-    height: 17px;
-    background-color: #e8f5f7;
-    position: absolute;
-    border-radius: 13px;
-    top: 2px;
-    left: 2px;
-    transition: 0.5s;
-  }
-
-  input:checked + label:after {
-    left: calc(100% - 3px);
-    transform: translateX(-100%);
-  }
-
-  input:checked + label {
-    background-color: #e3b82a;
-  }
-
-  label:active:after {
-    width: 34px;
-  }
-}
diff --git a/src/components/Prices/PriceSection.tsx b/src/components/Prices/PriceSection.tsx
index 51aee446..9be61bd3 100644
--- a/src/components/Prices/PriceSection.tsx
+++ b/src/components/Prices/PriceSection.tsx
@@ -13,6 +13,7 @@ import dayjs from 'dayjs'
 import utc from 'dayjs/plugin/utc'
 import timezone from 'dayjs/plugin/timezone'
 import PriceRow from './PriceRow'
+import { getAxiosXSRFHeader } from '../../axios.config'
 dayjs.extend(utc)
 dayjs.extend(timezone)
 
@@ -61,7 +62,10 @@ const PriceSection: React.FC<PriceSectionProps> = ({
         ...priceToSave,
         price: parseFloat(priceToSave.price as string),
       }
-      await priceService.savePrice(formattedPrice, user.xsrftoken)
+      await priceService.savePrice(
+        formattedPrice,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
       setRefreshData(true)
     }
   }, [priceToSave, user])
diff --git a/src/components/Routes/Routes.tsx b/src/components/Routes/Routes.tsx
index df33cea6..9e022e2e 100644
--- a/src/components/Routes/Routes.tsx
+++ b/src/components/Routes/Routes.tsx
@@ -15,10 +15,10 @@ const Routes: React.FC = () => {
     <Switch>
       {user && <Redirect path="/login" to="/editing" />}
       <Route path="/login" component={Login} />
-      <PrivateRoute path="/editing" component={Editing} exact />
-      <PrivateRoute path="/prices" component={Prices} exact />
-      <PrivateRoute path="/settings" component={Settings} exact />
-      <PrivateRoute path="/consents" component={Consents} exact />
+      <PrivateRoute exact path="/editing" component={Editing} />
+      <PrivateRoute exact path="/prices" component={Prices} />
+      <PrivateRoute exact path="/settings" component={Settings} />
+      <PrivateRoute exact path="/consents" component={Consents} />
       <Redirect path="*" to="/editing" />
     </Switch>
   )
diff --git a/src/components/Settings/Settings.tsx b/src/components/Settings/Settings.tsx
index e7aaaa50..62b9b304 100644
--- a/src/components/Settings/Settings.tsx
+++ b/src/components/Settings/Settings.tsx
@@ -1,17 +1,270 @@
-import React from 'react'
-import PartnersInfo from '../PartnersInfo/PartnersInfo'
-
-const Settings: React.FC = () => {
-  return (
-    <>
-      <div className="header">
-        <p className="title pagetitle">Paramètres de l&apos;appli</p>
-      </div>
-
-      <div className="content">
-        <PartnersInfo />
-      </div>
-    </>
-  )
-}
-export default Settings
+import React, { useCallback, useContext, useEffect, useState } from 'react'
+import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
+import { getAxiosXSRFHeader } from '../../axios.config'
+import { CheckboxType } from '../../enum/checkboxType.enum'
+import { UserContext, UserContextProps } from '../../hooks/userContext'
+import { ICustomPopup } from '../../models/cutomPopup.model'
+import { IPartnersInfo } from '../../models/partnersInfo.model'
+import { CustomPopupService } from '../../services/customPopup.service'
+import { PartnersInfoService } from '../../services/partnersInfo.service'
+import Loader from '../Loader/Loader'
+import './settings.scss'
+
+const Settings: React.FC = () => {
+  const [refreshData, setRefreshData] = useState(false)
+  const [isLoading, setIsLoading] = useState(false)
+  const [partnersInfo, setPartnersInfo] = useState<IPartnersInfo>({
+    grdf_failure: false,
+    enedis_failure: false,
+    egl_failure: false,
+    notification_activated: false,
+  })
+  const [customPopup, setCustomPopup] = useState<ICustomPopup>({
+    popupEnabled: false,
+    title: '',
+    description: '',
+  })
+  const { user }: Partial<UserContextProps> = useContext(UserContext)
+
+  const isPartnerNotificationOn = () =>
+    partnersInfo.enedis_failure ||
+    partnersInfo.egl_failure ||
+    partnersInfo.grdf_failure
+
+  const handleCheckboxChange = (value: boolean, type: CheckboxType): void => {
+    switch (type) {
+      case CheckboxType.GRDF:
+        setPartnersInfo((prevPartnersInfo) => ({
+          ...prevPartnersInfo,
+          grdf_failure: value,
+        }))
+        break
+      case CheckboxType.ENEDIS:
+        setPartnersInfo((prevPartnersInfo) => ({
+          ...prevPartnersInfo,
+          enedis_failure: value,
+        }))
+        break
+      case CheckboxType.EGL:
+        setPartnersInfo((prevPartnersInfo) => ({
+          ...prevPartnersInfo,
+          egl_failure: value,
+        }))
+        break
+      case CheckboxType.CUSTOM:
+        setCustomPopup((prev) => ({
+          ...prev,
+          popupEnabled: value,
+        }))
+        break
+      default:
+        throw new Error('Unknown checkbox type')
+    }
+  }
+
+  const handlePopupChange = (
+    event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
+    field: 'title' | 'description'
+  ) => {
+    setCustomPopup((prev) => ({
+      ...prev,
+      [field]: event.target.value,
+    }))
+  }
+
+  const handleCancel = useCallback(() => {
+    setRefreshData(true)
+  }, [setRefreshData])
+
+  const resetFields = useCallback(() => {
+    setPartnersInfo({
+      grdf_failure: false,
+      enedis_failure: false,
+      egl_failure: false,
+      notification_activated: false,
+    })
+  }, [setPartnersInfo])
+
+  useEffect(() => {
+    let subscribed = true
+    resetFields()
+    setIsLoading(true)
+
+    async function getSettings() {
+      if (user) {
+        const partnersInfoService = new PartnersInfoService()
+        const customPopupService = new CustomPopupService()
+        const partnersInfoData = await partnersInfoService.getPartnersInfo()
+        const customPopupData = await customPopupService.getCustomPopupInfo()
+
+        if (partnersInfoData) {
+          setPartnersInfo({
+            ...partnersInfoData,
+          })
+        }
+        if (customPopupData) {
+          setCustomPopup({
+            ...customPopupData,
+          })
+        }
+      }
+      setIsLoading(false)
+    }
+    if (subscribed) {
+      getSettings()
+    }
+    return () => {
+      subscribed = false
+      setRefreshData(false)
+    }
+  }, [user, refreshData, setPartnersInfo, setCustomPopup, resetFields])
+
+  const handleSave = async (): Promise<void> => {
+    if (user) {
+      const partnersInfoService = new PartnersInfoService()
+      const customPopupService = new CustomPopupService()
+      const updatedPartnersInfo = {
+        egl_failure: partnersInfo.egl_failure,
+        enedis_failure: partnersInfo.enedis_failure,
+        grdf_failure: partnersInfo.grdf_failure,
+        notification_activated: isPartnerNotificationOn(),
+      }
+      await partnersInfoService.savePartnersInfo(
+        updatedPartnersInfo,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
+      await customPopupService.saveCustomPopup(
+        customPopup,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
+    }
+  }
+
+  return (
+    <>
+      <div className="header">
+        <p className="title pagetitle">Paramètres de l&apos;appli</p>
+      </div>
+
+      <div className="content">
+        {isLoading && <Loader />}
+        {!isLoading && (
+          <>
+            <h1>Création de Pop-up</h1>
+            <div className="partnersInfo">
+              <h2 className="title">Affichage des pop-up de panne</h2>
+              <p>Services concernés</p>
+              <div className="switch_div">
+                <span>Panne Enedis</span>
+                <input
+                  type="checkbox"
+                  id="switch_enedis"
+                  onChange={(event) => {
+                    handleCheckboxChange(
+                      event.currentTarget.checked,
+                      CheckboxType.ENEDIS
+                    )
+                  }}
+                  checked={partnersInfo.enedis_failure}
+                />
+                <label htmlFor="switch_enedis"></label>
+              </div>
+              <div className="switch_div">
+                <span>Panne EGL</span>
+                <input
+                  type="checkbox"
+                  id="switch_egl"
+                  onChange={(event) => {
+                    handleCheckboxChange(
+                      event.currentTarget.checked,
+                      CheckboxType.EGL
+                    )
+                  }}
+                  checked={partnersInfo.egl_failure}
+                />
+                <label htmlFor="switch_egl"></label>
+              </div>
+              <div className="switch_div">
+                <span>Panne GRDF</span>
+                <input
+                  type="checkbox"
+                  id="switch_grdf"
+                  onChange={(event) => {
+                    handleCheckboxChange(
+                      event.currentTarget.checked,
+                      CheckboxType.GRDF
+                    )
+                  }}
+                  checked={partnersInfo.grdf_failure}
+                />
+                <label htmlFor="switch_grdf"></label>
+              </div>
+            </div>
+
+            <div className="customInfo">
+              <h2 className="title">Affichage de pop-up personnalisée</h2>
+              <div className="switch_div">
+                <span>Pop-up active</span>
+                <input
+                  type="checkbox"
+                  id="switch_popup"
+                  checked={customPopup.popupEnabled}
+                  onChange={(event) => {
+                    handleCheckboxChange(
+                      event.currentTarget.checked,
+                      CheckboxType.CUSTOM
+                    )
+                  }}
+                />
+                <label htmlFor="switch_popup"></label>
+              </div>
+              {customPopup.popupEnabled && (
+                <>
+                  <div className="popupTitle">
+                    <label htmlFor="title">Titre</label>
+                    <input
+                      type="text"
+                      name="title"
+                      id="title"
+                      placeholder="Titre"
+                      value={customPopup.title}
+                      onChange={(event) => handlePopupChange(event, 'title')}
+                    />
+                  </div>
+                  <div className="popupDescription">
+                    <label htmlFor="description">Description</label>
+                    <textarea
+                      name="description"
+                      id="description"
+                      placeholder="Description"
+                      rows={5}
+                      maxLength={250}
+                      value={customPopup.description}
+                      onChange={(event) =>
+                        handlePopupChange(event, 'description')
+                      }
+                    />
+                    <p className="count">
+                      {customPopup.description.length} / 250
+                    </p>
+                  </div>
+                </>
+              )}
+            </div>
+
+            <div className="buttons">
+              <button className="btnCancel" onClick={handleCancel}>
+                Annuler
+              </button>
+              <button className="btnValid" onClick={handleSave}>
+                Sauvegarder
+              </button>
+            </div>
+          </>
+        )}
+      </div>
+    </>
+  )
+}
+
+export default Settings
diff --git a/src/components/Settings/settings.scss b/src/components/Settings/settings.scss
new file mode 100644
index 00000000..1d4a66f9
--- /dev/null
+++ b/src/components/Settings/settings.scss
@@ -0,0 +1,115 @@
+@import '../../styles/config/colors';
+
+h2.title {
+  margin: 1rem 0;
+}
+
+.partnersInfo {
+  margin: 2rem 0;
+  h1 {
+    margin-bottom: 1rem;
+  }
+
+  p {
+    color: $text-grey;
+  }
+}
+
+.popupTitle {
+  margin-bottom: 1.5rem;
+}
+
+.popupTitle,
+.popupDescription {
+  display: flex;
+  flex-direction: column;
+  gap: 0.5rem;
+
+  label {
+    text-transform: uppercase;
+    font-weight: 700;
+  }
+
+  input,
+  textarea {
+    background: inherit;
+    border-radius: 4px;
+    border: 1px solid $text-chart;
+    max-width: 600px;
+    padding: 1rem;
+    color: $text-grey;
+    font-size: 1rem;
+  }
+
+  .count {
+    color: $text-dark;
+    max-width: 600px;
+    height: 19px;
+    font-weight: 400;
+    font-size: 0.8rem;
+    display: flex;
+    justify-content: flex-end;
+  }
+}
+
+.buttons {
+  position: fixed;
+  bottom: 1rem;
+  display: flex;
+  transform: translate(-25%);
+  left: 50%;
+}
+
+.switch_div {
+  display: inline-block;
+  padding: 1rem 1rem;
+  min-width: 135px;
+
+  span {
+    color: $text-dark;
+  }
+
+  input[type='checkbox'] {
+    width: 0;
+    height: 0;
+    visibility: hidden;
+    margin-bottom: 15px;
+  }
+
+  label {
+    display: block;
+    width: 50px;
+    height: 20px;
+    background-color: grey;
+    border-radius: 15px;
+    position: relative;
+    cursor: pointer;
+    transition: 0.5s;
+    box-shadow: 0 0 20px #80808050;
+  }
+
+  label::after {
+    content: '';
+    width: 17px;
+    height: 17px;
+    background-color: #e8f5f7;
+    position: absolute;
+    border-radius: 13px;
+    top: 2px;
+    left: 2px;
+    transition: 0.5s;
+  }
+
+  input:checked + label:after {
+    left: calc(100% - 3px);
+    transform: translateX(-100%);
+  }
+
+  input:checked + label {
+    background-color: #e3b82a;
+  }
+
+  label:active:after {
+    width: 34px;
+  }
+}
diff --git a/src/constants/routes.json b/src/constants/routes.json
index 05020de3..edb9f999 100644
--- a/src/constants/routes.json
+++ b/src/constants/routes.json
@@ -1,18 +1,18 @@
 [
   {
-    "label": "Edition",
-    "path": "/editing"
+    "label": "Consentements",
+    "path": "/consents"
   },
   {
-    "label": "Prix",
-    "path": "/prices"
+    "label": "Edition",
+    "path": "/editing"
   },
   {
     "label": "Paramètres",
     "path": "/settings"
   },
   {
-    "label": "Consentements",
-    "path": "/consents"
+    "label": "Prix",
+    "path": "/prices"
   }
 ]
diff --git a/src/enum/checkboxType.enum.ts b/src/enum/checkboxType.enum.ts
index 6363fcef..c5b6eb0c 100644
--- a/src/enum/checkboxType.enum.ts
+++ b/src/enum/checkboxType.enum.ts
@@ -1,6 +1,6 @@
 export enum CheckboxType {
-  NOTIFICATION = 0,
-  GRDF = 1,
-  ENEDIS = 2,
-  EGL = 3,
+  GRDF,
+  ENEDIS,
+  EGL,
+  CUSTOM,
 }
diff --git a/src/models/cutomPopup.model.ts b/src/models/cutomPopup.model.ts
new file mode 100644
index 00000000..9af8abd2
--- /dev/null
+++ b/src/models/cutomPopup.model.ts
@@ -0,0 +1,5 @@
+export interface ICustomPopup {
+  description: string
+  popupEnabled: boolean
+  title: string
+}
diff --git a/src/models/route.model.ts b/src/models/route.model.ts
new file mode 100644
index 00000000..116f14c7
--- /dev/null
+++ b/src/models/route.model.ts
@@ -0,0 +1,6 @@
+export interface Route {
+  label: string
+  path: string
+}
+
+export interface Routes extends Array<Route> {}
diff --git a/src/services/consent.service.ts b/src/services/consent.service.ts
index b0674288..fdfd233a 100644
--- a/src/services/consent.service.ts
+++ b/src/services/consent.service.ts
@@ -2,7 +2,7 @@ import {
   ConsentPaginationEntity,
   IConsentPagination,
 } from './../models/consent.model'
-import axios from 'axios'
+import axios, { AxiosRequestConfig } from 'axios'
 import { ConsentEntity, IConsent } from '../models/consent.model'
 import { toast } from 'react-toastify'
 import { DateTime } from 'luxon'
@@ -11,18 +11,17 @@ export class ConsentService {
   /**
    * Search for consents
    * @param search
-   * @param token
+   * @param axiosHeaders
    */
   public searchConsent = async (
     search: string,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IConsent[] | null> => {
     try {
-      const { data } = await axios.get(`/api/admin/consent?search=${search}`, {
-        headers: {
-          'XSRF-TOKEN': token,
-        },
-      })
+      const { data } = await axios.get(
+        `/api/admin/consent?search=${search}`,
+        axiosHeaders
+      )
       const consentEntities = data as ConsentEntity[]
       return consentEntities.map((entity) => this.parseConsent(entity))
     } catch (e: any) {
@@ -42,21 +41,17 @@ export class ConsentService {
    * Gets consents
    * @param limit
    * @param page
-   * @param token
+   * @param axiosHeaders
    */
   public getConsents = async (
     limit: number,
     page: number,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IConsentPagination | null> => {
     try {
       const { data } = await axios.get(
         `/api/admin/consent?limit=${limit}&page=${page}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       const consentPagination = data as ConsentPaginationEntity
       return this.parseConsentPagination(consentPagination)
diff --git a/src/services/customPopup.service.ts b/src/services/customPopup.service.ts
new file mode 100644
index 00000000..63580b78
--- /dev/null
+++ b/src/services/customPopup.service.ts
@@ -0,0 +1,42 @@
+import axios, { AxiosRequestConfig } from 'axios'
+import { toast } from 'react-toastify'
+import { ICustomPopup } from '../models/cutomPopup.model'
+
+export class CustomPopupService {
+  /**
+   * Save the customPopup info
+   * @param customPopup
+   * @param axiosHeaders
+   */
+  public saveCustomPopup = async (
+    customPopup: ICustomPopup,
+    axiosHeaders: AxiosRequestConfig
+  ): Promise<void> => {
+    try {
+      await axios.put(
+        `/api/admin/customPopup`,
+        {
+          ...customPopup,
+        },
+        axiosHeaders
+      )
+      toast.success('Pop-up personnalisée enregistrée !')
+    } catch (e) {
+      toast.error("Erreur lors de l'enregistement de la pop-up personnalisée")
+      console.error(e)
+    }
+  }
+
+  /**
+   * Gets the custom pop-up information
+   */
+  public getCustomPopupInfo = async (): Promise<ICustomPopup | null> => {
+    try {
+      const { data } = await axios.get(`/api/common/customPopup`)
+      return data as ICustomPopup
+    } catch (e) {
+      console.error('error', e)
+      return null
+    }
+  }
+}
diff --git a/src/services/newsletter.service.ts b/src/services/newsletter.service.ts
index f0676360..e0ef1123 100644
--- a/src/services/newsletter.service.ts
+++ b/src/services/newsletter.service.ts
@@ -1,4 +1,4 @@
-import axios from 'axios'
+import axios, { AxiosRequestConfig } from 'axios'
 import { IMailSubject } from '../models/mailSubject.model'
 import { IMonthlyNews } from '../models/monthlyNews.model'
 import { IMonthlyInfo } from '../models/monthlyInfo.model'
@@ -9,12 +9,12 @@ export class NewsletterService {
    * Saves a mail subject for selected month
    * @param date
    * @param subject
-   * @param token
+   * @param axiosHeaders
    */
   public saveMailSubject = async (
     date: Date,
     subject: string,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.put(
@@ -24,11 +24,7 @@ export class NewsletterService {
           year: date.getFullYear(),
           subject: subject,
         },
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Mail subject succesfully saved !')
     } catch (e: any) {
@@ -46,20 +42,16 @@ export class NewsletterService {
   /**
    * Gets the mail subject for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public getSingleMailSubject = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IMailSubject | null> => {
     try {
       const { data } = await axios.get(
         `/api/admin/mailSubject/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       return data as IMailSubject
     } catch (e: any) {
@@ -71,20 +63,16 @@ export class NewsletterService {
   /**
    * Deletes the mail subject for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public deleteMailSubject = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.delete(
         `/api/admin/mailSubject/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Mail subject succesfully deleted !')
     } catch (e: any) {
@@ -108,7 +96,7 @@ export class NewsletterService {
     date: Date,
     info: string,
     image: string,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.put(
@@ -119,11 +107,7 @@ export class NewsletterService {
           info: info,
           image: image,
         },
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Monthly info succesfully saved !')
     } catch (e: any) {
@@ -141,20 +125,16 @@ export class NewsletterService {
   /**
    * Gets the information for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public getSingleMonthlyInfo = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IMonthlyInfo | null> => {
     try {
       const { data } = await axios.get(
         `/api/admin/monthlyInfo/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       return data as IMonthlyInfo
     } catch (e: any) {
@@ -166,20 +146,16 @@ export class NewsletterService {
   /**
    * Deletes a Monthly Info for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public deleteMonthlyInfo = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.delete(
         `/api/admin/monthlyInfo/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Monthly info succesfully deleted !')
     } catch (e: any) {
@@ -204,7 +180,7 @@ export class NewsletterService {
     date: Date,
     title: string,
     content: string,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.put(
@@ -215,11 +191,7 @@ export class NewsletterService {
           title: title,
           content: content,
         },
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Monthly news succesfully saved !')
     } catch (e: any) {
@@ -237,20 +209,16 @@ export class NewsletterService {
   /**
    * Gets a news title and content for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public getSingleMonthlyNews = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IMonthlyNews | null> => {
     try {
       const { data } = await axios.get(
         `/api/admin/monthlyNews/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       return data as IMonthlyNews
     } catch (e) {
@@ -262,20 +230,16 @@ export class NewsletterService {
   /**
    * Deletes a Monthly News for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public deleteMonthlyNews = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.delete(
         `/api/admin/monthlyNews/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Monthly news succesfully deleted !')
     } catch (e: any) {
@@ -300,7 +264,7 @@ export class NewsletterService {
     date: Date,
     question: string,
     link: string,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.put(
@@ -311,11 +275,7 @@ export class NewsletterService {
           link: link,
           question: question,
         },
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Poll successfully saved !')
     } catch (e: any) {
@@ -333,20 +293,16 @@ export class NewsletterService {
   /**
    * Gets a poll with question and link for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
   public getSinglePoll = async (
     date: Date,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<IPoll | null> => {
     try {
       const { data } = await axios.get(
         `/api/admin/poll/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       return data as IPoll
     } catch (e) {
@@ -358,17 +314,16 @@ export class NewsletterService {
   /**
    * Deletes a poll for selected month
    * @param date
-   * @param token
+   * @param axiosHeaders
    */
-  public deletePoll = async (date: Date, token: string): Promise<void> => {
+  public deletePoll = async (
+    date: Date,
+    axiosHeaders: AxiosRequestConfig
+  ): Promise<void> => {
     try {
       await axios.delete(
         `/api/admin/poll/${date.getFullYear()}/${date.getMonth() + 1}`,
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
       toast.success('Poll succesfully deleted !')
     } catch (e: any) {
@@ -386,18 +341,16 @@ export class NewsletterService {
   /**
    * Gets the ecogesture images URLs
    */
-  public getEcogestureImages = async (token: string): Promise<string[]> => {
+  public getEcogestureImages = async (
+    axiosHeaders: AxiosRequestConfig
+  ): Promise<string[]> => {
     try {
-      const { data: imageNames } = await axios.get(`/api/admin/imageNames`, {
-        headers: {
-          'XSRF-TOKEN': token,
-        },
-      })
+      const { data: imageNames } = await axios.get(
+        `/api/admin/imageNames`,
+        axiosHeaders
+      )
       if (imageNames && imageNames !== null) {
-        const imageURLs = imageNames.map((image: string) => {
-          return `/assets/ecogesture/${image}`
-        })
-        return imageURLs
+        return imageNames.map((image: string) => `/assets/ecogesture/${image}`)
       }
       return []
     } catch (e) {
diff --git a/src/services/partnersInfo.service.ts b/src/services/partnersInfo.service.ts
index 0b930759..dfa14f86 100644
--- a/src/services/partnersInfo.service.ts
+++ b/src/services/partnersInfo.service.ts
@@ -1,15 +1,15 @@
-import axios from 'axios'
+import axios, { AxiosRequestConfig } from 'axios'
 import { IPartnersInfo } from '../models/partnersInfo.model'
 import { toast } from 'react-toastify'
 export class PartnersInfoService {
   /**
    * Save the partnersInfo
    * @param partnersInfo
-   * @param token
+   * @param axiosHeaders
    */
   public savePartnersInfo = async (
     partnersInfo: IPartnersInfo,
-    token: string
+    axiosHeaders: AxiosRequestConfig
   ): Promise<void> => {
     try {
       await axios.put(
@@ -20,13 +20,9 @@ export class PartnersInfoService {
           egl_failure: partnersInfo.egl_failure,
           notification_activated: partnersInfo.notification_activated,
         },
-        {
-          headers: {
-            'XSRF-TOKEN': token,
-          },
-        }
+        axiosHeaders
       )
-      toast.success('Partners info succesfully saved !')
+      toast.success('Information des partenaires mises à jour !')
     } catch (e) {
       toast.error('Failed to save partners info')
       console.error(e)
diff --git a/src/services/prices.service.ts b/src/services/prices.service.ts
index 723b1360..addd6f98 100644
--- a/src/services/prices.service.ts
+++ b/src/services/prices.service.ts
@@ -1,19 +1,18 @@
-import axios from 'axios'
+import axios, { AxiosRequestConfig } from 'axios'
 import { toast } from 'react-toastify'
 import { IPrice } from '../models/price.model'
 export class PricesService {
   /**
    * Save the partnersInfo
    * @param price
-   * @param token
+   * @param axiosHeaders
    */
-  public savePrice = async (price: IPrice, token: string): Promise<void> => {
+  public savePrice = async (
+    price: IPrice,
+    axiosHeaders: AxiosRequestConfig
+  ): Promise<void> => {
     try {
-      await axios.put(`/api/admin/prices`, price, {
-        headers: {
-          'XSRF-TOKEN': token,
-        },
-      })
+      await axios.put(`/api/admin/prices`, price, axiosHeaders)
       toast.success('Price succesfully saved !')
     } catch (e) {
       toast.error('Failed to save price')
diff --git a/src/styles/config/_colors.scss b/src/styles/config/_colors.scss
index aed78557..2abf8f66 100644
--- a/src/styles/config/_colors.scss
+++ b/src/styles/config/_colors.scss
@@ -8,6 +8,8 @@ $gold: #e3b82a;
 $btn-gold: #f1c017;
 $dark-light: #1b1c22;
 $grey-dark: #25262b;
+$grey-light: #32343d;
 $dark-bg: #121212;
 $text-grey: #e0e0e0;
 $text-dark: #a0a0a0;
+$text-chart: #7b7b7b;
diff --git a/src/styles/config/_typography.scss b/src/styles/config/_typography.scss
index aff2788f..b37644cf 100644
--- a/src/styles/config/_typography.scss
+++ b/src/styles/config/_typography.scss
@@ -70,7 +70,7 @@ $main-spacing: 4px;
   @include baseButton();
   display: inline-block;
   margin-left: auto;
-  background: transparent;
+  background: $grey-dark;
   color: $gold;
   border: 1px solid $text-dark;
   &:hover {
diff --git a/src/utils/editorStateManagment.ts b/src/utils/editorStateManagment.ts
index 2102519e..dd3ff893 100644
--- a/src/utils/editorStateManagment.ts
+++ b/src/utils/editorStateManagment.ts
@@ -6,6 +6,5 @@ export const convertStringToEditorState = (string: string): EditorState => {
     blocksFromHTML.contentBlocks,
     blocksFromHTML.entityMap
   )
-  const editorState = EditorState.createWithContent(state)
-  return editorState
+  return EditorState.createWithContent(state)
 }
-- 
GitLab