match-curriculum / react-todo-app-starter-files / src / components / TodoItem.js
TodoItem.js
Raw
import { format } from 'date-fns/esm';
import React, { useEffect, useState } from 'react';
import toast from 'react-hot-toast';
import { MdDelete, MdEdit } from 'react-icons/md';
import { useDispatch } from 'react-redux';
import { motion } from 'framer-motion';
import { deleteTodo, updateTodo } from '../slices/todoSlice';
import styles from '../styles/modules/todoItem.module.scss';
import { getClasses } from '../utils/getClasses';
import CheckButton from './CheckButton';
import ClassModal from './ClassModal';

const child = {
  hidden: { y: 20, opacity: 0 },
  visible: { y: 0, opacity: 1 },
};

async function getResponse(text) {
  const url = 'https://api.openai.com/v1/completions';
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`,
      },
      body: JSON.stringify({
        model: 'davinci',
        prompt: `I need advice on how to ${text}.`,
        temperature: 1.2,
        max_tokens: 100,
        n: 1,
        stop: '\n',
      }),
    });
    const data = await response.json();
    return data.choices[0].text.trim();
  } catch (error) {
    console.log(error);
    const advice =
      'Let me think about it and get back to you...sorry about that! Good luck!';
    return advice;
  }
}

async function getAdvice({ text, setAdvice }) {
  try {
    const advice = await getResponse(text);
    setAdvice(advice);
  } catch (error) {
    console.log(error);
    const advice =
      'Let me think about it and get back to you...sorry about that! Good luck!';
    setAdvice(advice);
  }
}

function TodoItem({ todo }) {
  const dispatch = useDispatch();
  const [checked, setChecked] = useState(false);
  const [updateModalOpen, setUpdateModalOpen] = useState(false);
  const [advice, setAdvice] = useState('');

  useEffect(() => {
    if (todo.status === 'complete') {
      setChecked(true);
    } else {
      setChecked(false);
    }
  }, [todo.status, todo.title]);

  const handleDelete = () => {
    dispatch(deleteTodo(todo.id));
    toast.success('Todo has been deleted.');
  };
  const handleUpdate = () => {
    setUpdateModalOpen(true);
  };

  const handleCheck = () => {
    dispatch(
      updateTodo({
        ...todo,
        status: checked ? 'incomplete' : 'complete',
      })
    );
  };

  useEffect(() => {
    if (todo.status === 'help') {
      getAdvice({ text: todo.title, setAdvice });
    } else {
      setAdvice('');
    }
  }, [todo.status, todo.title, setAdvice]);

  useEffect(() => {
    if (todo.status === 'help') {
      getAdvice({ text: todo.title, setAdvice });
    } else {
      setAdvice('');
    }
  }, [todo.status, todo.title]);

  return (
    <>
      <motion.div className={styles.item} variants={child}>
        <div className={styles.todoDetails}>
          <CheckButton checked={checked} handleCheck={handleCheck} />
          <div className={styles.text}>
            <p
              className={getClasses([
                styles.todoText,
                todo.status === 'complete' && styles['todoText--completed'],
              ])}
            >
              {todo.title} ({todo.tasktype})
            </p>
            {todo.status === 'help' && advice && <p>{advice}</p>}
            <p className={styles.time}>
              {format(new Date(todo.time), 'p, MM/dd/yyyy')}
            </p>
          </div>
        </div>
        <div className={styles.todoActions}>
          <div
            className={styles.icon}
            onClick={handleDelete}
            onKeyDown={handleDelete}
            role="button"
            tabIndex={0}
          >
            <MdDelete />
          </div>
          <div
            className={styles.icon}
            onClick={handleUpdate}
            onKeyDown={handleUpdate}
            role="button"
            tabIndex={0}
          >
            <MdEdit />
          </div>
        </div>
      </motion.div>
      <ClassModal
        type="update"
        todo={todo}
        modalOpen={updateModalOpen}
        setModalOpen={setUpdateModalOpen}
      />
    </>
  );
}

export default TodoItem;