Commit 660e363c authored by Kim, Subin's avatar Kim, Subin
Browse files

Merge branch 'kimpen'

parents 52f6e103 b7b819be
......@@ -6,6 +6,11 @@ const getTodo = async (userId, date = "", todoId = "") => {
return data
}
const getTodopercent = async (userId, start, end = "") => {
const { data } = await axios.get(`${baseUrl}/api/todo/percent/${userId}?start=${start}&end=${end}`)
return data
}
const submit = async (todo, userId) => {
const { data } = await axios.post(`${baseUrl}/api/todo/${userId}`, todo)
return data
......@@ -23,6 +28,7 @@ const remove = async (todoId, userId) => {
const todoApi = {
getTodo,
getTodopercent,
submit,
edit,
remove
......
......@@ -97,7 +97,7 @@ const ScheduleForm = () => {
return (
<form className="pt-5">
<div>
<input className={`form-control form-control-lg shadow-none rounded-0 px-1 mb-5 ${styles.textInput}`} type="text" name="title" value={schedule.title} placeholder="제목" aria-label="title" onChange={handleChange} autoFocus />
<input className={`form-control form-control-lg shadow-none rounded-0 px-1 mb-5 ${styles.textInput}`} type="text" name="title" value={schedule.title} placeholder="제목" aria-label="title" onChange={handleChange} autoFocus autoComplete="off" />
</div>
<div className="d-flex mb-4">
<label className="col col-form-label align-self-center py-0">시작</label>
......
......@@ -119,7 +119,7 @@ const StudyPlanEditForm = () => {
</select>
<input type="text" name="studyplanTitle"
className={`form-control shadow-none rounded-0 mb-5 ${styles.textInput}`}
placeholder="제목" value={studyplan.studyplanTitle} onChange={handleChange} />
placeholder="제목" value={studyplan.studyplanTitle} onChange={handleChange} autoComplete="off" />
<div className="d-flex mb-3">
<label className="col col-form-label align-self-center py-0">마감일</label>
<div className={studyplan.deadline === "on" ? "col-5" : "col-7"}>
......
......@@ -83,15 +83,15 @@ const SubjectForm = () => {
<div>
<div className="mb-5 d-flex flex-row">
<label className="form-label fs-4" style={{ width: "100px" }}>강의명</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.lectureName} name="lectureName" onChange={handleChange} />
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.lectureName} name="lectureName" onChange={handleChange} autoComplete="off" />
</div>
<div className="mb-5 pt-2 d-flex flex-row">
<label className="form-label fs-4" style={{ width: "100px" }}>교수명</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.prof} name="prof" onChange={handleChange} />
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.prof} name="prof" onChange={handleChange} autoComplete="off" />
</div>
<div className="mb-5 pt-2 d-flex flex-row">
<label className="form-label fs-4 " style={{ width: "100px", letterSpacing: "15px" }}>장소</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.classRoom} name="classRoom" onChange={handleChange} />
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.classRoom} name="classRoom" onChange={handleChange} autoComplete="off" />
</div>
</div>
<div className="pt-2">
......
......@@ -8,7 +8,7 @@ import styles from "./menu.module.scss";
const Menu = () => {
const { user, logout } = useAuth();
const [todoList, setTodoList] = useState([])
const [todoList, setTodoList] = useState({ percent: 0, list: [] })
const [error, setError] = useState("");
useEffect(() => {
......@@ -18,9 +18,9 @@ const Menu = () => {
async function todayTodo() {
try {
setError("")
const result = await todoApi.getTodo(user.id, moment().format("YYYY-MM-DD"))
const result = await todoApi.getTodopercent(user.id, moment().format("YYYY-MM-DD"))
console.log("client resList",result)
setTodoList(result)
setTodoList({...todoList, ...result})
} catch (error) {
catchErrors(error, setError)
}
......@@ -36,23 +36,17 @@ const Menu = () => {
<button type="button" className={`btn-close btn-close-white btn-lg position-absolute ${styles.close}`} data-bs-toggle="collapse" data-bs-target="#menuContent" aria-controls="menuContent" aria-expanded="true" aria-label="menu"></button>
<div className="d-flex flex-column align-items-center text-white py-5" style={{ backgroundColor: "crimson" }}>
<h1 className="my-3">{user.name} </h1>
<h2 className="my-2">오늘의 목표 95% 달성!</h2>
<h2 className="my-2">오늘의 목표 {todoList.percent}% 달성!</h2>
</div>
<div className="d-flex flex-column justify-content-between flex-grow-1 py-4 ps-3 text-dark" >
<div className="user-select-none w-75 ps-3">
<h2 className="mb-5">To-do</h2>
<div className="d-flex mt-2">
<p className={`form-check-label border-bottom border-2 fs-5 pb-1 me-3 ${styles.title}`}>sdasdsasdasdsadsadsadsadsadsadsadaddad</p>
<input className={`form-check-input rounded-0 border-dark shadow-none mt-1 ${styles.checkBox}`} type="checkbox" id="inlineCheckbox1" value="" aria-label="checkbox" />
</div>
<div className="d-flex">
<p className={`form-check-label border-bottom border-2 fs-5 pb-1 me-3 ${styles.title}`}>sdasdsadad</p>
<input className={`form-check-input rounded-0 border-dark shadow-none mt-1 ${styles.checkBox}`} type="checkbox" id="inlineCheckbox1" value="" aria-label="checkbox" />
</div>
<div className="d-flex">
<p className={`form-check-label border-bottom border-2 fs-5 pb-1 me-3 ${styles.title}`}>sdasdsadad</p>
<input className={`form-check-input rounded-0 border-dark shadow-none mt-1 ${styles.checkBox}`} type="checkbox" id="inlineCheckbox1" value="" aria-label="checkbox" />
<h2 className="mb-4">To-do</h2>
{todoList.list.length!==0 ? todoList.list.map((todo, idx) => {
if (idx <= 2) return <div className="d-flex">
<p className={`form-check-label border-bottom border-2 fs-5 pb-1 me-3 ${styles.title}`}>{todo.title}</p>
<input className={`form-check-input rounded-0 border-dark shadow-none mt-1 ${styles.checkBox}`} type="checkbox" id="inlineCheckbox1" aria-label="checkbox" checked={todo.done} />
</div>
}) : null}
<Link className="d-flex justify-content-center text-dark text-decoration-none" to={`/todo/${moment().format("YYYY-MM-DD")}`}>
<i className="bi bi-plus-lg me-2"></i>
<p className="mb-0">더보기</p>
......
const PlanAlertModal = ({ planId, handleClick }) => {
return (
<div className="modal fade" id="planmodal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="planLabel" aria-hidden="true">
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-body">
관련 학업계획까지 삭제됩니다.
정말 삭제하시겠습니까?
</div>
<div className="modal-footer p-1">
<button type="button" className="btn btn-secondary btn-sm" data-bs-dismiss="modal">취소</button>
<button type="button" className="btn btn-crimson btn-sm" onClick={() => handleClick(planId)}>삭제</button>
</div>
</div>
</div>
</div>
)
}
export default PlanAlertModal
\ No newline at end of file
import { useState, useEffect, useRef } from "react";
import { useState, useEffect } from "react";
import todoApi from "../../apis/todo.api";
import { useAuth } from "../../utils/context";
import catchErrors from "../../utils/catchErrors";
......@@ -47,7 +47,6 @@ const TodoModal = ({ curDate, selectTodo = "" }) => {
return (
<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-content" style={{ backgroundColor: "crimson" }}>
<div className="modal-header px-2 py-1" >
......
......@@ -2,7 +2,7 @@ import PlanItem from "./PlanItem";
import styles from "./studyplan.module.scss";
const AddplanList = ({ planList }) => {
console.log("planList ",planList)
return (
<div className={`mt-5 ${styles.list}`}>
<div className={`accordion accordion-flush`} id="addplanlist">
......
import { useState } from "react";
import { Link, useHistory } from "react-router-dom";
import AlertModal from "../Modal/PlanAlertModal";
import planApi from "../../apis/plan.api";
import { useAuth } from "../../utils/context";
import catchErrors from "../../utils/catchErrors";
......@@ -46,8 +45,7 @@ const PlanItem = ({ planList = [], subjectId }) => {
{plan.memo}
<div className="d-flex justify-content-end mt-3">
<Link className="btn btn-light btn-sm border-dark" to={`/studyplan/edit/${plan.id}`}>수정</Link>
<button type="button" className="btn btn-crimson btn-sm ms-2" data-bs-toggle="modal" data-bs-target="#planmodal">삭제</button>
<AlertModal planId={plan.id} handleClick={delPlan} />
<button type="button" className="btn btn-crimson btn-sm ms-2" onClick={() => delPlan(plan.id)}>삭제</button>
</div>
</div>
</div>
......
......@@ -3,7 +3,7 @@ import styles from "./studyplan.module.scss";
const PlanLineList = ({ subjectId, planList = [] }) => {
return (
<>
<Link to={`/studyplan/${subjectId}`}>
{planList.length !== 0 ? planList.map(plan => <div className="d-flex justify-content-between">
<p className={`card-text mb-1 ${styles.text}`}>- {plan.title}</p>
<input className={`form-check-input shadow-none ${styles.checkBox}`} type="checkbox" />
......@@ -13,7 +13,7 @@ const PlanLineList = ({ subjectId, planList = [] }) => {
<p className="card-text mb-1">새로운 계획 추가하기</p>
</div>
</Link>}
</>
</Link>
)
}
......
import { Link } from "react-router-dom";
import PlanLineList from "./PlanLineList";
const StudyPlanCard = ({ renList }) => {
const StudyPlanCard = ({ renList, handleClick }) => {
return (
<Link className="card text-decoration-none link-dark mb-3" style={{ width: "20rem" }} to={`/studyplan/${renList.id}`}>
<div className="card text-decoration-none link-dark mb-3" style={{ width: "20rem" }} >
<div className="card-body">
<div className="d-flex">
<h5 className="card-title col-10 text-nowrap" style={{ overflow: "hidden", textOverflow: "ellipsis" }}>{renList.name}</h5>
<div className="col-2 d-flex justify-content-end">
<Link className="text-decoration-none link-dark" to={`/subject/edit/${renList.id}`}><i className="bi bi-pencil-square pe-2"></i></Link>
<i className="bi bi-trash"></i>
<i className="bi bi-trash" onClick={() => handleClick(renList.id)}>
</i>
</div>
</div>
<p className="card-subtitle ms-1 mb-2 text-muted">{renList.prof && renList.room ? renList.prof + ' - ' + renList.room : (renList.prof || renList.room)}</p>
<PlanLineList subjectId={renList.id} planList={renList.planList} />
</div>
</Link>
</div>
)
}
......
import { useState, useEffect } from 'react';
import { Link } from "react-router-dom";
import { Link, useHistory } from "react-router-dom";
import StudyPlanCard from "./StudyPlanCard";
import subjectApi from '../../apis/subject.api';
import catchErrors from "../../utils/catchErrors";
......@@ -9,7 +9,9 @@ import styles from "./studyplan.module.scss";
const StudyPlanList = () => {
const { user } = useAuth();
const [renList, setRenList] = useState([])
const [success, setSuccess] = useState(false)
const [error, setError] = useState("")
const history = useHistory()
useEffect(() => {
getList(user.id);
......@@ -25,10 +27,23 @@ const StudyPlanList = () => {
}
}
async function delSubject(subjectId) {
try {
setError("")
await subjectApi.removeSubject(subjectId, user.id)
alert("해당 과목 정보가 성공적으로 삭제되었습니다.")
setSuccess(true)
} catch (error) {
catchErrors(error, setError)
}
}
if (success) history.push("/home")
return (
<div className={`mt-4 ${styles.list}`}>
<div className="d-flex flex-column align-items-center">
{renList.length !== 0 ? renList.map((info, idx) => <StudyPlanCard key={idx} renList={info} />) : null}
{renList.length !== 0 ? renList.map((info, idx) => <StudyPlanCard key={idx} renList={info} handleClick={delSubject} />) : null}
<Link className="card text-decoration-none link-dark" to="/subject/edit" style={{ width: "20rem" }}>
<div className="card-body d-flex flex-column bg-secondary bg-opacity-25">
<i className="bi bi-plus-lg d-flex justify-content-center fs-3"></i>
......
......@@ -35,6 +35,30 @@ const findbyDate = async (req, res, next) => {
}
}
const findforPercent = async (req, res) => {
try {
let doneTodo = null
const userId = req.userId
const { start, end } = req.query
if (end) {
const { count, rows } = await Todo.findAndCountAll({ where: { [Op.and]: [{ date: { [Op.eq]: start } }, { userId: userId }] } })
} else {
let percent = 0
console.log("findforPercent end 없음")
const nonCheck = await Todo.findAndCountAll({ where: { [Op.and]: [{ date: { [Op.eq]: start } }, { userId: userId }, { done: false }] } })
const check = await Todo.findAndCountAll({ where: { [Op.and]: [{ date: { [Op.eq]: start } }, { userId: userId }, { done: true }] } })
let total = nonCheck.count + check.count
check.rows.forEach(el => nonCheck.rows.push(el.dataValues))
console.log("non",nonCheck)
if (total === 0) percent = 0
else percent = Math.round((check.count / total)*100)
return res.json({ percent: percent, list: nonCheck.rows })
}
} catch (error) {
return res.status(500).send(error.message || "todo 가져오는 중 에러 발생")
}
}
const create = async (req, res) => {
try {
const userId = req.userId
......@@ -95,6 +119,7 @@ const send = async (req, res) => {
export default {
findbyId,
findbyDate,
findforPercent,
create,
edit,
remove,
......
......@@ -34,6 +34,11 @@ const Plan = PlanModel(sequelize)
Schedule.belongsTo(User)
Subject.belongsTo(User)
Todo.belongsTo(User)
Subject.hasOne(Plan, {
onDelete: "CASCADE"
})
Plan.belongsTo(Subject)
export {
......
......@@ -3,6 +3,10 @@ import todoCtrl from "../controllers/todo.controller.js";
const router = express.Router();
router
.route("/percent/:userId")
.get(todoCtrl.findforPercent)
router
.route("/:userId")
.get(todoCtrl.findbyId, todoCtrl.findbyDate, todoCtrl.send)
......
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