diff --git a/packages/manager/apps/procedures/src/components/FileInput/FileInputList.tsx b/packages/manager/apps/procedures/src/components/FileInput/FileInputList.tsx index abe034e047a6..f1e0e9ceddca 100644 --- a/packages/manager/apps/procedures/src/components/FileInput/FileInputList.tsx +++ b/packages/manager/apps/procedures/src/components/FileInput/FileInputList.tsx @@ -1,5 +1,11 @@ import React, { FunctionComponent, MouseEvent, useContext } from 'react'; import { useTranslation } from 'react-i18next'; +import { OsdsText } from '@ovhcloud/ods-components/react'; +import { + ODS_THEME_COLOR_INTENT, + ODS_THEME_TYPOGRAPHY_LEVEL, + ODS_THEME_TYPOGRAPHY_SIZE, +} from '@ovhcloud/ods-common-theming'; import { FileInputContext } from './FileInputContainer'; import { FileInputListItem } from './FileInputListItem'; @@ -26,9 +32,14 @@ export const FileInputList: FunctionComponent = ({ className }) => { return value?.length ? (
{multiple && ( - + )} {value.map((file, index) => ( = ({ } size={ODS_ICON_SIZE.sm} /> -
+ {file.name} {`(${bytesToSize(file.size)})`} {file.errors.map((error, index) => ( {error} ))} -
+ ; + required?: string; + helper?: string; + accept?: string; + maxFiles: number; + maxSize: number; + pattern?: ValidationRule; + tooltips?: string[]; + multiple?: boolean; + validate?: + | Validate + | Record>; +}; + +export const FileField: FunctionComponent = ({ + control, + name, + label, + required, + accept, + maxFiles, + maxSize, + multiple, + helper, +}) => { + return ( +
+ { + if (!files) return true; + return files.flatMap((itemFile) => itemFile.errors).length < 1; + }, + }, + }} + render={({ field: { onChange, value, name: _name } }) => ( + onChange(e.files)} + maxSize={maxSize} + multiple={multiple} + > + + + + {helper && {helper}} + + + + )} + /> +
+ ); +}; diff --git a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.component.tsx b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.component.tsx index 98943b631c37..639e781e8854 100644 --- a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.component.tsx +++ b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.component.tsx @@ -2,7 +2,7 @@ import { ODS_THEME_COLOR_INTENT, ODS_THEME_TYPOGRAPHY_LEVEL, } from '@ovhcloud/ods-common-theming'; -import { ODS_BUTTON_TYPE } from '@ovhcloud/ods-components'; +import { ODS_BUTTON_TYPE, ODS_TEXT_SIZE } from '@ovhcloud/ods-components'; import { OsdsButton, OsdsText } from '@ovhcloud/ods-components/react'; import React, { FunctionComponent, useEffect } from 'react'; import { useForm } from 'react-hook-form'; @@ -14,9 +14,13 @@ import { TextAreaField } from './TextAreaField/TextAreaField.component'; import { EmailRegex, GDPRSubjectValues, + MaxFileSize, + OtherDocumentsMaxFiles, + RGDPAcceptFile, TextInputRegex, } from './RGDPForm.constants'; import './RGDPForm.style.css'; +import { FileField } from './FileField/FileField.component'; export const RGDPForm: FunctionComponent = () => { const { t } = useTranslation('rgdp'); @@ -133,7 +137,82 @@ export const RGDPForm: FunctionComponent = () => { control={control} />
+
+
+ + {t('rgdp_form_upload_documents_title')} + + + + {t('rgdp_form_upload_documents_notice')} + + + + {t('rgdp_form_upload_documents_notice_readable_doc')} + + + + {t('rgdp_form_upload_documents_notice_no_valid_doc')} + + + + {t('rgdp_form_upload_documents_notice_file_format')} + +
+ + + + + +
]*$/; + +export const OtherDocumentsMaxFiles = 8; +export const RGDPAcceptFile = 'image/jpeg,image/jpg,image/png,application/pdf'; +export const MaxFileSize = 10 * 1024 * 1024; diff --git a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.test.tsx b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.test.tsx index da1ae233c1ca..692f4b03f905 100644 --- a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.test.tsx +++ b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/RGDPForm.test.tsx @@ -52,6 +52,12 @@ describe('RGDPForm', () => { expect( getByText('rgdp_form_field_label_request_description:'), ).toBeInTheDocument(); + + expect(getByText('rgdp_form_field_label_id_front:')).toBeInTheDocument(); + expect(getByText('rgdp_form_field_label_id_back:')).toBeInTheDocument(); + expect( + getByText('rgdp_form_field_label_other_documents:'), + ).toBeInTheDocument(); }); }); diff --git a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/SelectField/SelectField.component.tsx b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/SelectField/SelectField.component.tsx index 116bff9f8c63..d68b443df4a6 100644 --- a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/SelectField/SelectField.component.tsx +++ b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/SelectField/SelectField.component.tsx @@ -71,7 +71,7 @@ export const SelectField: FunctionComponent = ({ = ({ onOdsBlur={onBlur} error={Boolean(error) || undefined} id={id} - value={value} + value={value as string} color={ODS_THEME_COLOR_INTENT.primary} /> diff --git a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/TextField/TextField.component.tsx b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/TextField/TextField.component.tsx index d9b78cff6dc9..c09f907941c1 100644 --- a/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/TextField/TextField.component.tsx +++ b/packages/manager/apps/procedures/src/pages/rgdp/rgdpForm/TextField/TextField.component.tsx @@ -67,7 +67,7 @@ export const TextField: FunctionComponent = ({ name={name} onOdsInputBlur={onBlur} id={id} - value={value} + value={value as string} type={ODS_INPUT_TYPE.text} color={ODS_THEME_COLOR_INTENT.primary} /> diff --git a/packages/manager/apps/procedures/src/public/translations/rgdp/Messages_fr_FR.json b/packages/manager/apps/procedures/src/public/translations/rgdp/Messages_fr_FR.json index 5efc802dfdc4..e747532b09ac 100644 --- a/packages/manager/apps/procedures/src/public/translations/rgdp/Messages_fr_FR.json +++ b/packages/manager/apps/procedures/src/public/translations/rgdp/Messages_fr_FR.json @@ -26,5 +26,17 @@ "rgdp_form_subject_limitation_right": "Droit à la limitation du traitement", "rgdp_form_subject_portability_right": "Droit à la portabilité des données", "rgdp_form_subject_payment_method_remove": "Suppression des informations de paiement", - "rgdp_form_subject_other_request": "Autre demande" + "rgdp_form_subject_other_request": "Autre demande", + + "rgdp_form_upload_documents_title": "Déposez vos documents", + "rgdp_form_upload_documents_notice": "Pour exercer vos droits sur les données vous concernant, merci de joindre la copie d'un justificatif d'identité (tel que carte nationale d'identité, passeport ou autre), sauf si les éléments communiqués dans le cadre de votre demande permettent de vous identifier de façon certaine. À défaut, la demande ne pourra pas être traitée.", + "rgdp_form_upload_documents_notice_readable_doc": "Attention, veuillez vous assurer que tous vos documents sont corrects et lisibles avant envoi.", + "rgdp_form_upload_documents_notice_no_valid_doc": "En cas de documents non valides, cette procédure sera annulée et vous devrez en effectuer une nouvelle.", + "rgdp_form_upload_documents_notice_file_format": "Format : jpg, jpeg, pdf, png. La taille maximale du fichier pour chaque document est de 10 Mo.", + + "rgdp_form_field_label_id_front": "Pièce d'identité (recto)", + "rgdp_form_field_label_id_back": "Pièce d'identité (verso)", + "rgdp_form_field_label_other_documents": "Autre document nécessaire pour la demande", + "rgdp_form_field_helper_id": "Carte nationale d'identité, passeport, carte de séjour ou permis de conduire.", + "rgdp_form_field_helper_other_documents": "Le nombre maximal de documents supporté est de {{maxFiles}}." } diff --git a/packages/manager/apps/procedures/src/types/gdpr.type.ts b/packages/manager/apps/procedures/src/types/gdpr.type.ts index 7488ff3aaf4f..89c520f89dac 100644 --- a/packages/manager/apps/procedures/src/types/gdpr.type.ts +++ b/packages/manager/apps/procedures/src/types/gdpr.type.ts @@ -1,3 +1,5 @@ +import { FileWithError } from '@/components/FileInput/FileInputContainer'; + export type GDPRFormValues = { firstName: string; surname: string; @@ -7,4 +9,7 @@ export type GDPRFormValues = { nicHandle?: string; messageSubject: string; requestDescription: string; + idDocumentFront: FileWithError[]; + idDocumentBack: FileWithError[]; + otherDocuments: FileWithError[]; };