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

Merge branch 'main' into file-upload

parents 6a24c10c 80a2b663
import React from "react";
export const AEssayForm = () => {
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-3">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<form className="text-xl font-bold ml-6 w-1/2">input</form>
</div>
<form className="border w-11/12 my-3">설문조사 설명</form>
<input className="border w-11/12 h-36 my-3" type="text"></input>
</div>
);
};
import React from "react";
import { RadioType } from "../types";
// type Props = {
// element: RadioType;
// };
export const ARadioForm = () => {
return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-3">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<form className="text-xl font-bold ml-6 w-1/2">radio</form>
</div>
<form className="border w-11/12 my-4">설문조사 설명</form>
<div className="flex flex-row items-center m-3">
<div className="flex items-center mb-4 mx-4">
<input
id="default-radio-1"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">First radio</label>
</div>
<div className="flex items-center mb-4 mx-4">
<input
id="default-radio-1"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">Second radio</label>
</div>
<div className="flex items-center mb-4 mx-4">
<input
checked
id="default-radio-2"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">Checked state</label>
</div>
</div>
</div>
);
};
import React, { InputHTMLAttributes } from "react"; import React, { InputHTMLAttributes } from "react";
import { ACheckboxForm } from "./ACheckbox";
import { ADropdownForm } from "./ADropdown";
import { AEssayForm } from "./AEssayForm";
import { ARadioForm } from "./ARadioForm";
export const SurveyForm = () => { export const SurveyForm = () => {
return ( return (
...@@ -11,113 +15,15 @@ export const SurveyForm = () => { ...@@ -11,113 +15,15 @@ export const SurveyForm = () => {
rows={2} rows={2}
cols={60} cols={60}
></textarea> ></textarea>
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-3"> {/* <ACheckboxForm></ACheckboxForm> */}
<div className="flex flexgi-row h-16 w-full place-content-between items-center"> <ADropdownForm></ADropdownForm>
<form className="text-xl font-bold ml-6 w-1/2"> <AEssayForm></AEssayForm>
Q1. 첫번째 질문 <ARadioForm></ARadioForm>
</form> <div>
</div> <button className="rounded bg-themeColor my-5 py-2 px-5 font-bold text-white">
<form className="border w-11/12 my-3">설문조사 설명</form> 제출하기
<input </button>
className="border w-11/12 h-36 my-3"
type="text"
placeholder="설문조사 답변"
></input>
</div> </div>
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-3">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<form className="text-xl font-bold ml-6 w-1/2">
Q2. 두번째 질문
</form>
</div>
<form className="border w-11/12 my-4">설문조사 설명</form>
<div className="flex flex-row items-center m-3">
<div className="mb-4 mx-3">
<input
id="default-checkbox"
type="checkbox"
className="w-5 h-5 mt-3 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg font-medium">First checkbox</label>
</div>
<div className="mb-4 mx-3">
<input
id="default-checkbox"
type="checkbox"
className="w-5 h-5 mt-3 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg font-medium">
Second checkbox
</label>
</div>
<div className="mb-4 mx-3">
<input
id="default-checkbox"
type="checkbox"
value=""
className="w-5 h-5 mt-3 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg font-medium">Third checkbox</label>
</div>
<div className="mb-4 mx-4">
<input
id="default-checkbox"
type="checkbox"
value=""
className="w-5 h-5 mt-3 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg font-medium">
Fourth checkbox
</label>
</div>
</div>
</div>
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-3">
<div className="flex flexgi-row h-16 w-full place-content-between items-center">
<form className="text-xl font-bold ml-6 w-1/2">
Q3. 세번째 질문
</form>
</div>
<form className="border w-11/12 my-4">설문조사 설명</form>
<div className="flex flex-row items-center m-3">
<div className="flex items-center mb-4 mx-4">
<input
id="default-radio-1"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">First radio</label>
</div>
<div className="flex items-center mb-4 mx-4">
<input
id="default-radio-1"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">Second radio</label>
</div>
<div className="flex items-center mb-4 mx-4">
<input
checked
id="default-radio-2"
type="radio"
value=""
name="default-radio"
className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
/>
<label className="ml-2 text-lg">Checked state</label>
</div>
</div>
</div>
</div>
<div>
<button className="rounded bg-themeColor my-5 py-2 px-5 font-bold text-white">
제출하기
</button>
</div> </div>
</div> </div>
); );
......
import React from "react"; import React, { FormEvent } from "react";
import { Link } from "react-router-dom"; import { useAuth } from "../auth/auth.context";
export const Home = () => ( export const Home = () => {
<div className="flex flex-col place-items-center"> const { user } = useAuth();
<div className="justify-end text-center text-3xl text-black h-16 mt-12">
가장 쉽게 설문지를 만드세요! function clickHome(e: React.MouseEvent<HTMLButtonElement>) {
</div> e.preventDefault();
<div className="flex flex-col place-items-center container"> if (!user.isLoggedIn) {
<div> console.log("버튼");
<Link location.href = "/login";
to="/create" } else {
className="flex h-14 w-28 items-center border-2 border-themeColor font-bold text-black bg-gray-200 hover:bg-themeColor rounded-lg " location.href = "/profile";
> }
<div className="text-center w-28 font-bold text-black place-items-center"> }
return (
<div className="flex flex-col place-items-center">
<div className="justify-end text-center text-3xl text-black h-16 mt-12">
가장 쉽게 설문지를 만드세요!
</div>
<div className="flex flex-col place-items-center container">
<div className="flex h-14 w-28 items-center border-2 border-themeColor font-bold text-black bg-gray-200 hover:bg-themeColor rounded-lg ">
<button
type="button"
className="text-center h-full w-28 font-bold text-black place-items-center"
onClick={clickHome}
>
+ +
</div> </button>
</Link> </div>
<p className="text-center text-xl text-black mt-3">Create now!</p>
</div>
<div className="flex justify-center">
<img
src="https://3hbgf23vu0wr11wkpae5igwe-wpengine.netdna-ssl.com/wp-content/uploads/2021/04/SurveyExample_v3.jpg"
className="object-scale-down justify-center"
/>
</div> </div>
<p className="text-center text-xl text-black">Create now!</p>
</div>
<div className="flex justify-center">
<img
src="https://3hbgf23vu0wr11wkpae5igwe-wpengine.netdna-ssl.com/wp-content/uploads/2021/04/SurveyExample_v3.jpg"
className="object-scale-down justify-center"
/>
</div> </div>
</div> );
); };
import React from "react"; import React, { useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { surveyApi } from "../apis";
import { SurveyType } from "../types";
export const Profile = () => { export const Profile = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [survey, setSurvey] = useState<SurveyType>({
const createSurvey = () => { user: {},
// 먼저 서버에 survey 테이블에 새로운 survey 항목 추가 로직 필요 title: "",
navigate("/surveys/create", { replace: true }); comment: "",
}; questions: [],
});
async function createSurvey() {
const newSurvey: SurveyType = await surveyApi.createSurvey(survey);
navigate(`/surveys/edit/${newSurvey._id}`, {
replace: true,
});
}
return ( return (
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<div className="m-5">나의 설문조사</div> <div className="m-5">나의 설문조사</div>
<div className="flex flex-row space-x-4 mt-5"> <div className="flex space-x-4 mt-5">
<button <button
onClick={createSurvey} onClick={createSurvey}
className="flex h-60 w-48 items-center border-2 border-themeColor font-bold bg-gray-200 hover:bg-themeColor rounded-lg " className="flex h-60 w-48 items-center border-2 border-themeColor font-bold bg-gray-200 hover:bg-themeColor rounded-lg "
...@@ -31,7 +40,7 @@ export const Profile = () => { ...@@ -31,7 +40,7 @@ export const Profile = () => {
<div className="px-2 py-2"> <div className="px-2 py-2">
<label>설문조사 이름</label> <label>설문조사 이름</label>
</div> </div>
<div className="flex justify-end dropdown-toggle"> <div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white"> <select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option> <option selected>옵션</option>
<option>삭제</option> <option>삭제</option>
...@@ -50,7 +59,7 @@ export const Profile = () => { ...@@ -50,7 +59,7 @@ export const Profile = () => {
<div className="px-2 py-2"> <div className="px-2 py-2">
<label>설문조사이름</label> <label>설문조사이름</label>
</div> </div>
<div className="flex justify-end dropdown-toggle"> <div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white"> <select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option> <option selected>옵션</option>
<option>삭제</option> <option>삭제</option>
...@@ -69,7 +78,7 @@ export const Profile = () => { ...@@ -69,7 +78,7 @@ export const Profile = () => {
<div className="px-2 py-2"> <div className="px-2 py-2">
<label>설문조사 이름</label> <label>설문조사 이름</label>
</div> </div>
<div className="flex justify-end dropdown-toggle"> <div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white"> <select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option> <option selected>옵션</option>
<option>삭제</option> <option>삭제</option>
...@@ -88,7 +97,7 @@ export const Profile = () => { ...@@ -88,7 +97,7 @@ export const Profile = () => {
<div className="px-2 py-2"> <div className="px-2 py-2">
<label>설문조사 이름</label> <label>설문조사 이름</label>
</div> </div>
<div className="flex justify-end dropdown-toggle"> <div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white"> <select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option> <option selected>옵션</option>
<option>삭제</option> <option>삭제</option>
......
import React from "react"; import React, { useState } from "react";
import { CheckboxType } from "../types"; import { CheckboxType } from "../types";
import { useQuestion } from "./question.context";
import { Edit } from "./Edit";
import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: CheckboxType; element: CheckboxType;
handleQuestion: (id: string) => void;
currentId: string;
}; };
export const QCheckbox = ({ element }: Props) => { export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
const { questionListChange } = useQuestion(); const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
const { id, value } = event.target;
choices[+id].text = value;
element.content.choices = choices;
handleQuestion(element._id);
console.log(choices);
}
function deleteValue() {
//제일 마지막 index 제거
choices.splice(-1, 1);
element.content.choices = choices;
handleQuestion(element._id);
}
function addValue() {
choices.push({ text: "", value: choices.length });
element.content.choices = choices;
handleQuestion(element._id);
}
return ( 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"> <div id="content" className="mt-4 p-5">
<input {choices.map((choice: any, index: number) => (
type="text" <div className="m-5">
name="title" <input type="checkbox" disabled></input>
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={questionListChange}
></input>
<TypeChange tt="checkbox" />
</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 id="commentarea" className="flex mt-4">
{element.content.choices.map((e: any) => (
<div>
<input type="checkbox" checked={false}></input>
<input <input
id={`${index}`}
type="text" type="text"
className="mx-2 border-b-2" className="mx-2 border-b-2"
placeholder={e.text} placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
</div> </div>
))} ))}
</div> </div>
<div className="flex w-full flex-row justify-end py-2"> <div>
<button className="w-1/12">필수</button> <button
<button className="w-1/12">옵션</button> type="button"
<button className="w-1/12">삭제</button> name="rateValues"
<Edit id={element._id} /> className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
>
삭제
</button>
<button
type="button"
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
>
추가
</button>
</div> </div>
</div> </>
); );
}; };
import { useQuestion } from "./question.context";
import React from "react"; import React, { useState } from "react";
import { DropdownType } from "../types"; import { DropdownType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: DropdownType; element: DropdownType;
handleQuestion: (id: string) => void;
currentId: string;
}; };
export const QDropdown = ({ element }: Props) => { export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
const { questionListChange } = useQuestion(); const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
const { id, value } = event.target;
choices[+id].text = value;
element.content.choices = choices;
handleQuestion(element._id);
console.log(choices);
}
function deleteValue() {
//제일 마지막 index 제거
choices.splice(-1, 1);
element.content.choices = choices;
handleQuestion(element._id);
}
function addValue() {
choices.push({ text: "", value: choices.length });
element.content.choices = choices;
handleQuestion(element._id);
}
return ( 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"> <div id="content" className="flex-row mt-4 p-5">
<input <select className="mr-3">
type="text" {choices.map((choice: any, index: number) => (
name="title" <option>{choice.text}</option>
id={element._id} ))}
className="text-xl font-bold ml-6 border-b-2 w-1/2" </select>
placeholder={element.title} {choices.map((choice: any, index: number) => (
onChange={questionListChange} <div className="my-5">
></input>
<TypeChange tt="dropdown" />
</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 id="commentarea" className="flex mt-4">
{element.content.choices.map((e: any) => (
<div>
<input type="checkbox" checked={false}></input>
<input <input
id={`${index}`}
type="text" type="text"
className="mx-2 border-b-2" className="mx-2 border-b-2"
placeholder={e.text} placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
</div> </div>
))} ))}
</div> </div>
<div className="flex w-full flex-row justify-end py-2"> <div>
<button className="w-1/12">필수</button> <button
<button className="w-1/12">옵션</button> type="button"
<button className="w-1/12">삭제</button> name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
>
삭제
</button>
<button
type="button"
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
>
추가
</button>
</div> </div>
</div> </>
); );
}; };
import React, { useState } from "react"; import React from "react";
import { EssayType } from "../types"; import { EssayType } from "../types";
// import { useQuestion } from "./question.context";
// import { Edit } from "./Edit";
// import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: EssayType; element: EssayType;
currentId: string;
}; };
export const EssayForm = ({ element }: Props) => { export const EssayForm = ({ element, currentId }: Props) => {
// const { questionListChange } = useQuestion();
return ( return (
<div id="commentarea" className="flex mt-4 w-full justify-center"> <div id="commentarea" className="flex mt-4 w-full justify-center">
<input className="border w-11/12 h-16" disabled></input> <input className="border w-11/12 h-16" disabled></input>
......
import React, { useState } from "react"; import React, { useState } from "react";
import { FileType } from "../types"; import { FileType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: FileType; element: FileType;
currentId: string;
}; };
export const QFile = ({ element }: Props) => { export const FileForm = ({ element, currentId }: Props) => {
const { questionListChange } = useQuestion();
return ( return (
<div className="flex flex-col container w-4/5 h-auto border-2 border-themeColor items-center m-3 py-2"> <div id="content" className="flex mt-4 w-full justify-center">
<div className="flex h-16 w-full place-content-between items-center"> <input type="file" className=" w-11/12 h-16" disabled></input>
<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>
<TypeChange tt="file" />
</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 id="commentarea" className="flex mt-4 w-full justify-center">
<input type="file" className=" w-11/12 h-16" disabled></input>
</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> </div>
); );
}; };
import { useQuestion } from "./question.context"; // import { useQuestion } from "./question.context";
import React, { useState } from "react"; import React, { useState, Dispatch, SetStateAction } from "react";
import { BasicQuestionType, EssayType } from "../types"; import { BasicQuestionType, EssayType } from "../types";
import { questionApi } from "../apis";
import { EssayForm } from "./EssayForm"; import { EssayForm } from "./EssayForm";
import { CheckboxForm } from "./CheckboxForm";
import { RadioForm } from "./RadioForm";
import { DropdownForm } from "./DropdownForm";
import { FileForm } from "./FileForm";
import { RatingForm } from "./RatingForm";
type Props = { type Props = {
element: BasicQuestionType; element: BasicQuestionType;
handleQuestion: (id: string) => void;
deleteQuestion: (id: string) => void;
changeCurrentId: (id: string) => void;
currentId: string;
}; };
export const Question = ({ element }: Props) => { const typeDropDown = new Map([
const handleClick = () => {}; ["essay", "주관식"],
["radio", "객관식"],
["dropdown", "드롭다운"],
["checkbox", "체크박스"],
["file", "파일"],
["rating", "선형"],
["grid", "그리드"],
["date", "날짜"],
]);
const typeDD = new Map([ export const Question = ({
["essay", "주관식"], element,
["radio", "객관식"], handleQuestion,
["dropdown", "드롭다운(객관식)"], deleteQuestion,
["checkbox", "체크박스"], changeCurrentId,
["file", "파일"], currentId,
["rating", "선형"], }: Props) => {
["grid", "그리드"], const handleEditClick = () => {
["date", "날짜"], changeCurrentId(element._id);
]); };
async function handleEditComplete() {
try {
const newQuestion: BasicQuestionType = await questionApi.updateQuestion(
element
);
console.log(newQuestion);
changeCurrentId("");
// setSuccess(true);
// setError("");
} catch (error) {
console.log("에러발생");
// catchErrors(error, setError)
} finally {
// setLoading(false);
}
}
function handleSelect(event: React.ChangeEvent<HTMLSelectElement>) {
const selectedType = event.currentTarget.value;
console.log(selectedType);
if (
selectedType === "radio" ||
selectedType === "dropdown" ||
selectedType === "checkbox"
) {
element.content = {
choices: [
{ text: "", value: 0 },
{ text: "", value: 1 },
{ text: "", value: 2 },
],
};
} else if (selectedType === "essay") {
element.content = { choices: [] };
} else if (selectedType === "rating") {
element.content = {
minRateDescription: "",
maxRateDescription: "",
choices: [
{ text: "", value: 0 },
{ text: "", value: 1 },
{ text: "", value: 2 },
],
};
}
element.type = selectedType;
handleQuestion(element._id);
}
function changeDD(e: React.ChangeEvent<HTMLSelectElement>) { function handleQuestionInfo(event: React.ChangeEvent<HTMLInputElement>) {
const tt = e.target.value; const { name, value } = event.currentTarget;
// questionTypeChange(e); element[name] = value;
console.log(tt); handleQuestion(element._id);
//if문으로 type별로 content 바뀌게 해보기 }
function handleDelete() {
deleteQuestion(element._id);
} }
function getContent(element: BasicQuestionType) { function getContent(element: BasicQuestionType) {
switch (element.type) { switch (element.type) {
case "essay": case "essay":
return <EssayForm element={element} />; return <EssayForm element={element} currentId={currentId} />;
case "radio": case "radio":
// return <RadioForm element={element} />; return (
<RadioForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "checkbox": case "checkbox":
// return <CheckboxForm element={element} />; return (
<CheckboxForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "dropdown": case "dropdown":
// return <DropdownForm element={element} />; return (
<DropdownForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "file": case "file":
// return <FileForm element={element} />; return <FileForm element={element} currentId={currentId} />;
case "rating": case "rating":
// return <RatingForm element={element} />; return (
<RatingForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
default: default:
return <></>; return <></>;
} }
...@@ -54,18 +147,25 @@ export const Question = ({ element }: Props) => { ...@@ -54,18 +147,25 @@ export const Question = ({ element }: Props) => {
name="title" name="title"
id={element._id} id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2" className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title} placeholder={"Question Title"}
// onChange={questionListChange} value={element.title}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
></input> ></input>
<select <select
id="Questions" id={element._id}
name="type" name="type"
onChange={handleSelect}
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" 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"
defaultValue={element.type}
onChange={changeDD}
> >
{Array.from(typeDD.entries()).map(([k, v]) => ( {Array.from(typeDropDown.entries()).map(([key, value]) => (
<option value={k}>{v}</option> <option
id={element._id}
value={key}
selected={key === element.type}
>
{value}
</option>
))} ))}
</select> </select>
</div> </div>
...@@ -76,18 +176,32 @@ export const Question = ({ element }: Props) => { ...@@ -76,18 +176,32 @@ export const Question = ({ element }: Props) => {
id={element._id} id={element._id}
className="border w-11/12" className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요" placeholder="질문에 대한 설명을 입력해주세요"
// onChange={questionListChange} value={element.comment}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
></input> ></input>
</div> </div>
{getContent(element)} {getContent(element)}
<div className="flex w-full justify-end py-2"> <div className="place-self-end py-2">
<button className="w-1/12">필수</button> <button type="button" className="px-1">
<button className="w-1/12">옵션</button> 필수
<button className="w-1/12">삭제</button> </button>
<button id={element.id} className="w-1/12" onClick={handleClick}> <button type="button" className="px-1">
수정 옵션
</button>
<button type="button" className="px-1" onClick={handleDelete}>
삭제
</button> </button>
{currentId === element._id ? (
<button type="button" className="px-1" onClick={handleEditComplete}>
수정완료
</button>
) : (
<button type="button" className="px-1" onClick={handleEditClick}>
수정하기
</button>
)}
</div> </div>
</div> </div>
); );
......
import React from "react"; import React, { useState } from "react";
import { RadioType } from "../types"; import { RadioType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: RadioType; element: RadioType;
handleQuestion: (id: string) => void;
currentId: string;
}; };
export const QRadio = ({ element }: Props) => { export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
const { questionListChange } = useQuestion(); const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
const { id, value } = event.target;
choices[+id].text = value;
element.content.choices = choices;
handleQuestion(element._id);
console.log(choices);
}
function deleteValue() {
//제일 마지막 index 제거
choices.splice(-1, 1);
element.content.choices = choices;
handleQuestion(element._id);
}
function addValue() {
choices.push({ text: "", value: choices.length });
element.content.choices = choices;
handleQuestion(element._id);
}
return ( 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"> <div id="content" className="mt-4 p-5">
<input {choices.map((choice: any, index: number) => (
type="text" <div className="m-5">
name="title" <input type="radio" disabled></input>
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
onChange={questionListChange}
></input>
<TypeChange tt="radio" />
</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 mt-4">
{element.content.choices.map((e: any, index: number) => (
<div>
<input
type="radio"
id={element._id}
name="choice"
value={e.text}
disabled
/>
<input <input
id={`${index}`}
type="text" type="text"
name={"choice"}
// key={`${index}`}
className="mx-2 border-b-2" className="mx-2 border-b-2"
placeholder={e.text} placeholder="선택지"
onChange={questionListChange} value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
<button></button>
</div> </div>
))} ))}
{/* <button className="border rounded-full border-green-500 border-4 text-green-500 font-bold px-2">
+
</button> */}
</div> </div>
<div className="flex w-full flex-row justify-end py-2"> <div>
<button className="w-1/12">필수</button> <button
<button className="w-1/12">옵션</button> type="button"
<button className="w-1/12">삭제</button> name="rateValues"
className="border border-red-500 rounded mx-2 px-2"
onClick={deleteValue}
disabled={currentId !== element._id}
>
삭제
</button>
<button
type="button"
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
>
추가
</button>
</div> </div>
</div> </>
); );
}; };
import React from "react"; import React, { useState } from "react";
import { RatingType } from "../types"; import { RatingType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = { type Props = {
element: RatingType; element: RatingType;
// deleteValue: (e: React.MouseEvent<HTMLButtonElement>) => void; handleQuestion: (id: string) => void;
currentId: string;
}; };
export const QRating = ({ element }: Props) => { export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
const { questionListChange } = useQuestion(); const [choices, setChoices] = useState([...element.content.choices]);
function handleContent(event: React.ChangeEvent<HTMLInputElement>) {
const { id, value, name } = event.target;
if (name === "text") {
choices[+id].text = value;
element.content.choices = choices;
} else if (name === "minRateDescription") {
element.content = { ...element.content, minRateDescription: value };
} else if (name === "maxRateDescription") {
element.content = { ...element.content, maxRateDescription: value };
}
handleQuestion(element._id);
console.log(choices);
}
function deleteValue() {
//제일 마지막 index 제거
choices.splice(-1, 1);
element.content.choices = choices;
handleQuestion(element._id);
}
function addValue() {
choices.push({ text: "0", value: choices.length });
element.content.choices = choices;
handleQuestion(element._id);
}
return ( 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>
<TypeChange tt="rating" />
</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"> <div className="flex place-content-between items-center p-5">
<input <input
name="minRateDescription" name="minRateDescription"
id={element._id}
className="border-b-2 text-center" className="border-b-2 text-center"
size={10} size={10}
placeholder={element.content.minRateDescription} placeholder="비동의"
value={element.content.minRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
{element.content.choices.map((e) => ( {choices.map((choice: any, index: number) => (
<input <input
name="text" name="text"
id={element._id} id={`${index}`}
type="text" type="text"
className="border border-black rounded-full py-1 m-2 text-center" className="border border-black rounded-full py-1 m-2 text-center"
size={1} size={1}
placeholder={e.text} placeholder="0"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
))} ))}
<input <input
name="maxRateDescription" name="maxRateDescription"
id={element._id}
className="border-b-2 text-center" className="border-b-2 text-center"
size={10} size={10}
placeholder={element.content.maxRateDescription} placeholder="동의"
value={element.content.maxRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
></input> ></input>
</div> </div>
<div> <div>
<button <button
// type="button" type="button"
name="rateValues" name="rateValues"
id={element._id}
className="border border-red-500 rounded mx-2 px-2" className="border border-red-500 rounded mx-2 px-2"
// onClick={deleteValue} onClick={deleteValue}
disabled={currentId !== element._id}
> >
삭제 삭제
</button> </button>
<button className="border border-blue-500 rounded mx-2 px-2"> <button
type="button"
name="rateValues"
className="border border-blue-500 rounded mx-2 px-2"
onClick={addValue}
disabled={currentId !== element._id}
>
추가 추가
</button> </button>
</div> </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, { FormEvent, useState } from "react"; import React, { FormEvent, useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { questionApi, surveyApi } from "../apis"; import { questionApi, surveyApi } from "../apis";
import { SpinnerIcon } from "../icons";
import { Question } from "../questions"; import { Question } from "../questions";
import { BasicQuestionType, SurveyType } from "../types"; import { BasicQuestionType, SurveyType } from "../types";
export const CreateSurvey = () => { export const EditSurvey = () => {
let { surveyId } = useParams<{ surveyId: string }>();
useEffect(() => {
getSurvey();
}, [surveyId]);
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [survey, setSurvey] = useState<SurveyType>({ const [survey, setSurvey] = useState<SurveyType>({
_id: surveyId,
user: {},
title: "", title: "",
comment: "", comment: "",
questions: [], questions: [],
}); });
const [currentId, setCurrentId] = useState("");
const changeCurrentId = (id: string) => {
setCurrentId(id);
};
async function getSurvey() {
try {
if (surveyId) {
const thisSurvey: SurveyType = await surveyApi.getSurvey(surveyId);
setSurvey(thisSurvey);
setSuccess(true);
setError("");
} else {
setLoading(true);
}
} catch (error) {
console.log("에러발생");
// catchErrors(error, setError)
} finally {
setLoading(false);
}
}
const handleQuestion = (id: string) => {
const newList: BasicQuestionType[] = [...survey.questions];
setSurvey({ ...survey, questions: newList });
};
const handleChange = () => {}; const handleSurvey = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.currentTarget;
setSurvey({ ...survey, [name]: value });
};
async function handleSubmit(event: FormEvent) { async function handleSubmit(event: FormEvent) {
event.preventDefault(); event.preventDefault();
try { try {
const newSurvey: SurveyType = await surveyApi.createSurvey(survey); const newSurvey: SurveyType = await surveyApi.editSurvey(survey);
console.log(newSurvey); console.log(newSurvey);
// setSuccess(true); // setSuccess(true);
// setError(""); // setError("");
...@@ -31,7 +71,6 @@ export const CreateSurvey = () => { ...@@ -31,7 +71,6 @@ export const CreateSurvey = () => {
try { try {
const newQuestion: BasicQuestionType = await questionApi.createQuestion(); const newQuestion: BasicQuestionType = await questionApi.createQuestion();
setSurvey({ ...survey, questions: [...survey.questions, newQuestion] }); setSurvey({ ...survey, questions: [...survey.questions, newQuestion] });
// setQuestions([...questions, newQuestion]);
// setSuccess(true); // setSuccess(true);
// setError(""); // setError("");
} catch (error) { } catch (error) {
...@@ -42,10 +81,30 @@ export const CreateSurvey = () => { ...@@ -42,10 +81,30 @@ export const CreateSurvey = () => {
} }
} }
const questions = survey.questions; async function deleteQuestion(id: string) {
const newList: BasicQuestionType[] = [...survey.questions];
try {
const newQuestion: BasicQuestionType = await questionApi.deleteQuestion(
id
);
setSurvey({ ...survey, questions: newList.filter((a) => a._id !== id) });
// setSuccess(true);
// setError("");
} catch (error) {
console.log("에러발생");
// catchErrors(error, setError)
} finally {
// setLoading(false);
}
}
const questions = survey.questions;
console.log(questions);
return ( return (
<> <>
{loading && (
<SpinnerIcon className="animate-spin h-5 w-5 mr-1 text-slate" />
)}
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<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">
...@@ -54,7 +113,7 @@ export const CreateSurvey = () => { ...@@ -54,7 +113,7 @@ export const CreateSurvey = () => {
name="title" name="title"
className="font-bold text-4xl text-center m-2 border-b-2" className="font-bold text-4xl text-center m-2 border-b-2"
placeholder="설문지 제목" placeholder="설문지 제목"
onChange={handleChange} onChange={handleSurvey}
></input> ></input>
<input <input
type="text" type="text"
...@@ -62,11 +121,17 @@ export const CreateSurvey = () => { ...@@ -62,11 +121,17 @@ export const CreateSurvey = () => {
className="font-bold text-1xl text-center m-2 resize-none" className="font-bold text-1xl text-center m-2 resize-none"
placeholder="설문조사에 대한 설명을 입력해주세요" placeholder="설문조사에 대한 설명을 입력해주세요"
size={50} size={50}
onChange={handleChange} onChange={handleSurvey}
></input> ></input>
</div> </div>
{questions.map((question) => ( {questions.map((question) => (
<Question element={question} /> <Question
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"> <div className="flex w-4/5 content-center justify-center border-2 border-black h-8 mt-3">
<button type="button" onClick={addQuestion}> <button type="button" onClick={addQuestion}>
......
export { CreateSurvey } from "./CreateSurvey"; export { EditSurvey } from "./EditSurvey";
...@@ -11,6 +11,8 @@ export interface SignupUser { ...@@ -11,6 +11,8 @@ export interface SignupUser {
} }
export interface SurveyType { export interface SurveyType {
_id?: string;
user: any;
title: string; title: string;
comment: string; comment: string;
questions: BasicQuestionType[]; questions: BasicQuestionType[];
......
import { NextFunction, Request, Response } from "express";
import { questionDb } from "../db"; import { questionDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap"; import { asyncWrap } from "../helpers/asyncWrap";
export const createQuestion = asyncWrap(async (req, res) => { export interface TypedRequestAuth<T> extends Request {
auth: T;
user: any;
}
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);
}
);
export const updateQuestion = asyncWrap(async (req, res) => {
const question = req.body; const question = req.body;
console.log("question body", question); const newQuestion = await questionDb.updateQuestion(question);
const newQuestion = await questionDb.createQuestion(question); return res.json(newQuestion);
});
export const deleteQuestionById = asyncWrap(async (req, res) => {
const { questionId } = req.params;
const newQuestion = await questionDb.deleteQuestionById(questionId);
return res.json(newQuestion); return res.json(newQuestion);
}); });
export const userByQuestionId = async (
reqExp: Request,
res: Response,
next: NextFunction,
questionId: string
) => {
try {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
let user = await questionDb.findUserByQuestionId(questionId);
if (!user) {
return res.status(404).send("사용자를 찾을 수 없습니다");
}
req.user = user;
next();
} catch (error: any) {
return res
.status(500)
.send(error.message || "질문을 작성한 사용자를 찾아내는 중 오류 발생");
}
};
import { NextFunction, Request, Response } from "express";
import { surveyDb } from "../db"; import { surveyDb } from "../db";
import { asyncWrap } from "../helpers/asyncWrap"; import { asyncWrap } from "../helpers/asyncWrap";
export const createSurvey = asyncWrap(async (req, res) => { export interface TypedRequestAuth<T> extends Request {
auth: T;
user: any;
}
export const createSurvey = asyncWrap(
async (reqExp: Request, res: Response, next: NextFunction) => {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
const { userId } = req.auth;
let survey = req.body;
survey.user = userId;
console.log("survey body", survey);
const newSurvey = await surveyDb.createSurvey(survey);
return res.json(newSurvey);
}
);
export const getSurveyById = asyncWrap(async (req, res) => {
const { surveyId } = req.params;
const survey = await surveyDb.getSurveyById(surveyId);
console.log("Get완료", survey);
return res.json(survey);
});
export const updateSurvey = asyncWrap(async (req, res) => {
const survey = req.body; const survey = req.body;
console.log("Survey body", survey); const newSurvey = await surveyDb.updateSurvey(survey);
const newSurvey = await surveyDb.createSurvey(survey);
return res.json(newSurvey); return res.json(newSurvey);
}); });
export const userBySurveyId = async (
reqExp: Request,
res: Response,
next: NextFunction,
surveyId: string
) => {
try {
const req = reqExp as TypedRequestAuth<{ userId: string }>;
let user = await surveyDb.findUserBySurveyId(surveyId);
if (!user) {
return res.status(404).send("사용자를 찾을 수 없습니다");
}
req.user = user;
next();
} catch (error: any) {
return res
.status(500)
.send(
error.message || "설문조사를 작성한 사용자를 찾아내는 중 오류 발생"
);
}
};
import { Question, IQuestion } from "../models"; import { Question, IQuestion } from "../models";
export const findUserByQuestionId = async (questionId: string) => {
const question = await Question.findById(questionId).populate("user");
console.log(question);
if (question !== null) {
console.log(question.user);
return question.user;
}
return null;
};
export const createQuestion = async (question: IQuestion) => { export const createQuestion = async (question: IQuestion) => {
const newQuestion = await Question.create(question); const newQuestion = await Question.create(question);
return newQuestion; return newQuestion;
}; };
export const updateQuestion = async (question: IQuestion) => {
const id = question._id;
const newQuestion = await Question.findOneAndUpdate({ _id: id }, question);
return newQuestion;
};
export const deleteQuestionById = async (id: string) => {
const newQuestion = await Question.findByIdAndDelete(id);
return newQuestion;
};
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