tracking-code-which-will-go-to-the-HEAD FLAMEAL Documentation client/src/components/TransferForm/useForm.js

Source

client/src/components/TransferForm/useForm.js

import { useState, useEffect, useContext } from "react";
import SendData from "../../Web3/sendData.js";
import { fetchList } from "../List/useList";
import { fetchMetaState } from "../../Web3/getWeb3.js";
import { UserContext } from "../../context/UserContext.js";
import { updateInventory } from "../../api/actions.js";
import getData from "../../Web3/getData.js";

/**
 * The function the handle the logic of the transfer form and the validation of the data before attepmting to submit the transaction to the blockchain
 * @category Transfer
 * @function useForm
 * @borrows {@link SendData} to attept to submit the transaction to the blockchain
 * @param {Function} callback - the callback function used to fetch the submission state from the parent component
 * @param {Function} validate - the function to validate the inputs
 * @returns {Object} the functions required by the TransferFill component
 */
const useForm = (callback, validate) => {
  const [state, dispatch] = useContext(UserContext);
  //declaring a variable to hold the state of blockchain transfer errors
  let transferError = null;
  //hook to hold the values of the form
  const [values, setValues] = useState({
    address: "",
    comments: "",
    itemsList: null,
  });
  //hook to hold the erros from the validation function
  const [errors, setErrors] = useState({});
  //hook to hold the state of submission
  const [isSubmitting, setIsSubmitting] = useState(false);
  //Function to handle the change of a field and update the value to the one on the list
  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues({
      ...values,
      [name]: value,
    });
  };
  //Function to fetch the list of items from the List component
  const fetchItemList = () => {
    const fetchedItems = fetchList();
    console.log("items fetched", fetchedItems);
    setValues({
      ...values,
      itemsList: fetchedItems,
    });
  };
  //Function to handle the submition of the list
  const handleSubmit = (e) => {
    //stop refresing the form as soon as the submit button is clicked (to prevent purging the values before validation)
    e.preventDefault();
    //update the state of the errors with the erros returned by the validation function
    setErrors(validate(values));
    //put the form in submission state
    setIsSubmitting(true);
  };
  //function to remove the items sent from the list of goods
  const removeSentItems = (isUnion = false) => {
    //total items in the inventory
    const totalItems = state.inventory;
    //items sent from the transfer list
    const transferItems = values.itemsList;
    //the remaining items list created by intersecting the total items list with the items sent from the transfer list
    const remainingItems = totalItems.filter(
      (
        (set) => (a) =>
          isUnion === set.has(a.itemName)
      )(new Set(transferItems.map((b) => b.itemName)))
    );
    //call the api action to update the inventory
    updateInventory(remainingItems, state.address);
  };

  //hook to be called every time the errors are changed
  useEffect(() => {
    //if there are errors, attept to get the web3 metamask instance to log in the user
    if (Object.keys(errors).length === 0) getData();
    //test if the error array is empty and the form is submitting
    if (Object.keys(errors).length === 0 && isSubmitting) {
      //Preparing the payload by creating a new object without the address
      let payload = {
        comments: values.comments,
        itemsList: values.itemsList,
      };
      //Transform the object into a json strig
      payload = JSON.stringify(payload);
      //Send the json string to the SendData function
      transferError = SendData(values.address, payload);
      console.log("values attached to contract", JSON.stringify(values)); //!SHOULD BE REMOVED IN FINAL
      console.log("TRANSFER ERRORRR", transferError); //!SHOULD BE REMOVED IN FINAL
      // console.log("SHOULD KEEP", inFirstOnly(state.inventory, values.items));
      removeSentItems();
      //constant to hold a bool state of the MetaMask connection
      const metaState = fetchMetaState();
      if (!transferError) {
        //if there are no transfer errors the callback function is called
        //and the form is refreshed as the transfer is considered succesfull

        callback();
      } else if (metaState) {
        //if there are transfer errors while MetaMask is connected the errors are updated
        setErrors({
          ...errors,
          itemsList: "TRANSFER FAILED: The address was not found",
        });
      } else if (!metaState) {
        //if there are transfer errors while MetaMask is NOT connected the errors are updated
        setErrors({
          ...errors,
          itemsList: "ERROR: Please login with metamask",
        });
      }
    }
  }, [errors]);

  return { handleChange, handleSubmit, fetchItemList, values, errors };
};

export default useForm;