import { type FC, useCallback, useId } from 'react'; import { useIntl } from 'react-intl'; import type { Nullable } from '../../../../types'; import { type FormSubmitHandler, useForm, type FormSubmitStatus, type FormSubmitMessages, } from '../../../../utils/hooks'; import { Button, Form, type FormProps, Spinner, Input, TextArea, Label, Notice, } from '../../../atoms'; import { LabelledField } from '../../../molecules'; import styles from './comment-form.module.scss'; export type CommentFormData = { author: string; comment: string; email: string; parentId?: number; website?: string; }; export type CommentFormSubmit = FormSubmitHandler; export type CommentFormProps = Omit & { /** * A callback function to handle form submit. */ onSubmit?: CommentFormSubmit; /** * The comment parent id. */ parentId?: number; }; export const CommentForm: FC = ({ className = '', onSubmit, parentId, ...props }) => { const formId = useId(); const formClass = `${styles.form} ${className}`; const intl = useIntl(); const { messages, submit, submitStatus, update, values } = useForm({ initialValues: /* The order matter: it will be reused to generate the fields in the right * order. */ { parentId, author: '', email: '', website: '', comment: '', }, submitHandler: onSubmit, }); const renderFields = useCallback(() => { const entries = Object.entries(values) as [ keyof CommentFormData, CommentFormData[keyof CommentFormData], ][]; const labels: Record, string> = { author: intl.formatMessage({ defaultMessage: 'Name:', description: 'CommentForm: name label', id: 'ZIrTee', }), comment: intl.formatMessage({ defaultMessage: 'Comment:', description: 'CommentForm: comment label', id: 'A8hGaK', }), email: intl.formatMessage({ defaultMessage: 'Email:', description: 'CommentForm: email label', id: 'Bh7z5v', }), website: intl.formatMessage({ defaultMessage: 'Website:', description: 'CommentForm: website label', id: 'u41qSk', }), }; return entries.map(([field, value]) => { const isRequired = field !== 'website'; const inputType = field === 'email' ? 'email' : 'text'; const fieldId = `${formId}-${field}`; return field === 'parentId' ? null : ( ) : ( ) } key={field} label={ } /> ); }); }, [values, formId, intl, update]); const btnLabel = intl.formatMessage({ defaultMessage: 'Publish', description: 'CommentForm: submit button', id: 'OL0Yzx', }); const loadingMsg = intl.formatMessage({ defaultMessage: 'Submitting...', description: 'CommentForm: spinner message on submit', id: 'IY5ew6', }); const renderNotice = useCallback( ( currentStatus: FormSubmitStatus, msg: Nullable> ) => { switch (currentStatus) { case 'FAILED': return msg?.error ? ( {msg.error} ) : null; case 'PENDING': return ( {loadingMsg} ); case 'SUCCEEDED': return msg?.success ? ( {msg.success} ) : null; default: return null; } }, [loadingMsg] ); return (
{renderFields()} {renderNotice(submitStatus, messages)}
); };