From a6d9b39a5f34dad93a2192df22d9557a5b49c5df Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Fri, 27 Oct 2023 10:11:50 +0200 Subject: [PATCH 01/37] remove default env variables --- src/pages/_app.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 31e20063..f980e28f 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -43,16 +43,16 @@ const MyApp = (({ const getLayout = Component.getLayout ?? ((page) => ); const instance = FrontendVariables.getInstance(); - instance.BACK_API_PROTOCOL = backApiProtocol ?? "https://"; - instance.BACK_API_HOST = backApiHost ?? "api.stg.lecoffre.smart-chain.fr"; - instance.BACK_API_ROOT_URL = backApiRootUrl ?? "/api"; - instance.BACK_API_VERSION = backApiVersion ?? "/v1"; - instance.FRONT_APP_HOST = frontAppHost ?? "https://app.stg.lecoffre.smart-chain.fr"; - instance.IDNOT_BASE_URL = idNotBaseUrl ?? "https://qual-connexion.idnot.fr"; - instance.IDNOT_AUTHORIZE_ENDPOINT = idNotAuthorizeEndpoint ?? "/IdPOAuth2/authorize/idnot_idp_v1"; - instance.IDNOT_CLIENT_ID = idNotClientId ?? "4501646203F3EF67"; - instance.FC_AUTHORIZE_ENDPOINT= fcAuthorizeEndpoint ?? "https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize"; - instance.FC_CLIENT_ID = fcClientId ?? "211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e"; + instance.BACK_API_PROTOCOL = backApiProtocol; + instance.BACK_API_HOST = backApiHost; + instance.BACK_API_ROOT_URL = backApiRootUrl; + instance.BACK_API_VERSION = backApiVersion; + instance.FRONT_APP_HOST = frontAppHost; + instance.IDNOT_BASE_URL = idNotBaseUrl; + instance.IDNOT_AUTHORIZE_ENDPOINT = idNotAuthorizeEndpoint; + instance.IDNOT_CLIENT_ID = idNotClientId; + instance.FC_AUTHORIZE_ENDPOINT= fcAuthorizeEndpoint; + instance.FC_CLIENT_ID = fcClientId; instance.DOCAPOST_API_URL = docaposteApiUrl; return getLayout(); From 40831d9c0de919e86c6050a771bec143796fbdd8 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Fri, 27 Oct 2023 10:39:07 +0200 Subject: [PATCH 02/37] refacto env config --- src/pages/_app.tsx | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index f980e28f..46c35112 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -4,6 +4,7 @@ import "@Front/index.scss"; import type { NextPage } from "next"; import type { AppType, AppProps } from "next/app"; import type { ReactElement, ReactNode } from "react"; +import getConfig from 'next/config' export type NextPageWithLayout, TInitialProps = TProps> = NextPage & { getLayout?: (page: ReactElement) => ReactNode; @@ -25,6 +26,8 @@ type AppPropsWithLayout = AppProps & { docaposteApiUrl: string; }; +const { publicRuntimeConfig } = getConfig(); + const MyApp = (({ Component, pageProps, @@ -60,18 +63,18 @@ const MyApp = (({ MyApp.getInitialProps = async () => { return { - backApiProtocol: process.env["NEXT_PUBLIC_BACK_API_PROTOCOL"], - backApiHost: process.env["NEXT_PUBLIC_BACK_API_HOST"], - backApiRootUrl: process.env["NEXT_PUBLIC_BACK_API_ROOT_URL"], - backApiVersion: process.env["NEXT_PUBLIC_BACK_API_VERSION"], - frontAppHost: process.env["NEXT_PUBLIC_FRONT_APP_HOST"], - frontAppPort: process.env["NEXT_PUBLIC_FRONT_APP_PORT"], - idNotBaseUrl: process.env["NEXT_PUBLIC_IDNOT_BASE_URL"], - idNotAuthorizeEndpoint: process.env["NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT"], - idNotClientId: process.env["NEXT_PUBLIC_IDNOT_CLIENT_ID"], - fcAuthorizeEndpoint: process.env["NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT"], - fcClientId: process.env["NEXT_PUBLIC_FC_CLIENT_ID"], - docaposteApiUrl: process.env["NEXT_PUBLIC_DOCAPOST_API_URL"], + backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, + backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, + backApiRootUrl: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL, + backApiVersion: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION, + frontAppHost: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST, + frontAppPort: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_PORT, + idNotBaseUrl: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_BASE_URL, + idNotAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, + idNotClientId: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_CLIENT_ID, + fcAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT, + fcClientId: publicRuntimeConfig.NEXT_PUBLIC_FC_CLIENT_ID, + docaposteApiUrl: publicRuntimeConfig.NEXT_PUBLIC_DOCAPOST_API_URL, }; }; From fcc6f92ee874bda3112e593843c9204c4edb3dec Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Fri, 27 Oct 2023 10:59:26 +0200 Subject: [PATCH 03/37] log config --- src/pages/_app.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 46c35112..96ac146c 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -58,10 +58,13 @@ const MyApp = (({ instance.FC_CLIENT_ID = fcClientId; instance.DOCAPOST_API_URL = docaposteApiUrl; + console.log("instance", instance); + return getLayout(); }) as AppType; MyApp.getInitialProps = async () => { + console.log("runtime config", publicRuntimeConfig); return { backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, From c17236776a4fa8b67d72889414c7e40d8e77f11a Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Fri, 27 Oct 2023 11:06:43 +0200 Subject: [PATCH 04/37] try new env declaration --- next.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next.config.js b/next.config.js index b25da680..6db597c9 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,7 @@ const nextConfig = { reactStrictMode: false, publicRuntimeConfig: { // Will be available on both server and client - NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL, + NEXT_PUBLIC_BACK_API_PROTOCOL: process.env["NEXT_PUBLIC_BACK_API_PROTOCOL"], NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST, NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL, NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION, From 59fb35702980eb1204e39b92b5f12bec3f3bfd83 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 10:12:42 +0100 Subject: [PATCH 05/37] try server runtime config --- next.config.js | 15 ++++++++++++++- src/pages/_app.tsx | 27 ++++++++++++++------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/next.config.js b/next.config.js index 6db597c9..b2ceb073 100644 --- a/next.config.js +++ b/next.config.js @@ -4,7 +4,20 @@ const nextConfig = { reactStrictMode: false, publicRuntimeConfig: { // Will be available on both server and client - NEXT_PUBLIC_BACK_API_PROTOCOL: process.env["NEXT_PUBLIC_BACK_API_PROTOCOL"], + NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL, + NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST, + NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL, + NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION, + NEXT_PUBLIC_FRONT_APP_HOST: process.env.NEXT_PUBLIC_FRONT_APP_HOST, + NEXT_PUBLIC_FRONT_APP_PORT: process.env.NEXT_PUBLIC_FRONT_APP_PORT, + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: process.env.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, + NEXT_PUBLIC_IDNOT_CLIENT_ID: process.env.NEXT_PUBLIC_IDNOT_CLIENT_ID, + NEXT_PUBLIC_IDNOT_BASE_URL: process.env.NEXT_PUBLIC_IDNOT_BASE_URL, + NEXT_PUBLIC_DOCAPOSTE_API_URL: process.env.NEXT_PUBLIC_DOCAPOSTE_API_URL, + }, + + serverRuntimeConfig: { + NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL, NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST, NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL, NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION, diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 96ac146c..b9424204 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -26,7 +26,7 @@ type AppPropsWithLayout = AppProps & { docaposteApiUrl: string; }; -const { publicRuntimeConfig } = getConfig(); +const { publicRuntimeConfig, serverRuntimeConfig } = getConfig(); const MyApp = (({ Component, @@ -65,19 +65,20 @@ const MyApp = (({ MyApp.getInitialProps = async () => { console.log("runtime config", publicRuntimeConfig); + console.log("server runtime config", serverRuntimeConfig); return { - backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, - backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, - backApiRootUrl: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL, - backApiVersion: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION, - frontAppHost: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST, - frontAppPort: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_PORT, - idNotBaseUrl: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_BASE_URL, - idNotAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, - idNotClientId: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_CLIENT_ID, - fcAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT, - fcClientId: publicRuntimeConfig.NEXT_PUBLIC_FC_CLIENT_ID, - docaposteApiUrl: publicRuntimeConfig.NEXT_PUBLIC_DOCAPOST_API_URL, + backApiProtocol: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, + backApiHost: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, + backApiRootUrl: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL, + backApiVersion: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION, + frontAppHost: serverRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST, + frontAppPort: serverRuntimeConfig.NEXT_PUBLIC_FRONT_APP_PORT, + idNotBaseUrl: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_BASE_URL, + idNotAuthorizeEndpoint: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, + idNotClientId: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_CLIENT_ID, + fcAuthorizeEndpoint: serverRuntimeConfig.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT, + fcClientId: serverRuntimeConfig.NEXT_PUBLIC_FC_CLIENT_ID, + docaposteApiUrl: serverRuntimeConfig.NEXT_PUBLIC_DOCAPOST_API_URL, }; }; From 8b0ae0fa4942a95b1b5b63955dd0c4c38f01d6ab Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 10:58:55 +0100 Subject: [PATCH 06/37] copy env from builder --- Dockerfile | 2 ++ src/pages/_app.tsx | 25 +++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 11d63f6c..b8a0d2d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,7 @@ COPY --from=deps leCoffre-front/node_modules ./node_modules COPY --from=deps leCoffre-front/package.json package.json COPY tsconfig.json tsconfig.json COPY src src +COPY .env .env RUN npm run build @@ -34,6 +35,7 @@ WORKDIR leCoffre-front RUN adduser -D lecoffreuser --uid 10000 && chown -R lecoffreuser . COPY public ./public +COPY --from=builder --chown=lecoffreuser leCoffre-front/.env ./.env COPY --from=builder --chown=lecoffreuser leCoffre-front/node_modules ./node_modules COPY --from=builder --chown=lecoffreuser leCoffre-front/.next ./.next COPY --from=builder --chown=lecoffreuser leCoffre-front/package.json ./package.json diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index b9424204..a2e09430 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -66,19 +66,20 @@ const MyApp = (({ MyApp.getInitialProps = async () => { console.log("runtime config", publicRuntimeConfig); console.log("server runtime config", serverRuntimeConfig); + console.log("process env", process.env['NEXT_PUBLIC_BACK_API_PROTOCOL'] || "env undefined"); return { - backApiProtocol: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, - backApiHost: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, - backApiRootUrl: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL, - backApiVersion: serverRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION, - frontAppHost: serverRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST, - frontAppPort: serverRuntimeConfig.NEXT_PUBLIC_FRONT_APP_PORT, - idNotBaseUrl: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_BASE_URL, - idNotAuthorizeEndpoint: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, - idNotClientId: serverRuntimeConfig.NEXT_PUBLIC_IDNOT_CLIENT_ID, - fcAuthorizeEndpoint: serverRuntimeConfig.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT, - fcClientId: serverRuntimeConfig.NEXT_PUBLIC_FC_CLIENT_ID, - docaposteApiUrl: serverRuntimeConfig.NEXT_PUBLIC_DOCAPOST_API_URL, + backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, + backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, + backApiRootUrl: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL, + backApiVersion: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION, + frontAppHost: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST, + frontAppPort: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_PORT, + idNotBaseUrl: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_BASE_URL, + idNotAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, + idNotClientId: publicRuntimeConfig.NEXT_PUBLIC_IDNOT_CLIENT_ID, + fcAuthorizeEndpoint: publicRuntimeConfig.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT, + fcClientId: publicRuntimeConfig.NEXT_PUBLIC_FC_CLIENT_ID, + docaposteApiUrl: publicRuntimeConfig.NEXT_PUBLIC_DOCAPOST_API_URL, }; }; From f0c5bdf63669e9d759b31a89943d80fef6772c56 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 15:07:46 +0100 Subject: [PATCH 07/37] set env var for build job --- .circleci/config.yml | 18 ++++++++++++++++++ Dockerfile | 6 +++--- next.config.js | 14 ++++++++++++++ src/pages/_app.tsx | 3 ++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dfd1d18..ed4ca625 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,6 +52,24 @@ workflows: build-and-register-stg: jobs: - build-push-docker-image: + environment: + TAG: << pipeline.git.tag >> + NEXT_PUBLIC_ADMIN_ID: jelkvelknvlkn + NEXT_PUBLIC_BACK_API_HOST: api.stg.lecoffre.smart-chain.fr + NEXT_PUBLIC_BACK_API_PROTOCOL: https:// + NEXT_PUBLIC_BACK_API_ROOT_URL: /api + NEXT_PUBLIC_BACK_API_VERSION: /v1 + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize + NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e + NEXT_PUBLIC_FRONT_APP_HOST: https://app.stg.lecoffre.smart-chain.fr + NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" + NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" + NEXT_PUBLIC_DOCAPOST_API_URL: "https://preprod.id360docaposte.com/api/1.0.0" + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: 49508376-b160-475d-9224-9bb6511215b8 + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: 54c14875-f864-4819-8cd4-4fc6dd4a947b + NEXT_PUBLIC_DOCAPOST_APP_ID: leCoffre@smart_chain context: - sc-shared-prd filters: diff --git a/Dockerfile b/Dockerfile index b8a0d2d3..4bdea185 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN chmod 600 ~/.ssh/id_rsa RUN eval "$(ssh-agent -s)" && ssh-add /root/.ssh/id_rsa RUN ssh-keyscan github.com smart-chain-fr/leCoffre-resources.git >> /root/.ssh/known_hosts -RUN npm install --frozen-lockfile +# RUN npm install --frozen-lockfile # Rebuild the source code only when needed FROM node:19-alpine AS builder @@ -22,8 +22,8 @@ WORKDIR leCoffre-front COPY --from=deps leCoffre-front/node_modules ./node_modules COPY --from=deps leCoffre-front/package.json package.json COPY tsconfig.json tsconfig.json +COPY next.config.js next.config.js COPY src src -COPY .env .env RUN npm run build @@ -35,9 +35,9 @@ WORKDIR leCoffre-front RUN adduser -D lecoffreuser --uid 10000 && chown -R lecoffreuser . COPY public ./public -COPY --from=builder --chown=lecoffreuser leCoffre-front/.env ./.env COPY --from=builder --chown=lecoffreuser leCoffre-front/node_modules ./node_modules COPY --from=builder --chown=lecoffreuser leCoffre-front/.next ./.next +COPY --from=builder --chown=lecoffreuser leCoffre-front/next.config.js ./next.config.js COPY --from=builder --chown=lecoffreuser leCoffre-front/package.json ./package.json USER lecoffreuser diff --git a/next.config.js b/next.config.js index b2ceb073..997db3d9 100644 --- a/next.config.js +++ b/next.config.js @@ -28,6 +28,20 @@ const nextConfig = { NEXT_PUBLIC_IDNOT_BASE_URL: process.env.NEXT_PUBLIC_IDNOT_BASE_URL, NEXT_PUBLIC_DOCAPOSTE_API_URL: process.env.NEXT_PUBLIC_DOCAPOSTE_API_URL, }, + + env: { + NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL, + NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST, + NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL, + NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION, + NEXT_PUBLIC_FRONT_APP_HOST: process.env.NEXT_PUBLIC_FRONT_APP_HOST, + NEXT_PUBLIC_FRONT_APP_PORT: process.env.NEXT_PUBLIC_FRONT_APP_PORT, + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: process.env.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT, + NEXT_PUBLIC_IDNOT_CLIENT_ID: process.env.NEXT_PUBLIC_IDNOT_CLIENT_ID, + NEXT_PUBLIC_IDNOT_BASE_URL: process.env.NEXT_PUBLIC_IDNOT_BASE_URL, + NEXT_PUBLIC_DOCAPOSTE_API_URL: process.env.NEXT_PUBLIC_DOCAPOSTE_API_URL, + }, + // webpack: config => { // config.node = { // fs: 'empty', diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index a2e09430..bce2c795 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -26,7 +26,7 @@ type AppPropsWithLayout = AppProps & { docaposteApiUrl: string; }; -const { publicRuntimeConfig, serverRuntimeConfig } = getConfig(); +const { publicRuntimeConfig, serverRuntimeConfig, env } = getConfig(); const MyApp = (({ Component, @@ -67,6 +67,7 @@ MyApp.getInitialProps = async () => { console.log("runtime config", publicRuntimeConfig); console.log("server runtime config", serverRuntimeConfig); console.log("process env", process.env['NEXT_PUBLIC_BACK_API_PROTOCOL'] || "env undefined"); + console.log("env config", env); return { backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, From e5c51e211a802eda36c2c4233d73e63c3e6ff63f Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 16:59:42 +0100 Subject: [PATCH 08/37] add env var as job parameters --- .circleci/config.yml | 124 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed4ca625..fcaa3c85 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,8 +8,69 @@ jobs: build-push-docker-image: docker: - image: cimg/base:stable + parameters: + NEXT_PUBLIC_BACK_API_HOST: + type: string + default: "" + NEXT_PUBLIC_BACK_API_PROTOCOL: + type: string + default: "" + NEXT_PUBLIC_BACK_API_ROOT_URL: + type: string + default: "" + NEXT_PUBLIC_BACK_API_VERSION: + type: string + default: "" + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: + type: string + default: "" + NEXT_PUBLIC_FC_CLIENT_ID: + type: string + default: "" + NEXT_PUBLIC_FRONT_APP_HOST: + type: string + default: "" + NEXT_PUBLIC_FRONT_APP_PORT: + type: string + default: "" + NEXT_PUBLIC_IDNOT_BASE_URL: + type: string + default: "" + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: + type: string + default: "" + NEXT_PUBLIC_IDNOT_CLIENT_ID: + type: string + default: "" + NEXT_PUBLIC_DOCAPOST_API_URL: + type: string + default: "" + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: + type: string + default: "" + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: + type: string + default: "" + NEXT_PUBLIC_DOCAPOST_APP_ID: + type: string + default: "" environment: TAG: << pipeline.git.tag >> + NEXT_PUBLIC_BACK_API_HOST: << parameters.NEXT_PUBLIC_BACK_API_HOST >> + NEXT_PUBLIC_BACK_API_PROTOCOL: << parameters.NEXT_PUBLIC_BACK_API_PROTOCOL >> + NEXT_PUBLIC_BACK_API_ROOT_URL: << parameters.NEXT_PUBLIC_BACK_API_ROOT_URL >> + NEXT_PUBLIC_BACK_API_VERSION: << parameters.NEXT_PUBLIC_BACK_API_VERSION >> + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: << parameters.NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT >> + NEXT_PUBLIC_FC_CLIENT_ID: << parameters.NEXT_PUBLIC_FC_CLIENT_ID >> + NEXT_PUBLIC_FRONT_APP_HOST: << parameters.NEXT_PUBLIC_FRONT_APP_HOST >> + NEXT_PUBLIC_FRONT_APP_PORT: << parameters.NEXT_PUBLIC_FRONT_APP_PORT >> + NEXT_PUBLIC_IDNOT_BASE_URL: << parameters.NEXT_PUBLIC_IDNOT_BASE_URL >> + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: << parameters.NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT >> + NEXT_PUBLIC_IDNOT_CLIENT_ID: << parameters.NEXT_PUBLIC_IDNOT_CLIENT_ID >> + NEXT_PUBLIC_DOCAPOST_API_URL: << parameters.NEXT_PUBLIC_DOCAPOST_API_URL >> + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: << parameters.NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID >> + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: << parameters.NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID >> + NEXT_PUBLIC_DOCAPOST_APP_ID: << parameters.NEXT_PUBLIC_DOCAPOST_APP_ID >> steps: - checkout - add_ssh_keys: @@ -52,24 +113,21 @@ workflows: build-and-register-stg: jobs: - build-push-docker-image: - environment: - TAG: << pipeline.git.tag >> - NEXT_PUBLIC_ADMIN_ID: jelkvelknvlkn - NEXT_PUBLIC_BACK_API_HOST: api.stg.lecoffre.smart-chain.fr - NEXT_PUBLIC_BACK_API_PROTOCOL: https:// - NEXT_PUBLIC_BACK_API_ROOT_URL: /api - NEXT_PUBLIC_BACK_API_VERSION: /v1 - NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize - NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e - NEXT_PUBLIC_FRONT_APP_HOST: https://app.stg.lecoffre.smart-chain.fr - NEXT_PUBLIC_FRONT_APP_PORT: 3000 - NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" - NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" - NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" - NEXT_PUBLIC_DOCAPOST_API_URL: "https://preprod.id360docaposte.com/api/1.0.0" - NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: 49508376-b160-475d-9224-9bb6511215b8 - NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: 54c14875-f864-4819-8cd4-4fc6dd4a947b - NEXT_PUBLIC_DOCAPOST_APP_ID: leCoffre@smart_chain + NEXT_PUBLIC_BACK_API_HOST: api.stg.lecoffre.smart-chain.fr + NEXT_PUBLIC_BACK_API_PROTOCOL: https:// + NEXT_PUBLIC_BACK_API_ROOT_URL: /api + NEXT_PUBLIC_BACK_API_VERSION: /v1 + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize + NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e + NEXT_PUBLIC_FRONT_APP_HOST: https://app.stg.lecoffre.smart-chain.fr + NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" + NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" + NEXT_PUBLIC_DOCAPOST_API_URL: "https://preprod.id360docaposte.com/api/1.0.0" + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: 49508376-b160-475d-9224-9bb6511215b8 + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: 54c14875-f864-4819-8cd4-4fc6dd4a947b + NEXT_PUBLIC_DOCAPOST_APP_ID: leCoffre@smart_chain context: - sc-shared-prd filters: @@ -88,6 +146,21 @@ workflows: build-and-register-ppd: jobs: - build-push-docker-image: + NEXT_PUBLIC_BACK_API_HOST: api.ppd.lecoffre.smart-chain.fr + NEXT_PUBLIC_BACK_API_PROTOCOL: https:// + NEXT_PUBLIC_BACK_API_ROOT_URL: /api + NEXT_PUBLIC_BACK_API_VERSION: /v1 + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize + NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e + NEXT_PUBLIC_FRONT_APP_HOST: https://app.ppd.lecoffre.smart-chain.fr + NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" + NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" + NEXT_PUBLIC_DOCAPOST_API_URL: "https://preprod.id360docaposte.com/api/1.0.0" + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: 49508376-b160-475d-9224-9bb6511215b8 + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: 54c14875-f864-4819-8cd4-4fc6dd4a947b + NEXT_PUBLIC_DOCAPOST_APP_ID: leCoffre@smart_chain context: - sc-shared-prd filters: @@ -106,6 +179,21 @@ workflows: build-and-register-prd: jobs: - build-push-docker-image: + NEXT_PUBLIC_BACK_API_HOST: api.lecoffre.smart-chain.fr + NEXT_PUBLIC_BACK_API_PROTOCOL: https:// + NEXT_PUBLIC_BACK_API_ROOT_URL: /api + NEXT_PUBLIC_BACK_API_VERSION: /v1 + NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize + NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e + NEXT_PUBLIC_FRONT_APP_HOST: https://app.lecoffre.smart-chain.fr + NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" + NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" + NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" + NEXT_PUBLIC_DOCAPOST_API_URL: "https://preprod.id360docaposte.com/api/1.0.0" + NEXT_PUBLIC_DOCAPOST_DOCUMENT_PROCESS_ID: 49508376-b160-475d-9224-9bb6511215b8 + NEXT_PUBLIC_DOCAPOST_CONNECT_PROCESS_ID: 54c14875-f864-4819-8cd4-4fc6dd4a947b + NEXT_PUBLIC_DOCAPOST_APP_ID: leCoffre@smart_chain context: - sc-shared-prd filters: From 046d42110e49fd6f428ef290ae7eecf78f4c267f Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 17:01:31 +0100 Subject: [PATCH 09/37] refacto port as string --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fcaa3c85..d0f458b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -120,7 +120,7 @@ workflows: NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e NEXT_PUBLIC_FRONT_APP_HOST: https://app.stg.lecoffre.smart-chain.fr - NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_FRONT_APP_PORT: "3000" NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" @@ -153,7 +153,7 @@ workflows: NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e NEXT_PUBLIC_FRONT_APP_HOST: https://app.ppd.lecoffre.smart-chain.fr - NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_FRONT_APP_PORT: "3000" NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" @@ -186,7 +186,7 @@ workflows: NEXT_PUBLIC_FC_AUTHORIZE_ENDPOINT: https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize NEXT_PUBLIC_FC_CLIENT_ID: 211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6e NEXT_PUBLIC_FRONT_APP_HOST: https://app.lecoffre.smart-chain.fr - NEXT_PUBLIC_FRONT_APP_PORT: 3000 + NEXT_PUBLIC_FRONT_APP_PORT: "3000" NEXT_PUBLIC_IDNOT_BASE_URL: "https://qual-connexion.idnot.fr" NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT: "/IdPOAuth2/authorize/idnot_idp_v1" NEXT_PUBLIC_IDNOT_CLIENT_ID: "4501646203F3EF67" From ac2d7ecbe31be4c2fe9b29b50698e0c3c6d080ce Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 7 Nov 2023 17:06:15 +0100 Subject: [PATCH 10/37] fix dockerFile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4bdea185..be27f608 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN chmod 600 ~/.ssh/id_rsa RUN eval "$(ssh-agent -s)" && ssh-add /root/.ssh/id_rsa RUN ssh-keyscan github.com smart-chain-fr/leCoffre-resources.git >> /root/.ssh/known_hosts -# RUN npm install --frozen-lockfile +RUN npm install --frozen-lockfile # Rebuild the source code only when needed FROM node:19-alpine AS builder From e1468fbd6d780957a55661dd5dcdc427ab87708d Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 8 Nov 2023 09:34:59 +0100 Subject: [PATCH 11/37] remove env logs --- src/pages/_app.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index bce2c795..46c35112 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -26,7 +26,7 @@ type AppPropsWithLayout = AppProps & { docaposteApiUrl: string; }; -const { publicRuntimeConfig, serverRuntimeConfig, env } = getConfig(); +const { publicRuntimeConfig } = getConfig(); const MyApp = (({ Component, @@ -58,16 +58,10 @@ const MyApp = (({ instance.FC_CLIENT_ID = fcClientId; instance.DOCAPOST_API_URL = docaposteApiUrl; - console.log("instance", instance); - return getLayout(); }) as AppType; MyApp.getInitialProps = async () => { - console.log("runtime config", publicRuntimeConfig); - console.log("server runtime config", serverRuntimeConfig); - console.log("process env", process.env['NEXT_PUBLIC_BACK_API_PROTOCOL'] || "env undefined"); - console.log("env config", env); return { backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL, backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST, From 6df9cd7d073f8efb42aecf7a0d9413449cf1f363 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 8 Nov 2023 10:19:23 +0100 Subject: [PATCH 12/37] add verified folder error handling --- .../DepositOtherDocument/index.tsx | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx index 467be008..e6bb4ed9 100644 --- a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx +++ b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx @@ -40,6 +40,7 @@ type IState = { refusedReason?: string; isShowRefusedReasonModalVisible: boolean; showFailedUploaded: string | null; + showFailedDocument: string | null; isAddDocumentModalVisible: boolean; isLoading: boolean; }; @@ -159,11 +160,20 @@ export default class DepositOtherDocument extends React.Component - {this.state.showFailedUploaded && ( + {this.state.showFailedDocument && ( + header={"L'ajout de Document n'est plus autorisé"} + isOpen={!!this.state.showFailedDocument}> +
+ + {this.state.showFailedDocument} + +
+
+ )} + {this.state.showFailedUploaded && ( +
{this.state.showFailedUploaded} @@ -180,7 +190,7 @@ export default class DepositOtherDocument extends React.Component Date: Fri, 24 Nov 2023 15:15:25 +0100 Subject: [PATCH 13/37] :sparkles: Customer login page --- .../Layouts/LoginCustomer/classes.module.scss | 34 +++++++++++++++---- .../Layouts/LoginCustomer/index.tsx | 21 +++++++++--- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/classes.module.scss index e1e032e8..2fd71d0d 100644 --- a/src/front/Components/Layouts/LoginCustomer/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/classes.module.scss @@ -2,28 +2,48 @@ .root { display: flex; - align-items: center; - justify-content: center; flex-direction: column; - height: 100%; max-width: 530px; margin: auto; + margin-top: 220px; .title { - margin: 32px 0; - text-align: center; + margin-bottom: 32px; + text-align: left; @media (max-width: $screen-s) { font-family: 48px; } } + .logo { + margin-top: 32px; + cursor: pointer; + } + + .what_is_france_connect { + color: var(--light-text-action-high-blue-france, #000091); + /* 2.Corps de texte/SM - Texte détail/Desktop & Mobile - Regular */ + font-family: Marianne; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 24px; /* 171.429% */ + margin-top: 12px; + } + + .or { + margin-top: 32px; + } .forget-password { margin-top: 32px; margin-bottom: 8px; } - .logo { - cursor: pointer; + .form { + margin-top: 32px; + .submit_button { + margin-top: 32px; + } } } diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 40cb3edf..fb386de1 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -1,4 +1,3 @@ -import CoffreIcon from "@Assets/Icons/coffre.svg"; import franceConnectLogo from "./france-connect.svg"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; @@ -11,6 +10,8 @@ import classes from "./classes.module.scss"; import LandingImage from "./landing-connect.jpeg"; import Link from "next/link"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; +import Form from "@Front/Components/DesignSystem/Form"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; export default function Login() { const router = useRouter(); @@ -45,17 +46,27 @@ export default function Login() { return (
- coffre -
Connexion espace client
+
Identifiez-vous
+ Pour accéder à votre espace de dépôt des documents, veuillez vous identifier. france-connect - +
Qu'est ce que FranceConnect ?
+ + Ou + +
+ + + + {/*
Vous n'arrivez pas à vous connecter ?
- + */}
Date: Fri, 24 Nov 2023 15:34:24 +0100 Subject: [PATCH 14/37] :sparkles: Verify sms request working --- src/front/Api/Auth/Customer/Auth.ts | 29 ++++++++++++++++ .../Layouts/LoginCustomer/index.tsx | 33 ++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/front/Api/Auth/Customer/Auth.ts diff --git a/src/front/Api/Auth/Customer/Auth.ts b/src/front/Api/Auth/Customer/Auth.ts new file mode 100644 index 00000000..7d0481f2 --- /dev/null +++ b/src/front/Api/Auth/Customer/Auth.ts @@ -0,0 +1,29 @@ +import BaseApiService from "@Front/Api/BaseApiService"; + +export type IMailVerifyParams = { + email: string; +}; + +export type IMailVerifyReturn = { + partialPhoneNumber: string; +}; + +export default class Auth extends BaseApiService { + private static instance: Auth; + protected readonly namespaceUrl = this.getBaseUrl().concat("/customer"); + private readonly baseURl = this.namespaceUrl.concat("/auth"); + + public static getInstance() { + return (this.instance ??= new this()); + } + + public async mailVerifySms(body: IMailVerifyParams): Promise { + const url = new URL(this.baseURl.concat("/mail/verify-sms")); + try { + return this.postRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index fb386de1..384f59fd 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -8,15 +8,17 @@ import { useCallback, useEffect, useState } from "react"; import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; import classes from "./classes.module.scss"; import LandingImage from "./landing-connect.jpeg"; -import Link from "next/link"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import Form from "@Front/Components/DesignSystem/Form"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; +import Module from "@Front/Config/Module"; +import { ValidationError } from "class-validator"; +import Auth from "@Front/Api/Auth/Customer/Auth"; export default function Login() { const router = useRouter(); const error = router.query["error"]; - + const [validationError, setValidationError] = useState([]); const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); const redirectCustomerOnConnection = useCallback(() => { @@ -43,6 +45,25 @@ export default function Login() { if (error === "1") openErrorModal(); }, [error, openErrorModal]); + const onSubmitHandler = useCallback( + async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + console.log(values); + if (!values["email"]) return; + const phoneNumber = await Auth.getInstance().mailVerifySms({ email: values["email"] }); + /* router.push( + Module.getInstance().get().modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", "1"), + ); */ + } catch (validationErrors: Array | any) { + console.log(validationErrors); + if (validationErrors.length > 0) { + setValidationError(validationErrors as ValidationError[]); + } + return; + } + }, + [router], + ); return (
@@ -55,8 +76,12 @@ export default function Login() { Ou -
- + + error.property === "email")} + /> From 81731b72d82a2409c4d3a1c06124415e9c4380ef Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 24 Nov 2023 17:27:57 +0100 Subject: [PATCH 15/37] :construction: WIP login page --- src/front/Api/BaseApiService.ts | 7 +- .../StepEmail/classes.module.scss | 49 ++++++++++ .../Layouts/LoginCustomer/StepEmail/index.tsx | 91 +++++++++++++++++++ .../StepTotp/classes.module.scss | 24 +++++ .../Layouts/LoginCustomer/StepTotp/index.tsx | 67 ++++++++++++++ .../Layouts/LoginCustomer/classes.module.scss | 45 --------- .../Layouts/LoginCustomer/index.tsx | 81 ++++------------- 7 files changed, 253 insertions(+), 111 deletions(-) create mode 100644 src/front/Components/Layouts/LoginCustomer/StepEmail/classes.module.scss create mode 100644 src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx create mode 100644 src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss create mode 100644 src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx diff --git a/src/front/Api/BaseApiService.ts b/src/front/Api/BaseApiService.ts index 999ae0f0..198141b2 100644 --- a/src/front/Api/BaseApiService.ts +++ b/src/front/Api/BaseApiService.ts @@ -138,11 +138,16 @@ export default abstract class BaseApiService { } } else { // Handle error response + const responseCopy = response.clone(); try { const responseJson = await response.json(); return Promise.reject(responseJson); } catch (err) { - return Promise.reject(err); + const responseText = await responseCopy.text(); + return Promise.reject({ + http_status: response.status, + message: responseText, + }); } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepEmail/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepEmail/classes.module.scss new file mode 100644 index 00000000..2fd71d0d --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepEmail/classes.module.scss @@ -0,0 +1,49 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + flex-direction: column; + max-width: 530px; + margin: auto; + margin-top: 220px; + + .title { + margin-bottom: 32px; + text-align: left; + + @media (max-width: $screen-s) { + font-family: 48px; + } + } + + .logo { + margin-top: 32px; + cursor: pointer; + } + + .what_is_france_connect { + color: var(--light-text-action-high-blue-france, #000091); + /* 2.Corps de texte/SM - Texte détail/Desktop & Mobile - Regular */ + font-family: Marianne; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 24px; /* 171.429% */ + margin-top: 12px; + } + + .or { + margin-top: 32px; + } + .forget-password { + margin-top: 32px; + margin-bottom: 8px; + } + + .form { + margin-top: 32px; + .submit_button { + margin-top: 32px; + } + } +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx new file mode 100644 index 00000000..63607abe --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx @@ -0,0 +1,91 @@ +import React, { useCallback, useState } from "react"; +import classes from "./classes.module.scss"; +import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; +import Image from "next/image"; +import Form from "@Front/Components/DesignSystem/Form"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import franceConnectLogo from "../france-connect.svg"; +import { useRouter } from "next/router"; +import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; +import { ValidationError } from "class-validator"; +import { LoginStep } from ".."; +import Auth from "@Front/Api/Auth/Customer/Auth"; +type IProps = { + setPartialPhoneNumber: (phoneNumber: string) => void; + setStep: (step: LoginStep) => void; +}; + +export default function StepEmail(props: IProps) { + const { setPartialPhoneNumber, setStep } = props; + const [validationError, setValidationError] = useState([]); + const router = useRouter(); + const redirectCustomerOnConnection = useCallback(() => { + async function getCustomer() { + try { + const loginRes = await Customers.getInstance().login(); + router.push(loginRes.enrollment.franceConnectUrl); + } catch (e) { + console.error(e); + } + } + getCustomer(); + }, [router]); + + const onSubmitHandler = useCallback( + async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + if (!values["email"]) return; + const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); + setPartialPhoneNumber(res.partialPhoneNumber); + setStep(LoginStep.TOTP); + } catch (error: any) { + // If token already exists and is still valid redirect to the connect/register page + if (error.http_status === 425) { + setStep(LoginStep.TOTP); + return; + } + setValidationError([ + { + property: "email", + constraints: { + [error.http_status]: error.message, + }, + }, + ]); + return; + } + }, + [setPartialPhoneNumber, setStep], + ); + + return ( +
+ +
Identifiez-vous
+
+ Pour accéder à votre espace de dépôt des documents, veuillez vous identifier. + france-connect +
Qu'est ce que FranceConnect ?
+ + Ou + + + error.property === "email")} + /> + + + {/* +
Vous n'arrivez pas à vous connecter ?
+
+ + + */} +
+ ); +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss new file mode 100644 index 00000000..efbcd6ad --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss @@ -0,0 +1,24 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + flex-direction: column; + max-width: 530px; + margin: auto; + margin-top: 220px; + + .title { + text-align: left; + + @media (max-width: $screen-s) { + font-family: 48px; + } + } + + .form { + margin-top: 32px; + .submit_button { + margin-top: 32px; + } + } +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx new file mode 100644 index 00000000..421ea78f --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -0,0 +1,67 @@ +import React, { useCallback, useState } from "react"; +import classes from "./classes.module.scss"; +import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; +import Image from "next/image"; +import Form from "@Front/Components/DesignSystem/Form"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import franceConnectLogo from "./france-connect.svg"; +import { useRouter } from "next/router"; +import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; +import { ValidationError } from "class-validator"; +import { LoginStep } from ".."; +import Auth from "@Front/Api/Auth/Customer/Auth"; +type IProps = { + setStep: (step: LoginStep) => void; + setTotpCode: (code: string) => void; + partialPhoneNumber: string; +}; + +export default function StepTotp(props: IProps) { + const { setStep, setTotpCode, partialPhoneNumber } = props; + const [validationError, setValidationError] = useState([]); + const router = useRouter(); + const onSubmitHandler = useCallback( + async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + if (!values["email"]) return; + const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); + setStep(LoginStep.TOTP); + } catch (error: any) { + // If token already exists and is still valid redirect to the connect/register page + if (error.http_status === 425) { + setStep(LoginStep.TOTP); + return; + } + setValidationError([ + { + property: "code", + constraints: { + [error.http_status]: error.message, + }, + }, + ]); + return; + } + }, + [setStep], + ); + + return ( +
+ +
Votre code a été envoyé par SMS au ** ** ** {partialPhoneNumber}
+
+
+ error.property === "code")} + /> + + +
+ ); +} diff --git a/src/front/Components/Layouts/LoginCustomer/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/classes.module.scss index 2fd71d0d..f68b3ab0 100644 --- a/src/front/Components/Layouts/LoginCustomer/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/classes.module.scss @@ -1,49 +1,4 @@ @import "@Themes/constants.scss"; .root { - display: flex; - flex-direction: column; - max-width: 530px; - margin: auto; - margin-top: 220px; - - .title { - margin-bottom: 32px; - text-align: left; - - @media (max-width: $screen-s) { - font-family: 48px; - } - } - - .logo { - margin-top: 32px; - cursor: pointer; - } - - .what_is_france_connect { - color: var(--light-text-action-high-blue-france, #000091); - /* 2.Corps de texte/SM - Texte détail/Desktop & Mobile - Regular */ - font-family: Marianne; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 24px; /* 171.429% */ - margin-top: 12px; - } - - .or { - margin-top: 32px; - } - .forget-password { - margin-top: 32px; - margin-bottom: 8px; - } - - .form { - margin-top: 32px; - .submit_button { - margin-top: 32px; - } - } } diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 384f59fd..16901f60 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -1,37 +1,28 @@ -import franceConnectLogo from "./france-connect.svg"; -import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; -import Image from "next/image"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; -import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; + import classes from "./classes.module.scss"; import LandingImage from "./landing-connect.jpeg"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; -import Form from "@Front/Components/DesignSystem/Form"; -import TextField from "@Front/Components/DesignSystem/Form/TextField"; -import Module from "@Front/Config/Module"; -import { ValidationError } from "class-validator"; -import Auth from "@Front/Api/Auth/Customer/Auth"; +import StepEmail from "./StepEmail"; +import StepTotp from "./StepTotp"; +export enum LoginStep { + EMAIL, + TOTP, + NEW_PASSWORD, +} export default function Login() { const router = useRouter(); const error = router.query["error"]; - const [validationError, setValidationError] = useState([]); + const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); - const redirectCustomerOnConnection = useCallback(() => { - async function getCustomer() { - try { - const loginRes = await Customers.getInstance().login(); - router.push(loginRes.enrollment.franceConnectUrl); - } catch (e) { - console.error(e); - } - } - getCustomer(); - }, [router]); + const [step, setStep] = useState(LoginStep.EMAIL); + const [totpCode, setTotpCode] = useState(""); + const [partialPhoneNumber, setPartialPhoneNumber] = useState(""); const openErrorModal = useCallback(() => { setIsErrorModalOpen(true); @@ -45,53 +36,13 @@ export default function Login() { if (error === "1") openErrorModal(); }, [error, openErrorModal]); - const onSubmitHandler = useCallback( - async (e: React.FormEvent | null, values: { [key: string]: string }) => { - try { - console.log(values); - if (!values["email"]) return; - const phoneNumber = await Auth.getInstance().mailVerifySms({ email: values["email"] }); - /* router.push( - Module.getInstance().get().modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", "1"), - ); */ - } catch (validationErrors: Array | any) { - console.log(validationErrors); - if (validationErrors.length > 0) { - setValidationError(validationErrors as ValidationError[]); - } - return; - } - }, - [router], - ); return (
- -
Identifiez-vous
-
- Pour accéder à votre espace de dépôt des documents, veuillez vous identifier. - france-connect -
Qu'est ce que FranceConnect ?
- - Ou - -
- error.property === "email")} - /> - - - {/* -
Vous n'arrivez pas à vous connecter ?
-
- - - */} + {step === LoginStep.EMAIL && } + {step === LoginStep.TOTP && ( + + )}
Date: Mon, 27 Nov 2023 10:02:43 +0100 Subject: [PATCH 16/37] :sparkles: Two first steps working --- src/front/Api/Auth/Customer/Auth.ts | 19 ++++++ .../Layouts/LoginCustomer/StepEmail/index.tsx | 42 ++----------- .../Layouts/LoginCustomer/StepTotp/index.tsx | 47 +++----------- .../Layouts/LoginCustomer/index.tsx | 63 ++++++++++++++++++- 4 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/front/Api/Auth/Customer/Auth.ts b/src/front/Api/Auth/Customer/Auth.ts index 7d0481f2..d629f0eb 100644 --- a/src/front/Api/Auth/Customer/Auth.ts +++ b/src/front/Api/Auth/Customer/Auth.ts @@ -8,6 +8,15 @@ export type IMailVerifyReturn = { partialPhoneNumber: string; }; +export type IVerifyTotpCodeParams = { + totpCode: string; + email: string; +}; + +export type IVerifyTotpCodeReturn = { + validCode: boolean; +}; + export default class Auth extends BaseApiService { private static instance: Auth; protected readonly namespaceUrl = this.getBaseUrl().concat("/customer"); @@ -26,4 +35,14 @@ export default class Auth extends BaseApiService { return Promise.reject(err); } } + + public async verifyTotpCode(body: IVerifyTotpCodeParams): Promise { + const url = new URL(this.baseURl.concat("/verify-totp-code")); + try { + return this.postRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx index 63607abe..5a2595f6 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from "react"; +import React, { useCallback } from "react"; import classes from "./classes.module.scss"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import Image from "next/image"; @@ -9,16 +9,13 @@ import franceConnectLogo from "../france-connect.svg"; import { useRouter } from "next/router"; import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; import { ValidationError } from "class-validator"; -import { LoginStep } from ".."; -import Auth from "@Front/Api/Auth/Customer/Auth"; type IProps = { - setPartialPhoneNumber: (phoneNumber: string) => void; - setStep: (step: LoginStep) => void; + onSubmit: (e: React.FormEvent | null, values: { [key: string]: string }) => void; + validationErrors: ValidationError[]; }; export default function StepEmail(props: IProps) { - const { setPartialPhoneNumber, setStep } = props; - const [validationError, setValidationError] = useState([]); + const { onSubmit, validationErrors } = props; const router = useRouter(); const redirectCustomerOnConnection = useCallback(() => { async function getCustomer() { @@ -32,33 +29,6 @@ export default function StepEmail(props: IProps) { getCustomer(); }, [router]); - const onSubmitHandler = useCallback( - async (e: React.FormEvent | null, values: { [key: string]: string }) => { - try { - if (!values["email"]) return; - const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); - setPartialPhoneNumber(res.partialPhoneNumber); - setStep(LoginStep.TOTP); - } catch (error: any) { - // If token already exists and is still valid redirect to the connect/register page - if (error.http_status === 425) { - setStep(LoginStep.TOTP); - return; - } - setValidationError([ - { - property: "email", - constraints: { - [error.http_status]: error.message, - }, - }, - ]); - return; - } - }, - [setPartialPhoneNumber, setStep], - ); - return (
@@ -70,11 +40,11 @@ export default function StepEmail(props: IProps) { Ou -
+ error.property === "email")} + validationError={validationErrors.find((error) => error.property === "email")} /> + +
+ ); +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss new file mode 100644 index 00000000..efbcd6ad --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss @@ -0,0 +1,24 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + flex-direction: column; + max-width: 530px; + margin: auto; + margin-top: 220px; + + .title { + text-align: left; + + @media (max-width: $screen-s) { + font-family: 48px; + } + } + + .form { + margin-top: 32px; + .submit_button { + margin-top: 32px; + } + } +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx new file mode 100644 index 00000000..9d379a81 --- /dev/null +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import classes from "./classes.module.scss"; +import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; +import Form from "@Front/Components/DesignSystem/Form"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import { ValidationError } from "class-validator"; +import Link from "next/link"; +type IProps = { + onSubmit: (e: React.FormEvent | null, values: { [key: string]: string }) => void; + validationErrors: ValidationError[]; +}; + +export default function StepPassword(props: IProps) { + const { onSubmit, validationErrors } = props; + + return ( +
+ +
Entrez votre mot de passe
+
+
+ error.property === "password")} + password + /> + + +
Mot de passe oublié ?
+
+ + + +
+ ); +} diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 7a4267c1..4418fa4d 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -10,10 +10,15 @@ import StepEmail from "./StepEmail"; import StepTotp from "./StepTotp"; import Auth from "@Front/Api/Auth/Customer/Auth"; import { ValidationError } from "class-validator"; +import StepPassword from "./StepPassword"; +import StepNewPassword from "./StepNewPassword"; +import CustomerStore from "@Front/Stores/CustomerStore"; +import Module from "@Front/Config/Module"; export enum LoginStep { EMAIL, TOTP, + PASSWORD, NEW_PASSWORD, } export default function Login() { @@ -27,6 +32,7 @@ export default function Login() { const [email, setEmail] = useState(""); const [partialPhoneNumber, setPartialPhoneNumber] = useState(""); const [validationErrors, setValidationErrors] = useState([]); + const openErrorModal = useCallback(() => { setIsErrorModalOpen(true); }, []); @@ -72,10 +78,14 @@ export default function Login() { try { if (!values["totpCode"]) return; const res = await Auth.getInstance().verifyTotpCode({ totpCode: values["totpCode"], email }); - if (res.validCode) { - setTotpCode(values["totpCode"]); - setStep(LoginStep.NEW_PASSWORD); - } + + // If the code is valid setting it in state + if (res.validCode) setTotpCode(values["totpCode"]); + + // If it's first connection, show the form for first connection + if (res.firstConnection) setStep(LoginStep.NEW_PASSWORD); + // Else just login normally + else setStep(LoginStep.PASSWORD); } catch (error: any) { setValidationErrors([ { @@ -90,6 +100,64 @@ export default function Login() { }, [email, setStep], ); + + const onNewPasswordSubmit = useCallback( + async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + console.log(values); + if (!values["password"] || !values["confirm_password"]) return; + if (values["password"] !== values["confirm_password"]) { + setValidationErrors([ + { + property: "confirm_password", + constraints: { + "400": "Les mots de passe ne correspondent pas.", + }, + }, + ]); + return; + } + const token = await Auth.getInstance().setPassword({ totpCode, email, password: values["password"] }); + CustomerStore.instance.connect(token.accessToken, token.refreshToken); + router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path); + // If set password worked, setting the token and redirecting + } catch (error: any) { + setValidationErrors([ + { + property: "password", + constraints: { + [error.http_status]: error.message, + }, + }, + ]); + return; + } + }, + [email, totpCode, setValidationErrors], + ); + + const onPasswordSubmit = useCallback( + async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + if (!values["password"]) return; + const res = await Auth.getInstance().setPassword({ totpCode, email, password: values["password"] }); + + // If set password worked, setting the token and redirecting + } catch (error: any) { + setValidationErrors([ + { + property: "password", + constraints: { + [error.http_status]: error.message, + }, + }, + ]); + return; + } + }, + [email, totpCode], + ); + return (
@@ -97,9 +165,8 @@ export default function Login() { {step === LoginStep.TOTP && ( )} - {step === LoginStep.NEW_PASSWORD && ( - - )} + {step === LoginStep.PASSWORD && } + {step === LoginStep.NEW_PASSWORD && }
Date: Mon, 27 Nov 2023 10:54:07 +0100 Subject: [PATCH 18/37] :sparkles: Login working --- src/front/Api/Auth/Customer/Auth.ts | 16 ++++++++++++++++ .../Components/Layouts/LoginCustomer/index.tsx | 12 ++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/front/Api/Auth/Customer/Auth.ts b/src/front/Api/Auth/Customer/Auth.ts index 60c0788d..c04686c1 100644 --- a/src/front/Api/Auth/Customer/Auth.ts +++ b/src/front/Api/Auth/Customer/Auth.ts @@ -25,6 +25,12 @@ export type ISetPasswordParams = { totpCode: string; }; +export type ILoginParams = { + password: string; + email: string; + totpCode: string; +}; + export default class Auth extends BaseApiService { private static instance: Auth; protected readonly namespaceUrl = this.getBaseUrl().concat("/customer"); @@ -63,4 +69,14 @@ export default class Auth extends BaseApiService { return Promise.reject(err); } } + + public async login(body: ILoginParams): Promise { + const url = new URL(this.baseURl.concat("/login")); + try { + return this.postRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } } diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 4418fa4d..788c1700 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -49,9 +49,9 @@ export default function Login() { async (e: React.FormEvent | null, values: { [key: string]: string }) => { try { if (!values["email"]) return; + setEmail(values["email"]); const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); setPartialPhoneNumber(res.partialPhoneNumber); - setEmail(values["email"]); setStep(LoginStep.TOTP); } catch (error: any) { // If token already exists and is still valid redirect to the connect/register page @@ -133,16 +133,16 @@ export default function Login() { return; } }, - [email, totpCode, setValidationErrors], + [totpCode, email, router], ); const onPasswordSubmit = useCallback( async (e: React.FormEvent | null, values: { [key: string]: string }) => { try { if (!values["password"]) return; - const res = await Auth.getInstance().setPassword({ totpCode, email, password: values["password"] }); - - // If set password worked, setting the token and redirecting + const token = await Auth.getInstance().login({ totpCode, email, password: values["password"] }); + CustomerStore.instance.connect(token.accessToken, token.refreshToken); + router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path); } catch (error: any) { setValidationErrors([ { @@ -155,7 +155,7 @@ export default function Login() { return; } }, - [email, totpCode], + [email, router, totpCode], ); return ( From 4d884b865b926d2d7f16be10b734a0c7988b1a73 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 27 Nov 2023 10:57:11 +0100 Subject: [PATCH 19/37] :sparkles: Login design for forgot password --- .../Layouts/LoginCustomer/StepPassword/classes.module.scss | 5 +++++ .../Components/Layouts/LoginCustomer/StepPassword/index.tsx | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss index efbcd6ad..3ef4f0ef 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss @@ -20,5 +20,10 @@ .submit_button { margin-top: 32px; } + + .forgot-password { + margin-top: 8px; + text-decoration: underline; + } } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx index 9d379a81..b4632b76 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx @@ -27,8 +27,8 @@ export default function StepPassword(props: IProps) { password /> - -
Mot de passe oublié ?
+ + Mot de passe oublié ? + +
+ ); +} diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx index b4632b76..45888814 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx @@ -5,14 +5,29 @@ import Form from "@Front/Components/DesignSystem/Form"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import { ValidationError } from "class-validator"; -import Link from "next/link"; +import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; type IProps = { onSubmit: (e: React.FormEvent | null, values: { [key: string]: string }) => void; validationErrors: ValidationError[]; + onPasswordForgotClicked: () => void; }; export default function StepPassword(props: IProps) { - const { onSubmit, validationErrors } = props; + const { onSubmit, validationErrors, onPasswordForgotClicked } = props; + const [isModalOpened, setIsModalOpened] = React.useState(false); + + const closeModal = () => { + setIsModalOpened(false); + }; + + const openModal = () => { + setIsModalOpened(true); + }; + + const onModalAccept = () => { + onPasswordForgotClicked(); + setIsModalOpened(false); + }; return (
@@ -26,15 +41,29 @@ export default function StepPassword(props: IProps) { validationError={validationErrors.find((error) => error.property === "password")} password /> - +
Mot de passe oublié ? - +
+ +
+ + Un code à usage unique va vous être envoyé par sms pour réinitialiser votre mot de passe. + +
+
); } diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 3fe19a7f..0030af15 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -15,12 +15,14 @@ import StepNewPassword from "./StepNewPassword"; import CustomerStore from "@Front/Stores/CustomerStore"; import Module from "@Front/Config/Module"; import { TotpCodesReasons } from "le-coffre-resources/dist/Customer/TotpCodes"; +import PasswordForgotten from "./PasswordForgotten"; export enum LoginStep { EMAIL, TOTP, PASSWORD, NEW_PASSWORD, + PASSWORD_FORGOTTEN, } export default function Login() { const router = useRouter(); @@ -85,6 +87,8 @@ export default function Login() { // If it's first connection, show the form for first connection if (res.reason === TotpCodesReasons.FIRST_LOGIN) setStep(LoginStep.NEW_PASSWORD); + // If it's password forgotten, show the form for password forgotten + else if (res.reason === TotpCodesReasons.RESET_PASSWORD) setStep(LoginStep.PASSWORD_FORGOTTEN); // Else just login normally else setStep(LoginStep.PASSWORD); } catch (error: any) { @@ -105,7 +109,6 @@ export default function Login() { const onNewPasswordSubmit = useCallback( async (e: React.FormEvent | null, values: { [key: string]: string }) => { try { - console.log(values); if (!values["password"] || !values["confirm_password"]) return; if (values["password"] !== values["confirm_password"]) { setValidationErrors([ @@ -159,6 +162,21 @@ export default function Login() { [email, router, totpCode], ); + const onPasswordForgotClicked = useCallback(async () => { + try { + const res = await Auth.getInstance().askNewPassword({ email }); + setPartialPhoneNumber(res.partialPhoneNumber); + setStep(LoginStep.TOTP); + } catch (error: any) { + // If token already exists and is still valid redirect to the connect/register page + if (error.http_status === 425) { + setStep(LoginStep.TOTP); + return; + } + return; + } + }, [email]); + return (
@@ -166,8 +184,17 @@ export default function Login() { {step === LoginStep.TOTP && ( )} - {step === LoginStep.PASSWORD && } + {step === LoginStep.PASSWORD && ( + + )} {step === LoginStep.NEW_PASSWORD && } + {step === LoginStep.PASSWORD_FORGOTTEN && ( + + )}
Date: Wed, 29 Nov 2023 16:47:38 +0100 Subject: [PATCH 22/37] :sparkles: Send another code working --- src/front/Api/Auth/Customer/Auth.ts | 10 ++++ .../StepTotp/classes.module.scss | 20 ++++++++ .../Layouts/LoginCustomer/StepTotp/index.tsx | 47 +++++++++++++++++-- .../Layouts/LoginCustomer/index.tsx | 15 +++++- 4 files changed, 87 insertions(+), 5 deletions(-) diff --git a/src/front/Api/Auth/Customer/Auth.ts b/src/front/Api/Auth/Customer/Auth.ts index 237df5c3..906d939d 100644 --- a/src/front/Api/Auth/Customer/Auth.ts +++ b/src/front/Api/Auth/Customer/Auth.ts @@ -94,4 +94,14 @@ export default class Auth extends BaseApiService { return Promise.reject(err); } } + + public async sendAnotherCode(body: IMailVerifyParams): Promise { + const url = new URL(this.baseURl.concat("/send-another-code")); + try { + return this.postRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss index efbcd6ad..fae541af 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss @@ -21,4 +21,24 @@ margin-top: 32px; } } + + .ask-another-code { + margin-top: 48px; + display: flex; + flex-direction: column; + gap: 16px; + align-items: flex-start; + + .new-code-button { + &[data-disabled="true"] { + opacity: 0.5; + cursor: not-allowed; + } + } + .new-code-timer { + display: flex; + gap: 6px; + align-items: center; + } + } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx index c71044ee..443c2369 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React, { useEffect } from "react"; import classes from "./classes.module.scss"; -import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; +import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; import Form from "@Front/Components/DesignSystem/Form"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; @@ -9,15 +9,37 @@ type IProps = { onSubmit: (e: React.FormEvent | null, values: { [key: string]: string }) => void; validationErrors: ValidationError[]; partialPhoneNumber: string; + onSendAnotherCode: () => void; }; export default function StepTotp(props: IProps) { - const { onSubmit, validationErrors, partialPhoneNumber } = props; + const { onSubmit, validationErrors, partialPhoneNumber, onSendAnotherCode } = props; + const [disableNewCodeButton, setDisableNewCodeButton] = React.useState(true); + const [secondsBeforeNewCode, setSecondsBeforeNewCode] = React.useState(30); + + useEffect(() => { + const interval = setInterval(() => { + if (secondsBeforeNewCode > 0) { + setSecondsBeforeNewCode(secondsBeforeNewCode - 1); + } else { + setDisableNewCodeButton(false); + } + }, 1000); + return () => clearInterval(interval); + }, [secondsBeforeNewCode]); + + const sendAnotherCode = () => { + onSendAnotherCode(); + setDisableNewCodeButton(true); + setSecondsBeforeNewCode(30); + }; return (
-
Votre code a été envoyé par SMS au ** ** ** {partialPhoneNumber}
+
+ Votre code a été envoyé par SMS au ** ** ** {partialPhoneNumber.replace(/(.{2})/g, "$1 ")} +
+
+ Vous n'avez rien reçu ? + + + Redemandez un code dans + + 00:{secondsBeforeNewCode < 10 ? `0${secondsBeforeNewCode}` : secondsBeforeNewCode} + + +
); } diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 0030af15..c0a48bcc 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -177,12 +177,25 @@ export default function Login() { } }, [email]); + const onSendAnotherCode = useCallback(async () => { + try { + await Auth.getInstance().sendAnotherCode({ email }); + } catch (error: any) { + return; + } + }, [email]); + return (
{step === LoginStep.EMAIL && } {step === LoginStep.TOTP && ( - + )} {step === LoginStep.PASSWORD && ( Date: Wed, 29 Nov 2023 16:52:38 +0100 Subject: [PATCH 23/37] :sparkles: Sending validation errors to totp --- .../Components/Layouts/LoginCustomer/StepTotp/index.tsx | 2 +- src/front/Components/Layouts/LoginCustomer/index.tsx | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx index 443c2369..635a52de 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -56,8 +56,8 @@ export default function StepTotp(props: IProps) { diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index c0a48bcc..c4f1e117 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -181,6 +181,14 @@ export default function Login() { try { await Auth.getInstance().sendAnotherCode({ email }); } catch (error: any) { + setValidationErrors([ + { + property: "totpCode", + constraints: { + [error.http_status]: error.message, + }, + }, + ]); return; } }, [email]); From 1fbd6ce79e57f9f343f5468d64306aa615889f61 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Wed, 29 Nov 2023 16:54:20 +0100 Subject: [PATCH 24/37] :bug: Small adjustments --- .../Layouts/LoginCustomer/StepPassword/classes.module.scss | 1 + .../Components/Layouts/LoginCustomer/StepPassword/index.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss index 3ef4f0ef..0244c442 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/classes.module.scss @@ -24,6 +24,7 @@ .forgot-password { margin-top: 8px; text-decoration: underline; + cursor: pointer; } } } diff --git a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx index 45888814..978dd97b 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepPassword/index.tsx @@ -57,7 +57,8 @@ export default function StepPassword(props: IProps) { onAccept={onModalAccept} closeBtn header={"Mot de passe oublié ?"} - confirmText={"Valider"}> + confirmText={"Valider"} + cancelText={"Annuler"}>
Un code à usage unique va vous être envoyé par sms pour réinitialiser votre mot de passe. From 663d261b9578fc485d35f16dd24f128ee9e4d783 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Thu, 30 Nov 2023 10:59:06 +0100 Subject: [PATCH 25/37] :bug: Fixing build --- src/front/Components/DesignSystem/DepositOtherDocument/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx index e6bb4ed9..5076afa0 100644 --- a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx +++ b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx @@ -60,6 +60,7 @@ export default class DepositOtherDocument extends React.Component Date: Fri, 1 Dec 2023 09:49:26 +0100 Subject: [PATCH 26/37] :sparkles: Totpcode resend by uid --- src/front/Api/Auth/Customer/Auth.ts | 15 +++++- .../Layouts/LoginCustomer/StepTotp/index.tsx | 14 ++--- .../Layouts/LoginCustomer/index.tsx | 53 +++++++++---------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/front/Api/Auth/Customer/Auth.ts b/src/front/Api/Auth/Customer/Auth.ts index 906d939d..edb9a53d 100644 --- a/src/front/Api/Auth/Customer/Auth.ts +++ b/src/front/Api/Auth/Customer/Auth.ts @@ -8,6 +8,7 @@ export type IMailVerifyParams = { export type IMailVerifyReturn = { partialPhoneNumber: string; + totpCodeUid: string; }; export type IVerifyTotpCodeParams = { @@ -36,6 +37,16 @@ export type IAskNewPasswordParams = { email: string; }; +export type IAskAnotherCodeParams = { + email: string; + totpCodeUid: string; +}; + +export type IAskAnotherCodeReturn = { + partialPhoneNumber: string; + totpCodeUid: string; +}; + export default class Auth extends BaseApiService { private static instance: Auth; protected readonly namespaceUrl = this.getBaseUrl().concat("/customer"); @@ -95,10 +106,10 @@ export default class Auth extends BaseApiService { } } - public async sendAnotherCode(body: IMailVerifyParams): Promise { + public async sendAnotherCode(body: IAskAnotherCodeParams): Promise { const url = new URL(this.baseURl.concat("/send-another-code")); try { - return this.postRequest(url, body); + return this.postRequest(url, body); } catch (err) { this.onError(err); return Promise.reject(err); diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx index 635a52de..73c4d312 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -19,7 +19,7 @@ export default function StepTotp(props: IProps) { useEffect(() => { const interval = setInterval(() => { - if (secondsBeforeNewCode > 0) { + if (secondsBeforeNewCode > 1) { setSecondsBeforeNewCode(secondsBeforeNewCode - 1); } else { setDisableNewCodeButton(false); @@ -61,12 +61,14 @@ export default function StepTotp(props: IProps) { className={classes["new-code-button"]}> Envoyer un nouveau code - - Redemandez un code dans - - 00:{secondsBeforeNewCode < 10 ? `0${secondsBeforeNewCode}` : secondsBeforeNewCode} + {secondsBeforeNewCode !== 0 && ( + + Redemandez un code dans + + 00:{secondsBeforeNewCode < 10 ? `0${secondsBeforeNewCode}` : secondsBeforeNewCode} + - + )}
); diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index c4f1e117..06626062 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -31,6 +31,7 @@ export default function Login() { const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); const [step, setStep] = useState(LoginStep.EMAIL); + const [totpCodeUid, setTotpCodeUid] = useState(""); const [totpCode, setTotpCode] = useState(""); const [email, setEmail] = useState(""); const [partialPhoneNumber, setPartialPhoneNumber] = useState(""); @@ -48,33 +49,26 @@ export default function Login() { if (error === "1") openErrorModal(); }, [error, openErrorModal]); - const onEmailFormSubmit = useCallback( - async (e: React.FormEvent | null, values: { [key: string]: string }) => { - try { - if (!values["email"]) return; - setEmail(values["email"]); - const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); - setPartialPhoneNumber(res.partialPhoneNumber); - setStep(LoginStep.TOTP); - } catch (error: any) { - // If token already exists and is still valid redirect to the connect/register page - if (error.http_status === 425) { - setStep(LoginStep.TOTP); - return; - } - setValidationErrors([ - { - property: "email", - constraints: { - [error.http_status]: error.message, - }, + const onEmailFormSubmit = useCallback(async (e: React.FormEvent | null, values: { [key: string]: string }) => { + try { + if (!values["email"]) return; + setEmail(values["email"]); + const res = await Auth.getInstance().mailVerifySms({ email: values["email"] }); + setPartialPhoneNumber(res.partialPhoneNumber); + setTotpCodeUid(res.totpCodeUid); + setStep(LoginStep.TOTP); + } catch (error: any) { + setValidationErrors([ + { + property: "email", + constraints: { + [error.http_status]: error.message, }, - ]); - return; - } - }, - [setEmail, setPartialPhoneNumber, setStep], - ); + }, + ]); + return; + } + }, []); const onSmsCodeSubmit = useCallback( async (e: React.FormEvent | null, values: { [key: string]: string }) => { @@ -179,7 +173,10 @@ export default function Login() { const onSendAnotherCode = useCallback(async () => { try { - await Auth.getInstance().sendAnotherCode({ email }); + const res = await Auth.getInstance().sendAnotherCode({ email, totpCodeUid }); + + setPartialPhoneNumber(res.partialPhoneNumber); + setTotpCodeUid(res.totpCodeUid); } catch (error: any) { setValidationErrors([ { @@ -191,7 +188,7 @@ export default function Login() { ]); return; } - }, [email]); + }, [email, totpCodeUid]); return ( From 1642de5310af5d7830fc44dfeb927dc659e13414 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 1 Dec 2023 09:51:20 +0100 Subject: [PATCH 27/37] :bug: Fixing seconds counter on totp code --- .../Components/Layouts/LoginCustomer/StepTotp/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx index 73c4d312..bfc704f3 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -19,10 +19,11 @@ export default function StepTotp(props: IProps) { useEffect(() => { const interval = setInterval(() => { - if (secondsBeforeNewCode > 1) { + if (secondsBeforeNewCode > 0) { setSecondsBeforeNewCode(secondsBeforeNewCode - 1); - } else { - setDisableNewCodeButton(false); + if (secondsBeforeNewCode === 1) { + setDisableNewCodeButton(false); + } } }, 1000); return () => clearInterval(interval); From d310902111d8d7aea1b84abcb37ace44611613a9 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 1 Dec 2023 15:15:09 +0100 Subject: [PATCH 28/37] :sparkles: Removing france connect --- .../Components/Layouts/LoginCustomer/StepEmail/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx index 5a2595f6..673d3d4b 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx @@ -34,12 +34,13 @@ export default function StepEmail(props: IProps) {
Identifiez-vous
- Pour accéder à votre espace de dépôt des documents, veuillez vous identifier. + {/* Pour accéder à votre espace de dépôt des documents, veuillez vous identifier. france-connect
Qu'est ce que FranceConnect ?
Ou - +
*/} + Pour accéder à votre espace de dépôt des documents, veuillez vous identifier.
Date: Fri, 1 Dec 2023 15:22:39 +0100 Subject: [PATCH 29/37] :bug: Removing warnings on customer login --- .../Layouts/LoginCustomer/StepEmail/index.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx index 673d3d4b..a9348265 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepEmail/index.tsx @@ -1,13 +1,13 @@ -import React, { useCallback } from "react"; +import React from "react"; import classes from "./classes.module.scss"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; -import Image from "next/image"; +//import Image from "next/image"; import Form from "@Front/Components/DesignSystem/Form"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import franceConnectLogo from "../france-connect.svg"; -import { useRouter } from "next/router"; -import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; +//import franceConnectLogo from "../france-connect.svg"; +// import { useRouter } from "next/router"; +// import Customers from "@Front/Api/Auth/Id360/Customers/Customers"; import { ValidationError } from "class-validator"; type IProps = { onSubmit: (e: React.FormEvent | null, values: { [key: string]: string }) => void; @@ -16,7 +16,7 @@ type IProps = { export default function StepEmail(props: IProps) { const { onSubmit, validationErrors } = props; - const router = useRouter(); + /* const router = useRouter(); const redirectCustomerOnConnection = useCallback(() => { async function getCustomer() { try { @@ -27,7 +27,7 @@ export default function StepEmail(props: IProps) { } } getCustomer(); - }, [router]); + }, [router]); */ return (
From bed8dc90a954aef2ba9042166b1cc574edf94bea Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 1 Dec 2023 16:38:15 +0100 Subject: [PATCH 30/37] :sparkles: Can now send sms right away --- package-lock.json | 122 +++++++++--------- package.json | 2 +- .../Layouts/LoginCustomer/StepTotp/index.tsx | 4 +- 3 files changed, 64 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 50d8faa4..7308b495 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.99", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", @@ -432,9 +432,9 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", - "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.1.tgz", + "integrity": "sha512-QgcKYwzcc8vvZ4n/5uklchy8KVdjJwcOeI+HnnTNclJjs2nYsy23DOCf+sSV1kBwD9yDAoVKCkv/gEPzgQU3Pw==", "dependencies": { "@floating-ui/utils": "^0.1.3" } @@ -496,14 +496,14 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==" }, "node_modules/@mui/base": { - "version": "5.0.0-beta.24", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.24.tgz", - "integrity": "sha512-bKt2pUADHGQtqWDZ8nvL2Lvg2GNJyd/ZUgZAJoYzRgmnxBL9j36MSlS3+exEdYkikcnvVafcBtD904RypFKb0w==", + "version": "5.0.0-beta.25", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.25.tgz", + "integrity": "sha512-Iiv+IcappRRv6IBlknIVmLkXxfp51NEX1+l9f+dIbBuPU4PaRULegr1lCeHKsC45KU5ruxM5xMg4R/de03aJQg==", "dependencies": { - "@babel/runtime": "^7.23.2", + "@babel/runtime": "^7.23.4", "@floating-ui/react-dom": "^2.0.4", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", "@popperjs/core": "^2.11.8", "clsx": "^2.0.0", "prop-types": "^15.8.1" @@ -513,7 +513,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -527,26 +527,26 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.18.tgz", - "integrity": "sha512-yFpF35fEVDV81nVktu0BE9qn2dD/chs7PsQhlyaV3EnTeZi9RZBuvoEfRym1/jmhJ2tcfeWXiRuHG942mQXJJQ==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.19.tgz", + "integrity": "sha512-y4JseIen5pmZs1n9hHy95HKKioKco8f6N2lford2AmjJigVJOv0KsU0qryiCpyuEUZmi/xCduVilHsK9DSkPcA==", "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/material": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.18.tgz", - "integrity": "sha512-y3UiR/JqrkF5xZR0sIKj6y7xwuEiweh9peiN3Zfjy1gXWXhz5wjlaLdoxFfKIEBUFfeQALxr/Y8avlHH+B9lpQ==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.19.tgz", + "integrity": "sha512-jSPLXst/YPgDGolhiu4rbethKjLVrI1IkoK8YrFUv8ygxDuhQdsE6+ZqjSSRXk3ytTMf6ghPnQ88OFRk4XjpNw==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/base": "5.0.0-beta.24", - "@mui/core-downloads-tracker": "^5.14.18", - "@mui/system": "^5.14.18", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", - "@types/react-transition-group": "^4.4.8", + "@babel/runtime": "^7.23.4", + "@mui/base": "5.0.0-beta.25", + "@mui/core-downloads-tracker": "^5.14.19", + "@mui/system": "^5.14.19", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", + "@types/react-transition-group": "^4.4.9", "clsx": "^2.0.0", "csstype": "^3.1.2", "prop-types": "^15.8.1", @@ -558,7 +558,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", @@ -580,12 +580,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.18.tgz", - "integrity": "sha512-WSgjqRlzfHU+2Rou3HlR2Gqfr4rZRsvFgataYO3qQ0/m6gShJN+lhVEvwEiJ9QYyVzMDvNpXZAcqp8Y2Vl+PAw==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.19.tgz", + "integrity": "sha512-U9w39VpXLGVM8wZlUU/47YGTsBSk60ZQRRxQZtdqPfN1N7OVllQeN4cEKZKR8PjqqR3aYRcSciQ4dc6CttRoXQ==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/utils": "^5.14.18", + "@babel/runtime": "^7.23.4", + "@mui/utils": "^5.14.19", "prop-types": "^15.8.1" }, "engines": { @@ -593,7 +593,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -606,11 +606,11 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.18.tgz", - "integrity": "sha512-pW8bpmF9uCB5FV2IPk6mfbQCjPI5vGI09NOLhtGXPeph/4xIfC3JdIX0TILU0WcTs3aFQqo6s2+1SFgIB9rCXA==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.19.tgz", + "integrity": "sha512-jtj/Pyn/bS8PM7NXdFNTHWZfE3p+vItO4/HoQbUeAv3u+cnWXcTBGHHY/xdIn446lYGFDczTh1YyX8G4Ts0Rtg==", "dependencies": { - "@babel/runtime": "^7.23.2", + "@babel/runtime": "^7.23.4", "@emotion/cache": "^11.11.0", "csstype": "^3.1.2", "prop-types": "^15.8.1" @@ -620,7 +620,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.4.1", @@ -637,15 +637,15 @@ } }, "node_modules/@mui/system": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.18.tgz", - "integrity": "sha512-hSQQdb3KF72X4EN2hMEiv8EYJZSflfdd1TRaGPoR7CIAG347OxCslpBUwWngYobaxgKvq6xTrlIl+diaactVww==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.19.tgz", + "integrity": "sha512-4e3Q+2nx+vgEsd0h5ftxlZGB7XtkkPos/zWqCqnxUs1l/T70s0lF2YNrWHHdSQ7LgtBu0eQ0qweZG2pR7KwkAw==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/private-theming": "^5.14.18", - "@mui/styled-engine": "^5.14.18", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", + "@babel/runtime": "^7.23.4", + "@mui/private-theming": "^5.14.19", + "@mui/styled-engine": "^5.14.19", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", "clsx": "^2.0.0", "csstype": "^3.1.2", "prop-types": "^15.8.1" @@ -655,7 +655,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", @@ -676,9 +676,9 @@ } }, "node_modules/@mui/types": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.9.tgz", - "integrity": "sha512-k1lN/PolaRZfNsRdAqXtcR71sTnv3z/VCCGPxU8HfdftDkzi335MdJ6scZxvofMAd/K/9EbzCZTFBmlNpQVdCg==", + "version": "7.2.10", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.10.tgz", + "integrity": "sha512-wX1vbDC+lzF7FlhT6A3ffRZgEoKWPF8VqRoTu4lZwouFX2t90KyCMsgepMw5DxLak1BSp/KP86CmtZttikb/gQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -689,12 +689,12 @@ } }, "node_modules/@mui/utils": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.18.tgz", - "integrity": "sha512-HZDRsJtEZ7WMSnrHV9uwScGze4wM/Y+u6pDVo+grUjt5yXzn+wI8QX/JwTHh9YSw/WpnUL80mJJjgCnWj2VrzQ==", + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.19.tgz", + "integrity": "sha512-qAHvTXzk7basbyqPvhgWqN6JbmI2wLB/mf97GkSlz5c76MiKYV6Ffjvw9BjKZQ1YRb8rDX9kgdjRezOcoB91oQ==", "dependencies": { - "@babel/runtime": "^7.23.2", - "@types/prop-types": "^15.7.10", + "@babel/runtime": "^7.23.4", + "@types/prop-types": "^15.7.11", "prop-types": "^15.8.1", "react-is": "^18.2.0" }, @@ -703,7 +703,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -3360,7 +3360,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#a118b5320f7b834e52582f172beaa55a9921c684", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#1d7347879b5b3ca70f685e3b567d5eba2d67827c", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", @@ -3646,12 +3646,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, diff --git a/package.json b/package.json index 7bd63da3..87800449 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.99", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx index bfc704f3..9c97e688 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/index.tsx @@ -14,8 +14,8 @@ type IProps = { export default function StepTotp(props: IProps) { const { onSubmit, validationErrors, partialPhoneNumber, onSendAnotherCode } = props; - const [disableNewCodeButton, setDisableNewCodeButton] = React.useState(true); - const [secondsBeforeNewCode, setSecondsBeforeNewCode] = React.useState(30); + const [disableNewCodeButton, setDisableNewCodeButton] = React.useState(false); + const [secondsBeforeNewCode, setSecondsBeforeNewCode] = React.useState(0); useEffect(() => { const interval = setInterval(() => { From 7a7d06579a0649f56185126e55befac986bcf1fc Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 15:29:14 +0100 Subject: [PATCH 31/37] :sparkles: Updating resources --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7308b495..904f00f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.103", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", @@ -402,9 +402,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -1508,9 +1508,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001565", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz", - "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "funding": [ { "type": "opencollective", @@ -3360,7 +3360,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#1d7347879b5b3ca70f685e3b567d5eba2d67827c", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#21837e8b914b37757a676ad96a26b97840e6c575", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", diff --git a/package.json b/package.json index 87800449..d55f9482 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.103", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", From 10639ca35d3c894fbc492b85fba0bed052737faa Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 15:49:38 +0100 Subject: [PATCH 32/37] :sparkles: Modifying cell phone number validation --- .../UserFolder/UserFolderHeader/index.tsx | 24 +++++++++++++++++++ .../CollaboratorInformations/index.tsx | 2 +- .../Folder/AddClientToFolder/index.tsx | 10 ++++++++ .../Layouts/Folder/UpdateClient/index.tsx | 11 +++++++++ .../Components/Layouts/MyAccount/index.tsx | 2 +- .../Layouts/Users/UserInformations/index.tsx | 4 ++-- 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/front/Components/DesignSystem/UserFolder/UserFolderHeader/index.tsx b/src/front/Components/DesignSystem/UserFolder/UserFolderHeader/index.tsx index e6060bfe..b0d3b5e8 100644 --- a/src/front/Components/DesignSystem/UserFolder/UserFolderHeader/index.tsx +++ b/src/front/Components/DesignSystem/UserFolder/UserFolderHeader/index.tsx @@ -76,6 +76,30 @@ export default class UserFolderHeader extends React.Component { private formatPhoneNumber(phoneNumber: string): string { if (!phoneNumber) return ""; phoneNumber = phoneNumber.replace(/ /g, ""); + phoneNumber = phoneNumber.replace("+33", "0"); + + if (phoneNumber.length !== 10) { + // split the last 9 digits + const lastNineDigits = phoneNumber.slice(-9); + + // get the country code + const countryCode = phoneNumber.slice(0, -9); + + // isolate the first digit + const firstDigit = lastNineDigits.slice(0, 1); + + // isolate the 8 other ones + const lastEightDigits = lastNineDigits.slice(1); + + // make a space every two digits on the last eights + const output = lastEightDigits.split("").map((char, index) => { + if (index % 2) return char + " "; + return char; + }); + // format the phone number + phoneNumber = countryCode + " " + firstDigit + " " + output.join(""); + return phoneNumber; + } const output = phoneNumber.split("").map((char, index) => { if (index % 2) return char + " "; return char; diff --git a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx index 639617fd..8cde5107 100644 --- a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx +++ b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx @@ -163,7 +163,7 @@ export default function CollaboratorInformations(props: IProps) { Numéro de téléphone - {userSelected?.contact?.phone_number} + {userSelected?.contact?.cell_phone_number}
diff --git a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx index 56c98c0d..5da5c5bc 100644 --- a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx @@ -229,6 +229,16 @@ class AddClientToFolderClass extends BasePage { if (this.state.selectedOption === "new_customer") { try { + // remove every space from the phone number + values["cell_phone_number"] = values["cell_phone_number"].replace(/\s/g, ""); + if (values["cell_phone_number"] && values["cell_phone_number"].length === 10) { + // get the first digit of the phone number + const firstDigit = values["cell_phone_number"].charAt(0); + // if the first digit is a 0 replace it by +33 + if (firstDigit === "0") { + values["cell_phone_number"] = "+33" + values["cell_phone_number"].substring(1); + } + } const contactToCreate = Contact.hydrate(values); await contactToCreate.validateOrReject?.({ groups: ["createCustomer"], forbidUnknownValues: false }); } catch (validationErrors) { diff --git a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx index b8ba3045..7cc6b833 100644 --- a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx @@ -176,6 +176,17 @@ class UpdateClientClass extends BasePage { [key: string]: string; }, ) { + if (!values["cell_phone_number"]) return; + // remove every space from the phone number + values["cell_phone_number"] = values["cell_phone_number"].replace(/\s/g, ""); + if (values["cell_phone_number"] && values["cell_phone_number"].length === 10) { + // get the first digit of the phone number + const firstDigit = values["cell_phone_number"].charAt(0); + // if the first digit is a 0 replace it by +33 + if (firstDigit === "0") { + values["cell_phone_number"] = "+33" + values["cell_phone_number"].substring(1); + } + } const contact = Contact.hydrate({ first_name: values["first_name"], last_name: values["last_name"], diff --git a/src/front/Components/Layouts/MyAccount/index.tsx b/src/front/Components/Layouts/MyAccount/index.tsx index 4ac8be58..7510f09d 100644 --- a/src/front/Components/Layouts/MyAccount/index.tsx +++ b/src/front/Components/Layouts/MyAccount/index.tsx @@ -61,7 +61,7 @@ export default class MyAccount extends Base { diff --git a/src/front/Components/Layouts/Users/UserInformations/index.tsx b/src/front/Components/Layouts/Users/UserInformations/index.tsx index f93d0fcb..50a71fd3 100644 --- a/src/front/Components/Layouts/Users/UserInformations/index.tsx +++ b/src/front/Components/Layouts/Users/UserInformations/index.tsx @@ -173,7 +173,7 @@ export default function UserInformations(props: IProps) { const liveVote = await LiveVotes.getInstance().post(vote); if (liveVote.appointment.votes?.length === 3) { - if(superAdminModalType === "add") { + if (superAdminModalType === "add") { Toasts.getInstance().open({ title: `Le titre de super-administrateur a été attribué à ${userSelected.contact?.first_name} ${userSelected.contact?.last_name} `, }); @@ -238,7 +238,7 @@ export default function UserInformations(props: IProps) { Numéro de téléphone - {userSelected?.contact?.phone_number} + {userSelected?.contact?.cell_phone_number}
From 6a7c02fcfd6856ae9dbfa631ac01fa918c6fc0a9 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 16:00:04 +0100 Subject: [PATCH 33/37] :sparkles: Updating resources version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 904f00f7..73ec56b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.103", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.104", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", @@ -3360,7 +3360,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#21837e8b914b37757a676ad96a26b97840e6c575", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#fb0edf7da461aacab22b6bbf3a8928335f94e51a", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", diff --git a/package.json b/package.json index d55f9482..f0f72fa7 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "eslint-config-next": "13.2.4", "form-data": "^4.0.0", "jwt-decode": "^3.1.2", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.103", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.104", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", From bda932cf189b86f1b756f4b388330a1f7ec05591 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 5 Dec 2023 09:50:07 +0100 Subject: [PATCH 34/37] :sparkles: Password verification --- .../Components/Layouts/LoginCustomer/index.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/front/Components/Layouts/LoginCustomer/index.tsx b/src/front/Components/Layouts/LoginCustomer/index.tsx index 06626062..8dbc3736 100644 --- a/src/front/Components/Layouts/LoginCustomer/index.tsx +++ b/src/front/Components/Layouts/LoginCustomer/index.tsx @@ -115,6 +115,19 @@ export default function Login() { ]); return; } + + const passwordRegex = new RegExp(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$/); + if (!passwordRegex.test(values["password"])) { + setValidationErrors([ + { + property: "password", + constraints: { + "400": "Le mot de passe doit contenir au moins 8 caractères dont 1 majuscule, 1 minuscule et 1 chiffre.", + }, + }, + ]); + return; + } const token = await Auth.getInstance().setPassword({ totpCode, email, password: values["password"] }); CustomerStore.instance.connect(token.accessToken, token.refreshToken); router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path); From 11d81383e450e30edeba477412304ae1c9e6cdeb Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 5 Dec 2023 09:52:35 +0100 Subject: [PATCH 35/37] :sparkles: Add a margin bottom to the code prompt page --- .../Layouts/LoginCustomer/StepTotp/classes.module.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss index fae541af..fabaa162 100644 --- a/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss +++ b/src/front/Components/Layouts/LoginCustomer/StepTotp/classes.module.scss @@ -4,8 +4,7 @@ display: flex; flex-direction: column; max-width: 530px; - margin: auto; - margin-top: 220px; + margin: 220px auto; .title { text-align: left; From b1410b9ea5eede952da4c72f486957424cc37ebc Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 5 Dec 2023 09:58:20 +0100 Subject: [PATCH 36/37] :sparkles: Fixing anchoring button --- .../Layouts/Folder/FolderInformation/classes.module.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/front/Components/Layouts/Folder/FolderInformation/classes.module.scss b/src/front/Components/Layouts/Folder/FolderInformation/classes.module.scss index f84b215e..a274d91e 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/classes.module.scss +++ b/src/front/Components/Layouts/Folder/FolderInformation/classes.module.scss @@ -107,7 +107,7 @@ justify-content: center; height: 100%; .loader { - width: 40px; - height: 40px; + width: 21px; + height: 21px; } } From 8431e467bd5ecdd0d2922292f7731f062b37a11b Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 5 Dec 2023 10:04:07 +0100 Subject: [PATCH 37/37] :sparkles: Mark toasts read before redirecting --- .../Toasts/ToastsContainer/ToastElement/index.tsx | 6 ++++-- src/front/Stores/Toasts.tsx | 11 +++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/front/Components/DesignSystem/Toasts/ToastsContainer/ToastElement/index.tsx b/src/front/Components/DesignSystem/Toasts/ToastsContainer/ToastElement/index.tsx index 834009ad..f0f61287 100644 --- a/src/front/Components/DesignSystem/Toasts/ToastsContainer/ToastElement/index.tsx +++ b/src/front/Components/DesignSystem/Toasts/ToastsContainer/ToastElement/index.tsx @@ -38,6 +38,7 @@ class ToastElementClass extends React.Component { } public override render(): JSX.Element { + console.log(this.props); const toast = this.props.toast; const style = { "--data-duration": `${toast.time}ms`, @@ -98,7 +99,8 @@ class ToastElementClass extends React.Component { this.close(); } - private close() { + private async close() { + await Toasts.getInstance().markRead(this.props.toast); window.clearTimeout(this.closeTimeout); this.setState({ willClose: true, @@ -110,7 +112,7 @@ class ToastElementClass extends React.Component { private async handleClick(e: React.MouseEvent) { if (this.props.toast.redirectUrl) { - this.onClose(e); + await this.onClose(e); await this.props.router.push(this.props.toast.redirectUrl); this.props.router.reload(); } diff --git a/src/front/Stores/Toasts.tsx b/src/front/Stores/Toasts.tsx index 3cb81152..eafe0cb3 100644 --- a/src/front/Stores/Toasts.tsx +++ b/src/front/Stores/Toasts.tsx @@ -85,15 +85,18 @@ export default class Toasts { return () => this.close(toast); } + public markRead(toast: IToast) { + if (!toast.uid) return; + Notifications.getInstance().put(toast.uid, { + read: true, + }); + } + public close(toast: IToast) { const index = this.toastList.indexOf(toast); if (index === -1) return; this.toastList.splice(index, 1); - if (toast.uid) - Notifications.getInstance().put(toast.uid, { - read: true, - }); this.event.emit("change", this.toastList); }