From 81b1e0e05919eb368a66aef47adcf7738af76f29 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Fri, 29 Sep 2023 11:47:06 +0200
Subject: refactor(components): rewrite Spinner component

* Message should be set as children
* Default message is no longer available (depending on use case, the
consumer might prefer aria-label instead)
* It is now possible to define the message position
---
 .../organisms/forms/contact-form/contact-form.tsx  | 115 ++++++++++++---------
 1 file changed, 64 insertions(+), 51 deletions(-)

(limited to 'src/components/organisms/forms/contact-form/contact-form.tsx')

diff --git a/src/components/organisms/forms/contact-form/contact-form.tsx b/src/components/organisms/forms/contact-form/contact-form.tsx
index 6208b94..89fd331 100644
--- a/src/components/organisms/forms/contact-form/contact-form.tsx
+++ b/src/components/organisms/forms/contact-form/contact-form.tsx
@@ -1,4 +1,13 @@
-import { ChangeEvent, FC, FormEvent, ReactNode, useState } from 'react';
+/* eslint-disable max-statements */
+import {
+  type ChangeEvent,
+  type FC,
+  type FormEvent,
+  type ReactNode,
+  useState,
+  useCallback,
+  useMemo,
+} from 'react';
 import { useIntl } from 'react-intl';
 import { Button, Form, Input, Label, Spinner, TextArea } from '../../../atoms';
 import { LabelledField } from '../../../molecules';
@@ -38,51 +47,54 @@ export const ContactForm: FC<ContactFormProps> = ({
 }) => {
   const formClass = `${styles.form} ${className}`;
   const intl = useIntl();
-  const emptyForm: ContactFormData = {
-    email: '',
-    message: '',
-    name: '',
-    object: '',
-  };
+  const emptyForm: ContactFormData = useMemo(() => {
+    return {
+      email: '',
+      message: '',
+      name: '',
+      object: '',
+    };
+  }, []);
   const [data, setData] = useState(emptyForm);
   const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
 
   /**
    * Reset all the form fields.
    */
-  const resetForm = () => {
+  const resetForm = useCallback(() => {
     setData(emptyForm);
     setIsSubmitting(false);
-  };
+  }, [emptyForm]);
 
-  const updateForm = (
-    e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
-  ) => {
-    switch (e.target.name) {
-      case 'email':
-        setData((prevData) => {
-          return { ...prevData, email: e.target.value };
-        });
-        break;
-      case 'message':
-        setData((prevData) => {
-          return { ...prevData, message: e.target.value };
-        });
-        break;
-      case 'name':
-        setData((prevData) => {
-          return { ...prevData, name: e.target.value };
-        });
-        break;
-      case 'object':
-        setData((prevData) => {
-          return { ...prevData, object: e.target.value };
-        });
-        break;
-      default:
-        break;
-    }
-  };
+  const updateForm = useCallback(
+    (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
+      switch (e.target.name) {
+        case 'email':
+          setData((prevData) => {
+            return { ...prevData, email: e.target.value };
+          });
+          break;
+        case 'message':
+          setData((prevData) => {
+            return { ...prevData, message: e.target.value };
+          });
+          break;
+        case 'name':
+          setData((prevData) => {
+            return { ...prevData, name: e.target.value };
+          });
+          break;
+        case 'object':
+          setData((prevData) => {
+            return { ...prevData, object: e.target.value };
+          });
+          break;
+        default:
+          break;
+      }
+    },
+    []
+  );
 
   const formName = intl.formatMessage({
     defaultMessage: 'Contact form',
@@ -114,11 +126,20 @@ export const ContactForm: FC<ContactFormProps> = ({
     id: 'yN5P+m',
   });
 
-  const submitHandler = async (e: FormEvent) => {
-    e.preventDefault();
-    setIsSubmitting(true);
-    sendMail(data, resetForm).then(() => setIsSubmitting(false));
-  };
+  const loadingMsg = intl.formatMessage({
+    defaultMessage: 'Sending mail...',
+    description: 'ContactForm: spinner message on submit',
+    id: 'xaqaYQ',
+  });
+
+  const submitHandler = useCallback(
+    async (e: FormEvent) => {
+      e.preventDefault();
+      setIsSubmitting(true);
+      await sendMail(data, resetForm).then(() => setIsSubmitting(false));
+    },
+    [data, resetForm, sendMail]
+  );
 
   return (
     <Form aria-label={formName} className={formClass} onSubmit={submitHandler}>
@@ -195,15 +216,7 @@ export const ContactForm: FC<ContactFormProps> = ({
           id: 'VkAnvv',
         })}
       </Button>
-      {isSubmitting && (
-        <Spinner
-          message={intl.formatMessage({
-            defaultMessage: 'Sending mail...',
-            description: 'ContactForm: spinner message on submit',
-            id: 'xaqaYQ',
-          })}
-        />
-      )}
+      {isSubmitting ? <Spinner>{loadingMsg}</Spinner> : null}
       {Notice}
     </Form>
   );
-- 
cgit v1.2.3

