diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-02-14 15:48:34 +0100 | 
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-02-14 15:54:54 +0100 | 
| commit | 1b34f85f0e3188861c6804666f02b4495cab033c (patch) | |
| tree | 0f26c9b73b8cc47c7136bad6167a0f18a08fd835 /src/components/CommentForm/CommentForm.tsx | |
| parent | 637350e4d152de1346857d645bda8443900ec6f4 (diff) | |
chore: improve comment form user experience
Diffstat (limited to 'src/components/CommentForm/CommentForm.tsx')
| -rw-r--r-- | src/components/CommentForm/CommentForm.tsx | 150 | 
1 files changed, 98 insertions, 52 deletions
| diff --git a/src/components/CommentForm/CommentForm.tsx b/src/components/CommentForm/CommentForm.tsx index 0ea3276..762bb75 100644 --- a/src/components/CommentForm/CommentForm.tsx +++ b/src/components/CommentForm/CommentForm.tsx @@ -1,68 +1,107 @@  import { ButtonSubmit } from '@components/Buttons';  import { Form, FormItem, Input, TextArea } from '@components/Form';  import Notice from '@components/Notice/Notice'; +import Spinner from '@components/Spinner/Spinner';  import { createComment } from '@services/graphql/mutations'; +import { NoticeType } from '@ts/types/app';  import { ForwardedRef, forwardRef, useState } from 'react';  import { useIntl } from 'react-intl';  import styles from './CommentForm.module.scss';  const CommentForm = ( -  { -    articleId, -    parentId = 0, -    isReply = false, -  }: { -    articleId: number; -    parentId?: number; -    isReply?: boolean; -  }, +  { articleId, parentId = 0 }: { articleId: number; parentId?: number },    ref: ForwardedRef<HTMLInputElement>  ) => {    const intl = useIntl(); -  const [name, setName] = useState(''); -  const [email, setEmail] = useState(''); -  const [website, setWebsite] = useState(''); -  const [message, setMessage] = useState(''); -  const [isSuccess, setIsSuccess] = useState(false); -  const [isApproved, setIsApproved] = useState(false); +  const [name, setName] = useState<string>(''); +  const [email, setEmail] = useState<string>(''); +  const [website, setWebsite] = useState<string>(''); +  const [comment, setComment] = useState<string>(''); +  const [isSubmitting, setIsSubmitting] = useState<boolean>(false); +  const [notice, setNotice] = useState<string>(); +  const [noticeType, setNoticeType] = useState<NoticeType>('success');    const resetForm = () => {      setName('');      setEmail('');      setWebsite(''); -    setMessage(''); +    setComment(''); +    setIsSubmitting(false);    }; -  const submitHandler = async (e: SubmitEvent) => { -    e.preventDefault(); +  const isEmptyString = (value: string): boolean => value.trim() === ''; +  const areRequiredFieldsSet = (): boolean => +    !isEmptyString(name) && !isEmptyString(email) && !isEmptyString(comment); -    if (name && email && message && articleId) { -      const data = { -        author: name, -        authorEmail: email, -        authorUrl: website, -        content: message, -        parent: parentId, -        commentOn: articleId, -        mutationId: 'createComment', -      }; -      const createdComment = await createComment(data); +  const sendComment = async () => { +    const data = { +      author: name, +      authorEmail: email, +      authorUrl: website, +      content: comment, +      parent: parentId, +      commentOn: articleId, +      mutationId: 'createComment', +    }; -      if (createdComment.success) setIsSuccess(true); -      if (isSuccess) { -        resetForm(); -        if (createdComment.comment?.approved) setIsApproved(true); +    const createdComment = await createComment(data); -        setTimeout(() => { -          setIsSuccess(false); -          setIsApproved(false); -        }, 8000); +    if (createdComment.success) { +      resetForm(); +      setNoticeType('success'); +      if (createdComment.comment?.approved) { +        setNotice( +          intl.formatMessage({ +            defaultMessage: 'Thanks for your comment!', +            description: 'CommentForm: success notice', +          }) +        ); +      } else { +        setNotice( +          intl.formatMessage({ +            defaultMessage: +              'Thanks for your comment! It is now awaiting moderation.', +            description: 'CommentForm: success notice but awaiting moderation', +          }) +        );        } + +      setTimeout(() => { +        setNotice(undefined); +      }, 10000); +    } else { +      setNoticeType('error'); +      setNotice( +        intl.formatMessage({ +          defaultMessage: +            'An unexpected error happened. Comment cannot be submitted.', +          description: 'CommentForm: error notice', +        }) +      ); +    } +  }; + +  const submitHandler = async (e: SubmitEvent) => { +    e.preventDefault(); +    setNotice(undefined); +    setIsSubmitting(true); + +    if (areRequiredFieldsSet()) { +      sendComment();      } else { -      setIsSuccess(false); +      setIsSubmitting(false); +      setNoticeType('warning'); +      setNotice( +        intl.formatMessage({ +          defaultMessage: +            'Some required fields are empty. Comment cannot be submitted.', +          description: 'CommentForm: missing required fields', +        }) +      );      }    }; +  const isReply = parentId !== 0;    const wrapperClasses = `${styles.wrapper} ${      isReply ? styles['wrapper--reply'] : ''    }`; @@ -72,7 +111,7 @@ const CommentForm = (        <h2 className={styles.title}>          {intl.formatMessage({            defaultMessage: 'Leave a comment', -          description: 'CommentForm: form title', +          description: 'CommentForm: Form title',          })}        </h2>        <Form @@ -97,6 +136,7 @@ const CommentForm = (            <Input              id="commenter-email"              name="commenter-email" +            type="email"              label={intl.formatMessage({                defaultMessage: 'Email',                description: 'CommentForm: Email field label', @@ -120,18 +160,24 @@ const CommentForm = (          </FormItem>          <FormItem>            <TextArea -            id="commenter-message" -            name="commenter-message" +            id="commenter-comment" +            name="commenter-comment"              label={intl.formatMessage({                defaultMessage: 'Comment',                description: 'CommentForm: Comment field label',              })} -            value={message} -            setValue={setMessage} +            value={comment} +            setValue={setComment}              required={true}            />          </FormItem>          <FormItem> +          <noscript> +            {intl.formatMessage({ +              defaultMessage: 'Javascript is required to post a comment.', +              description: 'CommentForm: noscript tag', +            })} +          </noscript>            <ButtonSubmit>              {intl.formatMessage({                defaultMessage: 'Send', @@ -139,16 +185,16 @@ const CommentForm = (              })}            </ButtonSubmit>          </FormItem> -        {isSuccess && !isApproved && ( -          <Notice type="success"> -            {intl.formatMessage({ -              defaultMessage: -                'Thanks for your comment! It is now awaiting moderation.', -              description: 'CommentForm: Comment sent success message', -            })} -          </Notice> -        )}        </Form> +      {isSubmitting && ( +        <Spinner +          message={intl.formatMessage({ +            defaultMessage: 'Submitting...', +            description: 'CommentForm: submitting message', +          })} +        /> +      )} +      {notice && <Notice type={noticeType}>{notice}</Notice>}      </div>    );  }; | 
