Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
students
survey
Commits
578446f7
Commit
578446f7
authored
Jul 25, 2022
by
Jiwon Yoon
Browse files
result 불러오기 완성
parent
6262a322
Changes
9
Hide whitespace changes
Inline
Side-by-side
frontend/src/SurveyRouter.tsx
View file @
578446f7
...
...
@@ -18,11 +18,11 @@ export const SurveyRouter = () => {
<
Route
index
element
=
{
<
Home
/>
}
/>
<
Route
path
=
"login"
element
=
{
<
Login
/>
}
/>
<
Route
path
=
"signup"
element
=
{
<
SignUp
/>
}
/>
<
Route
path
=
"surveys/
edit
/"
element
=
{
<
EditResultButton
/>
}
>
<
Route
path
=
"
:surveyId
"
element
=
{
<
EditSurvey
/>
}
/>
<
Route
path
=
"
:surveyId/
result"
element
=
{
<
ResultSurvey
/>
}
/>
<
Route
path
=
"surveys/
:surveyId
/"
element
=
{
<
EditResultButton
/>
}
>
<
Route
path
=
"
edit
"
element
=
{
<
EditSurvey
/>
}
/>
<
Route
path
=
"result"
element
=
{
<
ResultSurvey
/>
}
/>
</
Route
>
<
Route
path
=
"survey
s
/:surveyId"
element
=
{
<
AnswerSurveyForm
/>
}
/>
<
Route
path
=
"survey/:surveyId"
element
=
{
<
AnswerSurveyForm
/>
}
/>
<
Route
path
=
"profile"
element
=
{
...
...
frontend/src/profile/MySurveyCard.tsx
View file @
578446f7
...
...
@@ -16,20 +16,14 @@ export const MySurveyCard = ({ data }: Props) => {
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
editSurvey
=
()
=>
{
navigate
(
`/surveys/
edit/
${
data
.
_id
}
`
,
{
navigate
(
`/surveys/
${
data
.
_id
}
/edit
`
,
{
replace
:
true
,
state
:
{
save
:
true
},
});
};
const
goSurvey
=
()
=>
{
navigate
(
`/surveys/
${
data
.
_id
}
`
,
{
replace
:
true
,
});
};
const
copyLink
=
()
=>
{
navigator
.
clipboard
.
writeText
(
`http://localhost:8080/survey
s
/
${
data
.
_id
}
`
);
navigator
.
clipboard
.
writeText
(
`http://localhost:8080/survey/
${
data
.
_id
}
`
);
alert
(
"
설문조사의 링크가 클립보드에 저장되었습니다.
"
);
};
...
...
frontend/src/profile/Profile.tsx
View file @
578446f7
...
...
@@ -21,7 +21,7 @@ export const Profile = () => {
async
function
createSurvey
()
{
const
newSurvey
:
SurveyType
=
await
surveyApi
.
createSurvey
(
survey
);
navigate
(
`/surveys/
edit/
${
newSurvey
.
_id
}
`
,
{
navigate
(
`/surveys/
${
newSurvey
.
_id
}
/edit
`
,
{
replace
:
true
,
});
}
...
...
@@ -36,7 +36,6 @@ export const Profile = () => {
return
(
<
div
className
=
"flex flex-col items-center"
>
<
div
className
=
"mt-10 text-xl font-bold"
>
나의 설문조사
</
div
>
<
img
src
=
{
`
${
baseImageUrl
}
/9e24ad36a2947b08c89913b01`
}
/>
<
div
className
=
"grid grid-cols-1 md:grid-cols-4 sm:grid-cols-2 gap-4 mt-6"
>
<
button
onClick
=
{
createSurvey
}
...
...
frontend/src/survey/Accordion.tsx
View file @
578446f7
import
React
,
{
useState
,
useRef
}
from
"
react
"
;
import
React
,
{
useState
,
useRef
,
useEffect
}
from
"
react
"
;
import
{
baseImageUrl
}
from
"
../apis
"
;
import
{
BasicQuestionType
}
from
"
../types
"
;
type
AccordionProps
=
{
question
:
any
;
answers
:
any
;
};
const
Accordion
=
({
question
,
answers
}:
AccordionProps
)
=>
{
const
Accordion
=
({
question
}:
AccordionProps
)
=>
{
const
[
isOpened
,
setOpened
]
=
useState
<
boolean
>
(
false
);
const
[
height
,
setHeight
]
=
useState
<
string
>
(
"
0px
"
);
const
contentElement
=
useRef
<
HTMLDivElement
>
(
null
);
// useEffect(() => {
// if (question.type === "file") {
// getFiles();
// }
// }, []);
// async function getFiles() {
// try {
// } catch (error) {}
// }
const
HandleOpening
=
()
=>
{
setOpened
(
!
isOpened
);
setHeight
(
!
isOpened
?
`
${
contentElement
.
current
?.
scrollHeight
}
px`
:
"
0px
"
);
...
...
@@ -26,9 +37,17 @@ const Accordion = ({ question, answers }: AccordionProps) => {
style
=
{
{
height
:
height
}
}
className
=
"bg-gray-100 overflow-hidden transition-all duration-700"
>
{
answers
.
map
((
answer
:
any
)
=>
(
<
p
className
=
"p-4"
>
{
answer
.
answer
}
</
p
>
))
}
{
question
.
type
===
"
file
"
?
question
.
answers
.
map
((
answer
:
any
)
=>
(
<
img
key
=
{
answer
.
url
}
alt
=
"file"
src
=
{
`
${
baseImageUrl
}
/
${
answer
.
url
}
`
}
/>
))
:
question
.
answers
.
map
((
answer
:
any
)
=>
(
<
p
className
=
"p-4"
>
{
answer
}
</
p
>
))
}
</
div
>
</
div
>
</
div
>
...
...
frontend/src/survey/EditResultButton.tsx
View file @
578446f7
...
...
@@ -6,18 +6,11 @@ export const EditResultButton = () => {
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
navigate
=
useNavigate
();
/*function editButtonClick(e: React.MouseEvent<HTMLButtonElement>) {
navigate(`/surveys/${surveyId}/edit`);
}
function resultButtonClick(e: React.MouseEvent<HTMLButtonElement>) {
navigate(`/surveys/${surveyId}/result`);
}*/
return
(
<
div
>
<
div
className
=
"flex place-content-center mt-6"
>
<
NavLink
to
=
{
`/surveys/
edit/
${
surveyId
}
`
}
to
=
{
`/surveys/
${
surveyId
}
/edit
`
}
style
=
{
({
isActive
})
=>
isActive
?
{
...
...
@@ -33,7 +26,7 @@ export const EditResultButton = () => {
<
div
className
=
"text-xl m-3 "
>
설문지 수정
</
div
>
</
NavLink
>
<
NavLink
to
=
{
`/surveys/
edit/
${
surveyId
}
/result`
}
to
=
{
`/surveys/
${
surveyId
}
/result`
}
style
=
{
({
isActive
})
=>
isActive
?
{
...
...
frontend/src/survey/ResultSurvey.tsx
View file @
578446f7
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
answerApi
}
from
"
../apis
"
;
import
{
answerApi
,
surveyApi
}
from
"
../apis
"
;
import
{
catchErrors
}
from
"
../helpers
"
;
import
Accordion
from
"
./Accordion
"
;
import
{
useParams
}
from
"
react-router-dom
"
;
import
{
SurveyType
}
from
"
../types
"
;
export
const
ResultSurvey
=
()
=>
{
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
[
error
,
setError
]
=
useState
(
""
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
success
,
setSuccess
]
=
useState
(
false
);
const
[
answers
,
setAnswers
]
=
useState
([
{
_id
:
""
,
answers
:
[],
question
:
{}
},
]);
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
[
survey
,
setSurvey
]
=
useState
<
SurveyType
>
({
_id
:
surveyId
||
""
,
user
:
{},
title
:
""
,
comment
:
""
,
questions
:
[],
});
useEffect
(()
=>
{
getAnswers
();
},
[
surveyId
]);
...
...
@@ -19,9 +24,9 @@ export const ResultSurvey = () => {
async
function
getAnswers
()
{
try
{
if
(
surveyId
)
{
const
answers
=
await
answerApi
.
getAnswers
(
surveyId
);
console
.
log
(
answers
);
set
Answers
(
answers
);
const
survey
=
await
answerApi
.
getAnswers
(
surveyId
);
console
.
log
(
survey
);
set
Survey
(
survey
);
}
else
{
setLoading
(
true
);
}
...
...
@@ -32,40 +37,20 @@ export const ResultSurvey = () => {
}
}
const
data
=
[
{
title
:
"
1번질문
"
,
content
:
"
1번 답변들asdfadsgsjadhfasld;nvaldkfnbljgnahgvlajnbl janl;nvja; sabv;jnsvjl;asjvh asjfagkfnjf;nvasgn va;sdn va sglanksvl ds af adb adf afg dgafbg dfh jbvlkna lkslbk kjv nbkkdlfn akdl nvjbnkdjf nlkbakdn bkjnakjn n knk
"
,
},
{
title
:
"
2번질문
"
,
content
:
"
2번답변들
"
,
},
{
title
:
"
3번질문
"
,
content
:
"
3번답변들
"
,
},
];
return
(
<
div
className
=
"flex flex-col place-items-center"
>
<
div
className
=
"flex flex-col container place-items-center mt-4"
>
<
div
className
=
"font-bold text-4xl text-center m-2 border-b-2"
>
설문지 제목
{
survey
.
title
}
</
div
>
<
div
className
=
"font-bold text-1xl text-center m-2 resize-none"
>
설문조사 설명
{
survey
.
comment
}
</
div
>
</
div
>
<
div
className
=
"container w-11/12 place-self-center"
>
{
answers
.
map
((
item
)
=>
(
<
Accordion
key
=
{
item
.
_id
}
question
=
{
item
.
question
}
answers
=
{
item
.
answers
}
/>
{
survey
.
questions
.
map
((
question
)
=>
(
<
Accordion
key
=
{
question
.
_id
}
question
=
{
question
}
/>
))
}
</
div
>
</
div
>
...
...
frontend/src/types/index.ts
View file @
578446f7
...
...
@@ -27,6 +27,7 @@ export interface BasicQuestionType {
isRequired
:
boolean
;
comment
:
string
;
content
:
any
;
answers
?:
any
;
[
key
:
string
]:
string
|
number
|
boolean
|
any
;
}
...
...
src/controllers/answer.controller.ts
View file @
578446f7
...
...
@@ -3,7 +3,7 @@ import { asyncWrap } from "../helpers";
import
{
TypedRequest
}
from
"
../types
"
;
import
formidable
from
"
formidable
"
;
import
{
FileInfo
}
from
"
../models
"
;
import
{
fileDb
,
userDb
,
answerDb
}
from
"
../db
"
;
import
{
fileDb
,
userDb
,
answerDb
,
surveyDb
}
from
"
../db
"
;
import
fs
from
"
fs/promises
"
;
export
const
createAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
...
...
@@ -11,14 +11,18 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
const
answer
=
req
.
body
;
const
answers
=
JSON
.
parse
(
answer
.
answers
);
answer
.
answers
=
answers
;
const
files
=
req
.
files
.
uploadFiles
as
formidable
.
File
[];
let
files
:
any
[]
=
[];
if
(
Array
.
isArray
(
req
.
files
.
uploadFiles
))
{
files
=
req
.
files
.
uploadFiles
as
formidable
.
File
[];
}
else
{
files
.
push
(
req
.
files
.
uploadFiles
);
}
let
uploadFile
;
try
{
if
(
files
)
{
// 1) 파일을 DB에 저장 후 다시 retFile가져와서
// *근데 파일이 여러 개일 수 있기 때문에 순회해야 됨-map()을 쓰면 async function이 되어버려서 for문 이용함
for
(
let
index
=
0
;
index
<
files
.
length
;
index
++
)
{
const
file
=
files
[
index
];
// *근데 파일이 여러 개일 수 있기 때문에 순회해야 됨
const
f
=
files
.
map
(
async
(
file
)
=>
{
uploadFile
=
new
FileInfo
({
name
:
file
.
originalFilename
,
url
:
file
.
newFilename
,
...
...
@@ -31,26 +35,24 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
);
// 3) answer에다가 retFile의 _id 넣어주기
targetObj
.
answer
=
retFile
.
_id
;
}
});
await
Promise
.
all
(
f
);
}
// 3) Answer DB 만들기
console
.
log
(
"
원래 answer
"
,
answer
);
console
.
log
(
"
원래 answer
"
,
answer
.
answers
.
length
);
// for (let index = 0; index < answer.answers.length; index++) {
// const element = answer.answers[index];
// const newAnswer = await answerDb.createAnswer({
// surveyId: answer.surveyId,
// guestId: answer.guestId,
// questionId: element.questionId,
// answer: element.answer,
// });
// // console.log("DB에 넣은 answer", newAnswer);
// }
const
c
=
answer
.
answers
.
map
(
async
(
element
:
any
)
=>
{
const
newAnswer
=
await
answerDb
.
createAnswer
({
surveyId
:
answer
.
surveyId
,
guestId
:
answer
.
guestId
,
questionId
:
element
.
questionId
,
answer
:
element
.
answer
,
});
});
await
Promise
.
all
(
c
);
return
res
.
json
();
}
catch
(
error
:
any
)
{
console
.
log
(
"
error in create answer:
"
,
error
);
// 오류 발생시 저장된 파일 제거
if
(
files
)
{
if
(
req
.
files
)
{
// uploadFiles && (await fileDb.deleteFileById(uploadFiles._id.toString()));
// await fs.unlink(files.filepath);
}
...
...
@@ -61,11 +63,27 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
export
const
getAnswers
=
asyncWrap
(
async
(
reqExp
,
res
)
=>
{
const
req
=
reqExp
as
TypedRequest
;
const
{
surveyId
}
=
req
.
params
;
console
.
log
(
surveyId
);
try
{
const
survey
=
await
surveyDb
.
getSurveyById
(
surveyId
);
const
answers
=
await
answerDb
.
getAnswers
(
surveyId
);
console
.
log
(
"
Db에서 가져온 answers=
"
,
answers
);
return
res
.
json
(
answers
);
console
.
log
(
answers
);
const
jsonSurvey
=
survey
?.
toJSON
();
if
(
jsonSurvey
&&
answers
)
{
const
a
=
answers
.
map
(
async
(
a
)
=>
{
const
targetObj
=
jsonSurvey
.
questions
.
find
(
(
q
:
any
)
=>
String
(
q
.
_id
)
===
String
(
a
.
_id
)
)
as
any
;
if
(
targetObj
)
{
if
(
a
.
file
.
length
)
{
targetObj
.
answers
=
a
.
file
;
}
else
{
targetObj
.
answers
=
a
.
answers
;
}
}
});
await
Promise
.
all
(
a
);
}
return
res
.
json
(
jsonSurvey
);
}
catch
(
error
:
any
)
{
res
.
status
(
422
).
send
(
error
.
message
||
"
설문조사 결과 불러오기 오류
"
);
}
...
...
src/db/answer.db.ts
View file @
578446f7
...
...
@@ -10,19 +10,17 @@ export const getAnswers = async (surveyId: string) => {
const
answers
=
await
Answer
.
aggregate
([
{
$match
:
{
surveyId
:
new
Types
.
ObjectId
(
surveyId
)
}
},
{
$lookup
:
{
from
:
"
questions
"
,
localField
:
"
questionId
"
,
foreignField
:
"
_id
"
,
as
:
"
question
"
,
$group
:
{
_id
:
"
$questionId
"
,
answers
:
{
$push
:
"
$answer
"
},
},
},
{
$unwind
:
"
$question
"
},
{
$group
:
{
_id
:
"
$questionId
"
,
answers
:
{
$push
:
{
guestId
:
"
$guestId
"
,
answer
:
"
$answer
"
}
},
question
:
{
$mergeObjects
:
"
$question
"
},
$lookup
:
{
from
:
"
fileinfos
"
,
localField
:
"
answers
"
,
foreignField
:
"
_id
"
,
as
:
"
file
"
,
},
},
]);
...
...
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