diff --git a/app/frontend/src/javascript/components/form/form-rich-text.tsx b/app/frontend/src/javascript/components/form/form-rich-text.tsx new file mode 100644 index 000000000..7c1cb686d --- /dev/null +++ b/app/frontend/src/javascript/components/form/form-rich-text.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { FormControlledComponent } from '../../models/form-component'; +import { AbstractFormItem, AbstractFormItemProps } from './abstract-form-item'; +import { FieldValues } from 'react-hook-form/dist/types/fields'; +import { FabTextEditor } from '../base/text-editor/fab-text-editor'; +import { Controller, Path } from 'react-hook-form'; +import { FieldPath } from 'react-hook-form/dist/types/path'; +import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types'; + +interface FormRichTextProps extends FormControlledComponent, AbstractFormItemProps { + valueDefault?: string, + limit?: number, + paragraphTools?: boolean, + video?: boolean, + image?: boolean, +} + +/** + * THis component is a rich-text editor to use with react-hook-form. + */ +export const FormRichText = ({ id, label, tooltip, className, control, valueDefault, error, warning, rules, disabled, formState, limit, paragraphTools, video, image }: FormRichTextProps) => { + return ( + + } + control={control} + defaultValue={valueDefault as UnpackNestedValue>>} + render={({ field: { onChange, value } }) => + + } /> + + ); +}; diff --git a/app/frontend/src/javascript/components/form/form-switch.tsx b/app/frontend/src/javascript/components/form/form-switch.tsx index d46a09752..a02f51b8c 100644 --- a/app/frontend/src/javascript/components/form/form-switch.tsx +++ b/app/frontend/src/javascript/components/form/form-switch.tsx @@ -38,7 +38,7 @@ export const FormSwitch = ({ id, label, t onChange(val); onChangeCb(val); }} - checked={value as boolean} + checked={value as boolean || false} height={19} width={40} ref={ref} diff --git a/app/frontend/src/javascript/components/plan-categories/plan-category-form.tsx b/app/frontend/src/javascript/components/plan-categories/plan-category-form.tsx index 92405342d..2b0a572ae 100644 --- a/app/frontend/src/javascript/components/plan-categories/plan-category-form.tsx +++ b/app/frontend/src/javascript/components/plan-categories/plan-category-form.tsx @@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next'; import PlanCategoryAPI from '../../api/plan-category'; import { PlanCategory } from '../../models/plan-category'; import { Loader } from '../base/loader'; -import { useForm, Controller, SubmitHandler } from 'react-hook-form'; -import { FabTextEditor } from '../base/text-editor/fab-text-editor'; +import { useForm, SubmitHandler } from 'react-hook-form'; import { FormInput } from '../form/form-input'; import { FabAlert } from '../base/fab-alert'; import { FabButton } from '../base/fab-button'; +import { FormRichText } from '../form/form-rich-text'; interface PlanCategoryFormProps { action: 'create' | 'update', @@ -47,9 +47,7 @@ const PlanCategoryFormComponent: React.FC = ({ action, ca
- - - } /> + diff --git a/app/frontend/src/javascript/components/user/user-profile-form.tsx b/app/frontend/src/javascript/components/user/user-profile-form.tsx index faccb204c..b4f9656a7 100644 --- a/app/frontend/src/javascript/components/user/user-profile-form.tsx +++ b/app/frontend/src/javascript/components/user/user-profile-form.tsx @@ -11,6 +11,7 @@ import { GenderInput } from './gender-input'; import { ChangePassword } from './change-password'; import { PasswordInput } from './password-input'; import { FormSwitch } from '../form/form-switch'; +import { FormRichText } from '../form/form-rich-text'; declare const Application: IApplication; @@ -25,6 +26,10 @@ interface UserProfileFormProps { export const UserProfileForm: React.FC = ({ action, size, user, className, onError }) => { const { t } = useTranslation('shared'); + // regular expression to validate the the input fields + const phoneRegex = /^((00|\+)[0-9]{2,3})?[0-9]{4,14}$/; + const urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([-a-z0-9.]{2,30})([/\w .-]*)*\/?$/; + const { handleSubmit, register, control, formState } = useForm({ defaultValues: { ...user } }); const output = useWatch({ control }); @@ -67,7 +72,7 @@ export const UserProfileForm: React.FC = ({ action, size, register={register} rules={{ pattern: { - value: /^((00|\+)[0-9]{2,3})?[0-9]{4,14}$/, + value: phoneRegex, message: t('app.shared.user_profile_form.phone_number_invalid') } }} @@ -133,6 +138,30 @@ export const UserProfileForm: React.FC = ({ action, size,

{t('app.shared.user_profile_form.profile_data')}

+
+ + +
+
+ + +

{t('app.shared.user_profile_form.preferences_data')}

@@ -145,6 +174,9 @@ export const UserProfileForm: React.FC = ({ action, size, label={t('app.shared.user_profile_form.allow_newsletter')} tooltip={t('app.shared.user_profile_form.allow_newsletter_help')} />
+
+ +
); diff --git a/app/frontend/src/stylesheets/application.scss b/app/frontend/src/stylesheets/application.scss index 21d46212e..634034e57 100644 --- a/app/frontend/src/stylesheets/application.scss +++ b/app/frontend/src/stylesheets/application.scss @@ -31,6 +31,7 @@ @import "modules/calendar/calendar"; @import "modules/form/form-input"; @import "modules/form/form-item"; +@import "modules/form/form-rich-text"; @import "modules/form/form-switch"; @import "modules/machines/machine-card"; @import "modules/machines/machines-filters"; diff --git a/app/frontend/src/stylesheets/modules/form/form-rich-text.scss b/app/frontend/src/stylesheets/modules/form/form-rich-text.scss new file mode 100644 index 000000000..ec6c1bb0e --- /dev/null +++ b/app/frontend/src/stylesheets/modules/form/form-rich-text.scss @@ -0,0 +1,6 @@ +.form-rich-text { + .form-item-field { + border: 0; + display: block; + } +} diff --git a/app/frontend/src/stylesheets/modules/user/user-profile-form.scss b/app/frontend/src/stylesheets/modules/user/user-profile-form.scss index fdd54e3b7..c8ee5e78d 100644 --- a/app/frontend/src/stylesheets/modules/user/user-profile-form.scss +++ b/app/frontend/src/stylesheets/modules/user/user-profile-form.scss @@ -9,11 +9,11 @@ margin-top: 1.5rem; } - .names, .birth-phone { + .names, .birth-phone, .website-job, .interests-CAD { display: flex; flex-direction: row; - .form-input:first-child { + .form-item:first-child { margin-right: 32px; } } @@ -32,10 +32,10 @@ &--small { flex-direction: column; - .names, .birth-phone { + .names, .birth-phone, .website-job, .interests-CAD { flex-direction: column; - .form-input:first-child { + .form-item:first-child { margin-right: 0; } } diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index 8bd474394..224024607 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -50,6 +50,7 @@ en: organization_address: "Organization address" date_of_birth: "Date of birth" website: "Website" + website_invalid: "The website address is not a valid URL" job: "Job" interests: "Interests" CAD_softwares_mastered: "CAD Softwares mastered" @@ -57,7 +58,7 @@ en: birthday_is_required: "Date of birth is required." address: "Address" phone_number: "Phone number" - phone_number_is_required: "Phone number is required." + phone_number_invalid: "Phone number is invalid." allow_public_profile: "I authorize users, registered on the site, to contact me" allow_public_profile_help: "Your profile will be visible to other users and you'll be able to collaborate on projects." allow_newsletter: "I accept to receive information from the FabLab"