Commit 35723d3f authored by Kim, Subin's avatar Kim, Subin
Browse files

Todo 완성중

parent 9dec93a5
import { useParams } from "react-router-dom";
import TodoModal from "../Modal/TodoModal"; import TodoModal from "../Modal/TodoModal";
import styles from "./buttons.module.scss"; import styles from "./buttons.module.scss";
const AddBtn = () => { const AddBtn = () => {
const { date } = useParams()
return ( return (
<> <>
<i className={`bi bi-plus-circle me-2 mb-1 ${styles.icon}`} data-bs-toggle="modal" data-bs-target="#todomodal"></i> <i className={`bi bi-plus-circle me-2 mb-1 ${styles.icon}`} data-bs-toggle="modal" data-bs-target="#todomodal"></i>
<TodoModal /> <TodoModal curDate={date} />
</> </>
) )
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
.icon { .icon {
color: crimson; color: crimson;
font-size: 2.7em; font-size: 2.7em;
cursor: pointer;
} }
.backBtn { .backBtn {
......
...@@ -9,14 +9,14 @@ import styles from "./form.module.scss"; ...@@ -9,14 +9,14 @@ import styles from "./form.module.scss";
const SubjectForm = () => { const SubjectForm = () => {
const { user } = useAuth(); const { user } = useAuth();
const { subjectId } = useParams(); const { subjectId } = useParams();
const [success, setSuccess] = useState(false) const [success, setSuccess] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [disabled, setDisabled] = useState(true) const [disabled, setDisabled] = useState(true);
const [subject, setSubject] = useState({ const [subject, setSubject] = useState({
lectureName: "", lectureName: "",
prof: "", prof: "",
classRoom: "" classRoom: ""
}) });
useEffect(() => { useEffect(() => {
if (subjectId) getInfo(subjectId); if (subjectId) getInfo(subjectId);
......
import { useState } from "react"; import { useState, useEffect, useRef } from "react";
import todoApi from "../../apis/todo.api";
import { useAuth } from "../../utils/context";
import catchErrors from "../../utils/catchErrors";
import moment from "moment"; import moment from "moment";
import styles from "./modal.module.scss"; import styles from "./modal.module.scss";
const TodoModal = () => { const TodoModal = ({ curDate, selectTodo = "" }) => {
const { user } = useAuth()
const [todo, setTodo] = useState({ const [todo, setTodo] = useState({
todoTitle: "", todoTitle: "",
todoDate: moment().format("YYYY-MM-DD") todoDate: moment(curDate).format("YYYY-MM-DD")
}) })
const [error, setError] = useState("");
useEffect(() => {
setTodo({ ...todo, todoDate: curDate })
}, [curDate])
useEffect(() => {
if (selectTodo) {
console.log("selectTodo 값 변경으로 실행")
setTodo({ ...todo, ...selectTodo })
}
}, [selectTodo])
const handleChange = (e) => { const handleChange = (e) => {
const { name, value } = e.target const { name, value } = e.target
setTodo({ ...todo, [name]: value }) setTodo({ ...todo, [name]: value })
} }
const handleClick = () => { async function handleSubmit() {
setTodo({ try {
todoTitle: "", setError("")
todoDate: moment().format("YYYY-MM-DD") if (selectTodo) {
}) await todoApi.edit(todo, user.id)
alert("해당 할일이 성공적으로 수정되었습니다.")
} else {
await todoApi.submit(todo, user.id)
alert("해당 할일이 성공적으로 등록되었습니다.")
}
window.location.reload()
} catch (error) {
catchErrors(error, setError)
}
} }
return ( return (
<div className="modal fade" id="todomodal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="todoLabel" aria-hidden="true"> <div className="modal fade" id="todomodal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="todoLabel" aria-hidden="true">
{console.log("Modal date==", curDate, selectTodo)}
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">
<div className="modal-content" style={{ backgroundColor: "crimson" }}> <div className="modal-content" style={{ backgroundColor: "crimson" }}>
<div className="modal-header px-2 py-1" > <div className="modal-header px-2 py-1" >
...@@ -31,7 +57,7 @@ const TodoModal = () => { ...@@ -31,7 +57,7 @@ const TodoModal = () => {
<div className="modal-body bg-white"> <div className="modal-body bg-white">
<input type="text" name="todoTitle" <input type="text" name="todoTitle"
className={`form-control border-top-0 border-end-0 border-start-0 shadow-none rounded-0 ${styles.textInput}`} className={`form-control border-top-0 border-end-0 border-start-0 shadow-none rounded-0 ${styles.textInput}`}
placeholder="제목" onChange={handleChange} value={todo.todoTitle} /> placeholder="제목" onChange={handleChange} value={todo.todoTitle} autoComplete="off" />
<div className="d-flex justify-content-between mt-4"> <div className="d-flex justify-content-between mt-4">
<label className="col-2 col-form-label ms-2">날짜</label> <label className="col-2 col-form-label ms-2">날짜</label>
<div className="col-8 d-flex align-items-center"> <div className="col-8 d-flex align-items-center">
...@@ -41,8 +67,8 @@ const TodoModal = () => { ...@@ -41,8 +67,8 @@ const TodoModal = () => {
</div> </div>
<div className="modal-footer bg-white p-1" > <div className="modal-footer bg-white p-1" >
<button type="button" className="btn btn-secondary btn-sm" <button type="button" className="btn btn-secondary btn-sm"
data-bs-dismiss="modal" onClick={handleClick}>취소</button> data-bs-dismiss="modal" onClick={() => setTodo({ todoTitle: "", todoDate: "" })}>취소</button>
<button type="button" className="btn btn-crimson btn-sm">확인</button> <button type="button" className="btn btn-crimson btn-sm" onClick={handleSubmit}>{selectTodo ? "수정" : "확인"}</button>
</div> </div>
</div> </div>
</div> </div>
......
const TodoPostModal = () => { const TodoPostModal = ({ handleClick }) => {
return ( return (
<>
<div className="modal fade" id="postmodal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true"> <div className="modal fade" id="postmodal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">
<div className="modal-content"> <div className="modal-content">
...@@ -8,14 +7,13 @@ const TodoPostModal = () => { ...@@ -8,14 +7,13 @@ const TodoPostModal = () => {
<p className="m-2 text-center" style={{ fontSize: "17px" }}>해당 일정을 내일로 미루시겠습니까?</p> <p className="m-2 text-center" style={{ fontSize: "17px" }}>해당 일정을 내일로 미루시겠습니까?</p>
</div> </div>
<div className="modal-footer p-1"> <div className="modal-footer p-1">
<button type="button" className="btn btn-crimson btn-sm"></button> <button type="button" className="btn btn-crimson btn-sm" data-bs-dismiss="modal" onClick={handleClick}></button>
<button type="button" className="btn btn-secondary btn-sm" <button type="button" className="btn btn-secondary btn-sm"
data-bs-dismiss="modal">아니요</button> data-bs-dismiss="modal">아니요</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</>
) )
} }
......
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import PlanLineList from "../StudyPlan/PlanLineList"; import PlanLineList from "./PlanLineList";
const StudyPlanCard = ({ renList }) => { const StudyPlanCard = ({ renList }) => {
......
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import StudyPlanCard from "./Card/StudyPlanCard"; import StudyPlanCard from "./StudyPlanCard";
import subjectApi from '../apis/subject.api'; import subjectApi from '../../apis/subject.api';
import catchErrors from "../utils/catchErrors"; import catchErrors from "../../utils/catchErrors";
import { useAuth } from "../utils/context"; import { useAuth } from "../../utils/context";
import styles from "./StudyPlan/studyplan.module.scss"; import styles from "./studyplan.module.scss";
const StudyPlanList = () => { const StudyPlanList = () => {
const { user } = useAuth(); const { user } = useAuth();
......
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import TodoModal from "../components/Modal/TodoModal"; import TodoModal from "../components/Modal/TodoModal";
import TodoPostModal from "../components/Modal/TodoPostModal"; import TodoPostModal from "../components/Modal/TodoPostModal";
import todoApi from "../apis/todo.api";
import { useAuth } from "../utils/context";
import catchErrors from "../utils/catchErrors";
import moment from "moment";
import styles from "../components/Form/form.module.scss"; import styles from "../components/Form/form.module.scss";
const TodoList = () => { const TodoList = () => {
const { user } = useAuth()
const { date } = useParams()
const [todoList, setTodoList] = useState([])
const [selectTodo, setSelectTodo] = useState(null)
const [error, setError] = useState("");
useEffect(() => {
getAll()
}, [date])
async function getAll() {
try {
setError("")
const resList = await todoApi.getTodo(user.id, date)
setTodoList(resList)
} catch (error) {
catchErrors(error, setError)
}
}
async function delayTodo() {
try {
setError("")
const nextDate = moment(date).add(1, 'day').format("YYYY-MM-DD")
await todoApi.edit({ id: selectTodo.id, todoDate: nextDate }, user.id)
getAll()
} catch (error) {
catchErrors(error, setError)
}
}
async function delTodo(todoId) {
try {
setError("")
await todoApi.remove(todoId, user.id)
alert("해당 할일이 성공적으로 삭제되었습니다.")
getAll()
} catch (error) {
catchErrors(error, setError)
}
}
return ( return (
<div className="d-flex mt-3"> <div className={"mt-3 " + (todoList.length ? "d-flex" : "d-block")}>
{todoList.length !== 0 ?
todoList.map((todo, idx) => <>
<div className="d-flex align-items-center" style={{ width: "75%" }}> <div className="d-flex align-items-center" style={{ width: "75%" }}>
<input className={`form-check-input rounded-0 shadow-none mt-0 ${styles.checkBox}`} type="checkbox" /> <input className={`form-check-input rounded-0 shadow-none mt-0 ${styles.checkBox}`} type="checkbox" checked={todo.done} />
<label className="form-check-label fs-5 ms-3 pe-2 text-nowrap" style={{ overflow: "hidden", textOverflow: "ellipsis" }}>과제03 제출하기sadsa</label> <label className="form-check-label fs-5 ms-3 pe-2 text-nowrap" style={{ overflow: "hidden", textOverflow: "ellipsis" }}>{todo.todoTitle}</label>
</div> </div>
<div className="d-flex justify-content-between" style={{ cursor: "pointer", width: "25%" }}> <div className="d-flex justify-content-between" style={{ cursor: "pointer", width: "25%" }}>
<i className="bi bi-arrow-right fs-5" data-bs-toggle="modal" data-bs-target="#postmodal"><TodoPostModal /></i> <i className="bi bi-arrow-right fs-5" data-bs-toggle="modal" data-bs-target="#postmodal" onClick={() => setSelectTodo(todo)}></i>
<i className="bi bi-pencil-square fs-5" data-bs-toggle="modal" data-bs-target="#todomodal"></i> <i className="bi bi-pencil-square fs-5" data-bs-toggle="modal" data-bs-target="#todomodal" onClick={() => setSelectTodo(todo)}></i>
<TodoModal /> <i className="bi bi-trash fs-5" onClick={() => delTodo(todo.id)}></i>
<i className="bi bi-trash fs-5"></i>
</div> </div>
</>) : <p className="text-center">등록된 할일이 없습니다.</p>}
<TodoPostModal handleClick={delayTodo} />
<TodoModal curDate={date} selectTodo={selectTodo} />
</div> </div>
) )
} }
......
import Menu from "../components/Menu/Menu"; import Menu from "../components/Menu/Menu";
import HomeBtn from "../components/Buttons/HomeBtn"; import HomeBtn from "../components/Buttons/HomeBtn";
import StudyPlanList from "../components/StudyPlanList"; import StudyPlanList from "../components/StudyPlan/StudyPlanList";
const StudyPlanListPage = () => { const StudyPlanListPage = () => {
return ( return (
......
...@@ -6,14 +6,14 @@ import Footer from "../components/Footer"; ...@@ -6,14 +6,14 @@ import Footer from "../components/Footer";
const ToDoPage = () => { const ToDoPage = () => {
return ( return (
<> <div>
<Menu /> <Menu />
<HomeBtn /> <HomeBtn />
<h1 className="text-center">To-do</h1> <h1 className="text-center">To-do</h1>
<Weekly /> <Weekly />
<TodoList /> <TodoList />
<Footer /> <Footer />
</> </div>
) )
} }
......
import { Todo } from '../db/index.js'; import { Todo } from '../db/index.js';
import sequelize from 'sequelize';
const AddTodo = async(req, res)=>{ const { Op } = sequelize
const findbyId = async (req, res, next) => {
try {
const userId = req.userId
const { todoId } = req.query
if (todoId) {
console.log(" findbyId todoId가 있을 때 실행", todoId)
const findTodo = await Todo.findOne({ where: { [Op.and]: [{ id: todoId }, { userId: userId }] }, attributes: ['id', ['title', 'todoTitle'], ['date', 'todoDate'], 'done'] })
if (!findTodo) throw new Error("해당 todo를 찾지 못했습니다.")
req.todoOne = findTodo
}
next()
} catch (error) {
return res.status(500).send(error.message || "todo 가져오는 중 에러 발생")
}
} }
export default{ const findbyDate = async (req, res, next) => {
AddTodo, try {
const userId = req.userId
const { date } = req.query
if (date) {
console.log(" findbydate 날짜가 있을 때 실행", date, userId)
const findList = await Todo.findAll({ where: { [Op.and]: [{ date: { [Op.eq]: date } }, { userId: userId }] }, attributes: ['id', ['title', 'todoTitle'], ['date', 'todoDate'], 'done'] })
console.log("find==", findList)
req.todoList = findList
}
next()
} catch (error) {
return res.status(500).send(error.message || "todo 가져오는 중 에러 발생")
}
}
const create = async (req, res) => {
try {
const userId = req.userId
const { todoTitle, todoDate } = req.body
const newTodo = await Todo.create({ title: todoTitle, date: todoDate, userId: userId })
return res.json(newTodo)
} catch (error) {
return res.status(500).send(error.message || "todo 등록 중 에러 발생")
}
}
const edit = async (req, res) => {
try {
let updated = null
const userId = req.userId
const { todoId } = req.query
const { todoTitle, todoDate } = req.body
if (todoTitle) updated = await Todo.update({ title: todoTitle, date: todoDate }, { where: { [Op.and]: [{ id: todoId }, { userId: userId }] } })
else updated = await Todo.update({ date: todoDate }, { where: { [Op.and]: [{ id: todoId }, { userId: userId }] } })
if (!updated) throw new Error("해당 todo의 일부 정보를 수정하는데 실패하였습니다.")
else return res.send(200)
} catch (error) {
return res.status(500).send(error.message || "todo 수정 중 에러 발생")
}
}
const remove = async (req, res) => {
try {
const userId = req.userId
const { todoId } = req.query
const deleted = await Todo.destroy({ where: { [Op.and]: [{ id: todoId }, { userId: userId }] } })
if (!deleted) throw new Error("해당 todo를 삭제하는데 실패하였습니다.")
else return res.send(200)
} catch (error) {
return res.status(500).send(error.message || "todo 삭제 중 에러 발생")
}
}
const getParams = async (req, res, next) => {
try {
const { userId } = req.params
req.userId = userId
next()
} catch (error) {
return res.status(500).send(error.message || "todo 가져오는 중 에러 발생")
}
}
const send = async (req, res) => {
try {
const result = req.todoOne || req.todoList
return res.json(result)
} catch (error) {
return res.status(500).send(error.message || "todo 가져오는 중 에러 발생")
}
}
export default {
findbyId,
findbyDate,
create,
edit,
remove,
getParams,
send
} }
\ No newline at end of file
...@@ -33,6 +33,7 @@ const Plan = PlanModel(sequelize) ...@@ -33,6 +33,7 @@ const Plan = PlanModel(sequelize)
Schedule.belongsTo(User) Schedule.belongsTo(User)
Subject.belongsTo(User) Subject.belongsTo(User)
Todo.belongsTo(User)
Plan.belongsTo(Subject) Plan.belongsTo(Subject)
export { export {
......
...@@ -2,7 +2,8 @@ import express from "express"; ...@@ -2,7 +2,8 @@ import express from "express";
import userRouter from './user.route.js'; import userRouter from './user.route.js';
import scheduleRouter from "./schedule.route.js"; import scheduleRouter from "./schedule.route.js";
import subjectRouter from './subject.route.js'; import subjectRouter from './subject.route.js';
import planRouter from './plan.route.js' import planRouter from './plan.route.js';
import todoRouter from "./todo.route.js";
const router = express.Router(); const router = express.Router();
...@@ -10,5 +11,6 @@ router.use('/auth', userRouter) ...@@ -10,5 +11,6 @@ router.use('/auth', userRouter)
router.use('/schedule', scheduleRouter) router.use('/schedule', scheduleRouter)
router.use('/subject', subjectRouter) router.use('/subject', subjectRouter)
router.use('/plan', planRouter) router.use('/plan', planRouter)
router.use('/todo', todoRouter)
export default router; export default router;
\ No newline at end of file
import express from 'express';
import todoCtrl from "../controllers/todo.controller.js";
const router = express.Router();
router
.route("/:userId")
.get(todoCtrl.findbyId, todoCtrl.findbyDate, todoCtrl.send)
.post(todoCtrl.create)
.put(todoCtrl.edit)
.delete(todoCtrl.remove)
router.param("userId", todoCtrl.getParams)
export default router;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment