Merge branch 'dev' into feature/ora-502-ask-another-document
This commit is contained in:
commit
021a81ea1d
58
package-lock.json
generated
58
package-lock.json
generated
@ -19,7 +19,7 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"eslint": "8.36.0",
|
"eslint": "8.36.0",
|
||||||
"eslint-config-next": "13.2.4",
|
"eslint-config-next": "13.2.4",
|
||||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.38",
|
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.40",
|
||||||
"next": "13.2.4",
|
"next": "13.2.4",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
@ -1235,6 +1235,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
|
||||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
|
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
|
},
|
||||||
"node_modules/available-typed-arrays": {
|
"node_modules/available-typed-arrays": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||||
@ -1482,6 +1487,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@ -1637,6 +1653,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dir-glob": {
|
"node_modules/dir-glob": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||||
@ -2376,6 +2400,19 @@
|
|||||||
"is-callable": "^1.1.3"
|
"is-callable": "^1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@ -3266,6 +3303,25 @@
|
|||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mimic-fn": {
|
"node_modules/mimic-fn": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"eslint": "8.36.0",
|
"eslint": "8.36.0",
|
||||||
"eslint-config-next": "13.2.4",
|
"eslint-config-next": "13.2.4",
|
||||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.38",
|
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.40",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
"next": "13.2.4",
|
"next": "13.2.4",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
@ -31,6 +31,7 @@ export default abstract class BaseApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected buildBody(body: { [key: string]: unknown }): string {
|
protected buildBody(body: { [key: string]: unknown }): string {
|
||||||
|
console.log("2 >> body >>>", JSON.stringify(body));
|
||||||
return JSON.stringify(body);
|
return JSON.stringify(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +55,17 @@ export default abstract class BaseApiService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async postRequestFormData<T>(url: URL, body: FormData) {
|
||||||
|
return this.sendRequest<T>(
|
||||||
|
async () =>
|
||||||
|
await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.buildHeaders(ContentType.FORM_DATA),
|
||||||
|
body,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected async putRequest<T>(url: URL, body: { [key: string]: unknown } = {}) {
|
protected async putRequest<T>(url: URL, body: { [key: string]: unknown } = {}) {
|
||||||
const request = async () =>
|
const request = async () =>
|
||||||
await fetch(url, {
|
await fetch(url, {
|
||||||
|
@ -13,7 +13,8 @@ export interface IGetDocumentsparams {
|
|||||||
// TODO Type getbyuid query params
|
// TODO Type getbyuid query params
|
||||||
|
|
||||||
export type IPutDocumentsParams = {
|
export type IPutDocumentsParams = {
|
||||||
document_status?: EDocumentStatus
|
document_status?: EDocumentStatus;
|
||||||
|
refused_reason?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IPostDocumentsParams {}
|
export interface IPostDocumentsParams {}
|
||||||
@ -37,7 +38,8 @@ export default class Documents extends BaseSuperAdmin {
|
|||||||
|
|
||||||
public async get(q: IGetDocumentsparams): Promise<Document[]> {
|
public async get(q: IGetDocumentsparams): Promise<Document[]> {
|
||||||
const url = new URL(this.baseURl);
|
const url = new URL(this.baseURl);
|
||||||
Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
const query = { q };
|
||||||
|
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
||||||
try {
|
try {
|
||||||
return await this.getRequest<Document[]>(url);
|
return await this.getRequest<Document[]>(url);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -80,4 +82,14 @@ export default class Documents extends BaseSuperAdmin {
|
|||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async delete(uid: string): Promise<Document> {
|
||||||
|
const url = new URL(this.baseURl.concat(`/${uid}`));
|
||||||
|
try {
|
||||||
|
return await this.deleteRequest<Document>(url);
|
||||||
|
} catch (err) {
|
||||||
|
this.onError(err);
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,14 @@ export default class Files extends BaseSuperAdmin {
|
|||||||
|
|
||||||
public async get(q: IGetFilesparams): Promise<File[]> {
|
public async get(q: IGetFilesparams): Promise<File[]> {
|
||||||
const url = new URL(this.baseURl);
|
const url = new URL(this.baseURl);
|
||||||
Object.entries(q).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
const query = { q };
|
||||||
|
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
||||||
try {
|
try {
|
||||||
const files = await this.getRequest<File[]>(url);
|
const files = await this.getRequest<File[]>(url);
|
||||||
files.forEach(async(file) => {
|
files.forEach(async (file) => {
|
||||||
file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv);
|
file.file_path = await this.cryptoService.decrypt(file.file_path!, file.iv);
|
||||||
})
|
});
|
||||||
return files
|
return files;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.onError(err);
|
this.onError(err);
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
@ -54,7 +55,7 @@ export default class Files extends BaseSuperAdmin {
|
|||||||
public async post(body: any): Promise<File> {
|
public async post(body: any): Promise<File> {
|
||||||
const url = new URL(this.baseURl);
|
const url = new URL(this.baseURl);
|
||||||
try {
|
try {
|
||||||
return await this.postRequest<File>(url, body);
|
return await this.postRequestFormData<File>(url, body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.onError(err);
|
this.onError(err);
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
@ -84,4 +85,17 @@ export default class Files extends BaseSuperAdmin {
|
|||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Delete a folder only if the folder don't contains customers
|
||||||
|
*/
|
||||||
|
public async delete(uid: string): Promise<File> {
|
||||||
|
const url = new URL(this.baseURl.concat(`/${uid}`));
|
||||||
|
try {
|
||||||
|
return await this.deleteRequest<File>(url);
|
||||||
|
} catch (err) {
|
||||||
|
this.onError(err);
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,15 @@ import Button, { EButtonVariant } from "../Button";
|
|||||||
import Tooltip from "../ToolTip";
|
import Tooltip from "../ToolTip";
|
||||||
import Typography, { ITypo, ITypoColor } from "../Typography";
|
import Typography, { ITypo, ITypoColor } from "../Typography";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { File as FileCustomer } from "le-coffre-resources/dist/Customer";
|
import { Document, File as FileCustomer } from "le-coffre-resources/dist/Customer";
|
||||||
|
import Files from "@Front/Api/LeCoffreApi/SuperAdmin/Files/Files";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
title: string;
|
title: string;
|
||||||
dateAsked: Date;
|
dateAsked: Date;
|
||||||
defaultFiles?: FileCustomer[];
|
defaultFiles?: FileCustomer[];
|
||||||
onChange?: (files: File[]) => void;
|
onChange?: (files: File[]) => void;
|
||||||
|
document: Document;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IFile = {
|
type IFile = {
|
||||||
@ -26,6 +28,7 @@ type IFile = {
|
|||||||
type IState = {
|
type IState = {
|
||||||
files: IFile[];
|
files: IFile[];
|
||||||
isDragOver: boolean;
|
isDragOver: boolean;
|
||||||
|
currentFiles?: FileCustomer[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class DepositDocument extends React.Component<IProps, IState> {
|
export default class DepositDocument extends React.Component<IProps, IState> {
|
||||||
@ -38,6 +41,7 @@ export default class DepositDocument extends React.Component<IProps, IState> {
|
|||||||
this.state = {
|
this.state = {
|
||||||
files: [],
|
files: [],
|
||||||
isDragOver: false,
|
isDragOver: false,
|
||||||
|
currentFiles: this.props.defaultFiles,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addDocument = this.addDocument.bind(this);
|
this.addDocument = this.addDocument.bind(this);
|
||||||
@ -151,7 +155,7 @@ export default class DepositDocument extends React.Component<IProps, IState> {
|
|||||||
if (file) this.addFile(file);
|
if (file) this.addFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addFile(file: File) {
|
private async addFile(file: File) {
|
||||||
this.setState({
|
this.setState({
|
||||||
files: [
|
files: [
|
||||||
...this.state.files,
|
...this.state.files,
|
||||||
@ -163,17 +167,33 @@ export default class DepositDocument extends React.Component<IProps, IState> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
|
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", file, file.name);
|
||||||
|
const query = JSON.stringify({ document: { uid: this.props.document.uid } });
|
||||||
|
formData.append("q", query);
|
||||||
|
|
||||||
|
const newFile = await Files.getInstance().post(formData);
|
||||||
|
const files = this.state.currentFiles ? [...this.state.currentFiles, newFile] : [newFile];
|
||||||
|
this.setState({
|
||||||
|
currentFiles: files,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFile(e: any) {
|
private async removeFile(e: any) {
|
||||||
const image = e.target as HTMLElement;
|
const image = e.target as HTMLElement;
|
||||||
const indexToRemove = image.getAttribute("data-file");
|
const indexToRemove = image.getAttribute("data-file");
|
||||||
if (!indexToRemove) return;
|
if (!indexToRemove) return;
|
||||||
|
// const file = this.state.files.find((file) => file.index === parseInt(indexToRemove));
|
||||||
this.setState({
|
this.setState({
|
||||||
files: this.state.files.filter((file) => file.index !== parseInt(indexToRemove)),
|
files: this.state.files.filter((file) => file.index !== parseInt(indexToRemove)),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
|
if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
|
||||||
|
// TODO Finir la suppression de fichier
|
||||||
|
// const deletedFileUid = this.props.document.files?.find((file) => file.file_path === newFile.file_path)?.uid;
|
||||||
|
// console.log({ deletedFileUid });
|
||||||
|
// await Files.getInstance().delete(file?.uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onFileChange() {
|
private async onFileChange() {
|
||||||
|
@ -67,7 +67,6 @@ export default class UserFolderHeader extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private hasPendingFiles() {
|
private hasPendingFiles() {
|
||||||
console.log(this.props.folder.documents);
|
|
||||||
const documents =
|
const documents =
|
||||||
this.props.folder.documents?.filter((document) => document.depositor?.contact?.uid === this.props.customer.contact?.uid) ?? [];
|
this.props.folder.documents?.filter((document) => document.depositor?.contact?.uid === this.props.customer.contact?.uid) ?? [];
|
||||||
const notAskedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.DEPOSITED) ?? [];
|
const notAskedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.DEPOSITED) ?? [];
|
||||||
|
@ -15,6 +15,7 @@ import classes from "./classes.module.scss";
|
|||||||
import DocumentList from "./DocumentList";
|
import DocumentList from "./DocumentList";
|
||||||
import UserFolderHeader from "./UserFolderHeader";
|
import UserFolderHeader from "./UserFolderHeader";
|
||||||
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
|
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
|
||||||
|
import Documents from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
customer: Customer;
|
customer: Customer;
|
||||||
@ -26,6 +27,7 @@ type IProps = {
|
|||||||
};
|
};
|
||||||
type IState = {
|
type IState = {
|
||||||
isOpenDeletionModal: boolean;
|
isOpenDeletionModal: boolean;
|
||||||
|
selectedDocumentToDelete: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class UserFolder extends React.Component<IProps, IState> {
|
export default class UserFolder extends React.Component<IProps, IState> {
|
||||||
@ -39,10 +41,12 @@ export default class UserFolder extends React.Component<IProps, IState> {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isOpenDeletionModal: false,
|
isOpenDeletionModal: false,
|
||||||
|
selectedDocumentToDelete: "",
|
||||||
};
|
};
|
||||||
this.closeDeletionModal = this.closeDeletionModal.bind(this);
|
this.closeDeletionModal = this.closeDeletionModal.bind(this);
|
||||||
this.openDeletionModal = this.openDeletionModal.bind(this);
|
this.openDeletionModal = this.openDeletionModal.bind(this);
|
||||||
this.changeUserFolder = this.changeUserFolder.bind(this);
|
this.changeUserFolder = this.changeUserFolder.bind(this);
|
||||||
|
this.deleteAskedDocument = this.deleteAskedDocument.bind(this);
|
||||||
}
|
}
|
||||||
public override render(): JSX.Element {
|
public override render(): JSX.Element {
|
||||||
const documentsAsked: Document[] | null = this.getDocumentsByStatus("ASKED");
|
const documentsAsked: Document[] | null = this.getDocumentsByStatus("ASKED");
|
||||||
@ -55,6 +59,7 @@ export default class UserFolder extends React.Component<IProps, IState> {
|
|||||||
<Confirm
|
<Confirm
|
||||||
isOpen={this.state.isOpenDeletionModal}
|
isOpen={this.state.isOpenDeletionModal}
|
||||||
onClose={this.closeDeletionModal}
|
onClose={this.closeDeletionModal}
|
||||||
|
onAccept={this.deleteAskedDocument}
|
||||||
closeBtn
|
closeBtn
|
||||||
header={"Supprimer la demande de document ?"}
|
header={"Supprimer la demande de document ?"}
|
||||||
cancelText={"Cancel"}
|
cancelText={"Cancel"}
|
||||||
@ -122,11 +127,23 @@ export default class UserFolder extends React.Component<IProps, IState> {
|
|||||||
this.rootRefElement.current?.style.setProperty("--animation-delay", this.props.animationDelay!.toString().concat("ms"));
|
this.rootRefElement.current?.style.setProperty("--animation-delay", this.props.animationDelay!.toString().concat("ms"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async deleteAskedDocument(){
|
||||||
|
try{
|
||||||
|
await Documents.getInstance().delete(this.state.selectedDocumentToDelete);
|
||||||
|
window.location.reload();
|
||||||
|
}catch(e){
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private calculateDocumentsPercentageProgress(): number {
|
private calculateDocumentsPercentageProgress(): number {
|
||||||
if (!this.props.customer.documents) return 0;
|
if (!this.props.customer.documents) return 0;
|
||||||
const totalDocuments: number = this.props.customer.documents.length;
|
const totalDocuments: number = this.props.customer.documents.length;
|
||||||
const numberDocumentsAsked: number = this.getDocumentsByStatus(EDocumentStatus.ASKED)?.length || 0;
|
const numberDocumentsAsked: number = this.getDocumentsByStatus(EDocumentStatus.ASKED)?.length || 0;
|
||||||
return Math.round(((totalDocuments - numberDocumentsAsked) / totalDocuments) * 100);
|
|
||||||
|
const percentage = Math.round(((totalDocuments - numberDocumentsAsked) / totalDocuments) * 100);
|
||||||
|
if(!percentage) return 0;
|
||||||
|
return percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDocumentsByStatus(status: string): Document[] | null {
|
private getDocumentsByStatus(status: string): Document[] | null {
|
||||||
@ -159,9 +176,11 @@ export default class UserFolder extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private openDeletionModal(uid?: string): void {
|
private openDeletionModal(uid?: string): void {
|
||||||
// TODO: call API to delete document
|
if(!uid) return;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isOpenDeletionModal: true,
|
isOpenDeletionModal: true,
|
||||||
|
selectedDocumentToDelete: uid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private closeDeletionModal(): void {
|
private closeDeletionModal(): void {
|
||||||
|
@ -8,10 +8,14 @@ import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { documentDeposited } from "../DesignSystem/dummyData";
|
import { documentDeposited } from "../DesignSystem/dummyData";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents";
|
||||||
|
import { Document } from "le-coffre-resources/dist/Customer";
|
||||||
|
import Users from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users";
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
type IState = {
|
type IState = {
|
||||||
isAddDocumentModalVisible: boolean;
|
isAddDocumentModalVisible: boolean;
|
||||||
|
documents: Document[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ClientDashboard extends Base<IProps, IState> {
|
export default class ClientDashboard extends Base<IProps, IState> {
|
||||||
@ -19,6 +23,7 @@ export default class ClientDashboard extends Base<IProps, IState> {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isAddDocumentModalVisible: false,
|
isAddDocumentModalVisible: false,
|
||||||
|
documents: [],
|
||||||
};
|
};
|
||||||
this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this);
|
this.onCloseModalAddDocument = this.onCloseModalAddDocument.bind(this);
|
||||||
this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this);
|
this.onOpenModalAddDocument = this.onOpenModalAddDocument.bind(this);
|
||||||
@ -31,16 +36,15 @@ export default class ClientDashboard extends Base<IProps, IState> {
|
|||||||
{this.renderHeader()}
|
{this.renderHeader()}
|
||||||
<div className={classes["sub-container"]}>
|
<div className={classes["sub-container"]}>
|
||||||
<div className={classes["content"]}>
|
<div className={classes["content"]}>
|
||||||
|
{this.state.documents?.map((document) => (
|
||||||
<DepositDocument
|
<DepositDocument
|
||||||
title={"Carte d'identité - recto-verso"}
|
title={"Carte d'identité - recto-verso"}
|
||||||
dateAsked={new Date()}
|
dateAsked={new Date()}
|
||||||
defaultFiles={documentDeposited.files ?? []}
|
document={document}
|
||||||
|
key={document.uid}
|
||||||
|
defaultFiles={document.files ?? []}
|
||||||
/>
|
/>
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
))}
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
|
||||||
</div>
|
</div>
|
||||||
<Typography typo={ITypo.H2}>Documents supplémentaires (facultatif)</Typography>
|
<Typography typo={ITypo.H2}>Documents supplémentaires (facultatif)</Typography>
|
||||||
<Typography typo={ITypo.P_16} className={classes["text"]}>
|
<Typography typo={ITypo.P_16} className={classes["text"]}>
|
||||||
@ -67,7 +71,7 @@ export default class ClientDashboard extends Base<IProps, IState> {
|
|||||||
Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le
|
Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le
|
||||||
document correspondant.
|
document correspondant.
|
||||||
</Typography>
|
</Typography>
|
||||||
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} />
|
<DepositDocument title={"Carte d'identité - recto-verso"} dateAsked={new Date()} document={documentDeposited} />
|
||||||
</div>
|
</div>
|
||||||
</Confirm>
|
</Confirm>
|
||||||
</div>
|
</div>
|
||||||
@ -100,6 +104,21 @@ export default class ClientDashboard extends Base<IProps, IState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async componentDidMount() {
|
||||||
|
// TODO Get documents of the current customer according to userStore
|
||||||
|
// REMOVE this mock
|
||||||
|
const mockUsers = (await Users.getInstance().get({}))[2];
|
||||||
|
const query: IGetDocumentsparams = {
|
||||||
|
where: { depositor: mockUsers?.uid },
|
||||||
|
include: {
|
||||||
|
files: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const documents: Document[] = await Documents.getInstance().get(query);
|
||||||
|
console.log({ documents });
|
||||||
|
this.setState({ documents });
|
||||||
|
}
|
||||||
|
|
||||||
private onCloseModalAddDocument() {
|
private onCloseModalAddDocument() {
|
||||||
this.setState({ isAddDocumentModalVisible: false });
|
this.setState({ isAddDocumentModalVisible: false });
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,6 @@ class AskDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
}catch(e){
|
}catch(e){
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
console.log(values["document_types"]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
|
|
||||||
this.hasPrevious = this.hasPrevious.bind(this);
|
this.hasPrevious = this.hasPrevious.bind(this);
|
||||||
this.hasNext = this.hasNext.bind(this);
|
this.hasNext = this.hasNext.bind(this);
|
||||||
|
this.refuseDocument = this.refuseDocument.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override render(): JSX.Element | null {
|
public override render(): JSX.Element | null {
|
||||||
@ -156,7 +157,7 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
<Confirm
|
<Confirm
|
||||||
isOpen={this.state.isRefuseModalVisible}
|
isOpen={this.state.isRefuseModalVisible}
|
||||||
onClose={this.closeModals}
|
onClose={this.closeModals}
|
||||||
onAccept={this.closeModals}
|
onAccept={this.refuseDocument}
|
||||||
closeBtn
|
closeBtn
|
||||||
header={"Refuser le document ?"}
|
header={"Refuser le document ?"}
|
||||||
cancelText={"Annuler"}
|
cancelText={"Annuler"}
|
||||||
@ -244,6 +245,23 @@ class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
return index < this.state.document!.files!.length;
|
return index < this.state.document!.files!.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async refuseDocument(){
|
||||||
|
try{
|
||||||
|
await Documents.getInstance().put(this.props.documentUid, {
|
||||||
|
document_status: EDocumentStatus.REFUSED,
|
||||||
|
refused_reason: this.state.refuseText
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.router.push(
|
||||||
|
Module.getInstance()
|
||||||
|
.get()
|
||||||
|
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid),
|
||||||
|
);
|
||||||
|
}catch(e){
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async validateAnchoring() {
|
private async validateAnchoring() {
|
||||||
this.setState({
|
this.setState({
|
||||||
hasValidateAnchoring: true,
|
hasValidateAnchoring: true,
|
||||||
|
@ -5,7 +5,7 @@ import crypto from "crypto";
|
|||||||
@Service()
|
@Service()
|
||||||
export default class CryptoService {
|
export default class CryptoService {
|
||||||
private jwkKey: JsonWebKey;
|
private jwkKey: JsonWebKey;
|
||||||
private subtle: SubtleCrypto = crypto.webcrypto.subtle
|
private subtle: SubtleCrypto = window.crypto.subtle;
|
||||||
constructor(protected variables: FrontendVariables) {
|
constructor(protected variables: FrontendVariables) {
|
||||||
this.jwkKey = {
|
this.jwkKey = {
|
||||||
kty: "oct",
|
kty: "oct",
|
||||||
@ -16,7 +16,7 @@ export default class CryptoService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getKey() {
|
private async getKey() {
|
||||||
return await this.subtle.importKey("jwk", this.jwkKey, {name: "AES-GCM"}, false, ["encrypt", "decrypt"]);
|
return await this.subtle.importKey("jwk", this.jwkKey, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,8 +36,8 @@ export default class CryptoService {
|
|||||||
encodedData,
|
encodedData,
|
||||||
);
|
);
|
||||||
|
|
||||||
const cipherText = Buffer.from(cipherData).toString('base64');
|
const cipherText = Buffer.from(cipherData).toString("base64");
|
||||||
const ivStringified = Buffer.from(iv).toString('base64');
|
const ivStringified = Buffer.from(iv).toString("base64");
|
||||||
|
|
||||||
return { cipherText, ivStringified };
|
return { cipherText, ivStringified };
|
||||||
}
|
}
|
||||||
@ -47,8 +47,8 @@ export default class CryptoService {
|
|||||||
* @throws {Error} If data cannot be decrypted
|
* @throws {Error} If data cannot be decrypted
|
||||||
*/
|
*/
|
||||||
public async decrypt(cipherText: string, ivStringified: string): Promise<string> {
|
public async decrypt(cipherText: string, ivStringified: string): Promise<string> {
|
||||||
const cipherData = Buffer.from(cipherText, 'base64');
|
const cipherData = Buffer.from(cipherText, "base64");
|
||||||
const iv = Buffer.from(ivStringified, 'base64');
|
const iv = Buffer.from(ivStringified, "base64");
|
||||||
const key = await this.getKey();
|
const key = await this.getKey();
|
||||||
const decryptedData = await this.subtle.decrypt(
|
const decryptedData = await this.subtle.decrypt(
|
||||||
{
|
{
|
||||||
@ -59,6 +59,6 @@ export default class CryptoService {
|
|||||||
cipherData,
|
cipherData,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Buffer.from(decryptedData).toString('utf-8');
|
return Buffer.from(decryptedData).toString("utf-8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,30 @@
|
|||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@Api/*": ["src/api/*"],
|
"@Api/*": [
|
||||||
"@Front/*": ["src/front/*"],
|
"src/api/*"
|
||||||
"@Assets/*": ["src/front/Assets/*"],
|
],
|
||||||
"@Components/*": ["src/front/Components/*"],
|
"@Front/*": [
|
||||||
"@Themes/*": ["src/front/Themes/*"],
|
"src/front/*"
|
||||||
"@Stores/*": ["src/front/Stores/*"],
|
],
|
||||||
"@FrontServices/*": ["src/front/services/*"],
|
"@Assets/*": [
|
||||||
"@Page/*": ["src/pages/*"],
|
"src/front/Assets/*"
|
||||||
|
],
|
||||||
|
"@Components/*": [
|
||||||
|
"src/front/Components/*"
|
||||||
|
],
|
||||||
|
"@Themes/*": [
|
||||||
|
"src/front/Themes/*"
|
||||||
|
],
|
||||||
|
"@Stores/*": [
|
||||||
|
"src/front/Stores/*"
|
||||||
|
],
|
||||||
|
"@FrontServices/*": [
|
||||||
|
"src/front/services/*"
|
||||||
|
],
|
||||||
|
"@Page/*": [
|
||||||
|
"src/pages/*"
|
||||||
|
],
|
||||||
},
|
},
|
||||||
// "rootDirs": [],
|
// "rootDirs": [],
|
||||||
// "typeRoots": [],
|
// "typeRoots": [],
|
||||||
@ -69,10 +85,10 @@
|
|||||||
"include": [
|
"include": [
|
||||||
"next-env.d.ts",
|
"next-env.d.ts",
|
||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
"**/*.tsx"
|
"**/*.tsx",
|
||||||
, "src/front/next.config.js" ],
|
"src/front/next.config.js"
|
||||||
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user