1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-19 08:52:25 +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 dba636b6e6
commit 7a6fe34b90
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);
onChangeCb(val);
}}
checked={value as boolean}
checked={value as boolean || false}
height={19}
width={40}
ref={ref}

View File

@ -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<PlanCategoryFormProps> = ({ action, ca
<form onSubmit={handleSubmit(onSubmit)}>
<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 } }) =>
<FabTextEditor label={t('app.admin.manage_plan_category.description')} onChange={onChange} content={value} limit={100} />
} />
<FormRichText control={control} id="description" label={t('app.admin.manage_plan_category.description')} limit={100} />
<FormInput id='weight' register={register} type='number' label={t('app.admin.manage_plan_category.significance')} />
<FabAlert level="info" className="significance-info">

View File

@ -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<UserProfileFormProps> = ({ 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<User>({ defaultValues: { ...user } });
const output = useWatch<User>({ control });
@ -67,7 +72,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ 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<UserProfileFormProps> = ({ action, size,
</div>
<div className="profile-data">
<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 className="preferences-data">
<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')}
tooltip={t('app.shared.user_profile_form.allow_newsletter_help')} />
</div>
<div>
<button type="submit">GO</button>
</div>
</div>
</form>
);

View File

@ -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";

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;
}
.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;
}
}

View File

@ -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"