🔨 email reminder
This commit is contained in:
parent
1e4ab173ee
commit
62b51b4047
@ -4,11 +4,11 @@ import Tooltip from "../ToolTip";
|
|||||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { IOptionOld } from "../Form/SelectFieldOld";
|
import { IOption } from "../Form/SelectFieldOld";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
name?: string;
|
name?: string;
|
||||||
option: IOptionOld;
|
option: IOption;
|
||||||
toolTip?: string;
|
toolTip?: string;
|
||||||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -10,9 +10,9 @@ import classes from "./classes.module.scss";
|
|||||||
import { NextRouter, useRouter } from "next/router";
|
import { NextRouter, useRouter } from "next/router";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
selectedOption?: IOptionOld;
|
selectedOption?: IOption;
|
||||||
onChange?: (selectedOption: IOptionOld) => void;
|
onChange?: (selectedOption: IOption) => void;
|
||||||
options: IOptionOld[];
|
options: IOption[];
|
||||||
hasBorderRightCollapsed?: boolean;
|
hasBorderRightCollapsed?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -21,7 +21,7 @@ type IProps = {
|
|||||||
errors?: ValidationError;
|
errors?: ValidationError;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IOptionOld = {
|
export type IOption = {
|
||||||
value: unknown;
|
value: unknown;
|
||||||
label: string;
|
label: string;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
@ -32,7 +32,7 @@ type IState = {
|
|||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
listWidth: number;
|
listWidth: number;
|
||||||
listHeight: number;
|
listHeight: number;
|
||||||
selectedOption: IOptionOld | null;
|
selectedOption: IOption | null;
|
||||||
errors: ValidationError | null;
|
errors: ValidationError | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ class SelectFieldClass extends React.Component<IPropsClass, IState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSelect(option: IOptionOld, e: React.MouseEvent<HTMLLIElement, MouseEvent>) {
|
private onSelect(option: IOption, e: React.MouseEvent<HTMLLIElement, MouseEvent>) {
|
||||||
if (this.props.disabled) return;
|
if (this.props.disabled) return;
|
||||||
this.props.onChange && this.props.onChange(option);
|
this.props.onChange && this.props.onChange(option);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -13,14 +13,14 @@ import React, { useCallback, useEffect, useState } from "react";
|
|||||||
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import ParameterDocuments from "./ParameterDocuments";
|
import ParameterDocuments from "./ParameterDocuments";
|
||||||
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
import { IOption } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import backgroundImage from "@Assets/images/background_refonte.svg";
|
import backgroundImage from "@Assets/images/background_refonte.svg";
|
||||||
|
|
||||||
export default function AskDocuments() {
|
export default function AskDocuments() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
let { folderUid, customerUid } = router.query;
|
let { folderUid, customerUid } = router.query;
|
||||||
const [isCreateDocumentModalVisible, setIsCreateDocumentModalVisible] = useState<boolean>(false);
|
const [isCreateDocumentModalVisible, setIsCreateDocumentModalVisible] = useState<boolean>(false);
|
||||||
const [documentTypes, setDocumentTypes] = useState<IOptionOld[]>([]);
|
const [documentTypes, setDocumentTypes] = useState<IOption[]>([]);
|
||||||
const [folder, setFolder] = useState<OfficeFolder | null>(null);
|
const [folder, setFolder] = useState<OfficeFolder | null>(null);
|
||||||
|
|
||||||
const closeModal = () => setIsCreateDocumentModalVisible(false);
|
const closeModal = () => setIsCreateDocumentModalVisible(false);
|
||||||
@ -62,7 +62,7 @@ export default function AskDocuments() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const getAvailableDocuments = useCallback(
|
const getAvailableDocuments = useCallback(
|
||||||
async (folder: OfficeFolder): Promise<IOptionOld[]> => {
|
async (folder: OfficeFolder): Promise<IOption[]> => {
|
||||||
// Getting already asked documents UIDs in an array
|
// Getting already asked documents UIDs in an array
|
||||||
const userDocumentTypesUids = folder
|
const userDocumentTypesUids = folder
|
||||||
.documents!.filter((document) => document.depositor!.uid! === customerUid!)
|
.documents!.filter((document) => document.depositor!.uid! === customerUid!)
|
||||||
@ -81,7 +81,7 @@ export default function AskDocuments() {
|
|||||||
if (!documentTypes) return [];
|
if (!documentTypes) return [];
|
||||||
|
|
||||||
// Else, return an array document types formatted as IOPtions
|
// Else, return an array document types formatted as IOPtions
|
||||||
const documentTypesOptions: IOptionOld[] = documentTypes.map((documentType) => {
|
const documentTypesOptions: IOption[] = documentTypes.map((documentType) => {
|
||||||
return {
|
return {
|
||||||
label: documentType!.name!,
|
label: documentType!.name!,
|
||||||
value: documentType!.uid!,
|
value: documentType!.uid!,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md, 16px);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
|
||||||
|
import { IOption } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import Modal from "@Front/Components/DesignSystem/Modal";
|
import Modal from "@Front/Components/DesignSystem/Modal";
|
||||||
|
import Separator, { ESeperatorColor } from "@Front/Components/DesignSystem/Separator";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
import Customer from "le-coffre-resources/dist/Customer";
|
import Customer from "le-coffre-resources/dist/Customer";
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback, useMemo, useState } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
|
||||||
@ -14,11 +17,52 @@ type IProps = {
|
|||||||
|
|
||||||
export default function ReminderModal(props: IProps) {
|
export default function ReminderModal(props: IProps) {
|
||||||
const { isOpen, onClose, onRemindSuccess, customer } = props;
|
const { isOpen, onClose, onRemindSuccess, customer } = props;
|
||||||
|
const [selectedOptions, setSelectedOptions] = useState<IOption[]>([]);
|
||||||
|
const [isAllSelected, setIsAllSelected] = useState(false);
|
||||||
|
|
||||||
const onRemind = useCallback(() => {
|
const onRemind = useCallback(() => {
|
||||||
|
console.log("selectedOptions", selectedOptions);
|
||||||
onRemindSuccess();
|
onRemindSuccess();
|
||||||
onClose?.();
|
onClose?.();
|
||||||
}, [onClose, onRemindSuccess]);
|
}, [onClose, onRemindSuccess, selectedOptions]);
|
||||||
|
|
||||||
|
const documentsOptions: IOption[] = useMemo(
|
||||||
|
() =>
|
||||||
|
customer.documents?.map((document) => {
|
||||||
|
return {
|
||||||
|
label: document.document_type?.name ?? "",
|
||||||
|
value: document.document_type?.uid ?? "",
|
||||||
|
};
|
||||||
|
}) ?? [],
|
||||||
|
[customer],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleOnChange = useCallback(
|
||||||
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const { value, checked } = e.target;
|
||||||
|
const optionSelected = documentsOptions.find((option) => option.value === value);
|
||||||
|
if (checked && optionSelected) {
|
||||||
|
setSelectedOptions((prev) => [...prev, optionSelected]);
|
||||||
|
} else {
|
||||||
|
setSelectedOptions((prev) => prev.filter((option) => option.value !== value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[documentsOptions],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelectAll = useCallback(
|
||||||
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const { checked } = e.target;
|
||||||
|
if (checked) {
|
||||||
|
setSelectedOptions(documentsOptions);
|
||||||
|
setIsAllSelected(true);
|
||||||
|
} else {
|
||||||
|
setSelectedOptions([]);
|
||||||
|
setIsAllSelected(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[documentsOptions],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -31,6 +75,21 @@ export default function ReminderModal(props: IProps) {
|
|||||||
<Typography typo={ETypo.TEXT_MD_LIGHT}>
|
<Typography typo={ETypo.TEXT_MD_LIGHT}>
|
||||||
Sélectionnez le(s) document(s) pour lequel vous souhaitez relancer le client.
|
Sélectionnez le(s) document(s) pour lequel vous souhaitez relancer le client.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<CheckBox
|
||||||
|
option={{ label: "Tous les documents", value: "all-documents" }}
|
||||||
|
checked={isAllSelected}
|
||||||
|
onChange={handleSelectAll}
|
||||||
|
/>
|
||||||
|
<Separator color={ESeperatorColor.LIGHT} />
|
||||||
|
{documentsOptions.map((option) => (
|
||||||
|
<CheckBox
|
||||||
|
key={option.value as string}
|
||||||
|
option={option}
|
||||||
|
onChange={handleOnChange}
|
||||||
|
checked={isAllSelected}
|
||||||
|
disabled={isAllSelected}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -13,10 +13,12 @@ import Link from "next/link";
|
|||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
customer: Customer;
|
customer: Customer;
|
||||||
|
doesCustomerHaveDocument: boolean;
|
||||||
|
isAnchored: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function EmailReminder(props: IProps) {
|
export default function EmailReminder(props: IProps) {
|
||||||
const { customer } = props;
|
const { customer, doesCustomerHaveDocument, isAnchored } = props;
|
||||||
const { isOpen, open, close } = useOpenable();
|
const { isOpen, open, close } = useOpenable();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -24,14 +26,17 @@ export default function EmailReminder(props: IProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes["root"]}>
|
<div className={classes["root"]}>
|
||||||
|
{!isAnchored && (
|
||||||
<Button
|
<Button
|
||||||
onClick={open}
|
onClick={open}
|
||||||
rightIcon={<EnvelopeIcon />}
|
rightIcon={<EnvelopeIcon />}
|
||||||
variant={EButtonVariant.PRIMARY}
|
variant={EButtonVariant.PRIMARY}
|
||||||
styletype={EButtonstyletype.OUTLINED}
|
styletype={EButtonstyletype.OUTLINED}
|
||||||
fullwidth>
|
fullwidth
|
||||||
|
disabled={doesCustomerHaveDocument}>
|
||||||
Relancer par mail
|
Relancer par mail
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
<div className={classes["reminder-info"]}>
|
<div className={classes["reminder-info"]}>
|
||||||
<Link
|
<Link
|
||||||
title={"Voir l'historique des relances"}
|
title={"Voir l'historique des relances"}
|
||||||
@ -41,11 +46,13 @@ export default function EmailReminder(props: IProps) {
|
|||||||
<IconButton icon={<ClockIcon />} variant={EIconButtonVariant.NEUTRAL} />
|
<IconButton icon={<ClockIcon />} variant={EIconButtonVariant.NEUTRAL} />
|
||||||
</Link>
|
</Link>
|
||||||
<div className={classes["info"]}>
|
<div className={classes["info"]}>
|
||||||
|
{/* TODO: mettre la date de la dernière relance */}
|
||||||
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
||||||
Dernière relance: todo
|
Dernière relance: -
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{/* TODO: mettre le nombre de relance */}
|
||||||
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
||||||
Nombre de relance: todo
|
Nombre de relance: -
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,7 +35,7 @@ $mobile-breakpoint: 664px;
|
|||||||
.button-container {
|
.button-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--spacing-lg, 24px);
|
gap: var(--spacing-md, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-s) {
|
@media screen and (max-width: $screen-s) {
|
||||||
|
@ -115,7 +115,11 @@ export default function ClientView(props: IProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
<EmailReminder customer={customer} />
|
<EmailReminder
|
||||||
|
customer={customer}
|
||||||
|
doesCustomerHaveDocument={!doesCustomerHaveDocument}
|
||||||
|
isAnchored={anchorStatus !== AnchorStatus.NOT_ANCHORED}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import Select, { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
import Select, { IOption } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||||
@ -81,7 +81,7 @@ export default function UpdateFolderMetadata() {
|
|||||||
const deedOption = {
|
const deedOption = {
|
||||||
label: selectedFolder?.deed?.deed_type?.name,
|
label: selectedFolder?.deed?.deed_type?.name,
|
||||||
value: selectedFolder?.deed?.deed_type?.uid,
|
value: selectedFolder?.deed?.deed_type?.uid,
|
||||||
} as IOptionOld;
|
} as IOption;
|
||||||
const openingDate = new Date(selectedFolder?.created_at ?? "");
|
const openingDate = new Date(selectedFolder?.created_at ?? "");
|
||||||
if (!selectedFolder?.created_at) return <></>;
|
if (!selectedFolder?.created_at) return <></>;
|
||||||
const defaultValue = openingDate.toISOString().split("T")[0];
|
const defaultValue = openingDate.toISOString().split("T")[0];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import Select, { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
import Select, { IOption } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||||
@ -18,7 +18,7 @@ type IProps = {
|
|||||||
};
|
};
|
||||||
type IState = {
|
type IState = {
|
||||||
selectedFolder: OfficeFolder | null;
|
selectedFolder: OfficeFolder | null;
|
||||||
selectedOption?: IOptionOld;
|
selectedOption?: IOption;
|
||||||
};
|
};
|
||||||
class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
@ -74,7 +74,7 @@ class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSelectedOption(option: IOptionOld) {
|
private onSelectedOption(option: IOption) {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedOption: option,
|
selectedOption: option,
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user