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
b0b76f7f
Commit
b0b76f7f
authored
Sep 19, 2022
by
Yoon, Daeki
😅
Browse files
survey 수정 작업중
parent
67f22c42
Changes
10
Show whitespace changes
Inline
Side-by-side
docs/todo.md
View file @
b0b76f7f
...
...
@@ -2,4 +2,10 @@
## 리덕스
리덕스는 전역 상태를 관리하는 프레임워크입니다.
### 리덕스 데이터 비동기
1.
리덕스와 프론트 api와 연결을 해서 api에서 서버에서 데이터를 가져오면 리덕스 상태를 변경시켜야 하고 변경된 상태가 컴포넌트에 즉시 적용되도록 해야하는 문제를 연구해야 합니다.
-
[
리덕스 홈페이지 비동기 로직
](
https://redux.js.org/tutorials/fundamentals/part-6-async-logic
)
frontend/src/apis/survey.api.ts
View file @
b0b76f7f
import
axios
from
"
axios
"
;
import
{
ISurvey
}
from
"
../types
"
;
import
{
CreateQuestionData
,
IQuestionData
,
ISurvey
}
from
"
../types
"
;
import
baseUrl
from
"
./baseUrl
"
;
export
const
addQuestion
=
async
(
surveyId
:
string
,
question
:
IQuestionData
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
/questions`
,
question
);
return
data
;
};
export
const
createSurvey
=
async
(
survey
:
ISurvey
)
=>
{
const
{
data
}
=
await
axios
.
post
(
`
${
baseUrl
}
/surveys`
,
survey
);
return
data
;
};
export
const
deleteQuestion
=
async
(
surveyId
:
string
,
questionId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
/questions/
${
questionId
}
`
);
return
data
;
};
export
const
deleteSurvey
=
async
(
surveyId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
`
);
return
data
;
};
export
const
getSurvey
=
async
(
surveyId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
get
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
/edit`
);
return
data
;
...
...
@@ -22,11 +45,6 @@ export const getSurveys = async () => {
return
data
;
};
export
const
updateSurvey
=
async
(
survey
:
ISurvey
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/surveys/
${
survey
.
_id
}
`
,
survey
);
return
data
;
};
export
const
resultSurvey
=
async
(
survey
:
ISurvey
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/surveys/
${
survey
.
_id
}
/result`
,
...
...
@@ -35,7 +53,18 @@ export const resultSurvey = async (survey: ISurvey) => {
return
data
;
};
export
const
deleteSurvey
=
async
(
surveyId
:
string
)
=>
{
const
{
data
}
=
await
axios
.
delete
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
`
);
export
const
updateQuestion
=
async
(
surveyId
:
string
,
question
:
CreateQuestionData
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/surveys/
${
surveyId
}
/questions/
${
question
.
_id
}
`
,
question
);
return
data
;
};
export
const
updateSurvey
=
async
(
survey
:
ISurvey
)
=>
{
const
{
data
}
=
await
axios
.
put
(
`
${
baseUrl
}
/surveys/
${
survey
.
_id
}
`
,
survey
);
return
data
;
};
frontend/src/layouts/SurveyLayout.tsx
View file @
b0b76f7f
...
...
@@ -2,12 +2,16 @@ import React from "react";
import
{
NavLink
,
useOutletContext
}
from
"
react-router-dom
"
;
import
{
Outlet
,
useNavigate
,
useParams
}
from
"
react-router-dom
"
;
import
{
useSurveys
}
from
"
./SurveysLayout
"
;
import
type
{
ICreateSurvey
,
ISurvey
}
from
"
../types
"
;
import
type
{
CreateQuestionData
,
ICreateSurvey
,
ISurvey
}
from
"
../types
"
;
import
{
SpinnerIcon
}
from
"
../icons
"
;
import
{
surveyApi
}
from
"
../apis
"
;
type
SurveyContextType
=
{
survey
:
ICreateSurvey
;
update
:
(
survey
:
ISurvey
)
=>
Promise
<
any
>
;
createQuestion
:
(
question
:
CreateQuestionData
)
=>
Promise
<
any
>
;
removeQuestion
:
(
questionId
:
string
)
=>
Promise
<
any
>
;
updateQuestion
:
(
question
:
CreateQuestionData
)
=>
Promise
<
any
>
;
};
const
activeStyle
=
...
...
@@ -16,11 +20,11 @@ const inActiveStyle =
"
w-36 h-12 flex justify-center items-center bg-white border border-themeColor p-1 text-center font-bold text-xl
"
;
export
const
SurveyLayout
=
()
=>
{
const
{
surveys
,
update
}
=
useSurveys
();
const
{
surveys
,
update
,
updateLocalSurveysList
}
=
useSurveys
();
let
{
surveyId
}
=
useParams
<
{
surveyId
:
string
}
>
();
const
survey
=
surveys
.
find
((
survey
)
=>
survey
.
_id
===
surveyId
);
console
.
log
(
"
surveys in survey layout
"
,
surveys
);
//
console.log("surveys in survey layout", surveys);
if
(
!
survey
)
{
return
(
...
...
@@ -30,6 +34,40 @@ export const SurveyLayout = () => {
);
}
const
createQuestion
=
async
(
question
:
CreateQuestionData
)
=>
{
const
newQuestion
=
await
surveyApi
.
addQuestion
(
survey
.
_id
!
,
question
);
console
.
log
(
"
new question:
"
,
newQuestion
);
survey
.
questions
.
push
(
newQuestion
);
updateLocalSurveysList
(
survey
);
};
const
removeQuestion
=
async
(
questionId
:
string
)
=>
{
await
surveyApi
.
deleteQuestion
(
survey
.
_id
!
,
questionId
);
const
questions
=
survey
.
questions
;
const
updatedQuestions
=
questions
.
filter
((
q
)
=>
q
.
_id
!==
questionId
);
console
.
log
(
"
questions after deleted question:
"
,
updatedQuestions
);
survey
.
questions
=
updatedQuestions
;
updateLocalSurveysList
(
survey
);
};
const
updateQuestion
=
async
(
question
:
CreateQuestionData
)
=>
{
await
surveyApi
.
updateQuestion
(
survey
.
_id
!
,
question
);
const
questions
=
survey
.
questions
;
const
index
=
questions
.
findIndex
((
q
)
=>
q
.
_id
===
question
.
_id
);
if
(
index
<
0
)
{
return
;
}
questions
[
index
]
=
question
;
console
.
log
(
"
questions in update question:
"
,
questions
);
// setQuestions([...questions]);
survey
.
questions
=
questions
;
updateLocalSurveysList
(
survey
);
};
return
(
<
div
>
<
div
className
=
"flex justify-center items-center mt-6"
>
...
...
@@ -61,7 +99,15 @@ export const SurveyLayout = () => {
응답결과
</
NavLink
>
</
div
>
<
Outlet
context
=
{
{
survey
,
update
}
}
/>
<
Outlet
context
=
{
{
survey
,
createQuestion
,
removeQuestion
,
update
,
updateQuestion
,
}
}
/>
</
div
>
);
};
...
...
frontend/src/layouts/SurveysLayout.tsx
View file @
b0b76f7f
...
...
@@ -11,6 +11,7 @@ type SurveysContextType = {
create
:
()
=>
Promise
<
any
>
;
remove
:
(
id
:
string
)
=>
Promise
<
any
>
;
update
:
(
survey
:
ICreateSurvey
)
=>
Promise
<
any
>
;
updateLocalSurveysList
:
(
survey
:
ICreateSurvey
)
=>
void
;
};
export
const
SurveysLayout
=
()
=>
{
...
...
@@ -38,14 +39,25 @@ export const SurveysLayout = () => {
* @param surveyData 바꾸려는 설문 객체
*/
const
update
=
async
(
surveyData
:
ICreateSurvey
)
=>
{
// const result = await surveyApi.updateSurvey(surveyData);
// const index = surveys.findIndex((survey) => survey._id === result._id);
// surveys[index] = result;
const
result
=
await
surveyApi
.
updateSurvey
(
surveyData
);
const
index
=
surveys
.
findIndex
((
survey
)
=>
survey
.
_id
===
result
.
_id
);
surveys
[
index
]
=
result
;
// const index = surveys.findIndex((survey) => survey._id === surveyData._id);
// surveys[index] = surveyData;
// console.log("update in surveys layout layout:", surveyData);
console
.
log
(
"
updated survey data:
"
,
result
);
setSurveys
([...
surveys
]);
// return result;
};
const
updateLocalSurveysList
=
(
surveyData
:
ICreateSurvey
)
=>
{
const
index
=
surveys
.
findIndex
((
survey
)
=>
survey
.
_id
===
surveyData
.
_id
);
surveys
[
index
]
=
surveyData
;
console
.
log
(
"
update in surveys layout layout:
"
,
surveyData
);
// const index = surveys.findIndex((survey) => survey._id === surveyData._id);
// surveys[index] = surveyData;
// console.log("update in surveys layout layout:", surveyData);
console
.
log
(
"
updated local survey data:
"
,
surveyData
);
setSurveys
([...
surveys
]);
// return result;
};
/**
...
...
@@ -74,7 +86,17 @@ export const SurveysLayout = () => {
return
(
<>
<
Outlet
context
=
{
{
error
,
loading
,
surveys
,
create
,
remove
,
update
}
}
/>
<
Outlet
context
=
{
{
error
,
loading
,
surveys
,
create
,
remove
,
update
,
updateLocalSurveysList
,
}
}
/>
</>
);
};
...
...
frontend/src/surveys/EditSurvey.tsx
View file @
b0b76f7f
...
...
@@ -8,7 +8,8 @@ import { SpinnerIcon } from "../icons";
import
{
ModifySurveyView
}
from
"
./ModifySurveyView
"
;
export
const
EditSurvey
=
()
=>
{
const
{
survey
,
update
}
=
useSurvey
();
const
{
survey
,
createQuestion
,
removeQuestion
,
update
,
updateQuestion
}
=
useSurvey
();
// const [survey, setSurvey] = useState<ISurvey>(surveyData);
// const [questions, setQuestions] = useState<CreateQuestionData[]>(() => {
// const questions = survey.questions;
...
...
@@ -36,21 +37,20 @@ export const EditSurvey = () => {
* @param question 수정할 질문
* @returns 없음
*/
const
updateQuestion
=
(
question
:
CreateQuestionData
)
=>
{
const
index
=
questions
.
findIndex
((
q
)
=>
q
.
_id
===
question
.
_id
);
if
(
index
<
0
)
{
return
;
}
questions
[
index
]
=
question
;
console
.
log
(
"
questions in update question:
"
,
questions
);
// setQuestions([...questions]);
survey
.
questions
=
questions
;
update
(
survey
);
};
//
const updateQuestion = (question: CreateQuestionData) => {
//
const index = questions.findIndex((q) => q._id === question._id);
//
if (index < 0) {
//
return;
//
}
//
questions[index] = question;
//
console.log("questions in update question:", questions);
//
// setQuestions([...questions]);
//
survey.questions = questions;
//
update(survey);
//
};
const
addQuestion
=
()
=>
{
const
addQuestion
=
async
()
=>
{
const
question
:
CreateQuestionData
=
{
_id
:
Math
.
random
().
toString
(),
order
:
questions
.
length
,
type
:
"
singletext
"
,
title
:
""
,
...
...
@@ -59,11 +59,16 @@ export const EditSurvey = () => {
content
:
{
choices
:
[]
},
isEditing
:
true
,
};
// const updatedSurvey = await surveyApi.addQuestion(survey._id!, question);
await
createQuestion
(
question
);
// console.log("new question:", updatedSurvey);
// await update(updatedSurvey);
// setQuestions([...questions, question]);
};
async
function
deleteQuestion
(
id
:
string
)
{
const
delQuestions
=
questions
.
filter
((
question
)
=>
question
.
_id
!==
id
);
await
removeQuestion
(
id
);
// const delQuestions = questions.filter((question) => question._id !== id);
// setQuestions(delQuestions);
}
...
...
@@ -83,7 +88,7 @@ export const EditSurvey = () => {
deleteQuestion
=
{
deleteQuestion
}
handleQuestion
=
{
updateQuestion
}
handleTitle
=
{
handleTitle
}
callApi
=
{
update
}
//
callApi={update}
/>
);
};
frontend/src/surveys/ModifySurveyView.tsx
View file @
b0b76f7f
...
...
@@ -13,7 +13,7 @@ type Props = {
deleteQuestion
:
(
id
:
string
)
=>
void
;
handleQuestion
:
(
question
:
CreateQuestionData
)
=>
void
;
handleTitle
:
Function
;
callApi
:
(
surveyData
:
ISurvey
)
=>
Promise
<
any
>
;
//
callApi: (surveyData: ISurvey) => Promise<any>;
};
export
const
ModifySurveyView
=
({
...
...
@@ -23,8 +23,8 @@ export const ModifySurveyView = ({
deleteQuestion
,
handleQuestion
,
handleTitle
,
callApi
,
}:
Props
)
=>
{
}:
//
callApi,
Props
)
=>
{
const
[
error
,
setError
]
=
useState
(
""
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
// const [survey, setSurvey] = useState<ISurvey>(surveyData);
...
...
src/controllers/question.controller.ts
View file @
b0b76f7f
...
...
@@ -28,9 +28,7 @@ export const createQuestion = asyncWrap(
return
res
.
json
(
newQuestion
);
}
}
catch
(
error
:
any
)
{
return
res
.
status
(
500
)
.
send
(
error
.
message
||
"
질문을 생성하는 중 오류 발생
"
);
return
res
.
status
(
500
).
send
(
error
.
message
||
"
질문 생성 오류
"
);
}
}
);
...
...
src/controllers/survey.controller.ts
View file @
b0b76f7f
import
{
NextFunction
,
Request
,
Response
}
from
"
express
"
;
import
{
Types
}
from
"
mongoose
"
;
import
{
surveyDb
}
from
"
../db
"
;
import
{
questionDb
,
surveyDb
}
from
"
../db
"
;
import
{
asyncWrap
}
from
"
../helpers/asyncWrap
"
;
import
{
ISurvey
}
from
"
../models
"
;
...
...
@@ -9,6 +9,23 @@ export interface TypedRequestAuth<T> extends Request {
user
:
any
;
}
/**
* 설문에 새로운 질문을 추가
*/
export
const
addQuestion
=
asyncWrap
(
async
(
reqExp
:
Request
,
res
:
Response
)
=>
{
const
req
=
reqExp
as
TypedRequestAuth
<
{
userId
:
string
}
>
;
// Question controller 이용 질문 생성
const
{
userId
}
=
req
.
auth
;
const
{
_id
,
...
questionInput
}
=
req
.
body
;
questionInput
.
user
=
userId
;
const
newQuestion
=
await
questionDb
.
createQuestion
(
questionInput
);
// 생성된 질문을 survey에 추가
const
{
surveyId
}
=
req
.
params
;
await
surveyDb
.
addQuestion
(
surveyId
,
newQuestion
);
res
.
json
(
newQuestion
);
});
export
const
createSurvey
=
asyncWrap
(
async
(
reqExp
:
Request
,
res
:
Response
)
=>
{
const
req
=
reqExp
as
TypedRequestAuth
<
{
userId
:
string
}
>
;
...
...
@@ -21,6 +38,19 @@ export const createSurvey = asyncWrap(
}
);
export
const
deleteQuestion
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
surveyId
,
questionId
}
=
req
.
params
;
const
deletedQuestion
=
await
questionDb
.
deleteQuestionById
(
questionId
);
const
survey
=
await
surveyDb
.
removeQuestion
(
surveyId
,
questionId
);
return
res
.
json
(
deletedQuestion
);
});
export
const
deleteSurvey
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
surveyId
}
=
req
.
params
;
const
survey
=
await
surveyDb
.
deleteSurvey
(
surveyId
);
return
res
.
json
(
survey
);
});
export
const
getSurveyById
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
surveyId
}
=
req
.
params
;
const
survey
:
any
=
await
surveyDb
.
getSurveyById
(
surveyId
);
...
...
@@ -41,12 +71,6 @@ export const updateSurvey = asyncWrap(async (req, res) => {
return
res
.
json
(
newSurvey
);
});
export
const
deleteSurvey
=
asyncWrap
(
async
(
req
,
res
)
=>
{
const
{
surveyId
}
=
req
.
params
;
const
survey
=
await
surveyDb
.
deleteSurvey
(
surveyId
);
return
res
.
json
(
survey
);
});
export
const
userBySurveyId
=
async
(
reqExp
:
Request
,
res
:
Response
,
...
...
src/db/survey.db.ts
View file @
b0b76f7f
import
{
HydratedDocument
}
from
"
mongoose
"
;
import
{
Survey
,
ISurvey
,
Question
,
IQuestion
}
from
"
../models
"
;
export
const
findUserBySurveyId
=
async
(
surveyId
:
string
)
=>
{
const
survey
=
await
Survey
.
findById
(
surveyId
).
populate
(
"
user
"
);
console
.
log
(
survey
);
if
(
survey
!==
null
)
{
console
.
log
(
survey
.
user
);
return
survey
.
user
;
export
const
addQuestion
=
async
(
surveyId
:
string
,
question
:
any
)
=>
{
if
(
question
!==
null
)
{
const
updatedSurvey
=
await
Survey
.
findOneAndUpdate
(
{
_id
:
surveyId
},
{
$push
:
{
questions
:
question
}
},
{
new
:
true
}
).
populate
(
"
questions
"
);
return
updatedSurvey
;
}
return
null
;
};
...
...
@@ -32,6 +34,32 @@ export const createSurvey = async (surveyData: ISurvey) => {
return
newSurvey
;
};
export
const
removeQuestion
=
async
(
surveyId
:
string
,
questionId
:
string
)
=>
{
const
updatedSurvey
=
await
Survey
.
findOneAndUpdate
(
{
_id
:
surveyId
},
{
$pull
:
{
questions
:
questionId
}
},
{
new
:
true
}
);
return
updatedSurvey
;
};
export
const
deleteSurvey
=
async
(
surveyId
:
string
)
=>
{
console
.
log
(
"
survey id
"
,
surveyId
);
const
survey
=
await
Survey
.
findOneAndDelete
({
_id
:
surveyId
});
return
survey
;
};
export
const
findUserBySurveyId
=
async
(
surveyId
:
string
)
=>
{
const
survey
=
await
Survey
.
findById
(
surveyId
).
populate
(
"
user
"
);
console
.
log
(
survey
);
if
(
survey
!==
null
)
{
console
.
log
(
survey
.
user
);
return
survey
.
user
;
}
return
null
;
};
export
const
getSurveyById
=
async
(
surveyId
:
string
)
=>
{
console
.
log
(
"
survey id
"
,
surveyId
);
const
survey
=
await
Survey
.
findById
(
surveyId
).
populate
(
"
questions
"
);
...
...
@@ -61,12 +89,6 @@ export const updateSurvey = async (survey: HydratedDocument<ISurvey>) => {
return
newSurvey
;
};
export
const
deleteSurvey
=
async
(
surveyId
:
string
)
=>
{
console
.
log
(
"
survey id
"
,
surveyId
);
const
survey
=
await
Survey
.
findOneAndDelete
({
_id
:
surveyId
});
return
survey
;
};
export
const
putNewQuestion
=
async
(
newQuestion
:
any
,
surveyId
:
string
)
=>
{
console
.
log
(
newQuestion
,
surveyId
);
if
(
newQuestion
!==
null
)
{
...
...
src/routes/survey.route.ts
View file @
b0b76f7f
...
...
@@ -20,10 +20,14 @@ router
router
.
route
(
"
/:surveyId/questions
"
)
.
post
(
.
post
(
authCtrl
.
requireLogin
,
authCtrl
.
authenticate
,
surveyCtrl
.
addQuestion
);
router
.
route
(
"
/:surveyId/questions/:questionId
"
)
.
delete
(
authCtrl
.
requireLogin
,
authCtrl
.
authenticate
,
question
Ctrl
.
crea
teQuestion
survey
Ctrl
.
dele
teQuestion
);
router
.
param
(
"
surveyId
"
,
surveyCtrl
.
userBySurveyId
);
...
...
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