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:
parent
9ac9a2a725
commit
1c38073b1b
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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">
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user