Contact Form

  • + 0 comments

    Wont fulfill all the test cases, beacuse of the change in state variable's name, but the best way to write Form validations in Live projects.

    import { useState } from "react";
    import "./App.css";
    
    import "h8k-components";
    
    function App() {
      const [formState, setFormState] = useState({
        name: "",
        email: "",
        message: ""
    
      })
      const [isDirty, setIsDirty] = useState({})
      const [errors, setErrors] = useState({})
      const [isLoading, setIsLoading] = useState(false)
      const [isDataSubmitted, setIsDataSubmitted] = useState(false)
      const [edgeCaseErrorMessage, setEdgeCaseErrorMessage] = useState(false)
      const [payload, setPayload] = useState(null)
    
      const _handleChange = (e) => {
        const { name, value } = e.target
        const newFormState = { ...formState }
        const newIsDirty = { ...isDirty }
        newFormState[name] = value
        newIsDirty[name] = true
        setFormState(newFormState)
        setIsDirty(newIsDirty)
    
        _validateFields(newFormState, newIsDirty)
      }
    
      const _validateFields = (newFormState, newIsDirty) => {
        return new Promise((resolve) => {
          const newErrors = { ...errors }
          let isFormValid = true
    
          Object.keys(newFormState).forEach((key, _) => {
            if (newIsDirty[key]) {
              switch (key) {
                case "email": if (!newFormState[key]?.length) {
                  newErrors[key] = "*Required"
                  isFormValid = false
                } else {
                  const regExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
                  if (new RegExp(regExp).test(newFormState[key])) {
                    newErrors[key] = null
                    delete newIsDirty[key]
                  } else {
                    newErrors[key] = "*Invalid Email"
                    isFormValid = false
                  }
    
                };
                  break;
                default: if (!newFormState[key]?.length) {
                  newErrors[key] = "*Required"
                  isFormValid = false
                } else {
                  newErrors[key] = null
                  delete newIsDirty[key]
                }; break;
              }
            }
    
          })
    
          setIsDirty(newIsDirty)
          setErrors(newErrors)
          resolve(isFormValid)
        })
      }
    
      const handleSubmit = async (e) => {
        e.preventDefault();
        // TODO: Add logic to validate inputs and display submitted data
    
        const newIsDirty = {
          name: true,
          email: true,
          message: true
        }
        setIsLoading(true)
        const isValid = await _validateFields(formState, newIsDirty)
    
        if (!isValid) {
          setIsLoading(false)
          setEdgeCaseErrorMessage(true)
          return
        } else {
          console.log("payload", formState)
          setPayload(formState)
          setIsDataSubmitted(true)
          _resetData()
        }
        setIsLoading(false)
      };
    
      const _resetData = () => {
        setFormState({
          name: "",
          email: "",
          message: ""
        })
        setIsDirty({})
        setErrors({})
        setIsLoading(false)
        setIsDataSubmitted(false)
        setEdgeCaseErrorMessage(false)
      }
    
      return (
        <>
          <h8k-navbar header="Contact Form"></h8k-navbar>
          <div className="App">
            <h1>Contact Form</h1>
            <form onSubmit={handleSubmit}>
              <input
                type="text"
                name="name"
                value={formState.name}
                onChange={(e) => _handleChange(e)}
                placeholder="Name"
                data-testid="name-input"
              />
              {isDirty.name ? <small style={{ color: "red" }}>{errors.name}</small> : null}
              <input
                type="email"
                name="email"
                value={formState.email}
                onChange={(e) => _handleChange(e)}
                placeholder="Email"
                data-testid="email-input"
              />
              {isDirty.email ? <small style={{ color: "red" }}>{errors.email}</small> : null}
              <textarea
                value={formState.message}
                name="message"
                onChange={(e) => _handleChange(e)}
                placeholder="Message"
                data-testid="message-input"
              />
              {isDirty.message ? <small style={{ color: "red" }}>{errors.message}</small> : null}
              <button type="submit" data-testid="submit-button" disabled={isLoading}>
                Submit
              </button>
            </form>
            {edgeCaseErrorMessage && (
              <p data-testid="error-message" className="error">
                All fields are required
              </p>
            )}
            {payload !== null && (
              <div data-testid="submitted-data" className="submitted-data">
                <h2>Submitted Information</h2>
                <p>
                  <strong>Name:</strong> {payload.name}
                </p>
                <p>
                  <strong>Email:</strong> {payload.email}
                </p>
                <p>
                  <strong>Message:</strong> {payload.message}
                </p>
              </div>
            )}
          </div>
        </>
      );
    }
    
    export default App;