From eceaa3622a69ac43f6d948dcfd32f460898b2893 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 18:12:38 +0200 Subject: [PATCH 1/6] fix helm chart --- devops/ppd.values.yaml | 2 +- devops/prd.values.yaml | 2 +- devops/stg.values.yaml | 2 +- devops/templates/secrets.yaml | 17 +---------------- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index 7fb9b7fb..d235fabc 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -22,7 +22,7 @@ lecoffreFront: tls: hosts: - app.ppd.lecoffre.smart-chain.fr - secretName: api-tls + secretName: front-tls annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod diff --git a/devops/prd.values.yaml b/devops/prd.values.yaml index b93e7f88..403df50d 100644 --- a/devops/prd.values.yaml +++ b/devops/prd.values.yaml @@ -22,7 +22,7 @@ lecoffreFront: tls: hosts: - app.lecoffre.smart-chain.fr - secretName: api-tls + secretName: front-tls annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod diff --git a/devops/stg.values.yaml b/devops/stg.values.yaml index f73bcbd5..e57c6b3d 100644 --- a/devops/stg.values.yaml +++ b/devops/stg.values.yaml @@ -22,7 +22,7 @@ lecoffreFront: tls: hosts: - app.stg.lecoffre.smart-chain.fr - secretName: api-tls + secretName: front-tls annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod diff --git a/devops/templates/secrets.yaml b/devops/templates/secrets.yaml index 52f3c820..1c19ced3 100644 --- a/devops/templates/secrets.yaml +++ b/devops/templates/secrets.yaml @@ -1,16 +1 @@ -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ .Values.lecoffreFront.envSecrets }} -spec: - refreshInterval: 20s - secretStoreRef: - kind: SecretStore - name: secret-store - data: - {{ range $v := .Values.lecoffreFront.env }} - - secretKey: {{ $v.key }} - remoteRef: - key: {{ $v.scwID}} - version: latest_enabled - {{ end }} \ No newline at end of file +## same secret as back \ No newline at end of file From 7ed41809f55055fa58138abf9e675ce882b1fad0 Mon Sep 17 00:00:00 2001 From: pida123 Date: Fri, 4 Aug 2023 11:19:32 +0200 Subject: [PATCH 2/6] fix target port --- devops/templates/lecoffre-front.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/templates/lecoffre-front.yaml b/devops/templates/lecoffre-front.yaml index 76e79857..4479a457 100644 --- a/devops/templates/lecoffre-front.yaml +++ b/devops/templates/lecoffre-front.yaml @@ -32,7 +32,7 @@ spec: ports: - port: 80 name: http - targetPort: 3001 + targetPort: 3000 selector: app: lecoffre-front --- From 0967c142ddbcfe02f47e373051bca6505873cf5c Mon Sep 17 00:00:00 2001 From: Vins Date: Mon, 7 Aug 2023 11:07:48 +0200 Subject: [PATCH 3/6] Changed file namespace for Client-dashboard page --- .../Api/LeCoffreApi/Customer/BaseCustomer.ts | 2 +- .../Api/LeCoffreApi/Customer/Files/Files.ts | 93 +++++++++++++++++++ .../DesignSystem/DepositDocument/index.tsx | 2 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/front/Api/LeCoffreApi/Customer/Files/Files.ts diff --git a/src/front/Api/LeCoffreApi/Customer/BaseCustomer.ts b/src/front/Api/LeCoffreApi/Customer/BaseCustomer.ts index ac56570d..f732de84 100644 --- a/src/front/Api/LeCoffreApi/Customer/BaseCustomer.ts +++ b/src/front/Api/LeCoffreApi/Customer/BaseCustomer.ts @@ -1,5 +1,5 @@ import BaseApiService from "@Front/Api/BaseApiService"; export default abstract class BaseNotary extends BaseApiService { - protected readonly namespaceUrl = this.getBaseUrl().concat("/customers"); + protected readonly namespaceUrl = this.getBaseUrl().concat("/customer"); } diff --git a/src/front/Api/LeCoffreApi/Customer/Files/Files.ts b/src/front/Api/LeCoffreApi/Customer/Files/Files.ts new file mode 100644 index 00000000..4cf6ebd4 --- /dev/null +++ b/src/front/Api/LeCoffreApi/Customer/Files/Files.ts @@ -0,0 +1,93 @@ +import { File } from "le-coffre-resources/dist/SuperAdmin"; +import BaseCustomer from "../BaseCustomer"; + +// TODO Type get query params -> Where + inclue + orderby +export interface IGetFilesparams { + where?: {}; + include?: {}; +} + +// TODO Type getbyuid query params + +export type IPutFilesParams = {}; + +export interface IPostFilesParams {} + +export default class Files extends BaseCustomer { + private static instance: Files; + private readonly baseURl = this.namespaceUrl.concat("/files"); + + private constructor() { + super(); + } + + public static getInstance() { + return (this.instance ??= new this()); + } + + public async get(q: IGetFilesparams): Promise { + const url = new URL(this.baseURl); + const query = { q }; + if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + const files = await this.getRequest(url); + return files; + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + /** + * @description : Create a File + */ + public async post(body: any): Promise { + const url = new URL(this.baseURl); + try { + return await this.postRequestFormData(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public getUploadLink(uid: string): string { + return this.baseURl.concat(`/download/${uid}`); + } + + public async getByUid(uid: string, q?: any): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + const query = { q }; + if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + const file = await this.getRequest(url); + return file; + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async put(uid: string, body: IPutFilesParams): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + try { + return await this.putRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + /** + * @description : Delete a folder only if the folder don't contains customers + */ + public async delete(uid: string): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + try { + return await this.deleteRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Components/DesignSystem/DepositDocument/index.tsx b/src/front/Components/DesignSystem/DepositDocument/index.tsx index 8d1a75e1..56aa6122 100644 --- a/src/front/Components/DesignSystem/DepositDocument/index.tsx +++ b/src/front/Components/DesignSystem/DepositDocument/index.tsx @@ -10,7 +10,7 @@ import Tooltip from "../ToolTip"; import Typography, { ITypo, ITypoColor } from "../Typography"; import classes from "./classes.module.scss"; import { Document, DocumentHistory, File as FileCustomer } from "le-coffre-resources/dist/Customer"; -import Files from "@Front/Api/LeCoffreApi/SuperAdmin/Files/Files"; +import Files from "@Front/Api/LeCoffreApi/Customer/Files/Files"; import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; import classNames from "classnames"; import Confirm from "../Modal/Confirm"; From 489cdd968540236093b8fcce163b04fdf10b2b9e Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 9 Aug 2023 11:39:12 +0200 Subject: [PATCH 4/6] Page select folders unmocked --- src/front/Api/Auth/franceConnect/Customer.ts | 38 +++++++++++++ .../Api/LeCoffreApi/Customer/Files/Files.ts | 2 +- .../LeCoffreApi/Customer/Folders/Folders.ts | 57 +++++++++++++++++++ src/front/Components/Layouts/Login/index.tsx | 19 +++++++ .../Components/Layouts/SelectFolder/index.tsx | 22 ++++++- src/front/Services/JwtService/JwtService.ts | 4 +- src/front/Stores/UserStore.ts | 18 ++++++ 7 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 src/front/Api/Auth/franceConnect/Customer.ts create mode 100644 src/front/Api/LeCoffreApi/Customer/Folders/Folders.ts diff --git a/src/front/Api/Auth/franceConnect/Customer.ts b/src/front/Api/Auth/franceConnect/Customer.ts new file mode 100644 index 00000000..b7c60ba5 --- /dev/null +++ b/src/front/Api/Auth/franceConnect/Customer.ts @@ -0,0 +1,38 @@ +import BaseApiService from "@Front/Api/BaseApiService"; + +export default class Customer extends BaseApiService { + private static instance: Customer; + private readonly baseURl = this.getBaseUrl().concat("/france-connect/customer"); + + private constructor() { + super(); + } + + public static getInstance() { + if (!this.instance) { + return new Customer(); + } else { + return this.instance; + } + } + + public async login(email: string) { + const url = new URL(this.baseURl.concat("/login/").concat(email)); + try { + return await this.postRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async refreshToken(refreshToken: string): Promise<{ accessToken: string }> { + const url = new URL(this.baseURl.concat("/refresh-token")); + try { + return await this.postRequest(url, {}, refreshToken); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Api/LeCoffreApi/Customer/Files/Files.ts b/src/front/Api/LeCoffreApi/Customer/Files/Files.ts index 4cf6ebd4..6ae12cf0 100644 --- a/src/front/Api/LeCoffreApi/Customer/Files/Files.ts +++ b/src/front/Api/LeCoffreApi/Customer/Files/Files.ts @@ -1,4 +1,4 @@ -import { File } from "le-coffre-resources/dist/SuperAdmin"; +import { File } from "le-coffre-resources/dist/Customer"; import BaseCustomer from "../BaseCustomer"; // TODO Type get query params -> Where + inclue + orderby diff --git a/src/front/Api/LeCoffreApi/Customer/Folders/Folders.ts b/src/front/Api/LeCoffreApi/Customer/Folders/Folders.ts new file mode 100644 index 00000000..27bfd731 --- /dev/null +++ b/src/front/Api/LeCoffreApi/Customer/Folders/Folders.ts @@ -0,0 +1,57 @@ +import { type OfficeFolder } from "le-coffre-resources/dist/Customer"; + +import BaseCustomer from "../BaseCustomer"; + +// TODO Type get query params -> Where + inclue + orderby +export interface IGetFoldersParams { + q?: { + select?: {}; + where?: {}; + include?: {}; + }; +} + +export default class Folders extends BaseCustomer { + private static instance: Folders; + private readonly baseURl = this.namespaceUrl.concat("/folders"); + + private constructor() { + super(); + } + + public static getInstance() { + if (!this.instance) { + return new this(); + } else { + return this.instance; + } + } + + /** + * @description : Get all folders + */ + public async get(q: IGetFoldersParams): Promise { + const url = new URL(this.baseURl); + Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + /** + * @description : Get a folder by uid + */ + public async getByUid(uid: string, q?: any): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + if (q) Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Components/Layouts/Login/index.tsx b/src/front/Components/Layouts/Login/index.tsx index 977c4138..7bbcf405 100644 --- a/src/front/Components/Layouts/Login/index.tsx +++ b/src/front/Components/Layouts/Login/index.tsx @@ -15,6 +15,7 @@ import LandingImage from "./landing-connect.jpeg"; export default function Login() { const router = useRouter(); + const redirectUserOnConnection = useCallback(() => { async function getUser() { try { @@ -28,6 +29,21 @@ export default function Login() { getUser(); }, [router]); + + const redirectCustomerOnConnection = useCallback(() => { + async function getUser() { + try { + await UserStore.instance.connectCustomer("antoine.bernard@outlook.com"); + await JwtService.getInstance().checkJwt(); + router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path); + } catch (e) { + console.error(e); + } + } + + getUser(); + }, [router]); + return (
@@ -38,6 +54,9 @@ export default function Login() { +
Vous n'arrivez pas à vous connecter ?
diff --git a/src/front/Components/Layouts/SelectFolder/index.tsx b/src/front/Components/Layouts/SelectFolder/index.tsx index 441461ef..7b5ebfd6 100644 --- a/src/front/Components/Layouts/SelectFolder/index.tsx +++ b/src/front/Components/Layouts/SelectFolder/index.tsx @@ -1,4 +1,4 @@ -import Folders from "@Front/Api/LeCoffreApi/SuperAdmin/Folders/Folders"; +import Folders from "@Front/Api/LeCoffreApi/Customer/Folders/Folders"; import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; @@ -8,6 +8,7 @@ import { useCallback, useEffect, useState } from "react"; import LandingImage from "../Login/landing-connect.jpeg"; import classes from "./classes.module.scss"; +import JwtService from "@Front/Services/JwtService/JwtService"; export default function SelectFolder() { const [folders, setFolders] = useState([]); @@ -15,8 +16,23 @@ export default function SelectFolder() { useEffect(() => { async function getFolders() { - const folders = await Folders.getInstance().get({}); - setFolders(folders.slice(0, 3)); + const jwt = JwtService.getInstance().decodeJwt(); + if (!jwt) return; + console.log(jwt); + + const folders = await Folders.getInstance().get({ + q: { + where: { + customers: { + some: { + uid: jwt.userId, + }, + }, + }, + }, + }); + setFolders(folders); + console.log(folders); } getFolders(); diff --git a/src/front/Services/JwtService/JwtService.ts b/src/front/Services/JwtService/JwtService.ts index 66db5c7c..f753ae6f 100644 --- a/src/front/Services/JwtService/JwtService.ts +++ b/src/front/Services/JwtService/JwtService.ts @@ -38,7 +38,9 @@ export default class JwtService { */ public async checkJwt() { const decodedToken = this.decodeJwt(); - if(!decodedToken) return; + console.log(decodedToken); + + if (!decodedToken) return; const now = Math.floor(Date.now() / 1000); diff --git a/src/front/Stores/UserStore.ts b/src/front/Stores/UserStore.ts index c4bf3a1a..06c70182 100644 --- a/src/front/Stores/UserStore.ts +++ b/src/front/Stores/UserStore.ts @@ -1,6 +1,7 @@ "use client"; import User from "@Front/Api/Auth/IdNot/User"; +import Customer from "@Front/Api/Auth/franceConnect/Customer"; import CookieService from "@Front/Services/CookieService/CookieService"; import EventEmitter from "@Front/Services/EventEmitter"; @@ -33,6 +34,23 @@ export default class UserStore { return true; } + public async connectCustomer(email: string) { + try { + //call connection function + const customer: any = await Customer.getInstance().login(email); + + //Save tokens in cookies + CookieService.getInstance().setCookie("leCoffreAccessToken", customer.accessToken); + CookieService.getInstance().setCookie("leCoffreRefreshToken", customer.refreshToken); + + this.event.emit("connection", this.accessToken); + } catch (error) { + console.error(error); + return false; + } + return true; + } + public async disconnect() { try { //Remove tokens from cookies From 804e0d5976076e67e703caf74b2f7e28ed709b4b Mon Sep 17 00:00:00 2001 From: Vins Date: Thu, 10 Aug 2023 14:35:12 +0200 Subject: [PATCH 5/6] Unmocked client dashboard page --- src/front/Api/.BaseApiService.ts.swp | Bin 0 -> 16384 bytes .../Customer/Customers/Customers.ts | 67 ++++++ .../Customer/Documents/Documents.ts | 93 ++++++++ .../Layouts/ClientDashboard/index.tsx | 201 +++++++++--------- .../Layouts/ClientDashboard/index2.tsx | 141 ++++++++++++ src/front/Components/Layouts/Login/index.tsx | 4 +- .../Components/Layouts/SelectFolder/index.tsx | 4 +- src/front/Services/JwtService/JwtService.ts | 2 +- .../[folderUid]/index.tsx} | 4 +- src/pages/client-dashboard1.tsx | 2 +- src/pages/client-dashboard2.tsx | 2 +- src/pages/client-dashboard3.tsx | 2 +- src/pages/login-callback.tsx | 2 +- 13 files changed, 412 insertions(+), 112 deletions(-) create mode 100644 src/front/Api/.BaseApiService.ts.swp create mode 100644 src/front/Api/LeCoffreApi/Customer/Customers/Customers.ts create mode 100644 src/front/Api/LeCoffreApi/Customer/Documents/Documents.ts create mode 100644 src/front/Components/Layouts/ClientDashboard/index2.tsx rename src/pages/{client-dashboard.tsx => client-dashboard/[folderUid]/index.tsx} (54%) diff --git a/src/front/Api/.BaseApiService.ts.swp b/src/front/Api/.BaseApiService.ts.swp new file mode 100644 index 0000000000000000000000000000000000000000..e5645d500d76386bf55d9a55e9b7bec7aefdd052 GIT binary patch literal 16384 zcmeI2OKclO7{@0-fu$|sA@R7Nso`ML#4gZ6>oiFn*J)CcIyg=wK#;E2<7N|k*PR_F zgpih^@=}48#{oD25*z>tQ7XX!frOBd5VvvwuBZqBQV(1JiN}A&yM8ro(>9<2v+A$T z&hE^7^PkyozMY-iy79qbx+%Jj;JAX26?;F<|Gc5UZOhGs%-D`6lTUYy+m6K?;dKt1 zR-fxmcaCs3T68V5*qn2ZEHE}&GP$rOP1}hLrD!tU-=9gviY)0C3Y>Koxa)|R$E{fP zuSD67^_d>S?QTQjw1!@N)tJ^qE1(t73TOqi z0$KsBfL1^&pcVKZDIm%hkiBT{1%8|N`M+%~zkmA2<$n4jE!X{1{i7Ao3TOqi0$KsB zfL1^&pcT*xXa%$aS^=%Vd8mMyCu9}u>W~Wn`2HWf|9{j@NCgOR59k5cgKNR}SOoYC zJO&;GQ(zce1HN5N$lG8R2;hOc!A7tFtOxiENe-jZcflcW5HPS2tOsr2_)0>40zZN` z!2$3DcpMCYD7X%+07ow)&iKDdaGm%)Cp8^pmn5CLJ(2L8B^kl(>O-~bp0 zqaXu*Kwp0jJ^?R*J)i)#fh6byay+aBjfY{_1sYz%nOAllk44?-2%RUyFcyHpnW%7w zV(&-E#zoGim?grD^GH|qay8d>&vj@wbt=W8OkbduiQOPn-WaD9XWDUR9a*d@u_=o= zYubX=YM(+uVO6%^b1FlT)i29x;?#8J=tDtWW$p@?#PZbi<{XRS++v=W@td``YiZdYrH7QmS3^wNUi1_d)rwaQu^?-`2~a6$ zva&!mw#@ArQ!u{?9&_@Us(n@S&(+k$3xsj9KNggchLLmga~(3lm}F+2aW76)J98Dg zm>;Mng_GFFgH1u%xiX9Pr!&J7TNBwtq?)b7#H5>#)6mFRHl&iO4J|MXg>Z!zJ5+xL za;Qd0HB`5$ZXm`9y;%|cE-!60h1sA8%8Jvm%uolFM#pJzO9vJ1G;@06)Dzrxc2x&* zYsW2FjYa|bP*GUc<~MeU8f_mmsokE;>dhaxYNL5Mht38f% z0piau{5v!oNo11)%OzP^`lhp2?ED;6%lpusy*ei!Prjd7@SleUhjX?b$EdrU^r-K1 zj76P}(d1>C{CJBySi}dpp78Yu9F26#Cv!se;jvhQPvujVDno-)`NtJltmS{NhiRCi z&cW$!OD)@+w2KA9p;?U6%ssN#qE#ns7yP*du~L1;Qxk1%o{7_w%Nhy1d23+e3nW7@ z|Iet$L^zbFU~1;}gQl=uC)7cA_A!$)PH&o5MlbACLsbQQP5J!kzEjTk$cCvqnEh1- z88|ki(eCbU>Ss|Af*PpGMgzAY2=WV;ks_O=1Ab6}vS4ua4rLFnC$Zz$X2IrQNIr=C zCUzu;BT<}HFNZ_H4&#I+gTAbs{X^2U7FC0q8jOuMT3UZ*{RppRb8-%QmB+XYZR-WY z3V9cj5xdBMS;^NgcRC|}8#lRa=8DXd);8GQmq^|@kr)}A7*AzJ2h%%bR~bvrlu4(v z69|0h+B3>F0PlE)Sw=GHY&w~)*0i`9w70jrQ4rOEykZHL`-;@X;^=DEDbCTEKo|7! zX_~FnuExdadSP4C?}lLXcM>me&jDd1z#-HXI0aqS+znY>j;*vN18v#HfBJLe*q9Q BI#2)r literal 0 HcmV?d00001 diff --git a/src/front/Api/LeCoffreApi/Customer/Customers/Customers.ts b/src/front/Api/LeCoffreApi/Customer/Customers/Customers.ts new file mode 100644 index 00000000..b596a695 --- /dev/null +++ b/src/front/Api/LeCoffreApi/Customer/Customers/Customers.ts @@ -0,0 +1,67 @@ +import Customer, { Contact } from "le-coffre-resources/dist/Customer"; + +import BaseCustomer from "../BaseCustomer"; +import { ECivility } from "le-coffre-resources/dist/Customer/Contact"; + +// TODO Type get query params -> Where + inclue + orderby +export interface IGetCustomersparams { + where?: {}; + include?: {}; +} + +// TODO Type getbyuid query params + +export type IPutCustomersParams = { + uid?: Customer["uid"]; + contact?: Customer["contact"]; +}; + +export interface IPostCustomersParams { + first_name: string; + last_name: string; + email: string; + cell_phone_number: string; + civility: ECivility; + address?: Contact["address"]; +} + +export default class Customers extends BaseCustomer { + private static instance: Customers; + private readonly baseURl = this.namespaceUrl.concat("/customers"); + + private constructor() { + super(); + } + + public static getInstance() { + if (!this.instance) { + return new this(); + } else { + return this.instance; + } + } + + public async get(q: IGetCustomersparams): Promise { + const url = new URL(this.baseURl); + const query = { q }; + Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async getByUid(uid: string, q?: any): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + const query = { q }; + if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Api/LeCoffreApi/Customer/Documents/Documents.ts b/src/front/Api/LeCoffreApi/Customer/Documents/Documents.ts new file mode 100644 index 00000000..8590554b --- /dev/null +++ b/src/front/Api/LeCoffreApi/Customer/Documents/Documents.ts @@ -0,0 +1,93 @@ +import { Document } from "le-coffre-resources/dist/Customer"; + +import BaseCustomer from "../BaseCustomer"; +import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; + +// TODO Type get query params -> Where + inclue + orderby +export interface IGetDocumentsparams { + where?: {}; + include?: {}; +} + +// TODO Type getbyuid query params + +export type IPutDocumentsParams = { + document_status?: EDocumentStatus; + refused_reason?: string; +}; + +export interface IPostDocumentsParams {} + +export default class Documents extends BaseCustomer { + private static instance: Documents; + private readonly baseURl = this.namespaceUrl.concat("/documents"); + + private constructor() { + super(); + } + + public static getInstance() { + if (!this.instance) { + return new this(); + } else { + return this.instance; + } + } + + public async get(q: IGetDocumentsparams): Promise { + const url = new URL(this.baseURl); + const query = { q }; + if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + /** + * @description : Create a Document + */ + public async post(body: any): Promise { + const url = new URL(this.baseURl); + try { + return await this.postRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async getByUid(uid: string, q?: any): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + const query = { q }; + if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); + try { + return await this.getRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async put(uid: string, body: IPutDocumentsParams): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + try { + return await this.putRequest(url, body); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } + + public async delete(uid: string): Promise { + const url = new URL(this.baseURl.concat(`/${uid}`)); + try { + return await this.deleteRequest(url); + } catch (err) { + this.onError(err); + return Promise.reject(err); + } + } +} diff --git a/src/front/Components/Layouts/ClientDashboard/index.tsx b/src/front/Components/Layouts/ClientDashboard/index.tsx index f85d2560..bfb029a6 100644 --- a/src/front/Components/Layouts/ClientDashboard/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/index.tsx @@ -1,95 +1,74 @@ -import Customers from "@Front/Api/LeCoffreApi/SuperAdmin/Customers/Customers"; -import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents"; +"use client"; +import Customers from "@Front/Api/LeCoffreApi/Customer/Customers/Customers"; +import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/Customer/Documents/Documents"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import DepositDocument from "@Front/Components/DesignSystem/DepositDocument"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; -import Base from "@Front/Components/Layouts/Base"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import Customer, { Document, DocumentType } from "le-coffre-resources/dist/Customer"; -import React from "react"; +import React, { useCallback, useEffect, useState } from "react"; import classes from "./classes.module.scss"; +import { useRouter } from "next/router"; +import JwtService from "@Front/Services/JwtService/JwtService"; -type IProps = { - targetedCustormer: string; // MOCK -}; -type IState = { - isAddDocumentModalVisible: boolean; - documents: Document[]; - mockedCustomer: Customer | null; -}; +type IProps = {}; -export default class ClientDashboard extends Base { - public constructor(props: IProps) { - super(props); - this.state = { - isAddDocumentModalVisible: false, - documents: [], - mockedCustomer: null, - }; - this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this); - this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this); - } +export default function ClientDashboard(props: IProps) { + const router = useRouter(); + let { folderUid } = router.query; + const [documents, setDocuments] = useState(null); + const [customer, setCustomer] = useState(null); + const [isAddDocumentModalVisible, setIsAddDocumentModalVisible] = useState(false); - public override render(): JSX.Element { - return ( - -
- {this.renderHeader()} -
-
- {this.state.documents?.map((document) => ( - - ))} -
- Documents supplémentaires (facultatif) - - Vous souhaitez envoyer d'autres documents à votre notaire ? - - -
- -
- - Vous souhaitez envoyer un autre document à votre notaire ? - - - - Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le - document correspondant. - - ({ - document_type: DocumentType.hydrate({ - name: "Document annexe", - }), - })} - /> -
-
-
-
- ); - } + const onCloseModalAddDocument = useCallback(() => { + setIsAddDocumentModalVisible(false); + }, []); - private renderHeader(): JSX.Element { + const onOpenModalAddDocument = useCallback(() => { + setIsAddDocumentModalVisible(true); + }, []); + + useEffect(() => { + async function getDocuments() { + let jwt; + if (typeof document !== "undefined") { + jwt = JwtService.getInstance().decodeJwt(); + } + if (!jwt || !jwt.email) return; + const customers = await Customers.getInstance().get({ + where: { contact: { email: jwt.email }, office_folders: { some: { uid: folderUid } } }, + }); + const actualCustomer: Customer = customers[0]!; + + const query: IGetDocumentsparams = { + where: { depositor: { uid: actualCustomer.uid }, folder_uid: folderUid as string }, + include: { + files: true, + document_history: true, + document_type: true, + depositor: true, + }, + }; + + const documentList = await Documents.getInstance().get(query); + + setDocuments(documentList); + setCustomer(actualCustomer); + } + + getDocuments(); + }, [folderUid]); + + const renderHeader = useCallback(() => { return (
{/* TODO Get name from userStore */} - Bonjour {this.state.mockedCustomer?.contact?.first_name.concat(" ", this.state.mockedCustomer?.contact?.last_name)} + Bonjour {customer?.contact?.first_name.concat(" ", customer?.contact?.last_name)} @@ -108,31 +87,53 @@ export default class ClientDashboard extends Base {
); - } + }, [customer]); - public override async componentDidMount() { - // TODO Get documents of the current customer according to userStore - // REMOVE this mock - const mockedCustomers = await Customers.getInstance().get({ where: { contact: { email: this.props.targetedCustormer } } }); - const mockedCustomer: Customer = mockedCustomers[0]!; - - const query: IGetDocumentsparams = { - where: { depositor: { uid: mockedCustomer.uid } }, - include: { - files: true, - document_history: true, - document_type: true, - }, - }; - const documents: Document[] = await Documents.getInstance().get(query); - this.setState({ documents, mockedCustomer }); - } - - private onCloseModalAddDocument() { - this.setState({ isAddDocumentModalVisible: false }); - } - - private onOpenModalAddDocument() { - this.setState({ isAddDocumentModalVisible: true }); - } + return ( + +
+ {renderHeader()} +
+
+ {documents?.map((document) => ( + + ))} +
+ Documents supplémentaires (facultatif) + + Vous souhaitez envoyer d'autres documents à votre notaire ? + + +
+ +
+ + Vous souhaitez envoyer un autre document à votre notaire ? + + + + Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le + document correspondant. + + ({ + document_type: DocumentType.hydrate({ + name: "Document annexe", + }), + })} + /> +
+
+
+
+ ); } diff --git a/src/front/Components/Layouts/ClientDashboard/index2.tsx b/src/front/Components/Layouts/ClientDashboard/index2.tsx new file mode 100644 index 00000000..506e9249 --- /dev/null +++ b/src/front/Components/Layouts/ClientDashboard/index2.tsx @@ -0,0 +1,141 @@ +import Customers from "@Front/Api/LeCoffreApi/Customer/Customers/Customers"; +import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/Customer/Documents/Documents"; +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import DepositDocument from "@Front/Components/DesignSystem/DepositDocument"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; +import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; +import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; +import Base from "@Front/Components/Layouts/Base"; +import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; +import Customer, { Document, DocumentType } from "le-coffre-resources/dist/Customer"; +import React from "react"; + +import classes from "./classes.module.scss"; +import JwtService from "@Front/Services/JwtService/JwtService"; + +type IProps = {}; +type IState = { + isAddDocumentModalVisible: boolean; + documents: Document[]; + mockedCustomer: Customer | null; +}; + +export default class ClientDashboard extends Base { + public constructor(props: IProps) { + super(props); + this.state = { + isAddDocumentModalVisible: false, + documents: [], + mockedCustomer: null, + }; + this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this); + this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this); + } + + public override render(): JSX.Element { + return ( + +
+ {this.renderHeader()} +
+
+ {this.state.documents?.map((document) => ( + + ))} +
+ Documents supplémentaires (facultatif) + + Vous souhaitez envoyer d'autres documents à votre notaire ? + + +
+ +
+ + Vous souhaitez envoyer un autre document à votre notaire ? + + + + Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le + document correspondant. + + ({ + document_type: DocumentType.hydrate({ + name: "Document annexe", + }), + })} + /> +
+
+
+
+ ); + } + + private renderHeader(): JSX.Element { + return ( +
+
+ {/* TODO Get name from userStore */} + + Bonjour {this.state.mockedCustomer?.contact?.first_name.concat(" ", this.state.mockedCustomer?.contact?.last_name)} + + + + Documents à envoyer + + + + Votre notaire est dans l'attente de documents pour valider votre dossier. Voici la liste des documents.Veuillez + glisser / déposez chaque document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le + document correspondant. Si un des documents demandés ne vous concernent pas, veuillez contacter votre notaire à + l’aide du bouton ci-dessus. + +
+ + + +
+ ); + } + + public override async componentDidMount() { + // TODO Get documents of the current customer according to userStore + // REMOVE this mock + + const jwt = JwtService.getInstance().decodeJwt(); + const mockedCustomers = await Customers.getInstance().get({ + where: { contact: { email: jwt?.email } }, + }); + const mockedCustomer: Customer = mockedCustomers[0]!; + + const query: IGetDocumentsparams = { + where: { depositor: { uid: mockedCustomer.uid } }, + include: { + files: true, + document_history: true, + document_type: true, + }, + }; + const documents: Document[] = await Documents.getInstance().get(query); + this.setState({ documents, mockedCustomer }); + } + + private onCloseModalAddDocument() { + this.setState({ isAddDocumentModalVisible: false }); + } + + private onOpenModalAddDocument() { + this.setState({ isAddDocumentModalVisible: true }); + } +} diff --git a/src/front/Components/Layouts/Login/index.tsx b/src/front/Components/Layouts/Login/index.tsx index 7bbcf405..3145b579 100644 --- a/src/front/Components/Layouts/Login/index.tsx +++ b/src/front/Components/Layouts/Login/index.tsx @@ -31,7 +31,7 @@ export default function Login() { }, [router]); const redirectCustomerOnConnection = useCallback(() => { - async function getUser() { + async function getCustomer() { try { await UserStore.instance.connectCustomer("antoine.bernard@outlook.com"); await JwtService.getInstance().checkJwt(); @@ -41,7 +41,7 @@ export default function Login() { } } - getUser(); + getCustomer(); }, [router]); return ( diff --git a/src/front/Components/Layouts/SelectFolder/index.tsx b/src/front/Components/Layouts/SelectFolder/index.tsx index 7b5ebfd6..881f7f78 100644 --- a/src/front/Components/Layouts/SelectFolder/index.tsx +++ b/src/front/Components/Layouts/SelectFolder/index.tsx @@ -18,7 +18,6 @@ export default function SelectFolder() { async function getFolders() { const jwt = JwtService.getInstance().decodeJwt(); if (!jwt) return; - console.log(jwt); const folders = await Folders.getInstance().get({ q: { @@ -32,7 +31,6 @@ export default function SelectFolder() { }, }); setFolders(folders); - console.log(folders); } getFolders(); @@ -40,7 +38,7 @@ export default function SelectFolder() { const handleSelectBlock = useCallback( (block: IBlock) => { - router.push("/client-dashboard"); + router.push("/client-dashboard/" + block.id); }, [router], ); diff --git a/src/front/Services/JwtService/JwtService.ts b/src/front/Services/JwtService/JwtService.ts index f753ae6f..41b84d92 100644 --- a/src/front/Services/JwtService/JwtService.ts +++ b/src/front/Services/JwtService/JwtService.ts @@ -8,6 +8,7 @@ enum PROVIDER_OPENID { interface IUserJwtPayload { userId: string; + email: string | null; openId: { providerName: PROVIDER_OPENID; userId: string | number; @@ -38,7 +39,6 @@ export default class JwtService { */ public async checkJwt() { const decodedToken = this.decodeJwt(); - console.log(decodedToken); if (!decodedToken) return; diff --git a/src/pages/client-dashboard.tsx b/src/pages/client-dashboard/[folderUid]/index.tsx similarity index 54% rename from src/pages/client-dashboard.tsx rename to src/pages/client-dashboard/[folderUid]/index.tsx index 7a37a3f1..e5f0d92a 100644 --- a/src/pages/client-dashboard.tsx +++ b/src/pages/client-dashboard/[folderUid]/index.tsx @@ -1,5 +1,5 @@ -import ClientDashboard from "@Front/Components/Layouts/ClientDashboard"; +import ClientDashboard from "@Front/Components/Layouts/ClientDashboard/index"; export default function Route() { - return ; + return ; } diff --git a/src/pages/client-dashboard1.tsx b/src/pages/client-dashboard1.tsx index 9c2082f6..8af5b0c0 100644 --- a/src/pages/client-dashboard1.tsx +++ b/src/pages/client-dashboard1.tsx @@ -1,4 +1,4 @@ -import ClientDashboard from "@Front/Components/Layouts/ClientDashboard"; +import ClientDashboard from "@Front/Components/Layouts/ClientDashboard/index2"; export default function Route() { return ; diff --git a/src/pages/client-dashboard2.tsx b/src/pages/client-dashboard2.tsx index 3f09fb4f..0f303bc6 100644 --- a/src/pages/client-dashboard2.tsx +++ b/src/pages/client-dashboard2.tsx @@ -1,4 +1,4 @@ -import ClientDashboard from "@Front/Components/Layouts/ClientDashboard"; +import ClientDashboard from "@Front/Components/Layouts/ClientDashboard/index2"; export default function Route() { return ; diff --git a/src/pages/client-dashboard3.tsx b/src/pages/client-dashboard3.tsx index d4f29e4f..75b2b0b8 100644 --- a/src/pages/client-dashboard3.tsx +++ b/src/pages/client-dashboard3.tsx @@ -1,4 +1,4 @@ -import ClientDashboard from "@Front/Components/Layouts/ClientDashboard"; +import ClientDashboard from "@Front/Components/Layouts/ClientDashboard/index2"; export default function Route() { return ; diff --git a/src/pages/login-callback.tsx b/src/pages/login-callback.tsx index 931db6d5..c6c7d7c7 100644 --- a/src/pages/login-callback.tsx +++ b/src/pages/login-callback.tsx @@ -1,4 +1,4 @@ -import ClientDashboard from "@Front/Components/Layouts/ClientDashboard"; +import ClientDashboard from "@Front/Components/Layouts/ClientDashboard/index2"; export default function Route() { return ; From d6d0839f357e6b5c1b70e778bf6f7058b4e91669 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Thu, 17 Aug 2023 11:48:18 +0200 Subject: [PATCH 6/6] add roles and rules label --- package.json | 2 +- .../Components/Layouts/Roles/RolesInformations/index.tsx | 8 ++++---- .../Components/Layouts/Users/UserInformations/index.tsx | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index a2f6f2f1..f3c96218 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.66", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.68", "next": "13.2.4", "prettier": "^2.8.7", "react": "18.2.0", diff --git a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx index 8599a657..5da3eda9 100644 --- a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx @@ -6,7 +6,7 @@ import Form from "@Front/Components/DesignSystem/Form"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import DefaultRoleDashboard from "@Front/Components/LayoutTemplates/DefaultRoleDashboard"; -import { Role, Rule } from "le-coffre-resources/dist/Admin"; +import { OfficeRole, Rule } from "le-coffre-resources/dist/Admin"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; import React from "react"; @@ -21,7 +21,7 @@ export default function RolesInformations(props: IProps) { const router = useRouter(); let { roleUid } = router.query; - const [roleSelected, setRoleSelected] = useState(null); + const [roleSelected, setRoleSelected] = useState(null); const [rulesCheckboxes, setRulesCheckboxes] = useState([]); const [selectAll, setSelectAll] = useState(false); @@ -56,7 +56,7 @@ export default function RolesInformations(props: IProps) { } return { ...rule, checked: false }; }) - .sort((ruleA, ruleB) => (ruleA.name < ruleB.name ? 1 : -1)) + .sort((ruleA, ruleB) => (ruleA.label < ruleB.label ? 1 : -1)) .sort((rule) => (rule.checked ? -1 : 1)); const selectAll = rulesCheckboxes.every((rule) => rule.checked); @@ -134,7 +134,7 @@ export default function RolesInformations(props: IProps) { {rulesCheckboxes.map((rule) => (
diff --git a/src/front/Components/Layouts/Users/UserInformations/index.tsx b/src/front/Components/Layouts/Users/UserInformations/index.tsx index 5ade8659..4bff2860 100644 --- a/src/front/Components/Layouts/Users/UserInformations/index.tsx +++ b/src/front/Components/Layouts/Users/UserInformations/index.tsx @@ -182,9 +182,9 @@ export default function UserInformations(props: IProps) { setRoleModalOpened(false); setSelectedOption({ value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid, - label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.name!, + label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.label!, }); - }, [userSelected?.office_role, userSelected?.role?.name, userSelected?.role?.uid]); + }, [userSelected?.office_role, userSelected?.role?.label, userSelected?.role?.uid]); const changeRole = useCallback(async () => { await Users.getInstance().put( @@ -271,7 +271,7 @@ export default function UserInformations(props: IProps) { onChange={handleRoleChange} selectedOption={{ value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid, - label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.name!, + label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.label!, }} />