1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-30 19:52:20 +01:00

(quality) Editorial-block component + clean up

This commit is contained in:
vincent 2023-01-19 14:13:41 +01:00 committed by Sylvain
parent 9ac9a2a725
commit 1c38073b1b
10 changed files with 98 additions and 181 deletions

View File

@ -0,0 +1,80 @@
import * as React from 'react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import { Control, FormState, UseFormRegister } from 'react-hook-form';
import { FormSwitch } from '../form/form-switch';
import { FormRichText } from '../form/form-rich-text';
import { FormInput } from '../form/form-input';
interface EditorialBlockFormProps<TFieldValues> {
register: UseFormRegister<TFieldValues>,
control: Control<TFieldValues>,
formState: FormState<TFieldValues>,
info?: string
}
// regular expression to validate the input fields
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
/**
* Allows to create a formatted text and optional cta button in a form block, to be included in a resource form managed by react-hook-form.
*/
export const EditorialBlockForm = <TFieldValues extends FieldValues>({ register, control, formState, info }: EditorialBlockFormProps<TFieldValues>) => {
const { t } = useTranslation('admin');
const [isActiveTextBlock, setIsActiveTextBlock] = useState<boolean>(false);
const [isActiveCta, setIsActiveCta] = useState<boolean>(false);
/** Callback triggered when the text block switch has changed. */
const toggleTextBlockSwitch = (value: boolean) => {
setIsActiveTextBlock(value);
};
/** Callback triggered when the CTA switch has changed. */
const toggleTextBlockCta = (value: boolean) => {
setIsActiveCta(value);
};
return (
<>
<header>
<p className="title">{t('app.admin.editorial_block_form.title')}</p>
{info && <p className="description">{info}</p>}
</header>
<div className="content">
<FormSwitch id="active_text_block" control={control}
onChange={toggleTextBlockSwitch} formState={formState}
defaultValue={isActiveTextBlock}
label={t('app.admin.editorial_block_form.switch')} />
{/* TODO: error message if empty */}
<FormRichText id="text_block"
control={control}
heading
limit={280}
rules={{ required: isActiveTextBlock }}
disabled={!isActiveTextBlock} />
{isActiveTextBlock && <>
<FormSwitch id="active_cta" control={control}
onChange={toggleTextBlockCta} formState={formState}
label={t('app.admin.editorial_block_form.cta_switch')} />
{isActiveCta && <>
<FormInput id="cta_label"
register={register}
rules={{ required: isActiveCta }}
maxLength={40}
label={t('app.admin.editorial_block_form.cta_label')} />
<FormInput id="cta_url"
register={register}
rules={{ required: isActiveCta, pattern: urlRegex }}
label={t('app.admin.editorial_block_form.cta_url')} />
</>}
</>}
</div>
</>
);
};

View File

@ -2,7 +2,7 @@ import React from 'react';
import { IApplication } from '../../models/application';
import { Loader } from '../base/loader';
import { react2angular } from 'react2angular';
import { FabButton } from './fab-button';
import { FabButton } from '../base/fab-button';
declare const Application: IApplication;

View File

@ -10,10 +10,7 @@ import { MachineCategory } from '../../models/machine-category';
import { MachineCard } from './machine-card';
import { MachinesFilters } from './machines-filters';
import { User } from '../../models/user';
import { useTranslation } from 'react-i18next';
import { FabButton } from '../base/fab-button';
import { EditorialBlock } from '../base/editorial-block';
import { CalendarBlank } from 'phosphor-react';
import { EditorialBlock } from '../editorial-block/editorial-block';
declare const Application: IApplication;
@ -32,7 +29,6 @@ interface MachinesListProps {
* This component shows a list of all machines and allows filtering on that list.
*/
export const MachinesList: React.FC<MachinesListProps> = ({ onError, onSuccess, onShowMachine, onReserveMachine, onLoginRequested, onEnrollRequested, user, canProposePacks }) => {
const { t } = useTranslation('public');
// shown machines
const [machines, setMachines] = useState<Array<Machine>>(null);
// we keep the full list of machines, for filtering

View File

@ -1,15 +1,12 @@
import * as React from 'react';
import { useState } from 'react';
import { IApplication } from '../../models/application';
import { Loader } from '../base/loader';
import { react2angular } from 'react2angular';
import { ErrorBoundary } from '../base/error-boundary';
import { useTranslation } from 'react-i18next';
import { useForm, SubmitHandler } from 'react-hook-form';
import { FormRichText } from '../form/form-rich-text';
import { FormSwitch } from '../form/form-switch';
import { FormInput } from '../form/form-input';
import { FabButton } from '../base/fab-button';
import { EditorialBlockForm } from '../editorial-block/editorial-block-form';
declare const Application: IApplication;
@ -25,63 +22,6 @@ export const MachinesSettings: React.FC<MachinesSettingsProps> = () => {
const { t } = useTranslation('admin');
const { register, control, formState, handleSubmit } = useForm();
// regular expression to validate the input fields
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
const [isActiveAutoCancellation, setIsActiveAutoCancellation] = useState<boolean>(false);
const [isActiveAuthorizationValidity, setIsActiveAuthorizationValidity] = useState<boolean>(false);
const [isActiveTextBlock, setIsActiveTextBlock] = useState<boolean>(false);
const [isActiveValidationRule, setIsActiveValidationRule] = useState<boolean>(false);
const [isActiveCta, setIsActiveCta] = useState<boolean>(false);
/**
* Callback triggered when the auto cancellation switch has changed.
*/
const toggleAutoCancellation = (value: boolean) => {
setIsActiveAutoCancellation(value);
};
/**
* Callback triggered when the authorisation validity switch has changed.
*/
const toggleAuthorizationValidity = (value: boolean) => {
setIsActiveAuthorizationValidity(value);
};
/**
* Callback triggered when the authorisation validity switch has changed.
*/
const toggleValidationRule = (value: boolean) => {
setIsActiveValidationRule(value);
};
/**
* Callback triggered when the text block switch has changed.
*/
const toggleTextBlockSwitch = (value: boolean) => {
setIsActiveTextBlock(value);
};
/**
* Callback triggered when the CTA switch has changed.
*/
const toggleTextBlockCta = (value: boolean) => {
setIsActiveCta(value);
};
/**
* Callback triggered when the CTA label has changed.
*/
const handleCtaLabelChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
console.log('cta label:', event.target.value);
};
/**
* Callback triggered when the cta url has changed.
*/
const handleCtaUrlChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
console.log('cta url:', event.target.value);
};
/**
* Callback triggered when the form is submitted: save the settings
*/
@ -97,43 +37,10 @@ export const MachinesSettings: React.FC<MachinesSettingsProps> = () => {
</header>
<form className="machines-settings-content">
<div className="settings-section">
<header>
<p className="title">{t('app.admin.machines_settings.generic_text_block')}</p>
<p className="description">{t('app.admin.machines_settings.generic_text_block_info')}</p>
</header>
<div className="content">
<FormSwitch id="active_text_block" control={control}
onChange={toggleTextBlockSwitch} formState={formState}
defaultValue={isActiveTextBlock}
label={t('app.admin.machines_settings.generic_text_block_switch')} />
<FormRichText id="text_block"
control={control}
heading
limit={280}
disabled={!isActiveTextBlock} />
{isActiveTextBlock && <>
<FormSwitch id="active_cta" control={control}
onChange={toggleTextBlockCta} formState={formState}
label={t('app.admin.machines_settings.cta_switch')} />
{isActiveCta && <>
<FormInput id="cta_label"
register={register}
rules={{ required: true }}
onChange={handleCtaLabelChange}
maxLength={40}
label={t('app.admin.machines_settings.cta_label')} />
<FormInput id="cta_url"
register={register}
rules={{ required: true, pattern: urlRegex }}
onChange={handleCtaUrlChange}
label={t('app.admin.machines_settings.cta_url')} />
</>}
</>}
</div>
<EditorialBlockForm register={register}
control={control}
formState={formState}
info={t('app.admin.machines_settings.generic_text_block_info')} />
</div>
</form>
</div>

View File

@ -6,7 +6,6 @@ import ProductCategoryAPI from '../../../api/product-category';
import { ManageProductCategory } from './manage-product-category';
import { ProductCategoriesTree } from './product-categories-tree';
import { FabAlert } from '../../base/fab-alert';
import { HtmlTranslate } from '../../base/html-translate';
import { IApplication } from '../../../models/application';
import { Loader } from '../../base/loader';
import { react2angular } from 'react2angular';

View File

@ -4,7 +4,6 @@ import { SubmitHandler, useForm, useWatch } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import slugify from 'slugify';
import _ from 'lodash';
import { HtmlTranslate } from '../base/html-translate';
import { Product } from '../../models/product';
import { FormInput } from '../form/form-input';
import { FormSwitch } from '../form/form-switch';
@ -12,7 +11,6 @@ import { FormSelect } from '../form/form-select';
import { FormChecklist } from '../form/form-checklist';
import { FormRichText } from '../form/form-rich-text';
import { FabButton } from '../base/fab-button';
import { FabAlert } from '../base/fab-alert';
import ProductCategoryAPI from '../../api/product-category';
import MachineAPI from '../../api/machine';
import ProductAPI from '../../api/product';

View File

@ -10,10 +10,8 @@ import {
StockMovementReason,
StockType
} from '../../models/product';
import { HtmlTranslate } from '../base/html-translate';
import { FormSwitch } from '../form/form-switch';
import { FormInput } from '../form/form-input';
import { FabAlert } from '../base/fab-alert';
import { FabButton } from '../base/fab-button';
import { ProductStockModal } from './product-stock-modal';
import { FabStateLabel } from '../base/fab-state-label';

View File

@ -4,9 +4,7 @@ import { react2angular } from 'react2angular';
import { Loader } from '../base/loader';
import { IApplication } from '../../models/application';
import { useTranslation } from 'react-i18next';
import { HtmlTranslate } from '../base/html-translate';
import { useForm, SubmitHandler } from 'react-hook-form';
import { FabAlert } from '../base/fab-alert';
import { FormRichText } from '../form/form-rich-text';
import { FabButton } from '../base/fab-button';
import SettingAPI from '../../api/setting';

View File

@ -6,10 +6,10 @@ import { react2angular } from 'react2angular';
import { ErrorBoundary } from '../base/error-boundary';
import { useTranslation } from 'react-i18next';
import { useForm, SubmitHandler } from 'react-hook-form';
import { FormRichText } from '../form/form-rich-text';
import { FormSwitch } from '../form/form-switch';
import { FormInput } from '../form/form-input';
import { FabButton } from '../base/fab-button';
import { EditorialBlockForm } from '../editorial-block/editorial-block-form';
declare const Application: IApplication;
@ -25,14 +25,9 @@ export const TrainingsSettings: React.FC<TrainingsSettingsProps> = () => {
const { t } = useTranslation('admin');
const { register, control, formState, handleSubmit } = useForm();
// regular expression to validate the input fields
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
const [isActiveAutoCancellation, setIsActiveAutoCancellation] = useState<boolean>(false);
const [isActiveAuthorizationValidity, setIsActiveAuthorizationValidity] = useState<boolean>(false);
const [isActiveTextBlock, setIsActiveTextBlock] = useState<boolean>(false);
const [isActiveValidationRule, setIsActiveValidationRule] = useState<boolean>(false);
const [isActiveCta, setIsActiveCta] = useState<boolean>(false);
/**
* Callback triggered when the auto cancellation switch has changed.
@ -55,33 +50,6 @@ export const TrainingsSettings: React.FC<TrainingsSettingsProps> = () => {
setIsActiveValidationRule(value);
};
/**
* Callback triggered when the text block switch has changed.
*/
const toggleTextBlockSwitch = (value: boolean) => {
setIsActiveTextBlock(value);
};
/**
* Callback triggered when the CTA switch has changed.
*/
const toggleTextBlockCta = (value: boolean) => {
setIsActiveCta(value);
};
/**
* Callback triggered when the CTA label has changed.
*/
const handleCtaLabelChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
console.log('cta label:', event.target.value);
};
/**
* Callback triggered when the cta url has changed.
*/
const handleCtaUrlChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
console.log('cta url:', event.target.value);
};
/**
* Callback triggered when the form is submitted: save the settings
*/
@ -97,43 +65,10 @@ export const TrainingsSettings: React.FC<TrainingsSettingsProps> = () => {
</header>
<form className="trainings-settings-content">
<div className="settings-section">
<header>
<p className="title">{t('app.admin.trainings_settings.generic_text_block')}</p>
<p className="description">{t('app.admin.trainings_settings.generic_text_block_info')}</p>
</header>
<div className="content">
<FormSwitch id="active_text_block" control={control}
onChange={toggleTextBlockSwitch} formState={formState}
defaultValue={isActiveTextBlock}
label={t('app.admin.trainings_settings.generic_text_block_switch')} />
<FormRichText id="text_block"
control={control}
heading
limit={280}
disabled={!isActiveTextBlock} />
{isActiveTextBlock && <>
<FormSwitch id="active_cta" control={control}
onChange={toggleTextBlockCta} formState={formState}
label={t('app.admin.trainings_settings.cta_switch')} />
{isActiveCta && <>
<FormInput id="cta_label"
register={register}
rules={{ required: true }}
onChange={handleCtaLabelChange}
maxLength={40}
label={t('app.admin.trainings_settings.cta_label')} />
<FormInput id="cta_url"
register={register}
rules={{ required: true, pattern: urlRegex }}
onChange={handleCtaUrlChange}
label={t('app.admin.trainings_settings.cta_url')} />
</>}
</>}
</div>
<EditorialBlockForm register={register}
control={control}
formState={formState}
info={t('app.admin.trainings_settings.generic_text_block_info')} />
</div>
<div className="settings-section">

View File

@ -2388,3 +2388,9 @@ en:
value: "Value"
date: "Changed at"
operator: "By"
editorial_block_form:
title: "Editorial text block"
switch: "Display editorial block"
cta_switch: "Display a button"
cta_label: "Button label"
cta_url: "url"