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 { ACheckboxForm } from "./ACheckbox";
import { ADropdownForm } from "./ADropdown";
import { AEssayForm } from "./AEssayForm";
import { ARadioForm } from "./ARadioForm";
export const SurveyForm = () => {
return (
......@@ -11,113 +15,15 @@ export const SurveyForm = () => {
rows={2}
cols={60}
></textarea>
<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">
Q1. 첫번째 질문
</form>
</div>
<form className="border w-11/12 my-3">설문조사 설명</form>
<input
className="border w-11/12 h-36 my-3"
type="text"
placeholder="설문조사 답변"
></input>
{/* <ACheckboxForm></ACheckboxForm> */}
<ADropdownForm></ADropdownForm>
<AEssayForm></AEssayForm>
<ARadioForm></ARadioForm>
<div>
<button className="rounded bg-themeColor my-5 py-2 px-5 font-bold text-white">
제출하기
</button>
</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>
);
......
import React from "react";
import { Link } from "react-router-dom";
import React, { FormEvent } from "react";
import { useAuth } from "../auth/auth.context";
export const Home = () => (
<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>
<Link
to="/create"
className="flex h-14 w-28 items-center border-2 border-themeColor font-bold text-black bg-gray-200 hover:bg-themeColor rounded-lg "
>
<div className="text-center w-28 font-bold text-black place-items-center">
export const Home = () => {
const { user } = useAuth();
function clickHome(e: React.MouseEvent<HTMLButtonElement>) {
e.preventDefault();
if (!user.isLoggedIn) {
console.log("버튼");
location.href = "/login";
} else {
location.href = "/profile";
}
}
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>
</Link>
</button>
</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>
<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>
);
);
};
import React from "react";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { surveyApi } from "../apis";
import { SurveyType } from "../types";
export const Profile = () => {
const navigate = useNavigate();
const createSurvey = () => {
// 먼저 서버에 survey 테이블에 새로운 survey 항목 추가 로직 필요
navigate("/surveys/create", { replace: true });
};
const [survey, setSurvey] = useState<SurveyType>({
user: {},
title: "",
comment: "",
questions: [],
});
async function createSurvey() {
const newSurvey: SurveyType = await surveyApi.createSurvey(survey);
navigate(`/surveys/edit/${newSurvey._id}`, {
replace: true,
});
}
return (
<div className="flex flex-col items-center">
<div className="m-5">나의 설문조사</div>
<div className="flex flex-row space-x-4 mt-5">
<div className="flex space-x-4 mt-5">
<button
onClick={createSurvey}
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 = () => {
<div className="px-2 py-2">
<label>설문조사 이름</label>
</div>
<div className="flex justify-end dropdown-toggle">
<div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option>
<option>삭제</option>
......@@ -50,7 +59,7 @@ export const Profile = () => {
<div className="px-2 py-2">
<label>설문조사이름</label>
</div>
<div className="flex justify-end dropdown-toggle">
<div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option>
<option>삭제</option>
......@@ -69,7 +78,7 @@ export const Profile = () => {
<div className="px-2 py-2">
<label>설문조사 이름</label>
</div>
<div className="flex justify-end dropdown-toggle">
<div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option>
<option>삭제</option>
......@@ -88,7 +97,7 @@ export const Profile = () => {
<div className="px-2 py-2">
<label>설문조사 이름</label>
</div>
<div className="flex justify-end dropdown-toggle">
<div className="flex justify-end">
<select className="py-2 w-14 bg-themeColor rounded text-white">
<option selected>옵션</option>
<option>삭제</option>
......
import React from "react";
import React, { useState } from "react";
import { CheckboxType } from "../types";
import { useQuestion } from "./question.context";
import { Edit } from "./Edit";
import { TypeChange } from "./typeDD";
type Props = {
element: CheckboxType;
handleQuestion: (id: string) => void;
currentId: string;
};
export const QCheckbox = ({ element }: Props) => {
const { questionListChange } = useQuestion();
export const CheckboxForm = ({ element, handleQuestion, currentId }: Props) => {
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 (
<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="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="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>
<>
<div id="content" className="mt-4 p-5">
{choices.map((choice: any, index: number) => (
<div className="m-5">
<input type="checkbox" disabled></input>
<input
id={`${index}`}
type="text"
className="mx-2 border-b-2"
placeholder={e.text}
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
</div>
))}
</div>
<div className="flex w-full flex-row justify-end py-2">
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
<Edit id={element._id} />
<div>
<button
type="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>
</>
);
};
import { useQuestion } from "./question.context";
import React from "react";
import React, { useState } from "react";
import { DropdownType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = {
element: DropdownType;
handleQuestion: (id: string) => void;
currentId: string;
};
export const QDropdown = ({ element }: Props) => {
const { questionListChange } = useQuestion();
export const DropdownForm = ({ element, handleQuestion, currentId }: Props) => {
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 (
<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="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="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>
<>
<div id="content" className="flex-row mt-4 p-5">
<select className="mr-3">
{choices.map((choice: any, index: number) => (
<option>{choice.text}</option>
))}
</select>
{choices.map((choice: any, index: number) => (
<div className="my-5">
<input
id={`${index}`}
type="text"
className="mx-2 border-b-2"
placeholder={e.text}
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
</div>
))}
</div>
<div className="flex w-full flex-row justify-end py-2">
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
<div>
<button
type="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>
</>
);
};
import React, { useState } from "react";
import React from "react";
import { EssayType } from "../types";
// import { useQuestion } from "./question.context";
// import { Edit } from "./Edit";
// import { TypeChange } from "./typeDD";
type Props = {
element: EssayType;
currentId: string;
};
export const EssayForm = ({ element }: Props) => {
// const { questionListChange } = useQuestion();
export const EssayForm = ({ element, currentId }: 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 { FileType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = {
element: FileType;
currentId: string;
};
export const QFile = ({ element }: Props) => {
const { questionListChange } = useQuestion();
export const FileForm = ({ element, currentId }: Props) => {
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="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 id="content" className="flex mt-4 w-full justify-center">
<input type="file" className=" w-11/12 h-16" disabled></input>
</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 { questionApi } from "../apis";
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 = {
element: BasicQuestionType;
handleQuestion: (id: string) => void;
deleteQuestion: (id: string) => void;
changeCurrentId: (id: string) => void;
currentId: string;
};
export const Question = ({ element }: Props) => {
const handleClick = () => {};
const typeDropDown = new Map([
["essay", "주관식"],
["radio", "객관식"],
["dropdown", "드롭다운"],
["checkbox", "체크박스"],
["file", "파일"],
["rating", "선형"],
["grid", "그리드"],
["date", "날짜"],
]);
const typeDD = new Map([
["essay", "주관식"],
["radio", "객관식"],
["dropdown", "드롭다운(객관식)"],
["checkbox", "체크박스"],
["file", "파일"],
["rating", "선형"],
["grid", "그리드"],
["date", "날짜"],
]);
export const Question = ({
element,
handleQuestion,
deleteQuestion,
changeCurrentId,
currentId,
}: Props) => {
const handleEditClick = () => {
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>) {
const tt = e.target.value;
// questionTypeChange(e);
console.log(tt);
//if문으로 type별로 content 바뀌게 해보기
function handleQuestionInfo(event: React.ChangeEvent<HTMLInputElement>) {
const { name, value } = event.currentTarget;
element[name] = value;
handleQuestion(element._id);
}
function handleDelete() {
deleteQuestion(element._id);
}
function getContent(element: BasicQuestionType) {
switch (element.type) {
case "essay":
return <EssayForm element={element} />;
return <EssayForm element={element} currentId={currentId} />;
case "radio":
// return <RadioForm element={element} />;
return (
<RadioForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "checkbox":
// return <CheckboxForm element={element} />;
return (
<CheckboxForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "dropdown":
// return <DropdownForm element={element} />;
return (
<DropdownForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
case "file":
// return <FileForm element={element} />;
return <FileForm element={element} currentId={currentId} />;
case "rating":
// return <RatingForm element={element} />;
return (
<RatingForm
handleQuestion={handleQuestion}
element={element}
currentId={currentId}
/>
);
default:
return <></>;
}
......@@ -54,18 +147,25 @@ export const Question = ({ element }: Props) => {
name="title"
id={element._id}
className="text-xl font-bold ml-6 border-b-2 w-1/2"
placeholder={element.title}
// onChange={questionListChange}
placeholder={"Question Title"}
value={element.title}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
></input>
<select
id="Questions"
id={element._id}
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"
defaultValue={element.type}
onChange={changeDD}
>
{Array.from(typeDD.entries()).map(([k, v]) => (
<option value={k}>{v}</option>
{Array.from(typeDropDown.entries()).map(([key, value]) => (
<option
id={element._id}
value={key}
selected={key === element.type}
>
{value}
</option>
))}
</select>
</div>
......@@ -76,18 +176,32 @@ export const Question = ({ element }: Props) => {
id={element._id}
className="border w-11/12"
placeholder="질문에 대한 설명을 입력해주세요"
// onChange={questionListChange}
value={element.comment}
onChange={handleQuestionInfo}
disabled={currentId !== element._id}
></input>
</div>
{getContent(element)}
<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>
<button id={element.id} className="w-1/12" onClick={handleClick}>
수정
<div className="place-self-end py-2">
<button type="button" className="px-1">
필수
</button>
<button type="button" className="px-1">
옵션
</button>
<button type="button" className="px-1" onClick={handleDelete}>
삭제
</button>
{currentId === element._id ? (
<button type="button" className="px-1" onClick={handleEditComplete}>
수정완료
</button>
) : (
<button type="button" className="px-1" onClick={handleEditClick}>
수정하기
</button>
)}
</div>
</div>
);
......
import React from "react";
import React, { useState } from "react";
import { RadioType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = {
element: RadioType;
handleQuestion: (id: string) => void;
currentId: string;
};
export const QRadio = ({ element }: Props) => {
const { questionListChange } = useQuestion();
export const RadioForm = ({ element, handleQuestion, currentId }: Props) => {
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 (
<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="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
/>
<>
<div id="content" className="mt-4 p-5">
{choices.map((choice: any, index: number) => (
<div className="m-5">
<input type="radio" disabled></input>
<input
id={`${index}`}
type="text"
name={"choice"}
// key={`${index}`}
className="mx-2 border-b-2"
placeholder={e.text}
onChange={questionListChange}
placeholder="선택지"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
<button></button>
</div>
))}
{/* <button className="border rounded-full border-green-500 border-4 text-green-500 font-bold px-2">
+
</button> */}
</div>
<div className="flex w-full flex-row justify-end py-2">
<button className="w-1/12">필수</button>
<button className="w-1/12">옵션</button>
<button className="w-1/12">삭제</button>
<div>
<button
type="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>
</>
);
};
import React from "react";
import React, { useState } from "react";
import { RatingType } from "../types";
import { useQuestion } from "./question.context";
import { TypeChange } from "./typeDD";
type Props = {
element: RatingType;
// deleteValue: (e: React.MouseEvent<HTMLButtonElement>) => void;
handleQuestion: (id: string) => void;
currentId: string;
};
export const QRating = ({ element }: Props) => {
const { questionListChange } = useQuestion();
export const RatingForm = ({ element, handleQuestion, currentId }: Props) => {
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 (
<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">
<input
name="minRateDescription"
id={element._id}
className="border-b-2 text-center"
size={10}
placeholder={element.content.minRateDescription}
placeholder="비동의"
value={element.content.minRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
{element.content.choices.map((e) => (
{choices.map((choice: any, index: number) => (
<input
name="text"
id={element._id}
id={`${index}`}
type="text"
className="border border-black rounded-full py-1 m-2 text-center"
size={1}
placeholder={e.text}
placeholder="0"
value={choice.text}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
))}
<input
name="maxRateDescription"
id={element._id}
className="border-b-2 text-center"
size={10}
placeholder={element.content.maxRateDescription}
placeholder="동의"
value={element.content.maxRateDescription}
onChange={handleContent}
disabled={currentId !== element._id}
></input>
</div>
<div>
<button
// type="button"
type="button"
name="rateValues"
id={element._id}
className="border border-red-500 rounded mx-2 px-2"
// onClick={deleteValue}
onClick={deleteValue}
disabled={currentId !== element._id}
>
삭제
</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>
</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 { SpinnerIcon } from "../icons";
import { Question } from "../questions";
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>({
_id: surveyId,
user: {},
title: "",
comment: "",
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) {
event.preventDefault();
try {
const newSurvey: SurveyType = await surveyApi.createSurvey(survey);
const newSurvey: SurveyType = await surveyApi.editSurvey(survey);
console.log(newSurvey);
// setSuccess(true);
// setError("");
......@@ -31,7 +71,6 @@ export const CreateSurvey = () => {
try {
const newQuestion: BasicQuestionType = await questionApi.createQuestion();
setSurvey({ ...survey, questions: [...survey.questions, newQuestion] });
// setQuestions([...questions, newQuestion]);
// setSuccess(true);
// setError("");
} catch (error) {
......@@ -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 (
<>
{loading && (
<SpinnerIcon className="animate-spin h-5 w-5 mr-1 text-slate" />
)}
<form onSubmit={handleSubmit}>
<div className="flex flex-col place-items-center">
<div className="flex flex-col container place-items-center mt-4">
......@@ -54,7 +113,7 @@ export const CreateSurvey = () => {
name="title"
className="font-bold text-4xl text-center m-2 border-b-2"
placeholder="설문지 제목"
onChange={handleChange}
onChange={handleSurvey}
></input>
<input
type="text"
......@@ -62,11 +121,17 @@ export const CreateSurvey = () => {
className="font-bold text-1xl text-center m-2 resize-none"
placeholder="설문조사에 대한 설명을 입력해주세요"
size={50}
onChange={handleChange}
onChange={handleSurvey}
></input>
</div>
{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">
<button type="button" onClick={addQuestion}>
......
export { CreateSurvey } from "./CreateSurvey";
export { EditSurvey } from "./EditSurvey";
......@@ -11,6 +11,8 @@ export interface SignupUser {
}
export interface SurveyType {
_id?: string;
user: any;
title: string;
comment: string;
questions: BasicQuestionType[];
......
import { NextFunction, Request, Response } from "express";
import { questionDb } from "../db";
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;
console.log("question body", question);
const newQuestion = await questionDb.createQuestion(question);
const newQuestion = await questionDb.updateQuestion(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);
});
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 { 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;
console.log("Survey body", survey);
const newSurvey = await surveyDb.createSurvey(survey);
const newSurvey = await surveyDb.updateSurvey(survey);
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";
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) => {
const newQuestion = await Question.create(question);
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