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
survey
Commits
b9b919e7
Commit
b9b919e7
authored
Jul 28, 2022
by
Yoon, Daeki
😅
Browse files
Merge branch 'develop0727' into main-dev
parents
71ea74d6
287f9033
Changes
18
Hide whitespace changes
Inline
Side-by-side
frontend/src/answers/AEssayForm.tsx
View file @
b9b919e7
import
React
,
{
useState
}
from
"
react
"
;
import
{
AnswerProps
,
AnswerQuestionType
,
EssayType
}
from
"
../types
"
;
import
{
AnswerProps
}
from
"
../types
"
;
export
const
AEssayForm
=
({
element
,
answerQuestion
}:
AnswerProps
)
=>
{
const
[
answer
,
setAnswer
]
=
useState
(
""
);
...
...
@@ -19,7 +19,7 @@ export const AEssayForm = ({ element, answerQuestion }: AnswerProps) => {
<
div
className
=
"flex mt-3 w-full justify-center"
>
<
input
type
=
"text"
className
=
"border w-11/12 h-
36
my-3"
className
=
"border w-11/12 h-
24
my-3"
id
=
{
element
.
_id
}
onChange
=
{
handleChange
}
value
=
{
answer
}
...
...
frontend/src/commons/Header.tsx
View file @
b9b919e7
...
...
@@ -42,7 +42,7 @@ export const Header = () => {
</
button
>
</
Link
>
<
Link
to
=
"/signup"
>
<
button
className
=
"font-bold text-white hover:bg-
blue-500
mx-1 py-2 px-3 bg-themeColor rounded-md "
>
<
button
className
=
"font-bold text-white hover:bg-
themeColor2
mx-1 py-2 px-3 bg-themeColor rounded-md "
>
회원가입
</
button
>
</
Link
>
...
...
frontend/src/home/Home.tsx
View file @
b9b919e7
import
React
,
{
FormEvent
}
from
"
react
"
;
import
{
useAuth
}
from
"
../auth/auth.context
"
;
import
Survey
Img
from
"
../icons/
surveyi
mg.png
"
;
import
home
Img
from
"
../icons/
homeI
mg.png
"
;
export
const
Home
=
()
=>
{
const
{
user
}
=
useAuth
();
...
...
@@ -30,10 +30,10 @@ export const Home = () => {
+
</
button
>
</
div
>
<
p
className
=
"text-center text-xl text-black m
t
-3"
>
Create now!
</
p
>
<
p
className
=
"text-center text-xl text-black m
y
-3"
>
Create now!
</
p
>
</
div
>
<
div
className
=
"flex
justify-center mt-3
"
>
<
img
src
=
{
Survey
Img
}
className
=
"
object-scale-down justify-center
"
/>
<
div
className
=
"flex
mt-5 md:px-48 bg-themeColor
"
>
<
img
src
=
{
home
Img
}
className
=
"
m-3
"
/>
</
div
>
</
div
>
);
...
...
frontend/src/icons/homeImg.png
0 → 100644
View file @
b9b919e7
415 KB
frontend/src/questions/Question.tsx
View file @
b9b919e7
...
...
@@ -162,12 +162,12 @@ export const Question = ({
style
=
{
{
borderColor
:
isEditing
?
"
red
"
:
"
#0A8A8A
"
}
}
className
=
"flex flex-col container w-4/5 h-auto border-2 items-center m-3 py-2 rounded-lg"
>
<
div
className
=
"flex h-16 w-full place-content-
between
items-center"
>
<
div
className
=
"flex h-16 w-full place-content-
center
items-center"
>
<
input
type
=
"text"
name
=
"title"
id
=
{
question
.
_id
}
className
=
"text-xl font-bold
ml-6
border-b-2 w-1
/
2"
className
=
"text-xl font-bold border-b-2 w-1
1/1
2"
placeholder
=
{
"
Question Title
"
}
value
=
{
question
.
title
}
onChange
=
{
handleQuestionInfo
}
...
...
@@ -206,39 +206,58 @@ export const Question = ({
></
input
>
</
div
>
{
getContent
(
question
)
}
<
div
className
=
"place-self-end py-2"
>
<
input
type
=
"checkbox"
id
=
"isRequired"
value
=
"isRequired"
onChange
=
{
handleRequired
}
<
div
className
=
"flex flex-row place-content-between w-11/12 py-2"
>
<
select
id
=
{
question
.
_id
}
name
=
"type"
onChange
=
{
handleSelect
}
disabled
=
{
!
isEditing
}
checked
=
{
question
.
isRequired
}
/>
<
label
htmlFor
=
"isRequired"
className
=
"px-1"
>
필수
</
label
>
{
isEditing
?
(
<>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
onCancel
}
>
취소
</
button
>
value
=
{
question
.
type
}
className
=
"w-32 h-10 md:w-36 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-themeColor"
>
{
Array
.
from
(
QUESTION_TYPES
.
entries
()).
map
(([
key
,
value
])
=>
(
<
option
key
=
{
key
}
id
=
{
question
.
_id
}
value
=
{
key
}
>
{
value
}
</
option
>
))
}
</
select
>
<
div
className
=
"place-self-end py-2"
>
<
input
type
=
"checkbox"
id
=
"isRequired"
value
=
"isRequired"
onChange
=
{
handleRequired
}
disabled
=
{
!
isEditing
}
checked
=
{
question
.
isRequired
}
/>
<
label
htmlFor
=
"isRequired"
className
=
"px-1"
>
필수
</
label
>
{
isEditing
?
(
<>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
onCancel
}
>
취소
</
button
>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleEditComplete
}
>
확인
</
button
>
</>
)
:
(
<>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleDelete
}
>
삭제
</
button
>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleEditClick
}
>
수정
</
button
>
</>
)
}
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleEditComplete
}
>
확인
</
button
>
</>
)
:
(
<>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleDelete
}
>
삭제
</
button
>
<
button
type
=
"button"
className
=
"px-1"
onClick
=
{
handleEditClick
}
>
수정
</
button
>
</>
)
}
</
div
>
</
div
>
</
div
>
);
...
...
frontend/src/
survey
/Accordion.tsx
→
frontend/src/
results
/Accordion.tsx
View file @
b9b919e7
import
React
,
{
useState
,
useRef
,
useEffect
}
from
"
react
"
;
import
{
baseImageUrl
}
from
"
../apis
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
import
{
REssayForm
}
from
"
./REssayForm
"
;
import
{
RCheckboxForm
}
from
"
./RCheckboxForm
"
;
import
{
RRadioForm
}
from
"
./RRadioForm
"
;
import
{
RDropdownForm
}
from
"
./RDropdownForm
"
;
import
{
RFileForm
}
from
"
./RFileForm
"
;
import
{
RRatingForm
}
from
"
./RRatingForm
"
;
import
{
RDateForm
}
from
"
./RDateForm
"
;
type
AccordionProps
=
{
question
:
BasicQuestionType
;
};
const
Accordion
=
({
question
}:
AccordionProps
)
=>
{
export
const
Accordion
=
({
question
}:
AccordionProps
)
=>
{
const
[
isOpened
,
setOpened
]
=
useState
<
boolean
>
(
false
);
const
[
height
,
setHeight
]
=
useState
<
string
>
(
"
0px
"
);
const
contentElement
=
useRef
<
HTMLDivElement
>
(
null
);
...
...
@@ -14,7 +19,27 @@ const Accordion = ({ question }: AccordionProps) => {
setOpened
(
!
isOpened
);
setHeight
(
!
isOpened
?
`
${
contentElement
.
current
?.
scrollHeight
}
px`
:
"
0px
"
);
};
function
getContent
(
question
:
BasicQuestionType
)
{
switch
(
question
.
type
)
{
case
"
essay
"
:
return
<
REssayForm
question
=
{
question
}
/>;
case
"
radio
"
:
return
<
RRadioForm
question
=
{
question
}
/>;
case
"
checkbox
"
:
return
<
RCheckboxForm
question
=
{
question
}
/>;
case
"
dropdown
"
:
return
<
RDropdownForm
question
=
{
question
}
/>;
case
"
file
"
:
return
<
RFileForm
question
=
{
question
}
/>;
case
"
rating
"
:
return
<
RRatingForm
question
=
{
question
}
/>;
case
"
date
"
:
return
<
RDateForm
question
=
{
question
}
/>;
default
:
return
<></>;
}
}
console
.
log
(
question
);
return
(
<
div
className
=
"p-1"
>
<
div
onClick
=
{
HandleOpening
}
>
...
...
@@ -31,20 +56,7 @@ const Accordion = ({ question }: AccordionProps) => {
style
=
{
{
height
:
height
}
}
className
=
"bg-gray-100 overflow-hidden transition-all duration-300"
>
{
question
.
answers
&&
(
question
.
type
===
"
file
"
?
question
.
answers
.
map
((
answer
:
any
)
=>
(
<
img
key
=
{
answer
.
url
}
alt
=
"file"
src
=
{
`
${
baseImageUrl
}
/
${
answer
.
url
}
`
}
/>
))
:
question
.
answers
.
map
((
answer
:
any
,
index
:
number
)
=>
(
<
p
key
=
{
index
}
className
=
"p-4"
>
{
answer
}
</
p
>
)))
}
{
question
.
answers
&&
getContent
(
question
)
}
</
div
>
</
div
>
</
div
>
...
...
frontend/src/results/RCheckboxForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
RCheckboxForm
=
({
question
}:
Props
)
=>
{
const
result
=
question
.
answers
.
flat
().
reduce
((
acc
:
any
,
cur
:
any
)
=>
{
acc
[
cur
]
=
(
acc
[
cur
]
||
0
)
+
1
;
return
acc
;
},
{});
console
.
log
(
result
);
return
(
<
div
className
=
"m-5"
>
{
question
.
content
.
choices
.
map
((
choice
:
any
)
=>
(
<
div
className
=
""
>
<
span
className
=
"font-bold"
>
{
choice
.
text
}
</
span
>
<
span
className
=
"ml-3"
>
-
{
result
[
choice
.
text
]
?
result
[
choice
.
text
]
:
0
}
</
span
>
</
div
>
))
}
</
div
>
);
};
frontend/src/results/RDateForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
RDateForm
=
({
question
}:
Props
)
=>
{
return
(
<
div
className
=
"m-5"
>
{
question
.
answers
.
map
((
answer
:
any
)
=>
(
<
div
className
=
"font-bold"
>
{
answer
}
</
div
>
))
}
</
div
>
);
};
frontend/src/results/RDropdownForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
RDropdownForm
=
({
question
}:
Props
)
=>
{
const
result
=
question
.
answers
.
reduce
((
acc
:
any
,
cur
:
any
)
=>
{
acc
[
cur
]
=
(
acc
[
cur
]
||
0
)
+
1
;
return
acc
;
},
{});
console
.
log
(
result
);
return
(
<
div
className
=
"m-5"
>
{
question
.
content
.
choices
.
map
((
choice
:
any
)
=>
(
<
div
className
=
""
>
<
span
className
=
"font-bold"
>
{
choice
.
text
}
</
span
>
<
span
className
=
"ml-3"
>
-
{
result
[
choice
.
text
]
?
result
[
choice
.
text
]
:
0
}
</
span
>
</
div
>
))
}
</
div
>
);
};
frontend/src/results/REssayForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
REssayForm
=
({
question
}:
Props
)
=>
{
return
(
<
div
className
=
"m-5"
>
{
question
.
answers
.
map
((
answer
:
any
)
=>
(
<
div
className
=
"font-bold"
>
{
answer
}
</
div
>
))
}
</
div
>
);
};
frontend/src/results/RFileForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
baseImageUrl
}
from
"
../apis
"
;
type
Props
=
{
question
:
any
;
};
export
const
RFileForm
=
({
question
}:
Props
)
=>
{
return
(
<
div
className
=
"m-5 flex justify-start items-center"
>
{
question
.
answers
.
map
((
answer
:
any
)
=>
(
<>
<
img
className
=
"h-14"
key
=
{
answer
.
url
}
alt
=
"file"
src
=
{
`
${
baseImageUrl
}
/
${
answer
.
url
}
`
}
/>
<
div
className
=
"ml-3"
>
{
answer
.
name
}
</
div
>
</>
))
}
</
div
>
);
};
frontend/src/results/RRadioForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
RRadioForm
=
({
question
}:
Props
)
=>
{
const
result
=
question
.
answers
.
reduce
((
acc
:
any
,
cur
:
any
)
=>
{
acc
[
cur
]
=
(
acc
[
cur
]
||
0
)
+
1
;
return
acc
;
},
{});
console
.
log
(
result
);
return
(
<
div
className
=
"m-5"
>
{
question
.
content
.
choices
.
map
((
choice
:
any
)
=>
(
<
div
className
=
""
>
<
span
className
=
"font-bold"
>
{
choice
.
text
}
</
span
>
<
span
className
=
"ml-3"
>
-
{
result
[
choice
.
text
]
?
result
[
choice
.
text
]
:
0
}
</
span
>
</
div
>
))
}
</
div
>
);
};
frontend/src/results/RRatingForm.tsx
0 → 100644
View file @
b9b919e7
import
React
from
"
react
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
Props
=
{
question
:
BasicQuestionType
;
};
export
const
RRatingForm
=
({
question
}:
Props
)
=>
{
const
result
=
question
.
answers
.
reduce
((
acc
:
any
,
cur
:
any
)
=>
{
acc
[
cur
]
=
(
acc
[
cur
]
||
0
)
+
1
;
return
acc
;
},
{});
console
.
log
(
result
);
return
(
<
div
className
=
"m-5"
>
<
div
>
{
question
.
content
.
minRateDescription
}
</
div
>
{
question
.
content
.
choices
.
map
((
choice
:
any
)
=>
(
<
div
className
=
""
>
<
span
className
=
"font-bold"
>
{
choice
.
text
}
</
span
>
<
span
className
=
"ml-3"
>
-
{
result
[
choice
.
text
]
?
result
[
choice
.
text
]
:
0
}
</
span
>
</
div
>
))
}
<
div
>
{
question
.
content
.
maxRateDescription
}
</
div
>
</
div
>
);
};
frontend/src/results/index.tsx
0 → 100644
View file @
b9b919e7
export
{
Accordion
}
from
"
./Accordion
"
;
frontend/src/survey/CreateSurvey.tsx
View file @
b9b919e7
...
...
@@ -77,17 +77,22 @@ export const CreateSurvey = () => {
async
function
handleSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
try
{
const
newSurvey
:
SurveyType
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
const
notEditComplete
=
isEditing
?.
find
((
el
)
=>
el
.
isEditing
);
if
(
notEditComplete
)
{
alert
(
"
아직 수정이 완료되지 않은 질문이 존재합니다.
"
);
}
else
{
try
{
const
newSurvey
:
SurveyType
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
}
...
...
frontend/src/survey/EditSurvey.tsx
View file @
b9b919e7
...
...
@@ -79,17 +79,22 @@ export const EditSurvey = () => {
async
function
handleSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
try
{
const
newSurvey
:
SurveyType
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
const
notEditComplete
=
isEditing
?.
find
((
el
)
=>
el
.
isEditing
);
if
(
notEditComplete
)
{
alert
(
"
아직 수정이 완료되지 않은 질문이 존재합니다.
"
);
}
else
{
try
{
const
newSurvey
:
SurveyType
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
}
...
...
frontend/src/survey/ResultSurvey.tsx
View file @
b9b919e7
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
answerApi
,
surveyApi
}
from
"
../apis
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
Accordion
from
"
./
Accordion
"
;
import
{
Accordion
}
from
"
.
.
/
results
"
;
import
{
useParams
}
from
"
react-router-dom
"
;
import
{
SurveyType
}
from
"
../types
"
;
...
...
src/routes/survey.route.ts
View file @
b9b919e7
...
...
@@ -8,6 +8,7 @@ router.route("/").get(authCtrl.requireLogin, surveyCtrl.getSurveys);
router
.
route
(
"
/create
"
).
post
(
authCtrl
.
requireLogin
,
surveyCtrl
.
createSurvey
);
router
.
route
(
"
/:surveyId
"
).
get
(
surveyCtrl
.
getSurveyById
);
router
.
route
(
"
/:surveyId/edit
"
)
.
get
(
authCtrl
.
requireLogin
,
authCtrl
.
authenticate
,
surveyCtrl
.
getSurveyById
)
...
...
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