diff --git a/src/apis/todo.ts b/src/apis/todo.ts new file mode 100644 index 0000000..31428b7 --- /dev/null +++ b/src/apis/todo.ts @@ -0,0 +1,25 @@ +import { AuthInstance } from './instance' +import { TodoType } from '../components/TodoList/types' + +export const createTodoRequest = async (todo: string): Promise => { + const { data } = await AuthInstance.post('/todos', { todo }) + return data +} + +export const getTodosRequest = async (): Promise => { + const { data } = await AuthInstance.get('/todos') + return data +} + +export const updateTodoRequest = async ( + id: number, + todo: string, + isCompleted: boolean +): Promise => { + const { data } = await AuthInstance.put(`/todos/${id}`, { todo, isCompleted }) + return data +} + +export const deleteTodoRequest = async (id: number) => { + return AuthInstance.delete(`/todos/${id}`) +} diff --git a/src/components/TodoItem/TodoItem.tsx b/src/components/TodoItem/TodoItem.tsx new file mode 100644 index 0000000..47ef6cb --- /dev/null +++ b/src/components/TodoItem/TodoItem.tsx @@ -0,0 +1,81 @@ +import { useState } from 'react' +import TodoItemProps from './types' + +function TodoItem({ id, todo, isCompleted, updateTodo, deleteTodo }: TodoItemProps) { + const [todoCheck, setTodoCheck] = useState(isCompleted) + const [todoModify, setTodoModify] = useState('') + const [isEditMode, setIsEditMode] = useState(false) + + // TODO의 체크박스가 변경 되었을 때 + const onTodoCheckChanged = () => { + updateTodo(id, todo, !todoCheck) + setTodoCheck(!todoCheck) + } + + // TODO input창의 값이 변경 되었을 때 (수정모드) + const onTodoModifyChanged = (e: React.ChangeEvent) => { + const modifiedValue = e.target.value + setTodoModify(modifiedValue) + } + + // 수정 버튼을 눌렀을 때 + const onEditButtonClicked = () => { + setTodoModify(todo) + setIsEditMode(true) + } + + // 취소 버튼을 눌렀을 때 + const onCancelButtonClicked = () => { + setIsEditMode(false) + } + + // 제출 버튼을 눌렀을 때 + const onSubmitButtonClicked = () => { + updateTodo(id, todoModify, isCompleted) + setIsEditMode(false) + } + + // 삭제 버튼을 눌렀을 때 + const onDeleteButtonClicked = () => { + deleteTodo(id) + } + + return ( +
  • + + {isEditMode ? ( + <> + + + + ) : ( + <> + + + + )} +
  • + ) +} + +export default TodoItem diff --git a/src/components/TodoItem/types.ts b/src/components/TodoItem/types.ts new file mode 100644 index 0000000..214d208 --- /dev/null +++ b/src/components/TodoItem/types.ts @@ -0,0 +1,8 @@ +import { TodoType } from '../TodoList/types' + +interface TodoItemProps extends Omit { + updateTodo: (id: number, todo: string, isCompleted: boolean) => void + deleteTodo: (id: number) => void +} + +export default TodoItemProps diff --git a/src/components/TodoList/TodoList.tsx b/src/components/TodoList/TodoList.tsx new file mode 100644 index 0000000..e56524a --- /dev/null +++ b/src/components/TodoList/TodoList.tsx @@ -0,0 +1,83 @@ +import { useState, useEffect } from 'react' + +import TodoItem from '../TodoItem/TodoItem' +import { TodoType } from './types' +import { + createTodoRequest, + getTodosRequest, + updateTodoRequest, + deleteTodoRequest, +} from '../../apis/todo' +import { AxiosError } from 'axios' + +function TodoList() { + const [todos, setTodos] = useState([]) + const [newTodo, setNewTodo] = useState('') + + const createTodo = (todo: string) => { + createTodoRequest(todo) + .then((createdTodo) => { + setTodos((prevTodos) => [...prevTodos, createdTodo]) + setNewTodo('') + }) + .catch((e: AxiosError) => alert(e)) + } + + const getTodo = () => { + getTodosRequest() + .then((todos) => setTodos(todos)) + .catch((e: AxiosError) => alert(e.message)) + } + + const updateTodo = (id: number, todo: string, isCompleted: boolean) => { + updateTodoRequest(id, todo, isCompleted) + .then((updatedTodo) => + setTodos((prevTodos) => + prevTodos.map((prevTodo) => (prevTodo.id === id ? updatedTodo : prevTodo)) + ) + ) + .catch((e: AxiosError) => alert(e.message)) + } + + const deleteTodo = (id: number) => { + deleteTodoRequest(id) + .then(() => setTodos((prevTodos) => prevTodos.filter((prevTodo) => prevTodo.id !== id))) + .catch((e: AxiosError) => alert(e.message)) + } + + useEffect(() => { + getTodo() + }, []) + + return ( +
    +
    + + +
    +
      + {todos.map((todo) => ( + + ))} +
    +
    + ) +} + +export default TodoList diff --git a/src/components/TodoList/types.ts b/src/components/TodoList/types.ts new file mode 100644 index 0000000..563b53d --- /dev/null +++ b/src/components/TodoList/types.ts @@ -0,0 +1,6 @@ +export interface TodoType { + id: number + todo: string + isCompleted: boolean + userId: number +} diff --git a/src/pages/Todo.tsx b/src/pages/Todo.tsx index 511d213..7b5aca4 100644 --- a/src/pages/Todo.tsx +++ b/src/pages/Todo.tsx @@ -1,4 +1,5 @@ import { useNavigate } from 'react-router-dom' +import TodoList from '../components/TodoList/TodoList' function Todo() { const navigate = useNavigate() @@ -6,6 +7,7 @@ function Todo() { return (
    투두리스트 페이지입니다. +