1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-03-15 12:29:16 +01:00

(quality) add typing for status filter and settings

This commit is contained in:
Karen 2023-01-25 12:47:46 +01:00 committed by Sylvain
parent 7047c557cd
commit 82a88aadad
7 changed files with 25 additions and 27 deletions

View File

@ -1,21 +1,20 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import { Control, FormState, UseFormRegister, UseFormGetValues } from 'react-hook-form';
import { FormSwitch } from '../form/form-switch';
import { FormRichText } from '../form/form-rich-text';
import { FormInput } from '../form/form-input';
import { SettingName } from '../../models/setting';
import { SettingName, SettingValue } from '../../models/setting';
export type EditorialKeys = 'active_text_block' | 'text_block' | 'active_cta' | 'cta_label' | 'cta_url';
interface EditorialBlockFormProps<TFieldValues> {
register: UseFormRegister<TFieldValues>,
control: Control<TFieldValues>,
formState: FormState<TFieldValues>,
interface EditorialBlockFormProps {
register: UseFormRegister<Record<SettingName, SettingValue>>,
control: Control<Record<SettingName, SettingValue>>,
formState: FormState<Record<SettingName, SettingValue>>,
info?: string
keys: Record<EditorialKeys, SettingName>,
getValues?: UseFormGetValues<FieldValues>,
getValues?: UseFormGetValues<Record<SettingName, SettingValue>>,
}
// regular expression to validate the input fields
@ -24,7 +23,7 @@ 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, keys, getValues }: EditorialBlockFormProps<TFieldValues>) => {
export const EditorialBlockForm: React.FC<EditorialBlockFormProps> = ({ register, control, formState, info, keys, getValues }) => {
const { t } = useTranslation('admin');
const [isActiveTextBlock, setIsActiveTextBlock] = useState<boolean>(false);

View File

@ -3,7 +3,7 @@ import * as React from 'react';
import { FieldPathValue, UseFormGetValues } from 'react-hook-form';
import { debounce as _debounce } from 'lodash';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import { FieldPath } from 'react-hook-form/dist/types/path';
import { Path, FieldPath } from 'react-hook-form/dist/types/path';
import { FormComponent } from '../../models/form-component';
import { AbstractFormItem, AbstractFormItemProps } from './abstract-form-item';
@ -23,14 +23,14 @@ type FormInputProps<TFieldValues, TInputType> = FormComponent<TFieldValues> & Ab
nullable?: boolean,
ariaLabel?: string,
maxLength?: number,
getValues?: UseFormGetValues<FieldValues>
getValues?: UseFormGetValues<TFieldValues>
}
/**
* This component is a template for an input component to use within React Hook Form
*/
export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, register, getValues, label, tooltip, defaultValue, icon, className, rules, disabled, type, addOn, addOnAction, addOnClassName, addOnAriaLabel, placeholder, error, warning, formState, step, onChange, debounce, accept, nullable = false, ariaLabel, maxLength }: FormInputProps<TFieldValues, TInputType>) => {
const [characterCount, setCharacterCount] = useState(0);
const [characterCount, setCharacterCount] = useState<number>(0);
/**
* Debounced (ie. temporised) version of the 'on change' callback.
@ -72,7 +72,7 @@ export const FormInput = <TFieldValues extends FieldValues, TInputType>({ id, re
// If maxLength and getValues is provided, uses input ref to initiate the countdown of characters
useEffect(() => {
if (getValues && maxLength) {
setCharacterCount(getValues(id).length);
setCharacterCount(getValues(id as Path<TFieldValues>).length);
}
}, [maxLength, getValues]);

View File

@ -24,7 +24,7 @@ interface MachinesSettingsProps {
*/
export const MachinesSettings: React.FC<MachinesSettingsProps> = ({ onError, onSuccess, beforeSubmit }) => {
const { t } = useTranslation('admin');
const { register, control, formState, handleSubmit, reset, getValues } = useForm();
const { register, control, formState, handleSubmit, reset, getValues } = useForm<Record<SettingName, SettingValue>>();
/** Link Machines Banner Setting Names to generic keys expected by the Editorial Form */
const bannerKeys: Record<EditorialKeys, SettingName> = {

View File

@ -20,7 +20,7 @@ export const ProjectsSettingOptionForm: React.FC<ProjectsSettingOptionFormProps>
const enteredOptionName = useRef(null);
const enteredOptionDescription = useRef(null);
const [errorMessage, setErrorMessage] = useState('');
const [errorMessage, setErrorMessage] = useState<string>('');
/**
* Builds up new or updated option based on User input and provides it to parent component.

View File

@ -19,7 +19,7 @@ interface ProjectsSettingOptionProps {
export const ProjectsSettingOption: React.FC<ProjectsSettingOptionProps> = ({ option, handleDelete, handleUpdate, hasDescription }) => {
const { t } = useTranslation('admin');
const [isEditing, setIsEditing] = useState(false);
const [isEditing, setIsEditing] = useState<boolean>(false);
// If option is in display mode, sets it in editing mode, and vice-versa.
const toggleIsEditing = () => setIsEditing(prevState => !prevState);

View File

@ -21,7 +21,7 @@ interface ProjectsSettingProps {
*/
export const ProjectsSetting: React.FC<ProjectsSettingProps> = ({ hasDescription = false, handleAdd, handleUpdate, handleDelete, options, optionType }) => {
const { t } = useTranslation('admin');
const [isAdding, setIsAdding] = useState(false);
const [isAdding, setIsAdding] = useState<boolean>(false);
// Shows form to add an option if it's not already here. Else, removes it.
const toggleIsAdding = () => setIsAdding((prevState) => !prevState);

View File

@ -22,15 +22,15 @@ interface StatusFilterProps {
export const StatusFilter: React.FC<StatusFilterProps> = ({ currentStatusIndex, onError, onFilterChange }) => {
const { t } = useTranslation('public');
const defaultValue = { value: null, label: t('app.public.status_filter.all_statuses') };
const [statusesList, setStatusesList] = useState([]);
const [currentOption, setCurrentOption] = useState(defaultValue);
const [statusesList, setStatusesList] = useState<Array<Status>>([]);
const [currentOption, setCurrentOption] = useState<SelectOption<number>>(defaultValue);
/**
* From the statusesList (retrieved from API) and a default Value, generates an Array of options conform to react-select
*/
const buildOptions = (): Array<SelectOption<number|void>> => {
const buildOptions = (): Array<SelectOption<number, string>> => {
const apiStatusesList = statusesList.map(status => {
return { value: status.id, label: status.label };
return { value: status.id, label: status.name };
});
return [defaultValue, ...apiStatusesList];
};
@ -42,17 +42,16 @@ export const StatusFilter: React.FC<StatusFilterProps> = ({ currentStatusIndex,
useEffect(() => {
StatusAPI.index()
.then((data) => {
const options = data.map(status => {
return { id: status.id, label: status.name };
});
setStatusesList(options);
setStatusesList(data);
}).catch(onError);
}, []);
// If currentStatusIndex is provided, set currentOption accordingly
// If currentStatusIndex is provided and match a status, set currentOption accordingly
useEffect(() => {
const selectedOption = statusesList.find((status) => status.id === currentStatusIndex);
setCurrentOption(selectedOption || defaultValue);
const selectedStatus = statusesList.find((status) => status.id === currentStatusIndex);
if (selectedStatus) {
setCurrentOption({ value: selectedStatus.id, label: selectedStatus.name });
}
}, [currentStatusIndex, statusesList]);
/**