Commit b0b76f7f authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

survey 수정 작업중

parent 67f22c42
...@@ -2,4 +2,10 @@ ...@@ -2,4 +2,10 @@
## 리덕스 ## 리덕스
리덕스는 전역 상태를 관리하는 프레임워크입니다.
### 리덕스 데이터 비동기
1. 리덕스와 프론트 api와 연결을 해서 api에서 서버에서 데이터를 가져오면 리덕스 상태를 변경시켜야 하고 변경된 상태가 컴포넌트에 즉시 적용되도록 해야하는 문제를 연구해야 합니다. 1. 리덕스와 프론트 api와 연결을 해서 api에서 서버에서 데이터를 가져오면 리덕스 상태를 변경시켜야 하고 변경된 상태가 컴포넌트에 즉시 적용되도록 해야하는 문제를 연구해야 합니다.
- [리덕스 홈페이지 비동기 로직](https://redux.js.org/tutorials/fundamentals/part-6-async-logic)
import axios from "axios"; import axios from "axios";
import { ISurvey } from "../types"; import { CreateQuestionData, IQuestionData, ISurvey } from "../types";
import baseUrl from "./baseUrl"; 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) => { export const createSurvey = async (survey: ISurvey) => {
const { data } = await axios.post(`${baseUrl}/surveys`, survey); const { data } = await axios.post(`${baseUrl}/surveys`, survey);
return data; 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) => { export const getSurvey = async (surveyId: string) => {
const { data } = await axios.get(`${baseUrl}/surveys/${surveyId}/edit`); const { data } = await axios.get(`${baseUrl}/surveys/${surveyId}/edit`);
return data; return data;
...@@ -22,11 +45,6 @@ export const getSurveys = async () => { ...@@ -22,11 +45,6 @@ export const getSurveys = async () => {
return data; 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) => { export const resultSurvey = async (survey: ISurvey) => {
const { data } = await axios.put( const { data } = await axios.put(
`${baseUrl}/surveys/${survey._id}/result`, `${baseUrl}/surveys/${survey._id}/result`,
...@@ -35,7 +53,18 @@ export const resultSurvey = async (survey: ISurvey) => { ...@@ -35,7 +53,18 @@ export const resultSurvey = async (survey: ISurvey) => {
return data; return data;
}; };
export const deleteSurvey = async (surveyId: string) => { export const updateQuestion = async (
const { data } = await axios.delete(`${baseUrl}/surveys/${surveyId}`); 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; return data;
}; };
...@@ -2,12 +2,16 @@ import React from "react"; ...@@ -2,12 +2,16 @@ import React from "react";
import { NavLink, useOutletContext } from "react-router-dom"; import { NavLink, useOutletContext } from "react-router-dom";
import { Outlet, useNavigate, useParams } from "react-router-dom"; import { Outlet, useNavigate, useParams } from "react-router-dom";
import { useSurveys } from "./SurveysLayout"; import { useSurveys } from "./SurveysLayout";
import type { ICreateSurvey, ISurvey } from "../types"; import type { CreateQuestionData, ICreateSurvey, ISurvey } from "../types";
import { SpinnerIcon } from "../icons"; import { SpinnerIcon } from "../icons";
import { surveyApi } from "../apis";
type SurveyContextType = { type SurveyContextType = {
survey: ICreateSurvey; survey: ICreateSurvey;
update: (survey: ISurvey) => Promise<any>; update: (survey: ISurvey) => Promise<any>;
createQuestion: (question: CreateQuestionData) => Promise<any>;
removeQuestion: (questionId: string) => Promise<any>;
updateQuestion: (question: CreateQuestionData) => Promise<any>;
}; };
const activeStyle = const activeStyle =
...@@ -16,11 +20,11 @@ const inActiveStyle = ...@@ -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"; "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 = () => { export const SurveyLayout = () => {
const { surveys, update } = useSurveys(); const { surveys, update, updateLocalSurveysList } = useSurveys();
let { surveyId } = useParams<{ surveyId: string }>(); let { surveyId } = useParams<{ surveyId: string }>();
const survey = surveys.find((survey) => survey._id === surveyId); const survey = surveys.find((survey) => survey._id === surveyId);
console.log("surveys in survey layout", surveys); // console.log("surveys in survey layout", surveys);
if (!survey) { if (!survey) {
return ( return (
...@@ -30,6 +34,40 @@ export const SurveyLayout = () => { ...@@ -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 ( return (
<div> <div>
<div className="flex justify-center items-center mt-6"> <div className="flex justify-center items-center mt-6">
...@@ -61,7 +99,15 @@ export const SurveyLayout = () => { ...@@ -61,7 +99,15 @@ export const SurveyLayout = () => {
응답결과 응답결과
</NavLink> </NavLink>
</div> </div>
<Outlet context={{ survey, update }} /> <Outlet
context={{
survey,
createQuestion,
removeQuestion,
update,
updateQuestion,
}}
/>
</div> </div>
); );
}; };
......
...@@ -11,6 +11,7 @@ type SurveysContextType = { ...@@ -11,6 +11,7 @@ type SurveysContextType = {
create: () => Promise<any>; create: () => Promise<any>;
remove: (id: string) => Promise<any>; remove: (id: string) => Promise<any>;
update: (survey: ICreateSurvey) => Promise<any>; update: (survey: ICreateSurvey) => Promise<any>;
updateLocalSurveysList: (survey: ICreateSurvey) => void;
}; };
export const SurveysLayout = () => { export const SurveysLayout = () => {
...@@ -38,14 +39,25 @@ export const SurveysLayout = () => { ...@@ -38,14 +39,25 @@ export const SurveysLayout = () => {
* @param surveyData 바꾸려는 설문 객체 * @param surveyData 바꾸려는 설문 객체
*/ */
const update = async (surveyData: ICreateSurvey) => { const update = async (surveyData: ICreateSurvey) => {
// const result = await surveyApi.updateSurvey(surveyData); const result = await surveyApi.updateSurvey(surveyData);
// const index = surveys.findIndex((survey) => survey._id === result._id); const index = surveys.findIndex((survey) => survey._id === result._id);
// surveys[index] = result; 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); const index = surveys.findIndex((survey) => survey._id === surveyData._id);
surveys[index] = surveyData; 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]); setSurveys([...surveys]);
// return result;
}; };
/** /**
...@@ -74,7 +86,17 @@ export const SurveysLayout = () => { ...@@ -74,7 +86,17 @@ export const SurveysLayout = () => {
return ( return (
<> <>
<Outlet context={{ error, loading, surveys, create, remove, update }} /> <Outlet
context={{
error,
loading,
surveys,
create,
remove,
update,
updateLocalSurveysList,
}}
/>
</> </>
); );
}; };
......
...@@ -8,7 +8,8 @@ import { SpinnerIcon } from "../icons"; ...@@ -8,7 +8,8 @@ import { SpinnerIcon } from "../icons";
import { ModifySurveyView } from "./ModifySurveyView"; import { ModifySurveyView } from "./ModifySurveyView";
export const EditSurvey = () => { export const EditSurvey = () => {
const { survey, update } = useSurvey(); const { survey, createQuestion, removeQuestion, update, updateQuestion } =
useSurvey();
// const [survey, setSurvey] = useState<ISurvey>(surveyData); // const [survey, setSurvey] = useState<ISurvey>(surveyData);
// const [questions, setQuestions] = useState<CreateQuestionData[]>(() => { // const [questions, setQuestions] = useState<CreateQuestionData[]>(() => {
// const questions = survey.questions; // const questions = survey.questions;
...@@ -36,21 +37,20 @@ export const EditSurvey = () => { ...@@ -36,21 +37,20 @@ export const EditSurvey = () => {
* @param question 수정할 질문 * @param question 수정할 질문
* @returns 없음 * @returns 없음
*/ */
const updateQuestion = (question: CreateQuestionData) => { // const updateQuestion = (question: CreateQuestionData) => {
const index = questions.findIndex((q) => q._id === question._id); // const index = questions.findIndex((q) => q._id === question._id);
if (index < 0) { // if (index < 0) {
return; // return;
} // }
questions[index] = question; // questions[index] = question;
console.log("questions in update question:", questions); // console.log("questions in update question:", questions);
// setQuestions([...questions]); // // setQuestions([...questions]);
survey.questions = questions; // survey.questions = questions;
update(survey); // update(survey);
}; // };
const addQuestion = () => { const addQuestion = async () => {
const question: CreateQuestionData = { const question: CreateQuestionData = {
_id: Math.random().toString(),
order: questions.length, order: questions.length,
type: "singletext", type: "singletext",
title: "", title: "",
...@@ -59,11 +59,16 @@ export const EditSurvey = () => { ...@@ -59,11 +59,16 @@ export const EditSurvey = () => {
content: { choices: [] }, content: { choices: [] },
isEditing: true, isEditing: true,
}; };
// const updatedSurvey = await surveyApi.addQuestion(survey._id!, question);
await createQuestion(question);
// console.log("new question:", updatedSurvey);
// await update(updatedSurvey);
// setQuestions([...questions, question]); // setQuestions([...questions, question]);
}; };
async function deleteQuestion(id: string) { 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); // setQuestions(delQuestions);
} }
...@@ -83,7 +88,7 @@ export const EditSurvey = () => { ...@@ -83,7 +88,7 @@ export const EditSurvey = () => {
deleteQuestion={deleteQuestion} deleteQuestion={deleteQuestion}
handleQuestion={updateQuestion} handleQuestion={updateQuestion}
handleTitle={handleTitle} handleTitle={handleTitle}
callApi={update} // callApi={update}
/> />
); );
}; };
...@@ -13,7 +13,7 @@ type Props = { ...@@ -13,7 +13,7 @@ type Props = {
deleteQuestion: (id: string) => void; deleteQuestion: (id: string) => void;
handleQuestion: (question: CreateQuestionData) => void; handleQuestion: (question: CreateQuestionData) => void;
handleTitle: Function; handleTitle: Function;
callApi: (surveyData: ISurvey) => Promise<any>; // callApi: (surveyData: ISurvey) => Promise<any>;
}; };
export const ModifySurveyView = ({ export const ModifySurveyView = ({
...@@ -23,8 +23,8 @@ export const ModifySurveyView = ({ ...@@ -23,8 +23,8 @@ export const ModifySurveyView = ({
deleteQuestion, deleteQuestion,
handleQuestion, handleQuestion,
handleTitle, handleTitle,
callApi, }: // callApi,
}: Props) => { Props) => {
const [error, setError] = useState(""); const [error, setError] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
// const [survey, setSurvey] = useState<ISurvey>(surveyData); // const [survey, setSurvey] = useState<ISurvey>(surveyData);
......
...@@ -28,9 +28,7 @@ export const createQuestion = asyncWrap( ...@@ -28,9 +28,7 @@ export const createQuestion = asyncWrap(
return res.json(newQuestion); return res.json(newQuestion);
} }
} catch (error: any) { } catch (error: any) {
return res return res.status(500).send(error.message || "질문 생성 오류");
.status(500)
.send(error.message || "질문을 생성하는 중 오류 발생");
} }
} }
); );
......
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { surveyDb } from "../db"; import { questionDb, surveyDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap"; import { asyncWrap } from "../helpers/asyncWrap";
import { ISurvey } from "../models"; import { ISurvey } from "../models";
...@@ -9,6 +9,23 @@ export interface TypedRequestAuth<T> extends Request { ...@@ -9,6 +9,23 @@ export interface TypedRequestAuth<T> extends Request {
user: any; 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( export const createSurvey = asyncWrap(
async (reqExp: Request, res: Response) => { async (reqExp: Request, res: Response) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>; const req = reqExp as TypedRequestAuth<{ userId: string }>;
...@@ -21,6 +38,19 @@ export const createSurvey = asyncWrap( ...@@ -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) => { export const getSurveyById = asyncWrap(async (req, res) => {
const { surveyId } = req.params; const { surveyId } = req.params;
const survey: any = await surveyDb.getSurveyById(surveyId); const survey: any = await surveyDb.getSurveyById(surveyId);
...@@ -41,12 +71,6 @@ export const updateSurvey = asyncWrap(async (req, res) => { ...@@ -41,12 +71,6 @@ export const updateSurvey = asyncWrap(async (req, res) => {
return res.json(newSurvey); 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 ( export const userBySurveyId = async (
reqExp: Request, reqExp: Request,
res: Response, res: Response,
......
import { HydratedDocument } from "mongoose"; import { HydratedDocument } from "mongoose";
import { Survey, ISurvey, Question, IQuestion } from "../models"; import { Survey, ISurvey, Question, IQuestion } from "../models";
export const findUserBySurveyId = async (surveyId: string) => { export const addQuestion = async (surveyId: string, question: any) => {
const survey = await Survey.findById(surveyId).populate("user"); if (question !== null) {
console.log(survey); const updatedSurvey = await Survey.findOneAndUpdate(
if (survey !== null) { { _id: surveyId },
console.log(survey.user); { $push: { questions: question } },
return survey.user; { new: true }
).populate("questions");
return updatedSurvey;
} }
return null; return null;
}; };
...@@ -32,6 +34,32 @@ export const createSurvey = async (surveyData: ISurvey) => { ...@@ -32,6 +34,32 @@ export const createSurvey = async (surveyData: ISurvey) => {
return newSurvey; 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) => { export const getSurveyById = async (surveyId: string) => {
console.log("survey id", surveyId); console.log("survey id", surveyId);
const survey = await Survey.findById(surveyId).populate("questions"); const survey = await Survey.findById(surveyId).populate("questions");
...@@ -61,12 +89,6 @@ export const updateSurvey = async (survey: HydratedDocument<ISurvey>) => { ...@@ -61,12 +89,6 @@ export const updateSurvey = async (survey: HydratedDocument<ISurvey>) => {
return newSurvey; 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) => { export const putNewQuestion = async (newQuestion: any, surveyId: string) => {
console.log(newQuestion, surveyId); console.log(newQuestion, surveyId);
if (newQuestion !== null) { if (newQuestion !== null) {
......
...@@ -20,10 +20,14 @@ router ...@@ -20,10 +20,14 @@ router
router router
.route("/:surveyId/questions") .route("/:surveyId/questions")
.post( .post(authCtrl.requireLogin, authCtrl.authenticate, surveyCtrl.addQuestion);
router
.route("/:surveyId/questions/:questionId")
.delete(
authCtrl.requireLogin, authCtrl.requireLogin,
authCtrl.authenticate, authCtrl.authenticate,
questionCtrl.createQuestion surveyCtrl.deleteQuestion
); );
router.param("surveyId", surveyCtrl.userBySurveyId); router.param("surveyId", surveyCtrl.userBySurveyId);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment