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
be1ba639
Commit
be1ba639
authored
Aug 16, 2022
by
Yoon, Daeki
😅
Browse files
result, answer 로직 및 불필요한 폴더 파일 삭제
parent
e7ae6d3f
Changes
58
Hide whitespace changes
Inline
Side-by-side
frontend/src/results/index.tsx
deleted
100644 → 0
View file @
e7ae6d3f
export
{
Accordion
}
from
"
./Accordion
"
;
frontend/src/survey/CompleteSurvey.tsx
deleted
100644 → 0
View file @
e7ae6d3f
import
React
from
"
react
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
export
const
CompleteSurvey
=
()
=>
{
const
navigate
=
useNavigate
();
return
(
<
div
className
=
"flex flex-col place-items-center mt-24"
>
<
div
className
=
"flex flex-col container place-items-center place-content-center space-y-5 space-x-2 w-full h-56"
>
<
p
className
=
"text-3xl font-bold"
>
설문조사가 제출되었습니다
</
p
>
<
p
>
응답이 완료되었습니다
</
p
>
<
button
className
=
"flex place-content-start rounded-lg bg-themeColor w-20 h-10 text-center py-2 px-4 text-white"
type
=
"button"
onClick
=
{
()
=>
navigate
(
"
/
"
)
}
>
홈으로
</
button
>
</
div
>
</
div
>
);
};
frontend/src/survey/CreateSurvey.tsx
deleted
100644 → 0
View file @
e7ae6d3f
import
React
,
{
FormEvent
,
useEffect
,
useState
}
from
"
react
"
;
import
{
useParams
,
useLocation
,
useNavigate
}
from
"
react-router-dom
"
;
import
{
questionApi
,
surveyApi
}
from
"
../apis
"
;
import
{
SpinnerIcon
}
from
"
../icons
"
;
import
{
Question
}
from
"
../questions
"
;
import
{
IQuestionData
,
ISurvey
}
from
"
../types
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
export
const
CreateSurvey
=
()
=>
{
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
[
isEditing
,
setIsEditing
]
=
useState
<
{
qid
:
string
;
isEditing
:
boolean
}[]
>
();
const
[
error
,
setError
]
=
useState
(
""
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
navigate
=
useNavigate
();
const
[
survey
,
setSurvey
]
=
useState
<
ISurvey
>
({
_id
:
surveyId
||
""
,
user
:
{},
title
:
""
,
comment
:
""
,
questions
:
[],
});
useEffect
(()
=>
{
getSurvey
();
},
[
surveyId
]);
async
function
getSurvey
()
{
try
{
if
(
surveyId
)
{
const
thisSurvey
:
ISurvey
=
await
surveyApi
.
getSurvey
(
surveyId
);
const
initEditing
=
thisSurvey
.
questions
.
map
((
question
)
=>
{
return
{
qid
:
question
.
_id
,
isEditing
:
false
};
});
// console.log("init editing", initEditing);
setIsEditing
(
initEditing
);
setSurvey
(
thisSurvey
);
setSuccess
(
true
);
setError
(
""
);
}
else
{
setLoading
(
true
);
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
const
handleEditing
=
(
qid
:
string
,
edited
:
boolean
)
=>
{
console
.
log
(
"
handle editing:
"
,
qid
,
edited
);
if
(
isEditing
)
{
const
index
=
isEditing
.
findIndex
((
q
)
=>
q
.
qid
===
qid
);
isEditing
[
index
].
isEditing
=
edited
;
setIsEditing
([...
isEditing
]);
}
};
const
handleQuestion
=
(
element
:
IQuestionData
)
=>
{
const
index
=
survey
.
questions
.
findIndex
(
(
question
)
=>
question
.
_id
===
element
.
_id
);
survey
.
questions
[
index
]
=
element
;
const
newList
=
[...
survey
.
questions
];
console
.
log
(
"
new list in handle question
"
,
newList
);
setSurvey
({
...
survey
,
questions
:
newList
});
};
const
handleSurvey
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
{
name
,
value
}
=
event
.
currentTarget
;
setSurvey
({
...
survey
,
[
name
]:
value
});
};
async
function
handleSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
const
notEditComplete
=
isEditing
?.
find
((
el
)
=>
el
.
isEditing
);
if
(
notEditComplete
)
{
alert
(
"
아직 수정이 완료되지 않은 질문이 존재합니다.
"
);
}
else
{
try
{
const
newSurvey
:
ISurvey
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
}
async
function
addQuestion
()
{
try
{
if
(
surveyId
)
{
// const questions: BasicQuestionType[] = await questionApi.createQuestion(
// surveyId
// );
// console.log(questions);
const
question
:
IQuestionData
=
await
questionApi
.
createQuestion
(
surveyId
);
console
.
log
(
question
);
isEditing
&&
setIsEditing
([...
isEditing
,
{
qid
:
question
.
_id
,
isEditing
:
true
}]);
// setSurvey({ ...survey, questions: questions });
setSurvey
({
...
survey
,
questions
:
[...
questions
,
question
]
});
setSuccess
(
true
);
setError
(
""
);
}
else
{
setLoading
(
true
);
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
async
function
deleteQuestion
(
id
:
string
)
{
const
newList
:
IQuestionData
[]
=
[...
survey
.
questions
];
try
{
const
newQuestion
:
IQuestionData
=
await
questionApi
.
deleteQuestion
(
id
);
setSurvey
({
...
survey
,
questions
:
newList
.
filter
((
a
)
=>
a
.
_id
!==
id
)
});
setSuccess
(
true
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
const
questions
=
survey
.
questions
;
// console.log(questions);
return
(
<>
{
error
?
alert
(
error
)
:
<></>
}
{
loading
&&
(
<
SpinnerIcon
className
=
"animate-spin h-5 w-5 mr-1 text-slate"
/>
)
}
<
form
onSubmit
=
{
handleSubmit
}
>
<
div
className
=
"flex flex-col place-items-center"
>
<
div
className
=
"flex flex-col container place-items-center mt-4"
>
<
input
type
=
"text"
name
=
"title"
className
=
"font-bold text-4xl text-center m-2 border-b-2"
placeholder
=
"설문지 제목"
value
=
{
survey
.
title
}
onChange
=
{
handleSurvey
}
></
input
>
<
input
type
=
"text"
name
=
"comment"
className
=
"font-bold text-1xl text-center m-2 border-b-2 resize-none"
placeholder
=
"설문조사에 대한 설명을 입력해주세요"
size
=
{
50
}
value
=
{
survey
.
comment
}
onChange
=
{
handleSurvey
}
></
input
>
</
div
>
{
questions
.
map
((
question
)
=>
(
<
Question
key
=
{
question
.
_id
}
element
=
{
question
}
isEditing
=
{
isEditing
?.
filter
((
q
)
=>
q
.
qid
===
question
.
_id
)[
0
]
?.
isEditing
??
true
}
handleEditing
=
{
handleEditing
}
handleQuestion
=
{
handleQuestion
}
deleteQuestion
=
{
deleteQuestion
}
/>
))
}
<
div
className
=
"flex w-4/5 content-center justify-center border-2 border-black h-8 mt-3"
>
<
button
type
=
"button"
onClick
=
{
addQuestion
}
>
질문 추가
</
button
>
</
div
>
<
div
>
<
button
type
=
"submit"
className
=
"border bg-themeColor my-5 py-2 px-3 font-bold text-white"
>
저장하기
</
button
>
</
div
>
</
div
>
</
form
>
</>
);
};
frontend/src/survey/EditResultButton.tsx
deleted
100644 → 0
View file @
e7ae6d3f
import
React
from
"
react
"
;
import
{
NavLink
}
from
"
react-router-dom
"
;
import
{
Outlet
,
useNavigate
,
useParams
}
from
"
react-router-dom
"
;
export
const
EditResultButton
=
()
=>
{
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
navigate
=
useNavigate
();
return
(
<
div
>
<
div
className
=
"flex place-content-center mt-6"
>
<
NavLink
to
=
{
`/surveys/
${
surveyId
}
/edit`
}
style
=
{
({
isActive
})
=>
isActive
?
{
width
:
"
140px
"
,
color
:
"
white
"
,
backgroundColor
:
"
#008080
"
,
borderTopLeftRadius
:
"
25px
"
,
borderBottomLeftRadius
:
"
25px
"
,
textAlign
:
"
center
"
,
fontWeight
:
"
bold
"
,
fontSize
:
"
20px
"
,
}
:
{
width
:
"
140px
"
,
borderWidth
:
"
1px
"
,
borderColor
:
"
#008080
"
,
borderTopLeftRadius
:
"
25px
"
,
borderBottomLeftRadius
:
"
25px
"
,
textAlign
:
"
center
"
,
fontSize
:
"
18px
"
,
}
}
>
<
div
className
=
"m-3 "
>
설문지 수정
</
div
>
</
NavLink
>
<
NavLink
to
=
{
`/surveys/
${
surveyId
}
/result`
}
style
=
{
({
isActive
})
=>
isActive
?
{
width
:
"
140px
"
,
color
:
"
white
"
,
backgroundColor
:
"
#008080
"
,
borderTopRightRadius
:
"
25px
"
,
borderBottomRightRadius
:
"
25px
"
,
textAlign
:
"
center
"
,
fontWeight
:
"
bold
"
,
fontSize
:
"
20px
"
,
}
:
{
width
:
"
140px
"
,
borderWidth
:
"
1px
"
,
borderColor
:
"
#008080
"
,
borderTopRightRadius
:
"
25px
"
,
borderBottomRightRadius
:
"
25px
"
,
textAlign
:
"
center
"
,
fontSize
:
"
18px
"
,
}
}
>
<
div
className
=
"m-3"
>
응답결과
</
div
>
</
NavLink
>
</
div
>
<
Outlet
/>
</
div
>
);
};
frontend/src/survey/EditSurvey.tsx
deleted
100644 → 0
View file @
e7ae6d3f
import
React
,
{
FormEvent
,
useEffect
,
useState
}
from
"
react
"
;
import
{
useParams
,
useLocation
,
useNavigate
}
from
"
react-router-dom
"
;
import
{
questionApi
,
surveyApi
}
from
"
../apis
"
;
import
{
SpinnerIcon
}
from
"
../icons
"
;
import
{
Question
}
from
"
../questions
"
;
import
{
IQuestionData
,
ISurvey
}
from
"
../types
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
export
const
EditSurvey
=
()
=>
{
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
interface
CustomizedState
{
save
:
boolean
;
}
const
[
isEditing
,
setIsEditing
]
=
useState
<
{
qid
:
string
;
isEditing
:
boolean
}[]
>
();
const
[
error
,
setError
]
=
useState
(
""
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
navigate
=
useNavigate
();
const
[
survey
,
setSurvey
]
=
useState
<
ISurvey
>
({
_id
:
surveyId
||
""
,
user
:
{},
title
:
""
,
comment
:
""
,
questions
:
[],
});
useEffect
(()
=>
{
getSurvey
();
},
[
surveyId
]);
async
function
getSurvey
()
{
try
{
if
(
surveyId
)
{
const
thisSurvey
:
ISurvey
=
await
surveyApi
.
getSurvey
(
surveyId
);
const
initEditing
=
thisSurvey
.
questions
.
map
((
question
)
=>
{
return
{
qid
:
question
.
_id
,
isEditing
:
false
};
});
// console.log("init editing", initEditing);
setIsEditing
(
initEditing
);
setSurvey
(
thisSurvey
);
setSuccess
(
true
);
setError
(
""
);
}
else
{
setLoading
(
true
);
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
const
handleEditing
=
(
qid
:
string
,
edited
:
boolean
)
=>
{
console
.
log
(
"
handle editing:
"
,
qid
,
edited
);
if
(
isEditing
)
{
const
index
=
isEditing
.
findIndex
((
q
)
=>
q
.
qid
===
qid
);
isEditing
[
index
].
isEditing
=
edited
;
setIsEditing
([...
isEditing
]);
}
};
const
handleQuestion
=
(
element
:
IQuestionData
)
=>
{
const
index
=
survey
.
questions
.
findIndex
(
(
question
)
=>
question
.
_id
===
element
.
_id
);
survey
.
questions
[
index
]
=
element
;
const
newList
=
[...
survey
.
questions
];
console
.
log
(
"
new list in handle question
"
,
newList
);
setSurvey
({
...
survey
,
questions
:
newList
});
};
const
handleSurvey
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
{
name
,
value
}
=
event
.
currentTarget
;
setSurvey
({
...
survey
,
[
name
]:
value
});
};
async
function
handleSubmit
(
event
:
FormEvent
)
{
event
.
preventDefault
();
const
notEditComplete
=
isEditing
?.
find
((
el
)
=>
el
.
isEditing
);
if
(
notEditComplete
)
{
alert
(
"
아직 수정이 완료되지 않은 질문이 존재합니다.
"
);
}
else
{
try
{
const
newSurvey
:
ISurvey
=
await
surveyApi
.
editSurvey
(
survey
);
console
.
log
(
newSurvey
);
setSuccess
(
true
);
alert
(
"
저장되었습니다
"
);
navigate
(
"
/profile
"
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
}
async
function
addQuestion
()
{
try
{
if
(
surveyId
)
{
// const questions: BasicQuestionType[] = await questionApi.createQuestion(
// surveyId
// );
// console.log(questions);
const
question
:
IQuestionData
=
await
questionApi
.
createQuestion
(
surveyId
);
console
.
log
(
question
);
// const addedEditing = questions.map((question) => {
// return { qid: question._id, isEditing: false };
// });
// console.log("added editing", addedEditing);
isEditing
&&
setIsEditing
([...
isEditing
,
{
qid
:
question
.
_id
,
isEditing
:
true
}]);
// setSurvey({ ...survey, questions: questions });
setSurvey
({
...
survey
,
questions
:
[...
questions
,
question
]
});
setSuccess
(
true
);
setError
(
""
);
}
else
{
setLoading
(
true
);
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
async
function
deleteQuestion
(
id
:
string
)
{
const
newList
:
IQuestionData
[]
=
[...
survey
.
questions
];
try
{
const
newQuestion
:
IQuestionData
=
await
questionApi
.
deleteQuestion
(
id
);
setSurvey
({
...
survey
,
questions
:
newList
.
filter
((
a
)
=>
a
.
_id
!==
id
)
});
setSuccess
(
true
);
setError
(
""
);
}
catch
(
error
)
{
catchErrors
(
error
,
setError
);
}
finally
{
setLoading
(
false
);
}
}
const
questions
=
survey
.
questions
;
// console.log(questions);
// console.log("isediting", isEditing);
return
(
<>
{
error
?
alert
(
error
)
:
<></>
}
{
loading
&&
(
<
SpinnerIcon
className
=
"animate-spin h-5 w-5 mr-1 text-slate"
/>
)
}
<
form
onSubmit
=
{
handleSubmit
}
>
<
div
className
=
"flex flex-col place-items-center"
>
<
div
className
=
"flex flex-col container place-items-center mt-4"
>
<
input
type
=
"text"
name
=
"title"
className
=
"font-bold text-4xl text-center m-2 border-b-2"
placeholder
=
"설문지 제목"
value
=
{
survey
.
title
}
onChange
=
{
handleSurvey
}
></
input
>
<
input
type
=
"text"
name
=
"comment"
className
=
"font-bold text-1xl text-center m-2 border-b-2 resize-none"
placeholder
=
"설문조사에 대한 설명을 입력해주세요"
size
=
{
50
}
value
=
{
survey
.
comment
}
onChange
=
{
handleSurvey
}
></
input
>
</
div
>
{
questions
.
map
((
question
)
=>
(
<
Question
key
=
{
question
.
_id
}
element
=
{
question
}
isEditing
=
{
isEditing
?.
filter
((
q
)
=>
q
.
qid
===
question
.
_id
)[
0
]
?.
isEditing
??
false
}
handleEditing
=
{
handleEditing
}
handleQuestion
=
{
handleQuestion
}
deleteQuestion
=
{
deleteQuestion
}
/>
))
}
<
div
className
=
"flex w-4/5 content-center justify-center border-2 border-themeColor2 border-addQuestionColor h-8 mt-3 rounded-lg "
>
<
button
type
=
"button"
onClick
=
{
addQuestion
}
>
질문 추가
</
button
>
</
div
>
<
div
>
<
button
type
=
"submit"
className
=
"border bg-themeColor my-5 py-2 px-3 font-bold text-white"
>
저장하기
</
button
>
</
div
>
</
div
>
</
form
>
</>
);
};
frontend/src/survey/SameSurvey.tsx
deleted
100644 → 0
View file @
e7ae6d3f
import
React
from
"
react
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
export
const
SameSurvey
=
()
=>
{
const
navigate
=
useNavigate
();
return
(
<
div
className
=
"flex flex-col place-items-center mt-24"
>
<
div
className
=
"flex flex-col container place-items-center place-content-center space-y-5 space-x-2 w-full h-56"
>
<
p
className
=
"text-3xl font-bold px-3"
>
이미 제출된 설문조사입니다
</
p
>
<
button
className
=
"flex place-content-start rounded-lg bg-themeColor w-20 h-10 text-center py-2 px-4 text-white"
type
=
"button"
onClick
=
{
()
=>
navigate
(
"
/
"
)
}
>
홈으로
</
button
>
</
div
>
</
div
>
);
};
frontend/src/survey/index.tsx
deleted
100644 → 0
View file @
e7ae6d3f
export
{
EditResultButton
}
from
"
./EditResultButton
"
;
frontend/src/surveys/AQuestion.tsx
0 → 100644
View file @
be1ba639
import
React
from
"
react
"
;
import
{
IQuestionData
,
IAnswer
}
from
"
../types
"
;
import
{
getAnswerElementByType
}
from
"
../helpers
"
;
type
Props
=
{
question
:
IQuestionData
;
answer
:
IAnswer
;
};
export
const
AQuestion
=
({
question
,
answer
}:
Props
)
=>
{
return
(
<
div
className
=
"flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-4 rounded-lg"
>
<
div
className
=
"flex my-1 w-11/12 place-content-between items-center"
>
<
div
className
=
"text-xl font-bold"
>
{
question
.
title
}
</
div
>
{
question
.
isRequired
?
(
<
div
className
=
"text-xs text-red-600"
>
* 필수질문
</
div
>
)
:
(
<></>
)
}
</
div
>
<
div
className
=
"w-11/12 text-slate-500"
>
{
question
.
comment
}
</
div
>
{
getAnswerElementByType
(
question
,
answer
)
}
</
div
>
);
};
frontend/src/
result
s/Accordion.tsx
→
frontend/src/
survey
s/Accordion.tsx
View file @
be1ba639
import
React
,
{
useState
,
useRef
,
useEffect
}
from
"
react
"
;
import
React
,
{
useState
,
useRef
,
useEffect
}
from
"
react
"
;
import
{
IQuestionData
}
from
"
../types
"
;
import
{
IQuestionData
}
from
"
../types
"
;
import
{
REssayForm
}
from
"
./REssayForm
"
;
// import {
import
{
RCheckboxForm
}
from
"
./RCheckboxForm
"
;
// REssay,
import
{
RRadioForm
}
from
"
./RRadioForm
"
;
// RCheckbox,
import
{
RDropdownForm
}
from
"
./RDropdownForm
"
;
// RRadio,
import
{
RFileForm
}
from
"
./RFileForm
"
;
// RDropdown,
import
{
RRatingForm
}
from
"
./RRatingForm
"
;
// RFile,
import
{
RDateForm
}
from
"
./RDateForm
"
;
// RRating,
// RDate,
// } from "../forms";
import
{
getResultElementByType
}
from
"
../helpers/question.helper
"
;
type
AccordionProps
=
{
type
AccordionProps
=
{
question
:
IQuestionData
;
question
:
IQuestionData
;
...
@@ -21,26 +24,26 @@ export const Accordion = ({ question }: AccordionProps) => {
...
@@ -21,26 +24,26 @@ export const Accordion = ({ question }: AccordionProps) => {
setOpened
(
!
isOpened
);
setOpened
(
!
isOpened
);
setHeight
(
!
isOpened
?
`
${
contentElement
.
current
?.
scrollHeight
}
px`
:
"
0px
"
);
setHeight
(
!
isOpened
?
`
${
contentElement
.
current
?.
scrollHeight
}
px`
:
"
0px
"
);
};
};
function
getContent
(
question
:
IQuestionData
)
{
//
function getContent(question: IQuestionData) {
switch
(
question
.
type
)
{
//
switch (question.type) {
case
"
essay
"
:
//
case "
singletext
":
return
<
REssay
Form
question
=
{
question
}
/>;
//
return <REssay question={question} />;
case
"
radio
"
:
//
case "radio":
return
<
RRadio
Form
question
=
{
question
}
/>;
//
return <RRadio question={question} />;
case
"
checkbox
"
:
//
case "checkbox":
return
<
RCheckbox
Form
question
=
{
question
}
/>;
//
return <RCheckbox question={question} />;
case
"
dropdown
"
:
//
case "dropdown":
return
<
RDropdown
Form
question
=
{
question
}
/>;
//
return <RDropdown question={question} />;
case
"
file
"
:
//
case "file":
return
<
RFile
Form
question
=
{
question
}
/>;
//
return <RFile question={question} />;
case
"
rating
"
:
//
case "rating":
return
<
RRating
Form
question
=
{
question
}
/>;
//
return <RRating question={question} />;
case
"
date
"
:
//
case "date":
return
<
RDate
Form
question
=
{
question
}
/>;
//
return <RDate question={question} />;
default
:
//
default:
return
<></>;
//
return <></>;
}
//
}
}
//
}
// console.log(question);
// console.log(question);
...
@@ -60,7 +63,7 @@ export const Accordion = ({ question }: AccordionProps) => {
...
@@ -60,7 +63,7 @@ export const Accordion = ({ question }: AccordionProps) => {
style
=
{
{
height
:
height
}
}
style
=
{
{
height
:
height
}
}
className
=
"bg-gray-100 overflow-hidden transition-all duration-300"
className
=
"bg-gray-100 overflow-hidden transition-all duration-300"
>
>
{
question
.
answers
&&
get
Content
(
question
)
}
{
question
.
answers
&&
get
ResultElementByType
(
question
)
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
frontend/src/survey/ResultSurvey.tsx
→
frontend/src/survey
s
/ResultSurvey.tsx
View file @
be1ba639
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
answerApi
,
surveyApi
}
from
"
../apis
"
;
import
{
answerApi
,
surveyApi
}
from
"
../apis
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
{
Accordion
}
from
"
.
./results
"
;
import
{
Accordion
}
from
"
.
/Accordion
"
;
import
{
useParams
}
from
"
react-router-dom
"
;
import
{
useParams
}
from
"
react-router-dom
"
;
import
{
ISurvey
}
from
"
../types
"
;
import
{
ISurvey
}
from
"
../types
"
;
...
...
frontend/src/surveys/index.tsx
View file @
be1ba639
...
@@ -3,3 +3,4 @@ export { CreateSurvey } from "./CreateSurvey";
...
@@ -3,3 +3,4 @@ export { CreateSurvey } from "./CreateSurvey";
export
{
EditSurvey
}
from
"
./EditSurvey
"
;
export
{
EditSurvey
}
from
"
./EditSurvey
"
;
export
{
Preview
}
from
"
./Preview
"
;
export
{
Preview
}
from
"
./Preview
"
;
export
{
Profile
}
from
"
./Profile
"
;
export
{
Profile
}
from
"
./Profile
"
;
export
{
ResultSurvey
}
from
"
./ResultSurvey
"
;
frontend/src/types/index.ts
View file @
be1ba639
import
{
QUESTION_TYPES
}
from
"
../commons
"
;
// 타입 지정
export
interface
IUser
{
export
interface
IUser
{
email
?:
string
;
email
?:
string
;
isLoggedIn
:
boolean
;
isLoggedIn
:
boolean
;
...
@@ -11,7 +14,7 @@ export interface SignupUser {
...
@@ -11,7 +14,7 @@ export interface SignupUser {
}
}
export
interface
ISurvey
{
export
interface
ISurvey
{
_id
:
string
;
_id
?
:
string
;
user
:
any
;
user
:
any
;
title
:
string
;
title
:
string
;
comment
:
string
;
comment
:
string
;
...
@@ -33,7 +36,7 @@ interface IBasicContent {
...
@@ -33,7 +36,7 @@ interface IBasicContent {
export
interface
IQuestionData
{
export
interface
IQuestionData
{
_id
?:
string
;
_id
?:
string
;
order
:
number
;
order
:
number
;
type
:
string
;
type
:
IQuestionType
;
title
:
string
;
title
:
string
;
isRequired
:
boolean
;
isRequired
:
boolean
;
comment
:
string
;
comment
:
string
;
...
@@ -42,13 +45,8 @@ export interface IQuestionData {
...
@@ -42,13 +45,8 @@ export interface IQuestionData {
[
key
:
string
]:
string
|
number
|
boolean
|
any
;
[
key
:
string
]:
string
|
number
|
boolean
|
any
;
}
}
export
interface
AnswerQuestionType
extends
IQuestionData
{
export
interface
CreateQuestionData
extends
IQuestionData
{
requiredCheck
:
boolean
;
isEditing
:
boolean
;
answer
:
any
;
}
export
interface
AnswerSurveyType
extends
ISurvey
{
questions
:
AnswerQuestionType
[];
}
}
export
interface
IEssay
extends
IQuestionData
{}
export
interface
IEssay
extends
IQuestionData
{}
...
@@ -60,11 +58,6 @@ export interface IRadio extends IQuestionData {
...
@@ -60,11 +58,6 @@ export interface IRadio extends IQuestionData {
};
};
}
}
interface
IChoices
{
value
:
number
;
text
:
string
;
}
export
interface
ICheckbox
extends
IQuestionData
{
export
interface
ICheckbox
extends
IQuestionData
{
content
:
IBasicContent
&
{
maxCount
:
number
};
content
:
IBasicContent
&
{
maxCount
:
number
};
}
}
...
@@ -87,21 +80,55 @@ export interface IRating extends IQuestionData {
...
@@ -87,21 +80,55 @@ export interface IRating extends IQuestionData {
};
};
}
}
export
interface
AnswersType
{
export
interface
IAnswer
{
questionId
:
string
;
question
:
IQuestionData
;
type
:
string
;
surveyId
:
string
;
answer
:
any
;
guestId
?:
string
;
requiredCheck
:
boolean
;
content
:
any
;
}
}
export
interface
AnswerType
{
export
interface
IAnswerRequestData
{
questionId
:
string
;
surveyId
:
string
;
surveyId
:
string
;
guestId
:
string
;
guestId
?
:
string
;
answers
:
AnswersType
[]
;
content
:
any
;
}
}
export
interface
AnswerProps
{
// export interface IAnswerSurvey extends ISurvey {
// questions: IAnswerQuestion[];
// }
// export interface IAnswers {
// questionId: string;
// type: string;
// content: any;
// }
// export interface IAnswer {
// surveyId: string;
// guestId: string;
// answers: IAnswers[];
// }
export
interface
IAnswerProps
{
element
:
IQuestionData
;
element
:
IQuestionData
;
answer
Question
:
Answer
QuestionType
;
answer
:
I
Answer
;
// answers: AnswersType | undefined;
// answers: AnswersType | undefined;
// handleAnswer: () => void;
// handleAnswer: () => void;
}
}
export
interface
IQuestionProps
{
element
:
CreateQuestionData
;
// isEditing: boolean;
// handleEditing: Function;
handleQuestion
:
Function
;
deleteQuestion
:
Function
;
}
export
type
IQuestionFormProps
=
Pick
<
IQuestionProps
,
"
element
"
|
"
handleQuestion
"
>
&
{
isEditing
:
boolean
};
export
type
IQuestionType
=
keyof
typeof
QUESTION_TYPES
;
frontend/tsconfig.json
View file @
be1ba639
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
//
"disableReferencedProjectLoad"
:
true
,
/*
Reduce
the
number
of
projects
loaded
automatically
by
TypeScript.
*/
//
"disableReferencedProjectLoad"
:
true
,
/*
Reduce
the
number
of
projects
loaded
automatically
by
TypeScript.
*/
/*
Language
and
Environment
*/
/*
Language
and
Environment
*/
"target"
:
"
es2016
"
,
/*
Set
the
JavaScript
language
version
for
emitted
JavaScript
and
include
compatible
library
declarations.
*/
"target"
:
"
ES2020
"
,
/*
Set
the
JavaScript
language
version
for
emitted
JavaScript
and
include
compatible
library
declarations.
*/
//
"lib"
:
[],
/*
Specify
a
set
of
bundled
library
declaration
files
that
describe
the
target
runtime
environment.
*/
//
"lib"
:
[],
/*
Specify
a
set
of
bundled
library
declaration
files
that
describe
the
target
runtime
environment.
*/
"jsx"
:
"react"
,
/*
Specify
what
JSX
code
is
generated.
*/
"jsx"
:
"react"
,
/*
Specify
what
JSX
code
is
generated.
*/
//
"experimentalDecorators"
:
true
,
/*
Enable
experimental
support
for
TC
39
stage
2
draft
decorators.
*/
//
"experimentalDecorators"
:
true
,
/*
Enable
experimental
support
for
TC
39
stage
2
draft
decorators.
*/
...
...
src/controllers/answer.controller.ts
View file @
be1ba639
import
{
NextFunction
,
Request
,
Response
}
from
"
express
"
;
import
{
NextFunction
,
Request
,
Response
}
from
"
express
"
;
import
{
asyncWrap
,
isEmpty
}
from
"
../helpers
"
;
import
{
asyncWrap
,
formidableFilesToArray
,
isEmpty
}
from
"
../helpers
"
;
import
{
TypedRequest
}
from
"
../types
"
;
import
type
{
TypedRequest
}
from
"
../types
"
;
import
formidable
from
"
formidable
"
;
import
formidable
from
"
formidable
"
;
import
{
FileInfo
}
from
"
../models
"
;
import
{
FileInfo
,
IAnswer
}
from
"
../models
"
;
import
{
fileDb
,
userDb
,
answerDb
,
surveyDb
}
from
"
../db
"
;
import
{
fileDb
,
userDb
,
answerDb
,
surveyDb
}
from
"
../db
"
;
import
fs
from
"
fs/promises
"
;
import
fs
from
"
fs/promises
"
;
export
const
createAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
export
const
createAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
const
req
=
reqExp
as
TypedRequest
;
const
req
=
reqExp
as
TypedRequest
;
const
answer
=
req
.
body
;
const
answer
=
req
.
body
;
console
.
log
(
"
answer in create answers:
"
,
answer
);
const
answers
=
JSON
.
parse
(
answer
.
answers
);
const
answers
=
JSON
.
parse
(
answer
.
answers
);
answer
.
answers
=
answers
;
answer
.
answers
=
answers
;
let
files
:
any
[]
=
[];
let
files
:
any
[]
=
[];
...
@@ -47,7 +48,7 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
...
@@ -47,7 +48,7 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
surveyId
:
answer
.
surveyId
,
surveyId
:
answer
.
surveyId
,
guestId
:
answer
.
guestId
,
guestId
:
answer
.
guestId
,
questionId
:
element
.
questionId
,
questionId
:
element
.
questionId
,
answer
:
element
.
answer
,
content
:
element
.
answer
,
});
});
});
});
await
Promise
.
all
(
c
);
await
Promise
.
all
(
c
);
...
@@ -63,6 +64,45 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
...
@@ -63,6 +64,45 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
}
}
});
});
export
const
createAnswersWithoutFile
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
answers
=
req
.
body
as
IAnswer
[];
const
newAnswers
=
await
Promise
.
all
(
answers
.
map
(
async
(
answer
)
=>
await
answerDb
.
createAnswer
({
surveyId
:
answer
.
surveyId
,
guestId
:
answer
.
guestId
,
questionId
:
answer
.
questionId
,
content
:
answer
.
content
,
})
)
);
console
.
log
(
"
new answers:
"
,
newAnswers
);
res
.
json
(
newAnswers
);
});
export
const
createAnswerWithFile
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
const
req
=
reqExp
as
TypedRequest
;
console
.
log
(
"
body:
"
,
req
.
body
,
"
files:
"
,
req
.
files
);
const
answer
=
req
.
body
;
let
fileInfos
;
const
files
=
formidableFilesToArray
(
req
.
files
.
uploadFiles
);
if
(
files
)
{
fileInfos
=
await
Promise
.
all
(
files
.
map
(
async
(
file
)
=>
await
fileDb
.
createFile
(
file
))
);
}
answer
.
content
=
fileInfos
;
const
newAnswer
=
await
answerDb
.
createAnswer
(
answer
);
console
.
log
(
"
new answer:
"
,
newAnswer
);
res
.
json
(
newAnswer
);
});
export
const
getAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
export
const
getAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
const
req
=
reqExp
as
TypedRequest
;
const
req
=
reqExp
as
TypedRequest
;
const
{
surveyId
}
=
req
.
params
;
const
{
surveyId
}
=
req
.
params
;
...
...
src/db/answer.db.ts
View file @
be1ba639
...
@@ -12,7 +12,7 @@ export const getAnswers = async (surveyId: string) => {
...
@@ -12,7 +12,7 @@ export const getAnswers = async (surveyId: string) => {
{
{
$group
:
{
$group
:
{
_id
:
"
$questionId
"
,
_id
:
"
$questionId
"
,
answers
:
{
$push
:
"
$
answer
"
},
answers
:
{
$push
:
"
$
content
"
},
},
},
},
},
{
{
...
...
src/helpers/index.ts
View file @
be1ba639
import
type
{
File
}
from
"
formidable
"
;
export
{
asyncWrap
}
from
"
./asyncWrap
"
;
export
{
asyncWrap
}
from
"
./asyncWrap
"
;
export
const
isEmpty
=
(
obj
:
any
)
=>
{
export
const
isEmpty
=
(
obj
:
any
)
=>
{
...
@@ -7,3 +9,13 @@ export const isEmpty = (obj: any) => {
...
@@ -7,3 +9,13 @@ export const isEmpty = (obj: any) => {
Object
.
getPrototypeOf
(
obj
)
===
Object
.
prototype
Object
.
getPrototypeOf
(
obj
)
===
Object
.
prototype
);
);
};
};
export
const
formidableFilesToArray
=
(
files
:
File
|
File
[]):
File
[]
|
null
=>
{
if
(
Array
.
isArray
(
files
))
{
return
files
;
}
if
(
isEmpty
(
files
))
{
return
null
;
}
return
[
files
];
};
src/models/answer.model.ts
View file @
be1ba639
...
@@ -5,7 +5,7 @@ export interface IAnswer {
...
@@ -5,7 +5,7 @@ export interface IAnswer {
surveyId
?:
Types
.
ObjectId
;
surveyId
?:
Types
.
ObjectId
;
questionId
?:
Types
.
ObjectId
;
questionId
?:
Types
.
ObjectId
;
guestId
?:
string
;
guestId
?:
string
;
answer
?:
any
;
content
?:
any
;
}
}
const
schema
=
new
Schema
<
IAnswer
>
(
const
schema
=
new
Schema
<
IAnswer
>
(
...
@@ -13,7 +13,7 @@ const schema = new Schema<IAnswer>(
...
@@ -13,7 +13,7 @@ const schema = new Schema<IAnswer>(
surveyId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
"
Survey
"
},
surveyId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
"
Survey
"
},
questionId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
"
Question
"
},
questionId
:
{
type
:
Schema
.
Types
.
ObjectId
,
ref
:
"
Question
"
},
guestId
:
{
type
:
String
},
guestId
:
{
type
:
String
},
answer
:
{
type
:
Object
},
content
:
{
type
:
Object
},
},
},
{
timestamps
:
true
}
{
timestamps
:
true
}
);
);
...
...
src/routes/answer.route.ts
View file @
be1ba639
...
@@ -3,7 +3,12 @@ import { answerCtrl, authCtrl, fileCtrl, surveyCtrl } from "../controllers";
...
@@ -3,7 +3,12 @@ import { answerCtrl, authCtrl, fileCtrl, surveyCtrl } from "../controllers";
const
router
=
express
.
Router
();
const
router
=
express
.
Router
();
router
.
route
(
"
/
"
).
post
(
fileCtrl
.
uploadFile
,
answerCtrl
.
createAnswers
);
router
.
route
(
"
/
"
).
post
(
answerCtrl
.
createAnswersWithoutFile
);
router
.
route
(
"
/upload
"
)
.
post
(
fileCtrl
.
uploadFile
,
answerCtrl
.
createAnswerWithFile
);
router
router
.
route
(
"
/:surveyId
"
)
.
route
(
"
/:surveyId
"
)
.
get
(
authCtrl
.
requireLogin
,
authCtrl
.
authenticate
,
answerCtrl
.
getAnswers
);
.
get
(
authCtrl
.
requireLogin
,
authCtrl
.
authenticate
,
answerCtrl
.
getAnswers
);
...
...
Prev
1
2
3
Next
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