Merge branch 'dev' into staging
This commit is contained in:
commit
1650bdb7a5
@ -1,35 +1,34 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
max-width: 357px;
|
||||
width: 100%;
|
||||
gap: var(--spacing-sm, 8px);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: var(--spacing-sm, 8px);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
gap: var(--spacing-sm, 8px);
|
||||
align-items: center;
|
||||
.content {
|
||||
display: flex;
|
||||
gap: var(--spacing-sm, 8px);
|
||||
align-items: center;
|
||||
|
||||
.file-name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 277px;
|
||||
}
|
||||
}
|
||||
.file-name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 277px;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
min-width: var(--spacing-3, 24px);
|
||||
min-height: var(--spacing-3, 24px);
|
||||
width: var(--spacing-3, 24px);
|
||||
height: var(--spacing-3, 24px);
|
||||
stroke: var(--color-primary-500);
|
||||
}
|
||||
svg {
|
||||
min-width: var(--spacing-3, 24px);
|
||||
min-height: var(--spacing-3, 24px);
|
||||
width: var(--spacing-3, 24px);
|
||||
height: var(--spacing-3, 24px);
|
||||
stroke: var(--color-primary-500);
|
||||
}
|
||||
|
||||
.error{
|
||||
.error {
|
||||
min-width: var(--spacing-3, 24px);
|
||||
min-height: var(--spacing-3, 24px);
|
||||
width: var(--spacing-3, 24px);
|
||||
|
@ -75,4 +75,8 @@
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-fullwidth="true"] {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,10 @@ export type ISearchBlockListProps = {
|
||||
text: string;
|
||||
link: string;
|
||||
};
|
||||
fullwidth?: boolean;
|
||||
};
|
||||
export default function SearchBlockList(props: ISearchBlockListProps) {
|
||||
const { blocks, onSelectedBlock, bottomButton } = props;
|
||||
const { blocks, onSelectedBlock, bottomButton, fullwidth = false } = props;
|
||||
|
||||
const [selectedBlock, setSelectedBlock] = useState<IBlock | null>(null);
|
||||
const router = useRouter();
|
||||
@ -69,7 +70,7 @@ export default function SearchBlockList(props: ISearchBlockListProps) {
|
||||
}, [blocks]);
|
||||
|
||||
return (
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["root"]} data-fullwidth={fullwidth}>
|
||||
<div className={classes["searchbar"]} ref={searchBarRef}>
|
||||
<SearchBar placeholder="Chercher" onChange={handleSearchChange} />
|
||||
{bottomButton && (
|
||||
|
@ -7,7 +7,6 @@ type IProps = {
|
||||
documentUid: string;
|
||||
isOpen: boolean;
|
||||
onClose?: () => void;
|
||||
|
||||
onDeleteSuccess: (uid: string) => void;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
|
||||
import Modal from "@Front/Components/DesignSystem/Modal";
|
||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import React, { useCallback } from "react";
|
||||
|
||||
type IProps = {
|
||||
documentUid: string;
|
||||
isOpen: boolean;
|
||||
onClose?: () => void;
|
||||
onDeleteSuccess: (uid: string) => void;
|
||||
};
|
||||
|
||||
export default function DeleteSentDocumentModal(props: IProps) {
|
||||
const { isOpen, onClose, documentUid, onDeleteSuccess } = props;
|
||||
|
||||
const onDelete = useCallback(
|
||||
() =>
|
||||
Documents.getInstance()
|
||||
.delete(documentUid)
|
||||
.then(() => onDeleteSuccess(documentUid))
|
||||
.then(onClose)
|
||||
.catch((error) => console.warn(error)),
|
||||
[documentUid, onClose, onDeleteSuccess],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
title={"Supprimer l’envoi de document ?"}
|
||||
firstButton={{ children: "Annuler", onClick: onClose }}
|
||||
secondButton={{ children: "Oui, Supprimer", onClick: onDelete }}>
|
||||
<Typography typo={ETypo.TEXT_MD_LIGHT}>Cette action annulera l'envoi du document.</Typography>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -11,4 +11,10 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm, 8px);
|
||||
}
|
||||
}
|
||||
|
@ -15,31 +15,13 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal";
|
||||
import DeleteSentDocumentModal from "./DeleteSentDocumentModal";
|
||||
|
||||
type IProps = {
|
||||
documents: Document[];
|
||||
folderUid: string;
|
||||
};
|
||||
|
||||
const header: readonly IHead[] = [
|
||||
{
|
||||
key: "document_type",
|
||||
title: "Type de document",
|
||||
},
|
||||
{
|
||||
key: "document_status",
|
||||
title: "Statut",
|
||||
},
|
||||
{
|
||||
key: "created_at",
|
||||
title: "Demandé le",
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
title: "Actions",
|
||||
},
|
||||
];
|
||||
|
||||
const tradDocumentStatus: Record<EDocumentStatus, string> = {
|
||||
[EDocumentStatus.ASKED]: "Demandé",
|
||||
[EDocumentStatus.DEPOSITED]: "À valider",
|
||||
@ -52,7 +34,8 @@ export default function DocumentTables(props: IProps) {
|
||||
const [documents, setDocuments] = useState<Document[]>(documentsProps);
|
||||
const [documentUid, setDocumentUid] = useState<string | null>(null);
|
||||
|
||||
const deleteAskedOocumentModal = useOpenable();
|
||||
const deleteAskedDocumentModal = useOpenable();
|
||||
const deleteSentDocumentModal = useOpenable();
|
||||
|
||||
useEffect(() => {
|
||||
setDocuments(documentsProps);
|
||||
@ -62,9 +45,18 @@ export default function DocumentTables(props: IProps) {
|
||||
(uid: string | undefined) => {
|
||||
if (!uid) return;
|
||||
setDocumentUid(uid);
|
||||
deleteAskedOocumentModal.open();
|
||||
deleteAskedDocumentModal.open();
|
||||
},
|
||||
[deleteAskedOocumentModal],
|
||||
[deleteAskedDocumentModal],
|
||||
);
|
||||
|
||||
const openDeleteSentDocumentModal = useCallback(
|
||||
(uid: string | undefined) => {
|
||||
if (!uid) return;
|
||||
setDocumentUid(uid);
|
||||
deleteSentDocumentModal.open();
|
||||
},
|
||||
[deleteSentDocumentModal],
|
||||
);
|
||||
|
||||
const onDownload = useCallback((doc: Document) => {
|
||||
@ -99,7 +91,7 @@ export default function DocumentTables(props: IProps) {
|
||||
label={tradDocumentStatus[document.document_status].toUpperCase()}
|
||||
/>
|
||||
),
|
||||
created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
|
||||
date: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
|
||||
actions: <IconButton icon={<TrashIcon onClick={() => openDeleteAskedDocumentModal(document.uid)} />} />,
|
||||
};
|
||||
})
|
||||
@ -122,7 +114,7 @@ export default function DocumentTables(props: IProps) {
|
||||
label={tradDocumentStatus[document.document_status].toUpperCase()}
|
||||
/>
|
||||
),
|
||||
created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
|
||||
date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_",
|
||||
actions: (
|
||||
<Link
|
||||
href={Module.getInstance()
|
||||
@ -153,7 +145,7 @@ export default function DocumentTables(props: IProps) {
|
||||
label={tradDocumentStatus[document.document_status].toUpperCase()}
|
||||
/>
|
||||
),
|
||||
created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
|
||||
date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_",
|
||||
actions: (
|
||||
<div className={classes["actions"]}>
|
||||
<Link
|
||||
@ -187,7 +179,7 @@ export default function DocumentTables(props: IProps) {
|
||||
label={tradDocumentStatus[document.document_status].toUpperCase()}
|
||||
/>
|
||||
),
|
||||
created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
|
||||
date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_",
|
||||
actions: "",
|
||||
};
|
||||
})
|
||||
@ -195,6 +187,29 @@ export default function DocumentTables(props: IProps) {
|
||||
[documents],
|
||||
);
|
||||
|
||||
//TODO: modify accordingly when the back will handle sent documents
|
||||
const sentDocuments: IRowProps[] = useMemo(
|
||||
() =>
|
||||
documents
|
||||
.map((document) => {
|
||||
if (document.document_status !== "sent") return null;
|
||||
return {
|
||||
key: document.uid,
|
||||
document_type: document.document_type?.name ?? "_",
|
||||
document_status: <Tag color={ETagColor.ERROR} variant={ETagVariant.SEMI_BOLD} label={"Envoyé"} />,
|
||||
date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_",
|
||||
actions: (
|
||||
<div className={classes["actions"]}>
|
||||
<IconButton onClick={() => onDownload(document)} icon={<ArrowDownTrayIcon />} />
|
||||
<IconButton icon={<TrashIcon onClick={() => openDeleteSentDocumentModal(document.uid)} />} />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
})
|
||||
.filter((document) => document !== null) as IRowProps[],
|
||||
[documents, onDownload, openDeleteSentDocumentModal],
|
||||
);
|
||||
|
||||
const progress = useMemo(() => {
|
||||
const total = askedDocuments.length + toValidateDocuments.length + validatedDocuments.length + refusedDocuments.length;
|
||||
if (total === 0) return 0;
|
||||
@ -217,18 +232,48 @@ export default function DocumentTables(props: IProps) {
|
||||
</Typography>
|
||||
<CircleProgress percentage={progress} />
|
||||
</div>
|
||||
{askedDocuments.length > 0 && <Table header={header} rows={askedDocuments} />}
|
||||
{toValidateDocuments.length > 0 && <Table header={header} rows={toValidateDocuments} />}
|
||||
{validatedDocuments.length > 0 && <Table header={header} rows={validatedDocuments} />}
|
||||
{refusedDocuments.length > 0 && <Table header={header} rows={refusedDocuments} />}
|
||||
{askedDocuments.length > 0 && <Table header={getHeader("Demandé le")} rows={askedDocuments} />}
|
||||
{toValidateDocuments.length > 0 && <Table header={getHeader("Déposé le")} rows={toValidateDocuments} />}
|
||||
{validatedDocuments.length > 0 && <Table header={getHeader("Validé le")} rows={validatedDocuments} />}
|
||||
{refusedDocuments.length > 0 && <Table header={getHeader("Demandé le")} rows={refusedDocuments} />}
|
||||
{sentDocuments.length > 0 && <Table header={getHeader("Envoyé le")} rows={sentDocuments} />}
|
||||
{documentUid && (
|
||||
<DeleteAskedDocumentModal
|
||||
isOpen={deleteAskedOocumentModal.isOpen}
|
||||
onClose={deleteAskedOocumentModal.close}
|
||||
onDeleteSuccess={handleDelete}
|
||||
documentUid={documentUid}
|
||||
/>
|
||||
<>
|
||||
<DeleteAskedDocumentModal
|
||||
isOpen={deleteAskedDocumentModal.isOpen}
|
||||
onClose={deleteAskedDocumentModal.close}
|
||||
onDeleteSuccess={handleDelete}
|
||||
documentUid={documentUid}
|
||||
/>
|
||||
<DeleteSentDocumentModal
|
||||
isOpen={deleteSentDocumentModal.isOpen}
|
||||
onClose={deleteSentDocumentModal.close}
|
||||
onDeleteSuccess={handleDelete}
|
||||
documentUid={documentUid}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getHeader(dateColumnTitle: string): IHead[] {
|
||||
return [
|
||||
{
|
||||
key: "document_type",
|
||||
title: "Type de document",
|
||||
},
|
||||
{
|
||||
key: "document_status",
|
||||
title: "Statut",
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
title: dateColumnTitle,
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
title: "Action",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -62,13 +62,13 @@ export default function Folder() {
|
||||
<Image src={LogoIcon} alt="logo" />
|
||||
|
||||
{activeUser && activeUser.contact && (
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.COLOR_PRIMARY_500}>
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_ACCENT}>
|
||||
Bonjour {activeUser.contact.first_name}, bienvenue sur LeCoffre.io
|
||||
</Typography>
|
||||
)}
|
||||
{!activeUser ||
|
||||
(!activeUser.contact && (
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.COLOR_PRIMARY_500}>
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_ACCENT}>
|
||||
Bonjour, bienvenue sur LeCoffre.io
|
||||
</Typography>
|
||||
))}
|
||||
|
@ -1,17 +1,22 @@
|
||||
.root {
|
||||
position: relative;
|
||||
.select-folder-container {
|
||||
max-width: 530px;
|
||||
padding: 80px 72px;
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
margin: 80px auto;
|
||||
width: 472px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-xl, 32px);
|
||||
|
||||
@media (max-width: $screen-s) {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: var(--spacing-md, 16px);
|
||||
}
|
||||
|
||||
.title-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 48px;
|
||||
margin: auto;
|
||||
background-color: white;
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
gap: var(--spacing-sm, 8px);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,28 @@
|
||||
import backgroundImage from "@Assets/images/background_refonte.svg";
|
||||
import LogoIcon from "@Assets/logo_small_blue.svg";
|
||||
import Folders from "@Front/Api/LeCoffreApi/Customer/Folders/Folders";
|
||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
|
||||
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
|
||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
||||
import { OfficeFolder } from "le-coffre-resources/dist/Customer";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import LandingImage from "../Login/landing-connect.jpeg";
|
||||
import classes from "./classes.module.scss";
|
||||
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
|
||||
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
|
||||
|
||||
export default function SelectFolder() {
|
||||
const [folders, setFolders] = useState<OfficeFolder[]>([]);
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
async function getFolders() {
|
||||
const jwt = JwtService.getInstance().decodeCustomerJwt();
|
||||
if (!jwt) return;
|
||||
const jwt = JwtService.getInstance().decodeCustomerJwt();
|
||||
if (!jwt) return;
|
||||
|
||||
const folders = await Folders.getInstance().get({
|
||||
Folders.getInstance()
|
||||
.get({
|
||||
q: {
|
||||
where: {
|
||||
customers: {
|
||||
@ -40,11 +42,8 @@ export default function SelectFolder() {
|
||||
customers: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
setFolders(folders);
|
||||
}
|
||||
|
||||
getFolders();
|
||||
})
|
||||
.then((folders) => setFolders(folders));
|
||||
}, []);
|
||||
|
||||
const handleSelectBlock = useCallback(
|
||||
@ -55,26 +54,35 @@ export default function SelectFolder() {
|
||||
);
|
||||
|
||||
return (
|
||||
<DefaultDoubleSidePage title="Sélectionner un dossier" image={LandingImage}>
|
||||
<DefaultDoubleSidePage title="Sélectionner un dossier" image={backgroundImage}>
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["select-folder-container"]}>
|
||||
<div className={classes["title"]}>
|
||||
<Typography typo={ETypo.DISPLAY_LARGE}>Vos dossiers</Typography>
|
||||
</div>
|
||||
<div className={classes["folders-container"]}>
|
||||
<BlockList
|
||||
onSelectedBlock={handleSelectBlock}
|
||||
blocks={folders.map((folder) => {
|
||||
return {
|
||||
id: folder.uid!,
|
||||
primaryText: folder.name!,
|
||||
selected: false,
|
||||
};
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes["title-container"]}>
|
||||
<Image src={LogoIcon} alt="logo" width={56} />
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_ACCENT}>
|
||||
Vos dossiers en cours
|
||||
</Typography>
|
||||
|
||||
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.TEXT_PRIMARY}>
|
||||
Veuillez sélectionner le dossier pour lequel vous souhaitez déposer ou consulter des documents.
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<Typography typo={ETypo.TITLE_H6} color={ETypoColor.TEXT_ACCENT}>
|
||||
Liste des dossiers disponibles :
|
||||
</Typography>
|
||||
|
||||
<SearchBlockList blocks={getBlocks(folders)} onSelectedBlock={handleSelectBlock} fullwidth />
|
||||
</div>
|
||||
</DefaultDoubleSidePage>
|
||||
);
|
||||
}
|
||||
|
||||
function getBlocks(folders: OfficeFolder[]): IBlock[] {
|
||||
return folders.map((folder) => {
|
||||
return {
|
||||
id: folder.uid!,
|
||||
primaryText: folder.name!,
|
||||
secondaryText: folder.folder_number!,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user