Merge pull request 'ajanin' (#1) from ajanin into cicd
All checks were successful
Build and Push to Registry / build-and-push (push) Successful in 3m56s

Reviewed-on: #1
This commit is contained in:
ajanin 2025-07-07 13:20:15 +00:00
commit dc54ec1a9b
12 changed files with 165 additions and 105 deletions

View File

@ -16,9 +16,10 @@ import Button, { EButtonstyletype, EButtonVariant } from "../Button";
import Confirm from "../OldModal/Confirm";
import Alert from "../OldModal/Alert";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
type IProps = {
onChange?: (files: File[]) => void;
@ -238,14 +239,28 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
return;
}
const customer: any = await new Promise<void>((resolve: (customer: any) => void) => {
CustomerService.getCustomerByUid(this.props.customer_uid).then((process: any) => {
if (process) {
const customer: any = process.processData;
resolve(customer);
}
});
});
for (let i = 0; i < filesArray.length; i++) {
const file = filesArray[i]!.file;
await new Promise<void>((resolve: () => void) => {
const reader = new FileReader();
reader.onload = (event) => {
if (event.target?.result) {
const arrayBuffer = event.target.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const date: Date = new Date();
const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`;
const fileName: string = `aplc-${file.name.split('.')[0]}-${strDate}.${file.name.split('.').pop()}`;
const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer;
const uint8Array: Uint8Array = new Uint8Array(arrayBuffer);
const fileBlob: any = {
type: file.type,
@ -254,7 +269,7 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
const fileData: any = {
file_blob: fileBlob,
file_name: file.name
file_name: fileName
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';

View File

@ -8,6 +8,7 @@ import MenuItem from "@Front/Components/DesignSystem/Menu/MenuItem";
type IProps = {
isOpen: boolean;
closeModal: () => void;
isCustomer?: boolean;
};
type IState = {};
@ -19,29 +20,31 @@ export default class ProfileModal extends React.Component<IProps, IState> {
<>
<div className={classes["background"]} onClick={this.props.closeModal} />
<div className={classes["root"]}>
<MenuItem
{!this.props.isCustomer && <MenuItem
item={{
text: "Mon compte",
link: Module.getInstance().get().modules.pages.MyAccount.props.path,
}}
/>
/>}
<MenuItem
{!this.props.isCustomer && <MenuItem
item={{
text: "Guide de Prise en Main",
link: "https://ressources.lecoffre.io/",
target: "_blank",
}}
/>
/>}
<MenuItem
{!this.props.isCustomer && <MenuItem
item={{
text: "CGU",
link: "/CGU_LeCoffre_io.pdf",
hasSeparator: true,
}}
/>
<LogOutButton />
/>}
<LogOutButton isCustomer={this.props.isCustomer} />
</div>
</>
);

View File

@ -9,7 +9,7 @@ import ProfileModal from "./ProfileModal";
const headerBreakpoint = 1023;
export default function Profile() {
export default function Profile(props: { isCustomer?: boolean }) {
const { isOpen, toggle, close } = useOpenable();
useEffect(() => {
@ -27,7 +27,7 @@ export default function Profile() {
return (
<div className={classes["root"]}>
<IconButton icon={<UserIcon />} onClick={toggle} />
<ProfileModal isOpen={isOpen} closeModal={close} />
<ProfileModal isOpen={isOpen} closeModal={close} isCustomer={props.isCustomer} />
</div>
);
}

View File

@ -20,12 +20,13 @@ import Profile from "./Profile";
type IProps = {
isUserConnected: boolean;
isCustomer?: boolean;
};
const headerHeight = 75;
export default function Header(props: IProps) {
const { isUserConnected } = props;
const { isUserConnected, isCustomer } = props;
const router = useRouter();
const { pathname } = router;
@ -62,7 +63,7 @@ export default function Header(props: IProps) {
<Image src={LogoIcon} alt="logo" className={classes["logo"]} />
</Link>
</div>
{isUserConnected && (
{isUserConnected && !isCustomer && (
<>
<div className={classes["desktop"]}>
<Navigation />
@ -83,6 +84,11 @@ export default function Header(props: IProps) {
</div>
</>
)}
{isCustomer && (
<div className={classes["desktop"]}>
<Profile isCustomer={isCustomer} />
</div>
)}
{isOnCustomerLoginPage && <Image width={70} height={70} alt="ciel-nature" src={LogoCielNatureIcon}></Image>}
</div>
{/* {cancelAt && (

View File

@ -6,14 +6,19 @@ import React, { useCallback } from "react";
import MenuItem from "../Menu/MenuItem";
export default function LogOut() {
export default function LogOut(props: { isCustomer?: boolean }) {
const router = useRouter();
const variables = FrontendVariables.getInstance();
const disconnect = useCallback(() => {
UserStore.instance
.disconnect()
.then(() => router.push(`https://qual-connexion.idnot.fr/user/auth/logout?sourceURL=${variables.FRONT_APP_HOST}`));
if (!props.isCustomer) {
UserStore.instance
.disconnect()
.then(() => router.push(`https://qual-connexion.idnot.fr/user/auth/logout?sourceURL=${variables.FRONT_APP_HOST}`));
} else {
sessionStorage.setItem("customerIsConnected", "false");
router.push("/");
}
}, [router, variables.FRONT_APP_HOST]);
return <MenuItem item={{ text: "Déconnexion", icon: <PowerIcon />, onClick: disconnect }} />;

View File

@ -9,7 +9,9 @@ import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDas
import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
type IProps = IPropsDashboardWithList & {};
type IProps = IPropsDashboardWithList & {
isReady: boolean;
};
export default function DefaultCustomerDashboard(props: IProps) {
const router = useRouter();
@ -46,13 +48,15 @@ export default function DefaultCustomerDashboard(props: IProps) {
.then((folders) => setFolders(folders));
*/
FolderService.getFolders().then((processes: any[]) => {
if (processes.length > 0) {
const folders: any[] = processes.map((process: any) => process.processData);
setFolders(folders);
}
});
}, []);
if (props.isReady) {
FolderService.getFolders().then((processes: any[]) => {
if (processes.length > 0) {
const folders: any[] = processes.map((process: any) => process.processData);
setFolders(folders);
}
});
}
}, [props.isReady]);
const onSelectedBlock = (block: IBlock) => {
const folder = folders.find((folder) => folder.uid === block.id);
@ -65,7 +69,7 @@ export default function DefaultCustomerDashboard(props: IProps) {
.replace("[profileUid]", profileUid as string ?? ""),
);
};
return <DefaultDashboardWithList {...props} onSelectedBlock={onSelectedBlock} blocks={getBlocks(folders)} headerConnected={false} />;
return <DefaultDashboardWithList {...props} onSelectedBlock={onSelectedBlock} blocks={getBlocks(folders)} headerConnected={false} isCustomer={true} />;
function getBlocks(folders: OfficeFolder[]): IBlock[] {
return folders.map((folder) => {

View File

@ -15,6 +15,7 @@ export type IPropsDashboardWithList = {
mobileBackText?: string;
headerConnected?: boolean;
noPadding?: boolean;
isCustomer?: boolean;
};
type IProps = IPropsDashboardWithList & ISearchBlockListProps;
@ -29,11 +30,12 @@ export default function DefaultDashboardWithList(props: IProps) {
headerConnected = true,
bottomButton,
noPadding = false,
isCustomer = false,
} = props;
return (
<div className={classes["root"]}>
<Header isUserConnected={headerConnected} />
<Header isUserConnected={headerConnected} isCustomer={isCustomer} />
<div className={classes["content"]}>
<SearchBlockList blocks={blocks} onSelectedBlock={onSelectedBlock} bottomButton={bottomButton} />
<div className={classes["right-side"]} data-no-padding={noPadding}>

View File

@ -14,11 +14,12 @@ import WatermarkService from "@Front/Services/WatermarkService";
type IProps = {
document: any;
customer: any;
onChange: () => void;
};
export default function DepositDocumentComponent(props: IProps) {
const { document, onChange } = props;
const { document, customer, onChange } = props;
const [isModalOpen, setIsModalOpen] = useState(false);
const [refused_reason, setRefusedReason] = useState<string | null>(null);
@ -36,14 +37,19 @@ export default function DepositDocumentComponent(props: IProps) {
try {
// Add watermark to the file before processing
const watermarkedFile = await WatermarkService.getInstance().addWatermark(file);
return new Promise<void>(
(resolve: () => void) => {
const reader = new FileReader();
reader.onload = (event) => {
if (event.target?.result) {
const arrayBuffer = event.target.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const date: Date = new Date();
const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`;
const fileName: string = `aplc-${document.document_type.name}-${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`;
const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer;
const uint8Array: Uint8Array = new Uint8Array(arrayBuffer);
const fileBlob: FileBlob = {
type: watermarkedFile.type,
@ -52,7 +58,7 @@ export default function DepositDocumentComponent(props: IProps) {
const fileData: FileData = {
file_blob: fileBlob,
file_name: watermarkedFile.name
file_name: fileName
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
@ -88,8 +94,13 @@ export default function DepositDocumentComponent(props: IProps) {
const reader = new FileReader();
reader.onload = (event) => {
if (event.target?.result) {
const arrayBuffer = event.target.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const date: Date = new Date();
const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`;
const fileName: string = `aplc-${document.document_type.name}-${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`;
const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer;
const uint8Array: Uint8Array = new Uint8Array(arrayBuffer);
const fileBlob: FileBlob = {
type: file.type,
@ -98,7 +109,7 @@ export default function DepositDocumentComponent(props: IProps) {
const fileData: FileData = {
file_blob: fileBlob,
file_name: file.name
file_name: fileName
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';

View File

@ -208,7 +208,7 @@ function buildRows(
): IRowProps[] {
return documentsNotary.map((documentNotary) => ({
key: documentNotary.uid ?? "",
name: formatName(documentNotary.files?.[0]?.file_name?.split(".")?.[0] ?? "") || "_",
name: documentNotary.files?.[0]?.file_name?.split(".")?.[0] || "_",
sentAt: new Date(documentNotary.created_at!).toLocaleDateString(),
// actions: <IconButton onClick={() => onDownloadFileNotary(documentNotary)} icon={<ArrowDownTrayIcon />} />,
actions: {
@ -228,7 +228,3 @@ function buildRows(
},
}));
}
function formatName(text: string): string {
return text.replace(/[^a-zA-Z0-9 ]/g, "");
}

View File

@ -46,14 +46,16 @@ export default function ClientDashboard(props: IProps) {
const [documentsNotary, setDocumentsNotary] = useState<DocumentNotary[]>([]);
const [isAddDocumentModalVisible, setIsAddDocumentModalVisible] = useState<boolean>(false);
const [isReady, setIsReady] = useState(false);
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
const [isSmsModalOpen, setIsSmsModalOpen] = useState(false);
const [isSmsModalOpen, setIsSmsModalOpen] = useState(true);
const [smsCode, setSmsCode] = useState("");
const [smsError, setSmsError] = useState("");
const verifySmsCode = useCallback(() => {
if (smsCode === "1234") {
setIsSmsModalOpen(false);
setIsAuthModalOpen(true);
} else {
setSmsError("Code incorrect. Le code valide est 1234.");
}
@ -97,7 +99,6 @@ export default function ClientDashboard(props: IProps) {
setCustomer(customer);
setFolder(folder);
setIsAuthModalOpen(true);
LoaderService.getInstance().hide();
return { folder, customer };
@ -171,9 +172,11 @@ export default function ClientDashboard(props: IProps) {
[folderUid],
);
/*
useEffect(() => {
fetchFolderAndCustomer().then(({ customer }) => fetchDocuments(customer.uid));
}, [fetchDocuments, fetchFolderAndCustomer]);
*/
useEffect(() => {
const customerUid = customer?.uid;
@ -235,8 +238,8 @@ export default function ClientDashboard(props: IProps) {
}, [customer, folderUid, isAddDocumentModalVisible, onCloseModalAddDocument, folder]);
return (
<DefaultCustomerDashboard>
<div className={classes["root"]}>
<DefaultCustomerDashboard isReady={isReady}>
{isReady && (<div className={classes["root"]}>
<div className={classes["top"]}>
<div className={classes["folder-info-container"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
@ -315,6 +318,7 @@ export default function ClientDashboard(props: IProps) {
<DepositDocumentComponent
key={document.uid}
document={document}
customer={customer}
onChange={() => fetchDocuments(customer?.uid)}
/>
))}
@ -332,58 +336,61 @@ export default function ClientDashboard(props: IProps) {
Ajouter d'autres documents
</Button>
{isAddDocumentModalVisible && renderBox()}
</div>)}
{isAuthModalOpen && <AuthModal
isOpen={isAuthModalOpen}
onClose={() => {
setIsAuthModalOpen(false);
setIsSmsModalOpen(true);
}}
/>}
{isAuthModalOpen && <AuthModal
isOpen={isAuthModalOpen}
onClose={() => {
setIsReady(true);
setIsAuthModalOpen(false);
fetchFolderAndCustomer().then(({ customer }) => fetchDocuments(customer.uid));
{isSmsModalOpen && (
<Modal
isOpen={isSmsModalOpen}
onClose={() => setIsSmsModalOpen(false)}
title="Vérification SMS"
>
<div className={classes["sms-modal-content"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_PRIMARY}>
Veuillez saisir le code à 4 chiffres que vous avez reçu par SMS
sessionStorage.setItem("customerIsConnected", "true");
}}
/>}
{isSmsModalOpen && (
<Modal
isOpen={isSmsModalOpen}
onClose={() => setIsSmsModalOpen(false)}
title="Vérification SMS"
>
<div className={classes["sms-modal-content"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_PRIMARY}>
Veuillez saisir le code à 4 chiffres que vous avez reçu par SMS
</Typography>
<TextField
name="smsCode"
placeholder="Code SMS à 4 chiffres"
value={smsCode}
onChange={(e) => {
const value = e.target.value;
// Only allow digits
if (value === "" || /^\d+$/.test(value)) {
setSmsCode(value);
setSmsError("");
}
}}
/>
{smsError && (
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.TEXT_ACCENT}>
{smsError}
</Typography>
)}
<TextField
name="smsCode"
placeholder="Code SMS à 4 chiffres"
value={smsCode}
onChange={(e) => {
const value = e.target.value;
// Only allow digits
if (value === "" || /^\d+$/.test(value)) {
setSmsCode(value);
setSmsError("");
}
}}
/>
{smsError && (
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.TEXT_ACCENT}>
{smsError}
</Typography>
)}
<div style={{ marginTop: "20px" }}>
<Button
variant={EButtonVariant.PRIMARY}
onClick={verifySmsCode}
>
Vérifier
</Button>
</div>
<div style={{ marginTop: "20px" }}>
<Button
variant={EButtonVariant.PRIMARY}
onClick={verifySmsCode}
>
Vérifier
</Button>
</div>
</Modal>
)}
</div>
</div>
</Modal>
)}
</DefaultCustomerDashboard>
);
}

View File

@ -314,7 +314,7 @@ export default function DocumentTables(props: IProps) {
},
file: {
sx: { width: 120 },
content: document.files?.[0]?.file_name ?? "_",
content: document.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
},
actions: {
sx: { width: 76 },
@ -360,7 +360,7 @@ export default function DocumentTables(props: IProps) {
},
file: {
sx: { width: 120 },
content: document.files?.[0]?.file_name ?? "_",
content: document.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
},
actions: {
sx: { width: 76 },
@ -411,7 +411,7 @@ export default function DocumentTables(props: IProps) {
},
file: {
sx: { width: 120 },
content: document.files?.[0]?.file_name ?? "_",
content: document.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
},
actions: { sx: { width: 76 }, content: "" },
};
@ -428,7 +428,7 @@ export default function DocumentTables(props: IProps) {
key: document.uid,
document_type: {
sx: { width: 300 },
content: formatName(document.files?.[0]?.file_name?.split(".")?.[0] ?? "") || "_",
content: "Autre document",
},
document_status: {
sx: { width: 107 },
@ -440,7 +440,7 @@ export default function DocumentTables(props: IProps) {
},
file: {
sx: { width: 120 },
content: document.files?.[0]?.file_name ?? "_",
content: document.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
},
actions: {
sx: { width: 76 },
@ -539,10 +539,6 @@ function getHeader(dateColumnTitle: string, isMobile: boolean): IHead[] {
];
}
function formatName(text: string): string {
return text.replace(/[^a-zA-Z0-9 ]/g, "");
}
function getTagForSentDocument(status: EDocumentNotaryStatus) {
if (status === EDocumentNotaryStatus.SENT) {
return (

View File

@ -22,6 +22,7 @@ import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
enum EClientSelection {
ALL_CLIENTS = "all_clients",
@ -65,13 +66,27 @@ export default function SendDocuments() {
LoaderService.getInstance().show();
for (const selectedClient of selectedClients) {
const customer: any = await new Promise<void>((resolve: (customer: any) => void) => {
CustomerService.getCustomerByUid(selectedClient as string).then((process: any) => {
if (process) {
const customer: any = process.processData;
resolve(customer);
}
});
});
for (const file of files) {
await new Promise<void>((resolve: () => void) => {
const reader = new FileReader();
reader.onload = (event) => {
if (event.target?.result) {
const arrayBuffer = event.target.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const date: Date = new Date();
const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`;
const fileName: string = `aplc-${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`;
const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer;
const uint8Array: Uint8Array = new Uint8Array(arrayBuffer);
const fileBlob: any = {
type: file.type,
@ -80,7 +95,7 @@ export default function SendDocuments() {
const fileData: any = {
file_blob: fileBlob,
file_name: file.name
file_name: fileName
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';