Skip to content

Commit

Permalink
Ajuste no useError e emissão dos errors de mídia e texto. (#573)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
DominMFD authored Sep 5, 2024
1 parent b24640c commit f8e8648
Show file tree
Hide file tree
Showing 21 changed files with 441 additions and 227 deletions.
14 changes: 9 additions & 5 deletions src/components/FeedbackError/FeedbackError.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ import FeedbackError from './FeedbackError';
import { TFeedbackErrorProps } from './FeedbackError.type';

export const FeedbackErrorComponent: Story<TFeedbackErrorProps> = (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 <FeedbackError />;
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/FeedbackError/FeedbackError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function FeedbackError(): ReactNode {
variants={animationVariants}
>
{Object.values(errors).map((error) => (
<li key={error.id}>{error.message}</li>
<li key={error.message}>{error.message}</li>
))}
</motion.ul>
</AnimatePresence>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <FeedbackErrorMobile />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ describe('ComposeEditor', () => {
await userEvent.type(inputElement, testInputValue);

expect(inputElement).toHaveValue(testInputValue);
expect(mockOnChange).toHaveBeenCalledWith(testInputValue);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,58 +1,83 @@
import { ChangeEvent, ReactNode, useCallback, useState } from 'react';

import omit from 'lodash.omit';
import { nanoid } from 'nanoid';

import {
PostMode,
TextValidator,
} from '~services/api/social-media/social-media.types.ts';
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<ErrorMapText>({});

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<TextErrorMap>({});
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]
);

Expand All @@ -71,6 +96,7 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode {
}
return socialLimits;
}, [socialMedias]);

const getGreatestLimitsSocial = useCallback(() => {
const socialLimits = getBiggestLimitBySocial();
const maxLimit = socialLimits.reduce(
Expand All @@ -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<HTMLTextAreaElement>): 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 => {
Expand All @@ -113,7 +127,8 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode {
return (
<div className={scss.inputContainer}>
<textarea
onChange={props.onChangePost ?? handleInputChange}
className={scss.textArea}
onChange={handleInputChange}
placeholder="Digite algo aqui..."
value={props.value ?? inputValue}
/>
Expand All @@ -124,8 +139,7 @@ function ComposerEditor(props: ComposerEditorProps): ReactNode {
svg={null}
value={props.value ?? inputValue}
/>

{!props.postMode && (
{hasPostMode && (
<div className={scss.characterLimitWrapper}>
{socialLimits.socialLimits.map((postMode) => (
<CharacterLimit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
import { ChangeEvent, PropsWithChildren } from 'react';

import { PostMode } from '~services/api/social-media/social-media.types';
import { MainComposerChildrens } from '../MainComposerBase/MainComposerBase.type';

export type TInputChange = (newText: string) => void;
export type TInputPostChange = (
event: ChangeEvent<HTMLTextAreaElement>
) => void;
export type InputChange = (event: ChangeEvent<HTMLTextAreaElement>) => void;

export type ComposerEditorProps = PropsWithChildren<{
accountId?: string;
currentMaxLimit?: number;
onChange?: TInputChange;
onChangePost?: TInputPostChange;
onError?: (error: ErrorMapText) => void;
postMode?: PostMode;
value?: string;
}>;

export type ErrorText = {
accountId: string | undefined;
message: string;
postModeId: string | undefined;
};

export type ErrorMapText = Record<string, ErrorText[]>;
export type ComposerEditorProps = MainComposerChildrens &
PropsWithChildren<{
currentMaxLimit?: number;
onChange?: InputChange;
value?: string;
}>;

export type HigherLimitSocial = {
limit: number;
socialMediaId: string;
};

export enum TEXT_ERRORS {
MAX_LENGTH_EXCEED = 1,
}

export type TextErrorMap = Partial<Record<TEXT_ERRORS, string>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { TextValidators } from './textValidators';

import { ComposerEditorProps, TEXT_ERRORS } from '../../ComposerEditor.types';
import {
Payload,
Validator,
ValidatorError,
Validators,
} from './textValidator.types';

export const textValidator = ({
text,
validatorRules,
}: Validator): Validators => {
const textValidators = new TextValidators(text);

return {
textLength: (props: ComposerEditorProps): ValidatorError => {
const isTextTooLong = !textValidators.textLength(
validatorRules.maxLength
);

const payload: Payload = {
type: TEXT_ERRORS.MAX_LENGTH_EXCEED,
};
if (isTextTooLong && props.accountId && props.postMode) {
payload.error = {
accountId: props.accountId,
message: `Account ${props.accountId} on ${props.postMode.id} type of post overflowed the character limit`,
postModeId: props.postMode.id,
};
}
return payload;
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { TextValidator } from '~services/api/social-media/social-media.types';

import { TextValidators } from './textValidators';

import { Error } from '~components/MainComposer/components/MainComposerBase/MainComposerBase.type';

import { ComposerEditorProps, TEXT_ERRORS } from '../../ComposerEditor.types';

export type Validators = Record<
keyof typeof TextValidators.prototype,
(props: ComposerEditorProps) => ValidatorError
>;

export type Validator = {
text: string;
validatorRules: TextValidator;
};

export type ValidatorError = {
error?: Error;
type: TEXT_ERRORS;
};

export type Payload = {
error?: Error;
type: TEXT_ERRORS;
};
Loading

0 comments on commit f8e8648

Please sign in to comment.