Commit 578446f7 authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

result 불러오기 완성

parent 6262a322
...@@ -18,11 +18,11 @@ export const SurveyRouter = () => { ...@@ -18,11 +18,11 @@ export const SurveyRouter = () => {
<Route index element={<Home />} /> <Route index element={<Home />} />
<Route path="login" element={<Login />} /> <Route path="login" element={<Login />} />
<Route path="signup" element={<SignUp />} /> <Route path="signup" element={<SignUp />} />
<Route path="surveys/edit/" element={<EditResultButton />}> <Route path="surveys/:surveyId/" element={<EditResultButton />}>
<Route path=":surveyId" element={<EditSurvey />} /> <Route path="edit" element={<EditSurvey />} />
<Route path=":surveyId/result" element={<ResultSurvey />} /> <Route path="result" element={<ResultSurvey />} />
</Route> </Route>
<Route path="surveys/:surveyId" element={<AnswerSurveyForm />} /> <Route path="survey/:surveyId" element={<AnswerSurveyForm />} />
<Route <Route
path="profile" path="profile"
element={ element={
......
...@@ -16,20 +16,14 @@ export const MySurveyCard = ({ data }: Props) => { ...@@ -16,20 +16,14 @@ export const MySurveyCard = ({ data }: Props) => {
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
const editSurvey = () => { const editSurvey = () => {
navigate(`/surveys/edit/${data._id}`, { navigate(`/surveys/${data._id}/edit`, {
replace: true, replace: true,
state: { save: true }, state: { save: true },
}); });
}; };
const goSurvey = () => {
navigate(`/surveys/${data._id}`, {
replace: true,
});
};
const copyLink = () => { const copyLink = () => {
navigator.clipboard.writeText(`http://localhost:8080/surveys/${data._id}`); navigator.clipboard.writeText(`http://localhost:8080/survey/${data._id}`);
alert("설문조사의 링크가 클립보드에 저장되었습니다."); alert("설문조사의 링크가 클립보드에 저장되었습니다.");
}; };
......
...@@ -21,7 +21,7 @@ export const Profile = () => { ...@@ -21,7 +21,7 @@ export const Profile = () => {
async function createSurvey() { async function createSurvey() {
const newSurvey: SurveyType = await surveyApi.createSurvey(survey); const newSurvey: SurveyType = await surveyApi.createSurvey(survey);
navigate(`/surveys/edit/${newSurvey._id}`, { navigate(`/surveys/${newSurvey._id}/edit`, {
replace: true, replace: true,
}); });
} }
...@@ -36,7 +36,6 @@ export const Profile = () => { ...@@ -36,7 +36,6 @@ export const Profile = () => {
return ( return (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<div className="mt-10 text-xl font-bold">나의 설문조사</div> <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"> <div className="grid grid-cols-1 md:grid-cols-4 sm:grid-cols-2 gap-4 mt-6">
<button <button
onClick={createSurvey} onClick={createSurvey}
......
import React, { useState, useRef } from "react"; import React, { useState, useRef, useEffect } from "react";
import { baseImageUrl } from "../apis";
import { BasicQuestionType } from "../types"; import { BasicQuestionType } from "../types";
type AccordionProps = { type AccordionProps = {
question: any; question: any;
answers: any;
}; };
const Accordion = ({ question, answers }: AccordionProps) => { const Accordion = ({ question }: AccordionProps) => {
const [isOpened, setOpened] = useState<boolean>(false); const [isOpened, setOpened] = useState<boolean>(false);
const [height, setHeight] = useState<string>("0px"); const [height, setHeight] = useState<string>("0px");
const contentElement = useRef<HTMLDivElement>(null); const contentElement = useRef<HTMLDivElement>(null);
// useEffect(() => {
// if (question.type === "file") {
// getFiles();
// }
// }, []);
// async function getFiles() {
// try {
// } catch (error) {}
// }
const HandleOpening = () => { const HandleOpening = () => {
setOpened(!isOpened); setOpened(!isOpened);
setHeight(!isOpened ? `${contentElement.current?.scrollHeight}px` : "0px"); setHeight(!isOpened ? `${contentElement.current?.scrollHeight}px` : "0px");
...@@ -26,9 +37,17 @@ const Accordion = ({ question, answers }: AccordionProps) => { ...@@ -26,9 +37,17 @@ const Accordion = ({ question, answers }: AccordionProps) => {
style={{ height: height }} style={{ height: height }}
className="bg-gray-100 overflow-hidden transition-all duration-700" className="bg-gray-100 overflow-hidden transition-all duration-700"
> >
{answers.map((answer: any) => ( {question.type === "file"
<p className="p-4">{answer.answer}</p> ? 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> </div>
</div> </div>
......
...@@ -6,18 +6,11 @@ export const EditResultButton = () => { ...@@ -6,18 +6,11 @@ export const EditResultButton = () => {
let { surveyId } = useParams<{ surveyId: string }>(); let { surveyId } = useParams<{ surveyId: string }>();
const navigate = useNavigate(); const navigate = useNavigate();
/*function editButtonClick(e: React.MouseEvent<HTMLButtonElement>) {
navigate(`/surveys/${surveyId}/edit`);
}
function resultButtonClick(e: React.MouseEvent<HTMLButtonElement>) {
navigate(`/surveys/${surveyId}/result`);
}*/
return ( return (
<div> <div>
<div className="flex place-content-center mt-6"> <div className="flex place-content-center mt-6">
<NavLink <NavLink
to={`/surveys/edit/${surveyId}`} to={`/surveys/${surveyId}/edit`}
style={({ isActive }) => style={({ isActive }) =>
isActive isActive
? { ? {
...@@ -33,7 +26,7 @@ export const EditResultButton = () => { ...@@ -33,7 +26,7 @@ export const EditResultButton = () => {
<div className="text-xl m-3 ">설문지 수정</div> <div className="text-xl m-3 ">설문지 수정</div>
</NavLink> </NavLink>
<NavLink <NavLink
to={`/surveys/edit/${surveyId}/result`} to={`/surveys/${surveyId}/result`}
style={({ isActive }) => style={({ isActive }) =>
isActive isActive
? { ? {
......
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { answerApi } from "../apis"; import { answerApi, surveyApi } from "../apis";
import { catchErrors } from "../helpers"; import { catchErrors } from "../helpers";
import Accordion from "./Accordion"; import Accordion from "./Accordion";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { SurveyType } from "../types";
export const ResultSurvey = () => { export const ResultSurvey = () => {
let { surveyId } = useParams<{ surveyId: string }>();
const [error, setError] = useState(""); const [error, setError] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
const [answers, setAnswers] = useState([ const [survey, setSurvey] = useState<SurveyType>({
{ _id: "", answers: [], question: {} }, _id: surveyId || "",
]); user: {},
let { surveyId } = useParams<{ surveyId: string }>(); title: "",
comment: "",
questions: [],
});
useEffect(() => { useEffect(() => {
getAnswers(); getAnswers();
}, [surveyId]); }, [surveyId]);
...@@ -19,9 +24,9 @@ export const ResultSurvey = () => { ...@@ -19,9 +24,9 @@ export const ResultSurvey = () => {
async function getAnswers() { async function getAnswers() {
try { try {
if (surveyId) { if (surveyId) {
const answers = await answerApi.getAnswers(surveyId); const survey = await answerApi.getAnswers(surveyId);
console.log(answers); console.log(survey);
setAnswers(answers); setSurvey(survey);
} else { } else {
setLoading(true); setLoading(true);
} }
...@@ -32,40 +37,20 @@ export const ResultSurvey = () => { ...@@ -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 ( return (
<div className="flex flex-col place-items-center"> <div className="flex flex-col place-items-center">
<div className="flex flex-col container place-items-center mt-4"> <div className="flex flex-col container place-items-center mt-4">
<div className="font-bold text-4xl text-center m-2 border-b-2"> <div className="font-bold text-4xl text-center m-2 border-b-2">
설문지 제목 {survey.title}
</div> </div>
<div className="font-bold text-1xl text-center m-2 resize-none"> <div className="font-bold text-1xl text-center m-2 resize-none">
설문조사 설명 {survey.comment}
</div> </div>
</div> </div>
<div className="container w-11/12 place-self-center"> <div className="container w-11/12 place-self-center">
{answers.map((item) => ( {survey.questions.map((question) => (
<Accordion <Accordion key={question._id} question={question} />
key={item._id}
question={item.question}
answers={item.answers}
/>
))} ))}
</div> </div>
</div> </div>
......
...@@ -27,6 +27,7 @@ export interface BasicQuestionType { ...@@ -27,6 +27,7 @@ export interface BasicQuestionType {
isRequired: boolean; isRequired: boolean;
comment: string; comment: string;
content: any; content: any;
answers?: any;
[key: string]: string | number | boolean | any; [key: string]: string | number | boolean | any;
} }
......
...@@ -3,7 +3,7 @@ import { asyncWrap } from "../helpers"; ...@@ -3,7 +3,7 @@ import { asyncWrap } from "../helpers";
import { TypedRequest } from "../types"; import { TypedRequest } from "../types";
import formidable from "formidable"; import formidable from "formidable";
import { FileInfo } from "../models"; import { FileInfo } from "../models";
import { fileDb, userDb, answerDb } 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) => {
...@@ -11,14 +11,18 @@ export const createAnswers = asyncWrap(async (reqExp, res) => { ...@@ -11,14 +11,18 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
const answer = req.body; const answer = req.body;
const answers = JSON.parse(answer.answers); const answers = JSON.parse(answer.answers);
answer.answers = 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; let uploadFile;
try { try {
if (files) { if (files) {
// 1) 파일을 DB에 저장 후 다시 retFile가져와서 // 1) 파일을 DB에 저장 후 다시 retFile가져와서
// *근데 파일이 여러 개일 수 있기 때문에 순회해야 됨-map()을 쓰면 async function이 되어버려서 for문 이용함 // *근데 파일이 여러 개일 수 있기 때문에 순회해야 됨
for (let index = 0; index < files.length; index++) { const f = files.map(async (file) => {
const file = files[index];
uploadFile = new FileInfo({ uploadFile = new FileInfo({
name: file.originalFilename, name: file.originalFilename,
url: file.newFilename, url: file.newFilename,
...@@ -31,26 +35,24 @@ export const createAnswers = asyncWrap(async (reqExp, res) => { ...@@ -31,26 +35,24 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
); );
// 3) answer에다가 retFile의 _id 넣어주기 // 3) answer에다가 retFile의 _id 넣어주기
targetObj.answer = retFile._id; targetObj.answer = retFile._id;
} });
await Promise.all(f);
} }
// 3) Answer DB 만들기 // 3) Answer DB 만들기
console.log("원래 answer", answer); const c = answer.answers.map(async (element: any) => {
console.log("원래 answer", answer.answers.length); const newAnswer = await answerDb.createAnswer({
// for (let index = 0; index < answer.answers.length; index++) { surveyId: answer.surveyId,
// const element = answer.answers[index]; guestId: answer.guestId,
// const newAnswer = await answerDb.createAnswer({ questionId: element.questionId,
// surveyId: answer.surveyId, answer: element.answer,
// guestId: answer.guestId, });
// questionId: element.questionId, });
// answer: element.answer, await Promise.all(c);
// });
// // console.log("DB에 넣은 answer", newAnswer);
// }
return res.json(); return res.json();
} catch (error: any) { } catch (error: any) {
console.log("error in create answer:", error); console.log("error in create answer:", error);
// 오류 발생시 저장된 파일 제거 // 오류 발생시 저장된 파일 제거
if (files) { if (req.files) {
// uploadFiles && (await fileDb.deleteFileById(uploadFiles._id.toString())); // uploadFiles && (await fileDb.deleteFileById(uploadFiles._id.toString()));
// await fs.unlink(files.filepath); // await fs.unlink(files.filepath);
} }
...@@ -61,11 +63,27 @@ export const createAnswers = asyncWrap(async (reqExp, res) => { ...@@ -61,11 +63,27 @@ export const createAnswers = asyncWrap(async (reqExp, res) => {
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;
console.log(surveyId);
try { try {
const survey = await surveyDb.getSurveyById(surveyId);
const answers = await answerDb.getAnswers(surveyId); const answers = await answerDb.getAnswers(surveyId);
console.log("Db에서 가져온 answers= ", answers); console.log(answers);
return res.json(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) { } catch (error: any) {
res.status(422).send(error.message || "설문조사 결과 불러오기 오류"); res.status(422).send(error.message || "설문조사 결과 불러오기 오류");
} }
......
...@@ -10,19 +10,17 @@ export const getAnswers = async (surveyId: string) => { ...@@ -10,19 +10,17 @@ export const getAnswers = async (surveyId: string) => {
const answers = await Answer.aggregate([ const answers = await Answer.aggregate([
{ $match: { surveyId: new Types.ObjectId(surveyId) } }, { $match: { surveyId: new Types.ObjectId(surveyId) } },
{ {
$lookup: { $group: {
from: "questions", _id: "$questionId",
localField: "questionId", answers: { $push: "$answer" },
foreignField: "_id",
as: "question",
}, },
}, },
{ $unwind: "$question" },
{ {
$group: { $lookup: {
_id: "$questionId", from: "fileinfos",
answers: { $push: { guestId: "$guestId", answer: "$answer" } }, localField: "answers",
question: { $mergeObjects: "$question" }, foreignField: "_id",
as: "file",
}, },
}, },
]); ]);
......
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