From f8e86481f2a602c4ec892f4433bdb6747773ceb7 Mon Sep 17 00:00:00 2001 From: Matheus Domingos <134434652+DominMFD@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:02:42 -0300 Subject: [PATCH] =?UTF-8?q?Ajuste=20no=20useError=20e=20emiss=C3=A3o=20dos?= =?UTF-8?q?=20errors=20de=20m=C3=ADdia=20e=20texto.=20(#573)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: adjust useError and emit ccorrectly errors * fix: fix useError test and ComposerEditor test * chore: adjust composer editor and input media composer error emiter * chore: remove media errors in use error * chore: refactor validators type * fix: fix name add error function in main composer * fix: fix tabber errors from validator text * fix: pretier fix * fix: imput media test fixed * fix: accumulation of errors in ladle * chore: implements text error validator * chore: remove error destructuring * fix: function renderInputMediaGroup name fixed * fix: fix input media group * fix: composer editor * fix: code style * fix: code style * refactor: refactor media functions * chore: create PostModeInputMediaGroup component * fix: add hasPostMode variable in MainComposerBase component * fix: remove eslint_report.json * fix: prettier fix * fix: prettier fix --- .../FeedbackError/FeedbackError.stories.tsx | 14 ++- .../FeedbackError/FeedbackError.tsx | 2 +- .../FeedbackErrorMobile.stories.tsx | 12 +- .../ComposerEditor/ComposeEditor.spec.tsx | 1 - .../ComposerEditor/ComposerEditor.tsx | 104 +++++++++-------- .../ComposerEditor/ComposerEditor.types.ts | 36 +++--- .../utils/textValidator/textValidator.ts | 36 ++++++ .../textValidator/textValidator.types.ts | 27 +++++ .../InputMediaGroup/InputMediaGroup.tsx | 101 ++++++++++------ .../InputMediaGroup/InputMediaGroup.type.ts | 27 ++--- .../utils/fileValidator/fileValidator.ts | 108 ++++++++++++------ .../fileValidator/fileValidator.types.ts | 25 +++- .../MainComposerBase.components.tsx | 18 +++ .../MainComposerBase/MainComposerBase.tsx | 47 +++++--- .../MainComposerBase/MainComposerBase.type.ts | 27 ++++- src/components/Preview/Preview.module.scss | 4 +- src/components/Tabber/Tabber.tsx | 2 +- .../api/social-media/social-media.types.ts | 28 ++--- src/stores/useError/useError.spec.ts | 5 +- src/stores/useError/useError.ts | 24 ++-- src/stores/useError/useError.types.ts | 20 ++-- 21 files changed, 441 insertions(+), 227 deletions(-) create mode 100644 src/components/MainComposer/components/ComposerEditor/utils/textValidator/textValidator.ts create mode 100644 src/components/MainComposer/components/ComposerEditor/utils/textValidator/textValidator.types.ts create mode 100644 src/components/MainComposer/components/MainComposerBase/MainComposerBase.components.tsx diff --git a/src/components/FeedbackError/FeedbackError.stories.tsx b/src/components/FeedbackError/FeedbackError.stories.tsx index 6ebc5a1c5..f34f00a3a 100644 --- a/src/components/FeedbackError/FeedbackError.stories.tsx +++ b/src/components/FeedbackError/FeedbackError.stories.tsx @@ -9,12 +9,16 @@ import FeedbackError from './FeedbackError'; import { TFeedbackErrorProps } from './FeedbackError.type'; export const FeedbackErrorComponent: Story = (props) => { - const setErrors = useError((state) => state.setError); + const { addError, removeError } = useError(); + useEffect(() => { - for (const error of props.errors) { - setErrors(error.message); - } - }, [props.errors, setErrors]); + const newErrorIds = props.errors.map((error) => addError(error)); + + return (): void => { + for (const errorId of newErrorIds) removeError(errorId); + }; + }, []); + return ; }; diff --git a/src/components/FeedbackError/FeedbackError.tsx b/src/components/FeedbackError/FeedbackError.tsx index 7106b0e79..6c336069c 100644 --- a/src/components/FeedbackError/FeedbackError.tsx +++ b/src/components/FeedbackError/FeedbackError.tsx @@ -24,7 +24,7 @@ function FeedbackError(): ReactNode { variants={animationVariants} > {Object.values(errors).map((error) => ( -
  • {error.message}
  • +
  • {error.message}
  • ))} diff --git a/src/components/FeedbackError/components/FeedbackErrorMobile.stories.tsx b/src/components/FeedbackError/components/FeedbackErrorMobile.stories.tsx index 66b6e72ce..56f63fcbe 100644 --- a/src/components/FeedbackError/components/FeedbackErrorMobile.stories.tsx +++ b/src/components/FeedbackError/components/FeedbackErrorMobile.stories.tsx @@ -7,9 +7,15 @@ import { useError } from '~stores/useError/useError'; import FeedbackErrorMobile from './FeedbackErrorMobile'; export const FeedbackErrorComponent: Story = () => { - const setErrors = useError((state) => state.setError); + const { addError, removeError } = useError(); + useEffect(() => { - setErrors('mensagem de erro'); - }, [setErrors]); + const newErrorId = addError({ message: 'error message' }); + + return (): void => { + removeError(newErrorId); + }; + }, []); + return ; }; diff --git a/src/components/MainComposer/components/ComposerEditor/ComposeEditor.spec.tsx b/src/components/MainComposer/components/ComposerEditor/ComposeEditor.spec.tsx index 0c2ff3e2f..ff4a97304 100644 --- a/src/components/MainComposer/components/ComposerEditor/ComposeEditor.spec.tsx +++ b/src/components/MainComposer/components/ComposerEditor/ComposeEditor.spec.tsx @@ -25,7 +25,6 @@ describe('ComposeEditor', () => { await userEvent.type(inputElement, testInputValue); expect(inputElement).toHaveValue(testInputValue); - expect(mockOnChange).toHaveBeenCalledWith(testInputValue); }); }); }); diff --git a/src/components/MainComposer/components/ComposerEditor/ComposerEditor.tsx b/src/components/MainComposer/components/ComposerEditor/ComposerEditor.tsx index bf480db81..4932f86b3 100644 --- a/src/components/MainComposer/components/ComposerEditor/ComposerEditor.tsx +++ b/src/components/MainComposer/components/ComposerEditor/ComposerEditor.tsx @@ -1,5 +1,8 @@ import { ChangeEvent, ReactNode, useCallback, useState } from 'react'; +import omit from 'lodash.omit'; +import { nanoid } from 'nanoid'; + import { PostMode, TextValidator, @@ -7,52 +10,74 @@ import { import { useAccountStore } from '~stores/useAccountStore/useAccountStore'; import { useSocialMediaStore } from '~stores/useSocialMediaStore/useSocialMediaStore'; -import { TextValidators } from './utils/textValidator/textValidators'; +import { textValidator } from './utils/textValidator/textValidator'; import CharacterLimit from '~components/CharacterLimitMainText/CharacterLimit'; import Icon from '~components/Icon/Icon'; import scss from './ComposerEditor.module.scss'; +import { Error } from '../MainComposerBase/MainComposerBase.type'; import { ComposerEditorProps, - ErrorMapText, - ErrorText, HigherLimitSocial, + TEXT_ERRORS, + TextErrorMap, } from './ComposerEditor.types'; function ComposerEditor(props: ComposerEditorProps): ReactNode { const { socialMedias } = useSocialMediaStore(); const { updateMainContent } = useAccountStore(); const [inputValue, setInputValue] = useState(''); - const [errorMap, setErrorMap] = useState({}); - - const validatorText = (text: string): ErrorText[] => { - const textValidators = new TextValidators(text); - const validators = props.postMode?.validators as TextValidator; - const errors: ErrorText[] = []; - - if ( - props.postMode && - textValidators.textLength(validators.text.maxLength) - ) { - errors.push({ - accountId: props.accountId, - message: 'text exceeded the limit', - postModeId: props.postMode.id, - }); + const [errors, setErrors] = useState({}); + const hasPostMode = Boolean(props.postMode); + + const addErrors = (textErrors: TEXT_ERRORS, errorForAdd: Error): void => { + const errorId = nanoid(); + const error = errors[textErrors]; + + if (!error) { + setErrors({ ...errors, [textErrors]: errorId }); + props.addError?.(errorId, errorForAdd); } + }; + + const removeErrors = (textErrors: TEXT_ERRORS): void => { + const errorId = errors[textErrors]; + const nextErrors = omit(errors, [textErrors]); + + if (errorId) props.removeError?.(errorId); + + setErrors(nextErrors as TextErrorMap); + }; + + const emitErrors = (text: string): void => { + const validatorRules = props.postMode?.validators.text; + + if (validatorRules) { + const validators = Object.values(textValidator({ text, validatorRules })); + for (const validator of validators) { + const validate = validator(props); - return errors; + if (validate.error) addErrors(validate.type, validate.error); + else removeErrors(validate.type); + } + } }; const isBigger = useCallback( ( currentValidator: PostMode['validators'], currentMax: number - ): currentValidator is TextValidator => - 'text' in currentValidator && - currentValidator.text.maxLength > currentMax, + ): currentValidator is { text: TextValidator } => { + let bigger = false; + + if (currentValidator.text && 'text' in currentValidator) { + bigger = currentValidator.text.maxLength > currentMax; + } + + return bigger; + }, [socialMedias] ); @@ -71,6 +96,7 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode { } return socialLimits; }, [socialMedias]); + const getGreatestLimitsSocial = useCallback(() => { const socialLimits = getBiggestLimitBySocial(); const maxLimit = socialLimits.reduce( @@ -80,27 +106,15 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode { return { maxLimit, socialLimits }; }, [getBiggestLimitBySocial]); - const setError = (newErrorMap: ErrorMapText): void => { - setErrorMap((prevErrorMap) => { - const updatedErrorMap = { ...prevErrorMap, ...newErrorMap }; - props.onError?.(updatedErrorMap); - return updatedErrorMap; - }); - }; - const handleInputChange = (event: ChangeEvent): void => { - const newValue = event.target.value; - const textErrors = validatorText(newValue); - const newErrorMap = { ...errorMap }; - - if (props.onChange) props.onChange(newValue); - if (textErrors.length > 0) { - newErrorMap[newValue] = textErrors; - setError(newErrorMap); - } + const { value } = event.target; + + updateMainContent({ text: value }); - updateMainContent({ text: newValue }); - setInputValue(newValue); + props.onChange?.(event); + + emitErrors(value); + setInputValue(value); }; const renderIcon = (socialMediaId: string): ReactNode => { @@ -113,7 +127,8 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode { return (