Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
students
Today KU
Commits
660e363c
Commit
660e363c
authored
Nov 05, 2021
by
Kim, Subin
Browse files
Merge branch 'kimpen'
parents
52f6e103
b7b819be
Changes
15
Hide whitespace changes
Inline
Side-by-side
client/src/apis/todo.api.js
View file @
660e363c
...
...
@@ -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
...
...
client/src/components/Form/ScheduleForm.js
View file @
660e363c
...
...
@@ -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
>
...
...
client/src/components/Form/StudyPlanEditForm.js
View file @
660e363c
...
...
@@ -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
"
}
>
...
...
client/src/components/Form/SubjectForm.js
View file @
660e363c
...
...
@@ -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
"
>
...
...
client/src/components/Menu/Menu.js
View file @
660e363c
...
...
@@ -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
.
getTodo
percent
(
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
>
...
...
client/src/components/Modal/PlanAlertModal.js
deleted
100644 → 0
View file @
52f6e103
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
client/src/components/Modal/TodoModal.js
View file @
660e363c
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
"
>
...
...
client/src/components/StudyPlan/AddplanList.js
View file @
660e363c
...
...
@@ -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
"
>
...
...
client/src/components/StudyPlan/PlanItem.js
View file @
660e363c
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
>
...
...
client/src/components/StudyPlan/PlanLineList.js
View file @
660e363c
...
...
@@ -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
>
)
}
...
...
client/src/components/StudyPlan/StudyPlanCard.js
View file @
660e363c
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
>
)
}
...
...
client/src/components/StudyPlan/StudyPlanList.js
View file @
660e363c
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
>
...
...
server/controllers/todo.controller.js
View file @
660e363c
...
...
@@ -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
,
...
...
server/db/index.js
View file @
660e363c
...
...
@@ -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
{
...
...
server/routes/todo.route.js
View file @
660e363c
...
...
@@ -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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment