1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-21 15:54:22 +01:00

(ui) profile data: website, job, cad softwares, interests

This commit is contained in:
Sylvain 2022-05-02 15:29:32 +02:00
parent c541e02fe2
commit cad8484231
8 changed files with 85 additions and 12 deletions

View File

@ -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<TFieldValues, TContext extends object> extends FormControlledComponent<TFieldValues, TContext>, AbstractFormItemProps<TFieldValues> {
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 = <TFieldValues extends FieldValues, TContext extends object>({ id, label, tooltip, className, control, valueDefault, error, warning, rules, disabled, formState, limit, paragraphTools, video, image }: FormRichTextProps<TFieldValues, TContext>) => {
return (
<AbstractFormItem id={id} label={label} tooltip={tooltip}
className={`form-rich-text ${className || ''}`}
error={error} warning={warning} rules={rules}
disabled={disabled} formState={formState}>
<Controller name={id as FieldPath<TFieldValues>}
control={control}
defaultValue={valueDefault as UnpackNestedValue<FieldPathValue<TFieldValues, Path<TFieldValues>>>}
render={({ field: { onChange, value } }) =>
<FabTextEditor onChange={onChange} content={value} limit={limit} paragraphTools={paragraphTools} video={video} image={image} />
} />
</AbstractFormItem>
);
};

View File

@ -38,7 +38,7 @@ export const FormSwitch = <TFieldValues, TContext extends object>({ id, label, t
onChange(val); onChange(val);
onChangeCb(val); onChangeCb(val);
}} }}
checked={value as boolean} checked={value as boolean || false}
height={19} height={19}
width={40} width={40}
ref={ref} ref={ref}

View File

@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next';
import PlanCategoryAPI from '../../api/plan-category'; import PlanCategoryAPI from '../../api/plan-category';
import { PlanCategory } from '../../models/plan-category'; import { PlanCategory } from '../../models/plan-category';
import { Loader } from '../base/loader'; import { Loader } from '../base/loader';
import { useForm, Controller, SubmitHandler } from 'react-hook-form'; import { useForm, SubmitHandler } from 'react-hook-form';
import { FabTextEditor } from '../base/text-editor/fab-text-editor';
import { FormInput } from '../form/form-input'; import { FormInput } from '../form/form-input';
import { FabAlert } from '../base/fab-alert'; import { FabAlert } from '../base/fab-alert';
import { FabButton } from '../base/fab-button'; import { FabButton } from '../base/fab-button';
import { FormRichText } from '../form/form-rich-text';
interface PlanCategoryFormProps { interface PlanCategoryFormProps {
action: 'create' | 'update', action: 'create' | 'update',
@ -47,9 +47,7 @@ const PlanCategoryFormComponent: React.FC<PlanCategoryFormProps> = ({ action, ca
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<FormInput id='name' register={register} rules={{ required: 'true' }} label={t('app.admin.manage_plan_category.name')} /> <FormInput id='name' register={register} rules={{ required: 'true' }} label={t('app.admin.manage_plan_category.name')} />
<Controller name="description" control={control} render={({ field: { onChange, value } }) => <FormRichText control={control} id="description" label={t('app.admin.manage_plan_category.description')} limit={100} />
<FabTextEditor label={t('app.admin.manage_plan_category.description')} onChange={onChange} content={value} limit={100} />
} />
<FormInput id='weight' register={register} type='number' label={t('app.admin.manage_plan_category.significance')} /> <FormInput id='weight' register={register} type='number' label={t('app.admin.manage_plan_category.significance')} />
<FabAlert level="info" className="significance-info"> <FabAlert level="info" className="significance-info">

View File

@ -11,6 +11,7 @@ import { GenderInput } from './gender-input';
import { ChangePassword } from './change-password'; import { ChangePassword } from './change-password';
import { PasswordInput } from './password-input'; import { PasswordInput } from './password-input';
import { FormSwitch } from '../form/form-switch'; import { FormSwitch } from '../form/form-switch';
import { FormRichText } from '../form/form-rich-text';
declare const Application: IApplication; declare const Application: IApplication;
@ -25,6 +26,10 @@ interface UserProfileFormProps {
export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size, user, className, onError }) => { export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size, user, className, onError }) => {
const { t } = useTranslation('shared'); 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<User>({ defaultValues: { ...user } }); const { handleSubmit, register, control, formState } = useForm<User>({ defaultValues: { ...user } });
const output = useWatch<User>({ control }); const output = useWatch<User>({ control });
@ -67,7 +72,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
register={register} register={register}
rules={{ rules={{
pattern: { pattern: {
value: /^((00|\+)[0-9]{2,3})?[0-9]{4,14}$/, value: phoneRegex,
message: t('app.shared.user_profile_form.phone_number_invalid') message: t('app.shared.user_profile_form.phone_number_invalid')
} }
}} }}
@ -133,6 +138,30 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
</div> </div>
<div className="profile-data"> <div className="profile-data">
<h4>{t('app.shared.user_profile_form.profile_data')}</h4> <h4>{t('app.shared.user_profile_form.profile_data')}</h4>
<div className="website-job">
<FormInput id="profile_attributes.website"
register={register}
rules={{
pattern: {
value: urlRegex,
message: t('app.shared.user_profile_form.website_invalid')
}
}}
placeholder="https://www.example.com"
formState={formState}
label={t('app.shared.user_profile_form.website')} />
<FormInput id="profile_attributes.job"
register={register}
label={t('app.shared.user_profile_form.job')} />
</div>
<div className="interests-CAD">
<FormRichText control={control}
id="profile_attributes.interest"
label={t('app.shared.user_profile_form.interests')} />
<FormRichText control={control}
id="profile_attributes.software_mastered"
label={t('app.shared.user_profile_form.CAD_softwares_mastered')} />
</div>
</div> </div>
<div className="preferences-data"> <div className="preferences-data">
<h4>{t('app.shared.user_profile_form.preferences_data')}</h4> <h4>{t('app.shared.user_profile_form.preferences_data')}</h4>
@ -145,6 +174,9 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
label={t('app.shared.user_profile_form.allow_newsletter')} label={t('app.shared.user_profile_form.allow_newsletter')}
tooltip={t('app.shared.user_profile_form.allow_newsletter_help')} /> tooltip={t('app.shared.user_profile_form.allow_newsletter_help')} />
</div> </div>
<div>
<button type="submit">GO</button>
</div>
</div> </div>
</form> </form>
); );

View File

@ -31,6 +31,7 @@
@import "modules/calendar/calendar"; @import "modules/calendar/calendar";
@import "modules/form/form-input"; @import "modules/form/form-input";
@import "modules/form/form-item"; @import "modules/form/form-item";
@import "modules/form/form-rich-text";
@import "modules/form/form-switch"; @import "modules/form/form-switch";
@import "modules/machines/machine-card"; @import "modules/machines/machine-card";
@import "modules/machines/machines-filters"; @import "modules/machines/machines-filters";

View File

@ -0,0 +1,6 @@
.form-rich-text {
.form-item-field {
border: 0;
display: block;
}
}

View File

@ -9,11 +9,11 @@
margin-top: 1.5rem; margin-top: 1.5rem;
} }
.names, .birth-phone { .names, .birth-phone, .website-job, .interests-CAD {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
.form-input:first-child { .form-item:first-child {
margin-right: 32px; margin-right: 32px;
} }
} }
@ -32,10 +32,10 @@
&--small { &--small {
flex-direction: column; flex-direction: column;
.names, .birth-phone { .names, .birth-phone, .website-job, .interests-CAD {
flex-direction: column; flex-direction: column;
.form-input:first-child { .form-item:first-child {
margin-right: 0; margin-right: 0;
} }
} }

View File

@ -50,6 +50,7 @@ en:
organization_address: "Organization address" organization_address: "Organization address"
date_of_birth: "Date of birth" date_of_birth: "Date of birth"
website: "Website" website: "Website"
website_invalid: "The website address is not a valid URL"
job: "Job" job: "Job"
interests: "Interests" interests: "Interests"
CAD_softwares_mastered: "CAD Softwares mastered" CAD_softwares_mastered: "CAD Softwares mastered"
@ -57,7 +58,7 @@ en:
birthday_is_required: "Date of birth is required." birthday_is_required: "Date of birth is required."
address: "Address" address: "Address"
phone_number: "Phone number" 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: "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_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" allow_newsletter: "I accept to receive information from the FabLab"