From 7ada0cbd1a9d492ccee4aafbd5fe4f1d8d5f82fc Mon Sep 17 00:00:00 2001 From: Konrad Ryczko Date: Fri, 5 Jan 2024 09:58:06 +0100 Subject: [PATCH] Feature/Editing survey --- lib/axiosConfig.ts | 10 ++ locales/en/surveyCreate.json | 5 + prisma/schema.prisma | 5 +- public/images/creator.webp | Bin 22982 -> 12092 bytes .../AddQuestionButton/AddQuestionButton.tsx | 2 +- .../QuestionBlocks/QuestionBlockFactory.tsx | 3 + .../QuestionBlockWrapper.tsx | 15 ++- .../ShareSurveryModal/ShareSurveyModal.tsx | 2 +- .../components/SurveyRow/SurveyRow.tsx | 2 +- .../surveys/managers/createSurveyManager.ts | 68 ++++++++-- src/layout/Footer/Footer.tsx | 2 +- src/pages/api/answer/[id].ts | 31 +++-- src/pages/api/auth/[...nextauth].ts | 13 +- src/pages/api/survey/[id].ts | 110 ++++++++++++++--- src/pages/api/survey/index.ts | 16 ++- src/pages/survey/answer/[surveyId]/index.tsx | 22 +++- .../create/{index.tsx => [[...surveyId]].tsx} | 116 ++++++++++++++---- src/shared/components/Input/Input.tsx | 8 +- .../components/StyledDialog/StyledDialog.tsx | 29 +++-- 19 files changed, 369 insertions(+), 90 deletions(-) rename src/pages/survey/create/{index.tsx => [[...surveyId]].tsx} (67%) diff --git a/lib/axiosConfig.ts b/lib/axiosConfig.ts index 6937d1c7..215eb589 100644 --- a/lib/axiosConfig.ts +++ b/lib/axiosConfig.ts @@ -19,6 +19,7 @@ export const postFetch = (url: string, data = {}) => { data, }).then((response) => response.data); }; + export const patchFetch = (url: string, data = {}) => { return instance({ method: 'PATCH', @@ -26,6 +27,15 @@ export const patchFetch = (url: string, data = {}) => { data, }).then((response) => response.data); }; + +export const putFetch = (url: string, data = {}) => { + return instance({ + method: 'PUT', + url, + data, + }).then((response) => response.data); +}; + export const deleteFetch = (url: string) => { return instance({ method: 'DELETE', diff --git a/locales/en/surveyCreate.json b/locales/en/surveyCreate.json index 39d3be6c..35e4544c 100644 --- a/locales/en/surveyCreate.json +++ b/locales/en/surveyCreate.json @@ -2,7 +2,12 @@ "title": "Create Survey", "content": "Create Survey - FormsLab", "heading": "Create new survey", + "editHeading": "Edit survey", "buttonCreate": "Create Survey", + "editNote": "Some action like adding and removing questions or changing answers are not available in edit mode.", + "editNoteTitle": "Note", + "buttonSave": "Save changes", + "discardChanges": "Discard changes", "surveyTitleLable": "Survey Title", "surveyTitlePlaceholder": "Survey Title...", "questionPlaceholder": "Question...", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 564d63fc..9dedcb60 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -71,8 +71,8 @@ model Survey { description String? questions Question[] answers Answer[] - oneQuestionPerStep Boolean? - displayTitle Boolean? + oneQuestionPerStep Boolean + displayTitle Boolean user User @relation(fields: [userId], references: [id], onDelete: Cascade) } @@ -86,6 +86,7 @@ model Question { type QuestionType isRequired Boolean options String[] + order Int survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade) } diff --git a/public/images/creator.webp b/public/images/creator.webp index cd904dacfa3402f82d08005433adf50a4deac39c..70ad10931013b918679b55508b64bf15fbe6ade8 100644 GIT binary patch literal 12092 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 literal 22982 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 { const { closeModal, isModalOpen, openModal } = useModal(); return ( -
+
@@ -135,7 +138,15 @@ export default function QuestionBlockWrapper({ {expanded && (
- {children} + {isEditMode ? ( +
+
+ + {children} +
+ ) : ( + children + )}
- + {link}
diff --git a/src/features/surveys/components/SurveyRow/SurveyRow.tsx b/src/features/surveys/components/SurveyRow/SurveyRow.tsx index 5ebe9703..e80a670a 100644 --- a/src/features/surveys/components/SurveyRow/SurveyRow.tsx +++ b/src/features/surveys/components/SurveyRow/SurveyRow.tsx @@ -46,7 +46,7 @@ export default function SurveyRow({ return (
-
+
{question}
diff --git a/src/features/surveys/managers/createSurveyManager.ts b/src/features/surveys/managers/createSurveyManager.ts index 97fd4684..4784f0a1 100644 --- a/src/features/surveys/managers/createSurveyManager.ts +++ b/src/features/surveys/managers/createSurveyManager.ts @@ -4,9 +4,11 @@ import toast from 'react-hot-toast'; import useCopyToClipboard from 'shared/hooks/useCopyToClipboard'; import useTranslation from 'next-translate/useTranslation'; import { QuestionType } from '@prisma/client'; -import { postFetch } from '../../../../lib/axiosConfig'; +import { postFetch, putFetch } from '../../../../lib/axiosConfig'; import { defaultQuestions } from 'shared/constants/surveysConfig'; import { DRAFT_SURVEY_SESSION_STORAGE } from 'shared/constants/app'; +import { SurveyWithQuestions } from 'types/SurveyWithQuestions'; +import { Question as QuestionDto } from '@prisma/client'; export interface Question { id: string; @@ -22,19 +24,32 @@ export interface SurveyOptions { displayTitle: boolean; } -export const useCreateSurveyManager = () => { - const [title, setTitle] = useState(''); - const [questions, setQuestions] = useState(defaultQuestions); +export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => { + const [isEditMode] = useState(!!initialData); + + const [title, setTitle] = useState(initialData?.title ?? ''); + + const mapQuestionsWithExpanded = (questions?: QuestionDto[]) => { + return questions?.map((question) => ({ + ...question, + expanded: false, + })); + }; + + const [questions, setQuestions] = useState( + mapQuestionsWithExpanded(initialData?.questions) ?? defaultQuestions + ); + const [surveyOptions, setSurveyOptions] = useState({ + oneQuestionPerStep: initialData?.oneQuestionPerStep ?? true, + displayTitle: initialData?.displayTitle ?? true, + }); + const [error, setError] = useState(''); const [isCreating, setIsCreating] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false); const router = useRouter(); const { copy } = useCopyToClipboard(); const { t } = useTranslation('surveyCreate'); - const [surveyOptions, setSurveyOptions] = useState({ - oneQuestionPerStep: true, - displayTitle: true, - }); const signInToCreateSurvey = () => { router.push('/login'); @@ -249,6 +264,40 @@ export const useCreateSurveyManager = () => { setIsCreating(false); }; + const confirmEditSurvey = async () => { + if (!isSurveyValid() || !initialData) return; + + setIsCreating(true); + + try { + const newSurvey = await putFetch(`/api/survey/${initialData.id}`, { + title, + oneQuestionPerStep: surveyOptions.oneQuestionPerStep, + displayTitle: surveyOptions.displayTitle, + questions: questions.map((question) => ({ + id: question.id, + title: question.title, + options: question.options, + type: question.type, + isRequired: question.isRequired, + })), + }); + + await router.push(`/survey/answer/${newSurvey.id}`, undefined, { + scroll: false, + }); + } catch (error) { + toast.error(t('surveyCreationFailed')); + } + setIsCreating(false); + }; + + const discardChanges = () => { + router.push(`/survey/answer/${initialData?.id}`, undefined, { + scroll: false, + }); + }; + const reorderQuestion = (startIndex: number, endIndex: number) => { const newOrderedQuestions = Array.from(questions); @@ -288,5 +337,8 @@ export const useCreateSurveyManager = () => { surveyOptions, updateSurveyOptions, signInToCreateSurvey, + isEditMode, + confirmEditSurvey, + discardChanges, }; }; diff --git a/src/layout/Footer/Footer.tsx b/src/layout/Footer/Footer.tsx index 15b83fa9..ad9f4e07 100644 --- a/src/layout/Footer/Footer.tsx +++ b/src/layout/Footer/Footer.tsx @@ -3,7 +3,7 @@ import React from 'react'; export default function Footer() { return (
- FormsLab © 2023 + FormsLab © 2024
); } diff --git a/src/pages/api/answer/[id].ts b/src/pages/api/answer/[id].ts index 1f1b63bf..b8f2c941 100644 --- a/src/pages/api/answer/[id].ts +++ b/src/pages/api/answer/[id].ts @@ -7,18 +7,27 @@ interface AnswerData { answersData: { questionId: string; answer?: string }[]; } -export async function getSurveyData(surveyId: string) { - const survey = await prismadb.survey.findUnique({ - where: { - id: surveyId, - }, - include: { - questions: true, - answers: false, - }, - }); +export async function getSurveyData(surveyId: string, userId?: string) { + try { + const survey = await prismadb.survey.findFirst({ + where: { + id: surveyId, + userId, + }, + include: { + questions: { + orderBy: { + order: 'asc', + }, + }, + answers: false, + }, + }); - return survey; + return survey; + } catch (error) { + return null; + } } const isAnswerDataValid = (answerData: AnswerData) => { diff --git a/src/pages/api/auth/[...nextauth].ts b/src/pages/api/auth/[...nextauth].ts index c691c369..b63ab164 100644 --- a/src/pages/api/auth/[...nextauth].ts +++ b/src/pages/api/auth/[...nextauth].ts @@ -60,9 +60,20 @@ export const authOptions: NextAuthOptions = { }, callbacks: { session: async ({ session, token }) => { - if (session?.user) { + if (session?.user && token.uid) { + const isSessionValid = await prismadb.user.findUnique({ + where: { + id: token.uid as string, + }, + }); + + if (!isSessionValid) { + return Promise.reject(new Error('Session not valid')); + } + session.user.id = token.uid; } + return session; }, jwt: async ({ user, token }) => { diff --git a/src/pages/api/survey/[id].ts b/src/pages/api/survey/[id].ts index ad0f2f5c..36384ca6 100644 --- a/src/pages/api/survey/[id].ts +++ b/src/pages/api/survey/[id].ts @@ -2,6 +2,7 @@ import { NextApiRequest, NextApiResponse } from 'next'; import prismadb from '../../../../lib/prismadb'; import serverAuth from '../../../../lib/serverAuth'; +import { SurveyData, isSurveyValid } from '.'; export enum SurveyActionTypes { UPDATE_ACTIVE = 'UPDATE_ACTIVE', @@ -11,26 +12,35 @@ interface SurveyPatchPayloadI { } export async function getSurveyWithAnswers(surveyId: string, userId: string) { - const survey = await prismadb.survey.findFirst({ - where: { - id: surveyId, - userId: userId, - }, - include: { - questions: true, - answers: { - include: { - answerData: true, + try { + const survey = await prismadb.survey.findFirst({ + where: { + id: surveyId, + userId: userId, + }, + include: { + questions: { + orderBy: { + order: 'asc', + }, }, - orderBy: { - createdAt: 'desc', + answers: { + include: { + answerData: true, + }, + orderBy: { + createdAt: 'desc', + }, }, }, - }, - }); + }); - return survey; + return survey; + } catch (error) { + return null; + } } + export async function updateSurveyActiveStatus({ surveyId, isActive, @@ -46,6 +56,7 @@ export async function updateSurveyActiveStatus({ }); return survey; } + export async function handlePatch(req: NextApiRequest, res: NextApiResponse) { const surveyId = String(req.query.id); const { actionType } = req.body as SurveyPatchPayloadI; @@ -74,6 +85,7 @@ export async function handlePatch(req: NextApiRequest, res: NextApiResponse) { } } } + export default async function handler( req: NextApiRequest, res: NextApiResponse @@ -81,6 +93,7 @@ export default async function handler( try { const requestMethod = req.method; const session = await serverAuth(req, res); + const userId = session.currentUser.id; const { id } = req.query; switch (requestMethod) { @@ -92,7 +105,6 @@ export default async function handler( return res.status(200).json(survey); } - case 'DELETE': { const survey = await prismadb.survey.findFirst({ where: { @@ -116,6 +128,72 @@ export default async function handler( case 'PATCH': { return handlePatch(req, res); } + case 'PUT': { + const { + title, + description, + questions, + oneQuestionPerStep, + displayTitle, + } = req.body as SurveyData; + if (!isSurveyValid(req.body)) { + return res.status(400).end(); + } + + const surveyFound = await prismadb.survey.findFirst({ + where: { id: id as string, userId }, + }); + + if (!surveyFound?.id) { + return res.status(404).end(); + } + + const surveyQuestions = await prismadb.question.findMany({ + where: { + surveyId: id as string, + }, + }); + + const newQuestions = []; + + surveyQuestions.forEach(async (question) => { + const foundQuestionIndex = questions.findIndex( + (q) => q.id === question.id + ); + + if (foundQuestionIndex === -1) return; + + const questionFound = questions[foundQuestionIndex]; + + const newQuestion = await prismadb.question.update({ + where: { + id: question.id, + }, + data: { + title: questionFound.title, + description: questionFound.description, + isRequired: questionFound.isRequired, + order: foundQuestionIndex, + }, + }); + + newQuestions.push(newQuestion); + }); + + const survey = await prismadb.survey.update({ + where: { + id: id as string, + }, + data: { + title, + description, + oneQuestionPerStep, + displayTitle, + }, + }); + + return res.status(200).json({ id: survey.id }); + } default: return res.status(405).end(); } diff --git a/src/pages/api/survey/index.ts b/src/pages/api/survey/index.ts index b745c206..6dd765df 100644 --- a/src/pages/api/survey/index.ts +++ b/src/pages/api/survey/index.ts @@ -11,7 +11,7 @@ import { MIN_QUESTIONS, } from 'shared/constants/surveysConfig'; -interface SurveyData { +export interface SurveyData { title: string; description: string; questions: Question[]; @@ -38,7 +38,7 @@ export async function getAllUserSurveys(userId: string) { return surveys; } -const isSurveyValid = (survey: SurveyData) => { +export const isSurveyValid = (survey: SurveyData) => { if ( survey.title.trim() === '' || survey.title.length > MAX_TITLE_LENGTH || @@ -70,8 +70,13 @@ export default async function handler( return res.status(200).json({ surveys }); } case 'POST': { - const { title, description, questions, oneQuestionPerStep, displayTitle } = - req.body as SurveyData; + const { + title, + description, + questions, + oneQuestionPerStep, + displayTitle, + } = req.body as SurveyData; if (!isSurveyValid(req.body)) { return res.status(400).end(); @@ -86,12 +91,13 @@ export default async function handler( oneQuestionPerStep, displayTitle, questions: { - create: questions.map((question) => ({ + create: questions.map((question, index) => ({ type: question.type, title: question.title, description: question.description, options: question.options, isRequired: question.isRequired, + order: index, })), }, }, diff --git a/src/pages/survey/answer/[surveyId]/index.tsx b/src/pages/survey/answer/[surveyId]/index.tsx index 6bc476b6..fd935f7d 100644 --- a/src/pages/survey/answer/[surveyId]/index.tsx +++ b/src/pages/survey/answer/[surveyId]/index.tsx @@ -1,5 +1,11 @@ -import { RefreshIcon, ShareIcon, TrashIcon } from '@heroicons/react/outline'; import Toggle from 'shared/components/Toggle/Toggle'; +import { + PencilIcon, + RefreshIcon, + ShareIcon, + TrashIcon, +} from '@heroicons/react/outline'; + import Head from 'next/head'; import withAnimation from 'shared/HOC/withAnimation'; import withProtectedRoute from 'shared/HOC/withProtectedRoute'; @@ -16,6 +22,7 @@ import ResultComponent from 'features/surveys/components/ResultsComponents/Resul import useModal from 'features/surveys/hooks/useModal'; import DeleteSurveyModal from 'features/surveys/components/DeleteSurveyModal/DeleteSurveyModal'; import ShareSurveyModal from 'features/surveys/components/ShareSurveryModal/ShareSurveyModal'; +import { useRouter } from 'next/router'; export async function getServerSideProps(context: NextPageContext) { const session = await getSession(context); @@ -77,6 +84,12 @@ function SurveyResultsPage({ const { t } = useTranslation('surveyAnswer'); + const router = useRouter(); + + const handleEditSurvey = () => { + router.push(`/survey/create/${surveyId}`); + }; + return ( <> @@ -100,6 +113,13 @@ function SurveyResultsPage({ />
+ - ) : ( - - )} +
+ {questions.length < MAX_QUESTIONS && !isEditMode && ( + + )} + + {user ? ( +
+ {isEditMode && ( + + )} + +
+ ) : ( + + )} +
setShowPassword(!showPassword)} > - {showPassword ? : } + {showPassword ? ( + + ) : ( + + )} )}
diff --git a/src/shared/components/StyledDialog/StyledDialog.tsx b/src/shared/components/StyledDialog/StyledDialog.tsx index 18eda005..d55c4c1b 100644 --- a/src/shared/components/StyledDialog/StyledDialog.tsx +++ b/src/shared/components/StyledDialog/StyledDialog.tsx @@ -50,19 +50,22 @@ export default function StyledDialog({ contentClassName )} > - - {title} - - + {!!title && ( + + {title} + + + )} + {content}