Commit de41c36d authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

createQuestion, Profile UI 수정

parent 8b8c6f9c
......@@ -17,7 +17,7 @@ export const SurveyRouter = () => {
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignUp />} />
<Route path="surveys/edit/:surveyId" element={<EditSurvey />} />
<Route path="survey" element={<SurveyForm />} />
<Route path="surveys/:surveyId" element={<SurveyForm />} />
<Route
path="profile"
element={
......
......@@ -2,14 +2,17 @@ import axios from "axios";
import { BasicQuestionType } from "../types";
import baseUrl from "./baseUrl";
export const createQuestion = async () => {
const { data } = await axios.post(`${baseUrl}/questions/create`, {
type: "essay",
title: "",
isRequired: false,
comment: "",
content: { choices: [] },
});
export const createQuestion = async (surveyId: string) => {
const { data } = await axios.post(
`${baseUrl}/surveys/${surveyId}/questions`,
{
type: "essay",
title: "",
isRequired: false,
comment: "",
content: { choices: [] },
}
);
return data;
};
......
......@@ -11,6 +11,10 @@ export const getSurvey = async (surveyId: string) => {
const { data } = await axios.get(`${baseUrl}/surveys/edit/${surveyId}`);
return data;
};
export const getASurvey = async (surveyId: string) => {
const { data } = await axios.get(`${baseUrl}/surveys/edit/${surveyId}`);
return data;
};
//동혁
export const getSurveys = async () => {
const { data } = await axios.get(`${baseUrl}/surveys/`);
......
import React, { InputHTMLAttributes } from "react";
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { surveyApi } from "../apis";
import { Question } from "../questions";
import { SurveyType } from "../types";
import { ACheckboxForm } from "./ACheckbox";
import { ADropdownForm } from "./ADropdown";
import { AEssayForm } from "./AEssayForm";
import { ARadioForm } from "./ARadioForm";
export const SurveyForm = () => {
let { surveyId } = useParams<{ surveyId: string }>();
const [survey, setSurvey] = useState<SurveyType>({
_id: surveyId,
user: {},
title: "",
comment: "",
questions: [],
});
useEffect(() => {
getSurvey();
}, [surveyId]);
async function getSurvey() {
try {
if (surveyId) {
const thisSurvey: SurveyType = await surveyApi.getASurvey(surveyId);
console.log(thisSurvey);
setSurvey(thisSurvey);
// setSuccess(true);
// setError("");
} else {
// setLoading(true);
}
} catch (error) {
// catchErrors(error, setError);
} finally {
// setLoading(false);
}
}
return (
<div className="flex flex-col place-items-center">
<div className="flex flex-col container place-items-center mt-4">
......@@ -15,10 +47,6 @@ export const SurveyForm = () => {
rows={2}
cols={60}
></textarea>
{/* <ACheckboxForm></ACheckboxForm> */}
<ADropdownForm></ADropdownForm>
<AEssayForm></AEssayForm>
<ARadioForm></ARadioForm>
<div>
<button className="rounded bg-themeColor my-5 py-2 px-5 font-bold text-white">
제출하기
......
......@@ -20,6 +20,12 @@ export const MySurveyCard = ({ data }: Props) => {
});
};
const goSurvey = () => {
navigate(`/surveys/${data._id}`, {
replace: true,
});
};
async function deleteSurvey() {
try {
if (data._id) {
......@@ -47,9 +53,11 @@ export const MySurveyCard = ({ data }: Props) => {
</div>
<div className="flex flex-col px-5 py-3">
<div className="h-12">
<p className="font-bold">
{data.title ? data.title : "제목없는 설문조사"}
</p>
<button type="button" onClick={goSurvey}>
<p className="font-bold">
{data.title ? data.title : "제목없는 설문조사"}
</p>
</button>
<p className="text-gray-500 text-sm">
{data.updatedAt?.substring(0, 10)}
</p>
......
......@@ -36,7 +36,7 @@ export const Profile = () => {
<div className="flex flex-col items-center">
<div className="mt-10 text-xl font-bold">나의 설문조사</div>
<img src={`${baseImageUrl}/9e24ad36a2947b08c89913b01`} />
<div className="flex space-x-4 mt-6">
<div className="grid grid-cols-1 md:grid-cols-4 sm:grid-cols-2 gap-4 mt-6">
<button
onClick={createSurvey}
className="flex h-60 w-52 items-center border-2 border-themeColor font-bold bg-gray-200 hover:bg-themeColor rounded-lg "
......
......@@ -4,10 +4,10 @@ import { CheckboxType } from "../types";
type Props = {
element: CheckboxType;
handleQuestion: (id: string) => void;
currentId: string;
save: boolean;
};
export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
export const CheckboxForm = ({ element, handleQuestion, save }: Props) => {
const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
......@@ -41,7 +41,7 @@ export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
</div>
))}
......@@ -52,7 +52,7 @@ export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
disabled={save}
>
삭제
</button>
......@@ -61,7 +61,7 @@ export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
disabled={save}
>
추가
</button>
......
import React from "react";
// import { DateType } from "../types";
type Props = {
// element: DateType;
// save: boolean;
};
export const DateForm = ({}: Props) => {
return (
<div id="content" className="flex mt-4 w-full justify-center">
<input type="date" className="w-11/12" disabled></input>
</div>
);
};
......@@ -4,10 +4,10 @@ import { DropdownType } from "../types";
type Props = {
element: DropdownType;
handleQuestion: (id: string) => void;
currentId: string;
save: boolean;
};
export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
export const DropdownForm = ({ element, handleQuestion, save }: Props) => {
const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
......@@ -45,7 +45,7 @@ export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
</div>
))}
......@@ -56,7 +56,7 @@ export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
disabled={save}
>
삭제
</button>
......@@ -65,7 +65,7 @@ export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
disabled={save}
>
추가
</button>
......
......@@ -3,10 +3,10 @@ import { EssayType } from "../types";
type Props = {
element: EssayType;
currentId: string;
save: boolean;
};
export const EssayForm = ({ element, currentId }: Props) => {
export const EssayForm = ({ element, save }: Props) => {
return (
<div id="commentarea" className="flex mt-4 w-full justify-center">
<input className="border w-11/12 h-16" disabled></input>
......
import React, { useState } from "react";
import React from "react";
import { FileType } from "../types";
type Props = {
element: FileType;
currentId: string;
save: boolean;
};
export const FileForm = ({ element, currentId }: Props) => {
export const FileForm = ({ element, save }: Props) => {
return (
<div id="content" className="flex mt-4 w-full justify-center">
<input type="file" className=" w-11/12 h-16" disabled></input>
......
......@@ -7,13 +7,12 @@ import { RadioForm } from "./RadioForm";
import { DropdownForm } from "./DropdownForm";
import { FileForm } from "./FileForm";
import { RatingForm } from "./RatingForm";
import { DateForm } from "./DateForm";
type Props = {
element: BasicQuestionType;
handleQuestion: (id: string) => void;
deleteQuestion: (id: string) => void;
changeCurrentId: (id: string) => void;
currentId: string;
};
const typeDropDown = new Map([
......@@ -31,16 +30,15 @@ export const Question = ({
element,
handleQuestion,
deleteQuestion,
changeCurrentId,
currentId,
}: Props) => {
const [save, setSave] = useState(true);
async function handleEditComplete() {
try {
const newQuestion: BasicQuestionType = await questionApi.updateQuestion(
element
);
console.log(newQuestion);
changeCurrentId("");
setSave(true);
// setSuccess(true);
// setError("");
} catch (error) {
......@@ -92,13 +90,13 @@ export const Question = ({
function getContent(element: BasicQuestionType) {
switch (element.type) {
case "essay":
return <EssayForm element={element} currentId={currentId} />;
return <EssayForm element={element} save={save} />;
case "radio":
return (
<RadioForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
save={save}
/>
);
case "checkbox":
......@@ -106,7 +104,7 @@ export const Question = ({
<CheckboxForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
save={save}
/>
);
case "dropdown":
......@@ -114,19 +112,21 @@ export const Question = ({
<DropdownForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
save={save}
/>
);
case "file":
return <FileForm element={element} currentId={currentId} />;
return <FileForm element={element} save={save} />;
case "rating":
return (
<RatingForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
save={save}
/>
);
case "date":
return <DateForm />;
default:
return <></>;
}
......@@ -140,11 +140,11 @@ export const Question = ({
deleteQuestion(element._id);
};
const handleEditClick = () => {
changeCurrentId(element._id);
setSave(false);
};
return (
<div
style={{ borderColor: currentId === element._id ? "red" : "#58ACFA" }}
style={{ borderColor: save ? "#58ACFA" : "red" }}
className="flex flex-col container w-4/5 h-auto border-2 items-center m-3 py-2"
>
<div className="flex h-16 w-full place-content-between items-center">
......@@ -156,7 +156,7 @@ export const Question = ({
placeholder={"Question Title"}
value={element.title}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
disabled={save}
></input>
<select
id={element._id}
......@@ -184,7 +184,7 @@ export const Question = ({
placeholder="질문에 대한 설명을 입력해주세요"
value={element.comment}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
disabled={save}
></input>
</div>
{getContent(element)}
......@@ -195,7 +195,7 @@ export const Question = ({
id="isRequired"
value="isRequired"
onChange={handleRequired}
disabled={currentId !== element._id}
disabled={save}
checked={element.isRequired}
/>
<label htmlFor="isRequired" className="px-1">
......@@ -204,14 +204,14 @@ export const Question = ({
<button type="button" className="px-1" onClick={handleDelete}>
삭제
</button>
{currentId === element._id ? (
<button type="button" className="px-1" onClick={handleEditComplete}>
수정완료
</button>
) : (
{save ? (
<button type="button" className="px-1" onClick={handleEditClick}>
수정하기
</button>
) : (
<button type="button" className="px-1" onClick={handleEditComplete}>
수정완료
</button>
)}
</div>
</div>
......
......@@ -4,10 +4,10 @@ import { RadioType } from "../types";
type Props = {
element: RadioType;
handleQuestion: (id: string) => void;
currentId: string;
save: boolean;
};
export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
export const RadioForm = ({ element, handleQuestion, save }: Props) => {
const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
......@@ -42,7 +42,7 @@ export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
</div>
))}
......@@ -53,7 +53,7 @@ export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
disabled={save}
>
삭제
</button>
......@@ -62,7 +62,7 @@ export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
disabled={save}
>
추가
</button>
......
......@@ -4,10 +4,10 @@ import { RatingType } from "../types";
type Props = {
element: RatingType;
handleQuestion: (id: string) => void;
currentId: string;
save: boolean;
};
export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
export const RatingForm = ({ element, handleQuestion, save }: Props) => {
const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
......@@ -46,7 +46,7 @@ export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="비동의"
value={element.content.minRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
{choices.map((choice: any, index: number) => (
<input
......@@ -58,7 +58,7 @@ export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="0"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
))}
<input
......@@ -68,7 +68,7 @@ export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
placeholder="동의"
value={element.content.maxRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
disabled={save}
></input>
</div>
<div>
......@@ -77,7 +77,7 @@ export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
disabled={save}
>
삭제
</button>
......@@ -86,7 +86,7 @@ export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
disabled={save}
>
추가
</button>
......
import React, { FormEvent, useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useParams } from "react-router-dom";
import { questionApi, surveyApi } from "../apis";
import { SpinnerIcon } from "../icons";
import { Question } from "../questions";
......@@ -8,7 +8,6 @@ import { catchErrors } from "../helpers";
export const EditSurvey = () => {
let { surveyId } = useParams<{ surveyId: string }>();
const navigate = useNavigate();
useEffect(() => {
getSurvey();
}, [surveyId]);
......@@ -22,10 +21,6 @@ export const EditSurvey = () => {
comment: "",
questions: [],
});
const [currentId, setCurrentId] = useState("");
const changeCurrentId = (id: string) => {
setCurrentId(id);
};
async function getSurvey() {
try {
if (surveyId) {
......@@ -38,9 +33,6 @@ export const EditSurvey = () => {
}
} catch (error) {
catchErrors(error, setError);
// navigate(`/`, {
// replace: false,
// });
} finally {
setLoading(false);
}
......@@ -72,10 +64,17 @@ export const EditSurvey = () => {
async function addQuestion() {
try {
const newQuestion: BasicQuestionType = await questionApi.createQuestion();
setSurvey({ ...survey, questions: [...survey.questions, newQuestion] });
setSuccess(true);
setError("");
if (surveyId) {
const questions: BasicQuestionType[] = await questionApi.createQuestion(
surveyId
);
console.log(questions);
setSurvey({ ...survey, questions: questions });
setSuccess(true);
setError("");
} else {
setLoading(true);
}
} catch (error) {
catchErrors(error, setError);
} finally {
......@@ -133,8 +132,6 @@ export const EditSurvey = () => {
element={question}
handleQuestion={handleQuestion}
deleteQuestion={deleteQuestion}
changeCurrentId={changeCurrentId}
currentId={currentId}
/>
))}
<div className="flex w-4/5 content-center justify-center border-2 border-black h-8 mt-3">
......
import { NextFunction, Request, Response } from "express";
import { questionDb } from "../db";
import { questionDb, surveyDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap";
export interface TypedRequestAuth<T> extends Request {
......@@ -9,13 +9,28 @@ export interface TypedRequestAuth<T> extends Request {
export const createQuestion = asyncWrap(
async (reqExp: Request, res: Response, next: NextFunction) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
const { userId } = req.auth;
let question = req.body;
question.user = userId;
console.log("question body", question);
const newQuestion = await questionDb.createQuestion(question);
return res.json(newQuestion);
try {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
const { userId } = req.auth;
if (!userId) {
return res.status(404).send("올바른 접근이 아닙니다");
} else {
let question = req.body;
question.user = userId;
const newQuestion = await questionDb.createQuestion(question);
const { surveyId } = req.params;
const updatedSurvey = await surveyDb.putNewQuestion(
newQuestion,
surveyId
);
console.log(updatedSurvey);
return res.json(updatedSurvey?.questions);
}
} catch (error: any) {
return res
.status(500)
.send(error.message || "질문을 생성하는 중 오류 발생");
}
}
);
......
......@@ -26,7 +26,6 @@ export const getSurveyById = asyncWrap(async (req, res) => {
return res.json(survey);
});
//동혁
export const getSurveys = asyncWrap(async (reqExp: Request, res: Response) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
const { userId } = req.auth;
......
......@@ -22,7 +22,7 @@ export const getSurveyById = async (surveyId: string) => {
};
export const getSurveys = async (userId: string) => {
const surveys = await Survey.find({ user: userId });
const surveys = await Survey.find({ user: userId }).sort({ updatedAt: -1 });
return surveys;
};
......@@ -36,3 +36,16 @@ export const deleteSurvey = async (surveyId: string) => {
const survey = await Survey.findOneAndDelete({ _id: surveyId });
return survey;
};
export const putNewQuestion = async (newQuestion: any, surveyId: string) => {
console.log(newQuestion, surveyId);
if (newQuestion !== null) {
const updatedSurvey = await Survey.findOneAndUpdate(
{ _id: surveyId },
{ $push: { questions: newQuestion } },
{ new: true }
).populate("questions");
return updatedSurvey;
}
return null;
};
import { model, Schema, Types } from "mongoose";
export interface IResponse {
_id?: Types.ObjectId;
surveyId?: Types.ObjectId;
questionId?: Types.ObjectId;
respondent?: string;
answer?: any;
}
const schema = new Schema<IResponse>(
{
surveyId: { type: Schema.Types.ObjectId, ref: "Survey" },
questionId: { type: Schema.Types.ObjectId, ref: "Question" },
respondent: { type: String },
answer: { type: Object },
},
{ timestamps: true }
);
export default model<IResponse>("Response", schema);
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