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
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