match-curriculum / react-todo-app-starter-files / src / components / ClassModal.js
ClassModal.js
Raw
import { motion, AnimatePresence } from 'framer-motion';
import React, { useEffect, useState } from 'react';
import toast from 'react-hot-toast';
import { MdOutlineClose } from 'react-icons/md';
import { useDispatch } from 'react-redux';
import { v4 as uuid } from 'uuid';
import { addTodo, updateTodo } from '../slices/todoSlice';
import styles from '../styles/modules/modal.module.scss';
import Button from './Button';

const dropIn = {
  hidden: {
    opacity: 0,
    transform: 'scale(0.9)',
  },
  visible: {
    transform: 'scale(1)',
    opacity: 1,
    transition: {
      duration: 0.1,
      type: 'spring',
      damping: 25,
      stiffness: 500,
    },
  },
  exit: {
    transform: 'scale(0.9)',
    opacity: 0,
  },
};

function ClassModal({ type, modalOpen, setModalOpen, todo }) {
  const [title, setTitle] = useState('');
  const [tasktype, setTaskType] = useState('');
  const [status, setStatus] = useState('incomplete');

  useEffect(() => {
    if (type === 'update' && todo) {
      setTitle(todo.title);
      setTaskType(todo.tasktype);
      setStatus(todo.status);
    } else {
      // default
      setTitle('');
      setTaskType('');
      setStatus('incomplete');
    }
  }, [type, todo, modalOpen]);

  const dispatch = useDispatch();
  // handle submission functionality
  const handleSubmit = (e) => {
    // for help, want to deal with GPT API eventually
    e.preventDefault();
    if (title === '') {
      toast.error('Please enter a title.');
      return;
    }
    if (tasktype === '') {
      toast.error('Please enter a tasktype.');
      return;
    }
    if (title && status && tasktype) {
      if (type === 'add') {
        dispatch(
          addTodo({
            id: uuid(),
            title,
            tasktype,
            status,
            time: new Date().toLocaleString(),
          })
        );
        toast.success('Task Added Successfully');
      }
      if (type === 'update') {
        // update
        if (
          todo.title !== title ||
          todo.tasktype !== tasktype ||
          todo.status !== status
        ) {
          dispatch(updateTodo({ ...todo, title, tasktype, status }));
        } else {
          toast.error('No changes made.');
          return;
        }
      }
      setModalOpen(false);
    }
  };
  return (
    <div>
      <AnimatePresence>
        {modalOpen && (
          <motion.div
            className={styles.wrapper}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
          >
            <motion.div
              className={styles.container}
              variants={dropIn}
              initial="hidden"
              animate="visible"
              exit="exit"
            >
              <motion.div
                className={styles.closeButton}
                onClick={() => setModalOpen(false)}
                onKeyDown={() => setModalOpen(false)}
                tabIndex={0}
                role="button"
                initial={{ top: 40, opacity: 0 }}
                animate={{ top: -10, opacity: 1 }}
                exit={{ top: 40, opacity: 0 }}
              >
                <MdOutlineClose />
              </motion.div>
              <form className={styles.form} onSubmit={(e) => handleSubmit(e)}>
                <h1 className={styles.formTitle}>
                  {type === 'update' ? 'Update' : 'Add'} Task
                </h1>
                <label htmlFor="taskinfo">
                  Title
                  <input
                    type="text"
                    id="title"
                    value={title}
                    onChange={(e) => setTitle(e.target.value)}
                  />
                </label>
                <label htmlFor="typeTask">
                  Type of Task
                  <select
                    name="tasktype"
                    id="tasktype"
                    value={tasktype}
                    onChange={(e) => setTaskType(e.target.value)}
                  >
                    <option value="">SELECT TASK TYPE</option>
                    <option value="Graduation Requirements">
                      Graduation Requirements
                    </option>
                    <option value="Homework">Homework</option>
                    <option value="Quiz or Unit Test">Quiz or Unit Test</option>
                    <option value="Exam">Midterm or Final</option>
                    <option value="Higher Education">Higher Education</option>
                    <option value="Job Search">Job Search</option>
                    <option value="Student Employment">
                      Student Employment
                    </option>
                    <option value="Extracurriculars">Extracurriculars</option>
                    <option value="Other">Other</option>
                  </select>
                </label>
                <label htmlFor="status">
                  Status
                  <select
                    name="status"
                    id="status"
                    value={status}
                    onChange={(e) => setStatus(e.target.value)}
                  >
                    <option value="incomplete">Incomplete</option>
                    <option value="help">Need Help - Suggest Next Steps</option>
                    <option value="complete">Complete</option>
                  </select>
                </label>
                <div className={styles.buttonContainer}>
                  <Button type="submit" variant="primary">
                    {type === 'update' ? 'Update' : 'Add'} Task
                  </Button>
                  <Button
                    type="button"
                    variant="secondary"
                    onClick={() => setModalOpen(false)}
                    onKeyDown={() => setModalOpen(false)}
                    tabIndex={0}
                    role="button"
                  >
                    Cancel
                  </Button>
                </div>
              </form>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

export default ClassModal;