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

Merge branch 'develop'

parents 5c9540ec 2e1489ce
import React, { useState } from "react";
import { Question } from "./Question";
import { QuestionProvider } from "./question.context";
export interface BasicQuestionType {
type: string;
id: string;
_id: string;
title: string;
isRequired: boolean;
comment: string;
......@@ -38,8 +39,10 @@ export interface FileType extends BasicQuestionType {
}
export interface RatingType extends BasicQuestionType {
content: {
rateMin: number;
rateMax: number;
rateValues: {
value: number;
text: string;
}[];
minRateDescription: string;
maxRateDescription: string;
};
......@@ -47,7 +50,7 @@ export interface RatingType extends BasicQuestionType {
const EssayQ: EssayType = {
type: "essay",
id: "000000000000",
_id: "000000000000",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
......@@ -55,7 +58,7 @@ const EssayQ: EssayType = {
};
const RadioQ: RadioType = {
type: "radio",
id: "000000000001",
_id: "000000000001",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
......@@ -67,7 +70,7 @@ const RadioQ: RadioType = {
};
const CheckboxQ: CheckboxType = {
type: "checkbox",
id: "000000000002",
_id: "000000000002",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
......@@ -78,7 +81,7 @@ const CheckboxQ: CheckboxType = {
};
const DropdownQ: DropdownType = {
type: "dropdown",
id: "000000000003",
_id: "000000000003",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
......@@ -89,7 +92,7 @@ const DropdownQ: DropdownType = {
};
const FileQ: FileType = {
type: "file",
id: "000000000004",
_id: "000000000004",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
......@@ -100,58 +103,30 @@ const FileQ: FileType = {
};
const RatingQ: RatingType = {
type: "rating",
id: "000000000005",
_id: "000000000005",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
content: {
rateMin: 0,
rateMax: 10,
rateValues: [
{ value: 1, text: "1" },
{ value: 2, text: "2" },
{ value: 3, text: "3" },
],
minRateDescription: "가장 낮음",
maxRateDescription: "가장 높음",
},
};
export const CreateSurveyForm = () => {
const [questionList, setQuestionList] = useState<Array<BasicQuestionType>>([
EssayQ,
RadioQ,
CheckboxQ,
]);
const [survey, setSurvey] = useState();
function QuestionListChange(e: React.ChangeEvent<HTMLInputElement>): void {
const newList: BasicQuestionType[] = [...questionList];
const targetId: any = e.target.name;
const obj: any = newList.find((a) => a.id === e.target.id);
obj[targetId] = e.target.value;
setQuestionList(newList);
}
function addQuestion(): void {
//무작위로 12자리 ID제공, 추후에 질문을 DB에 생성하고 _id를 DB에서 가져오는 것으로 교체할 예정
function getRandomInt(min: number, max: number): string {
min = Math.ceil(min);
max = Math.floor(max);
const randomNum: number = Math.floor(Math.random() * (max - min)) + min;
return randomNum.toString();
}
const randomId: string = getRandomInt(100000000000, 999999999999);
//새로운 질문 생성
const newQ: EssayType = {
type: "essay",
id: randomId,
title: "Question",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
content: null,
};
setQuestionList([...questionList, newQ]);
}
function deleteQuestion(): void {}
const [error, setError] = useState("");
const [disabled, setDisabled] = useState(false);
const [success, setSuccess] = useState(false);
return (
<>
<QuestionProvider>
<div className="flex flex-col place-items-center">
<div className="flex flex-col container place-items-center mt-4">
<input
......@@ -166,16 +141,14 @@ export const CreateSurveyForm = () => {
cols={60}
></textarea>
</div>
<Question
questionList={questionList}
QuestionListChange={QuestionListChange}
addQuestion={addQuestion}
/>
<Question />
<div>
<button className="border bg-themeColor my-5 py-2 px-3 font-bold text-white">
설문조사 생성
</button>
</div>
</div>
</QuestionProvider>
</>
);
};
import React from "react";
import { useQuestion } from "./question.context";
type Props = {
id: string;
};
export const Edit = ({ id }: Props) => {
const { editClick } = useQuestion();
return (
<button id={id} className="w-1/12" onClick={editClick}>
수정
</button>
);
};
import React from "react";
import { CheckboxType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
import { Edit } from "./Edit";
type Props = {
element: CheckboxType;
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
export const QCheckbox = ({ element, QuestionListChange }: Props) => (
export const QCheckbox = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<input
type="text"
name={element.name}
id="title"
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<select
id="Questions"
......@@ -37,11 +41,11 @@ export const QCheckbox = ({ element, QuestionListChange }: Props) => (
<div className="flex w-full justify-center">
<input
type="text"
name={element.name}
id="comment"
name="comment"
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={QuestionListChange}
onChange={questionListChange}
></input>
</div>
<div id="commentarea" className="flex mt-4">
......@@ -60,6 +64,8 @@ export const QCheckbox = ({ element, QuestionListChange }: Props) => (
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
<Edit id={element._id} />
</div>
</div>
);
);
};
import { useQuestion } from "./question.context";
import React from "react";
import { DropdownType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
type Props = {
element: DropdownType;
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
export const QDropdown = ({ element, QuestionListChange }: Props) => (
export const QDropdown = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<input
type="text"
name={element.name}
id="title"
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<select
id="Questions"
......@@ -37,11 +39,11 @@ export const QDropdown = ({ element, QuestionListChange }: Props) => (
<div className="flex w-full justify-center">
<input
type="text"
name={element.name}
id="comment"
name="comment"
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={QuestionListChange}
onChange={questionListChange}
></input>
</div>
<div id="commentarea" className="flex mt-4">
......@@ -62,4 +64,5 @@ export const QDropdown = ({ element, QuestionListChange }: Props) => (
<button className="w-1/12">삭제</button>
</div>
</div>
);
);
};
import React, { useState } from "react";
import { EssayType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
import { Edit } from "./Edit";
type Props = {
element: EssayType;
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
export const QEssay = ({ element, QuestionListChange }: Props) => {
export const QEssay = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex h-16 w-full place-content-between items-center">
<input
type="text"
name="title"
id={element.id}
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<select
id="Questions"
......@@ -39,10 +42,10 @@ export const QEssay = ({ element, QuestionListChange }: Props) => {
<input
type="text"
name="comment"
id={element.id}
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={QuestionListChange}
onChange={questionListChange}
></input>
</div>
<div id="commentarea" className="flex mt-4 w-full justify-center">
......@@ -52,6 +55,7 @@ export const QEssay = ({ element, QuestionListChange }: Props) => {
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
<Edit id={element._id} />
</div>
</div>
);
......
import React, { useState } from "react";
import { FileType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
type Props = {
element: FileType;
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
export const QFile = ({ element, QuestionListChange }: Props) => {
export const QFile = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex h-16 w-full place-content-between items-center">
<input
type="text"
name={element.name}
id="title"
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<select
id="Questions"
......@@ -38,11 +40,11 @@ export const QFile = ({ element, QuestionListChange }: Props) => {
<div className="flex w-full justify-center">
<input
type="text"
name={element.name}
id="comment"
name="comment"
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={QuestionListChange}
onChange={questionListChange}
></input>
</div>
<div id="commentarea" className="flex mt-4 w-full justify-center">
......
import { useQuestion } from "./question.context";
import React from "react";
import { RadioType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
type Props = {
element: RadioType;
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
export const QRadio = ({ element, QuestionListChange }: Props) => (
export const QRadio = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex h-16 w-full place-content-between items-center">
<input
type="text"
id={element.id}
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<select
id="Questions"
......@@ -36,23 +38,30 @@ export const QRadio = ({ element, QuestionListChange }: Props) => (
<div className="flex w-full justify-center">
<input
type="text"
id={element.id}
name="comment"
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={QuestionListChange}
onChange={questionListChange}
></input>
</div>
<div className="flex mt-4">
{element.content.choices.map((e: string) => (
{element.content.choices.map((e: string, index: number) => (
<div>
<input type="radio" id={e} name="choice" value={e} checked={false} />
<input
type="radio"
id={element._id}
name="choice"
value={e}
disabled
/>
<input
type="text"
name="content"
name={"choice" + `${index}`}
// key={`${index}`}
className="mx-2 border-b-2"
placeholder={e}
onChange={QuestionListChange}
onChange={questionListChange}
></input>
<button></button>
</div>
......@@ -67,4 +76,5 @@ export const QRadio = ({ element, QuestionListChange }: Props) => (
<button className="w-1/12">삭제</button>
</div>
</div>
);
);
};
import React from "react";
import { RatingType } from "./CreateSurveyFormPage";
import { useQuestion } from "./question.context";
type Props = {
element: RatingType;
// deleteValue: (e: React.MouseEvent<HTMLButtonElement>) => void;
};
export const QRating = ({ element }: Props) => {
const { questionListChange } = useQuestion();
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2">
<div className="flex h-16 w-full place-content-between items-center">
<input
type="text"
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={questionListChange}
></input>
<select
id={element._id}
className="w-36 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-themeColor w-full mr-3 p-2.5"
>
<option>질문종류</option>
<option value="essay">주관식</option>
<option value="radio">객관식</option>
<option value="dropdown">드롭다운(객관식)</option>
<option value="checkbox">체크박스(객관식)</option>
<option value="file">파일업로드</option>
<option value="rating" selected>
선형
</option>
<option value="grid">그리드</option>
<option value="date">날짜</option>
</select>
</div>
<div className="flex w-full justify-center">
<input
type="text"
name="comment"
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
onChange={questionListChange}
></input>
</div>
<div className="flex place-content-between items-center p-5">
<input
name="minRateDescription"
id={element._id}
className="border-b-2 text-center"
size={10}
placeholder={element.content.minRateDescription}
></input>
{element.content.rateValues.map((e) => (
<input
name="text"
id={element._id}
type="text"
className="border border-black rounded-full py-1 m-2 text-center"
size={1}
placeholder={e.text}
></input>
))}
<input
name="maxRateDescription"
id={element._id}
className="border-b-2 text-center"
size={10}
placeholder={element.content.maxRateDescription}
></input>
</div>
<div>
<button
// type="button"
name="rateValues"
id={element._id}
className="border border-red-500 rounded mx-2 px-2"
// onClick={deleteValue}
>
삭제
</button>
<button className="border border-blue-500 rounded mx-2 px-2">
추가
</button>
</div>
<div className="flex w-full justify-end py-2">
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
</div>
</div>
);
};
import React, { useState } from "react";
import { BasicQuestionType } from "./CreateSurveyFormPage";
import { QEssay } from "./QEssay";
import { QCheckbox } from "./QCheckbox";
import { QRadio } from "./QRadio";
import { QDropdown } from "./QDropdown";
import { QFile } from "./QFile";
import { QRating } from "./QRating";
import { useQuestion } from "./question.context";
type Props = {
questionList: BasicQuestionType[];
QuestionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
addQuestion: () => void;
};
type Props = {};
export const Question = ({}: Props) => {
const { addQuestion, questionList, currentId } = useQuestion();
export const Question = ({
questionList,
QuestionListChange,
addQuestion,
}: Props) => {
return (
<>
{console.log(questionList)}
{console.log(questionList, currentId)}
{questionList.map((element) => {
switch (element.type) {
case "essay":
return (
<QEssay
element={element}
QuestionListChange={QuestionListChange}
/>
);
return <QEssay element={element} />;
case "radio":
return (
<QRadio
element={element}
QuestionListChange={QuestionListChange}
/>
);
return <QRadio element={element} />;
case "checkbox":
return (
<QCheckbox
element={element}
QuestionListChange={QuestionListChange}
/>
);
return <QCheckbox element={element} />;
case "dropdown":
return (
<QDropdown
element={element}
QuestionListChange={QuestionListChange}
/>
);
return <QDropdown element={element} />;
case "file":
return (
<QFile
element={element}
QuestionListChange={QuestionListChange}
/>
);
return <QFile element={element} />;
case "rating":
return <QRating element={element} />;
default:
break;
}
......
import React, {
createContext,
FC,
ReactNode,
useContext,
useState,
} from "react";
import axios from "axios";
import { BasicQuestionType } from "./CreateSurveyFormPage";
interface IQuestionContext {
questionListChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
questionList: BasicQuestionType[];
editClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
currentId: string;
addQuestion: (e: React.MouseEvent<HTMLButtonElement>) => Promise<void>;
}
const QuestionContext = createContext<IQuestionContext>({
questionListChange: () => {},
questionList: [],
editClick: () => {},
currentId: "",
addQuestion: async () => {},
});
export const QuestionProvider: FC<{ children: ReactNode }> = ({ children }) => {
const [questionList, setQuestionList] = useState<Array<BasicQuestionType>>(
[]
);
const [currentId, setCurrentId] = useState<string>("");
function questionListChange(e: React.ChangeEvent<HTMLInputElement>): void {
const newList: BasicQuestionType[] = [...questionList];
const obj: any = newList.find((a) => a._id === e.target.id); //고유 _id로 질문찾기
const targetKey: any = e.target.name;
obj[targetKey] = e.target.value;
setQuestionList(newList);
}
async function addQuestion(e: React.MouseEvent<HTMLButtonElement>) {
try {
const res = await axios.post("/api/questions/create", {
type: "essay",
title: "Question Title",
isRequired: false,
comment: "질문에 대한 설명을 입력해주세요",
content: null,
});
console.log(res.data);
setQuestionList([...questionList, res.data]);
// setSuccess(true);
// setError("");
} catch (error) {
console.log("에러발생");
// catchErrors(error, setError)
} finally {
// setLoading(false);
}
}
function editClick(e: React.MouseEvent<HTMLButtonElement>) {
setCurrentId(e.currentTarget.id);
}
return (
<QuestionContext.Provider
value={{
questionListChange,
addQuestion,
questionList,
editClick,
currentId,
}}
>
{children}
</QuestionContext.Provider>
);
};
export const useQuestion = () => useContext(QuestionContext);
......@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack TypeScript React TailwindCSS Template</title>
<title>Simple Survey Form</title>
</head>
<body>
<div id="root"></div>
......
export * as authCtrl from "./auth.controller";
export * as questionCtrl from "./question.controller";
export * as roleCtrl from "./role.controller";
export * as userCtrl from "./user.controller";
import { questionDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap";
export const createQuestion = asyncWrap(async (req, res) => {
const question = req.body;
console.log("question body", question);
const newQuestion = await questionDb.createQuestion(question);
return res.json(newQuestion);
});
export * as userDb from "./user.db";
export * as roleDb from "./role.db";
export * as questionDb from "./question.db";
export * as userDb from "./user.db";
import { Question, IQuestion } from "../models";
export const createQuestion = async (question: IQuestion) => {
const newQuestion = await Question.create(question);
const newQ = {
_id: newQuestion._id,
type: newQuestion.type,
title: newQuestion.title,
isRequired: newQuestion.isRequired,
comment: newQuestion.comment,
content: newQuestion.content,
}
return newQ;
};
export { default as User, IUser } from "./user.model";
export { default as Question, IQuestion } from "./question.model";
export { default as Role } from "./role.model";
export { default as User, IUser } from "./user.model";
import { model, Schema, Types } from "mongoose";
export interface IQuestion {
type: string;
// id: string;
title?: string;
isRequired: boolean;
comment?: string;
content?: any;
}
const schema = new Schema<IQuestion>({
// id: {type:String},
type:{type:String},
title: {type:String},
isRequired: {type:Boolean},
comment:{type: String},
content:{type: Object},
});
export default model<IQuestion>("Question", schema);
\ No newline at end of file
......@@ -16,7 +16,7 @@ const schema = new Schema<IUser>(
{
email: {
type: String,
rquired: true,
required: true,
unique: true,
validate: [validateEmail, "이메일을 입력해주세요"],
},
......
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