Skip to content

Commit

Permalink
Feature/Option to enable-disable survey
Browse files Browse the repository at this point in the history
  • Loading branch information
SidVermaS authored Nov 11, 2023
1 parent 216a4c5 commit a85b499
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/.pnp
.pnp.js


# testing
/coverage

Expand Down
8 changes: 7 additions & 1 deletion lib/axiosConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ export const postFetch = (url: string, data = {}) => {
data,
}).then((response) => response.data);
};

export const patchFetch = (url: string, data = {}) => {
return instance({
method: 'PATCH',
url,
data,
}).then((response) => response.data);
};
export const deleteFetch = (url: string) => {
return instance({
method: 'DELETE',
Expand Down
4 changes: 3 additions & 1 deletion locales/en/surveyAnswer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@
"copyLinkButtonTitle": "Copy link to clipboard",
"deleteSurveyButtonTitle": "Delete survey",
"tooltipValue": "value:",
"buttonShare": "Share"
"buttonShare": "Share",
"isActive": "Active",
"updateStatusFailure": "Failed to update survey's status"
}
21 changes: 9 additions & 12 deletions src/features/surveys/managers/surveyAnswerManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect } from 'react';
import toast from 'react-hot-toast';
import { LocalStorageKeys } from 'features/surveys/constants/types';
import useLocalStorage from 'features/surveys/hooks/useLocalStorage';
Expand Down Expand Up @@ -61,18 +61,9 @@ export const useSurveyAnswerManager = (initialData: SurveyWithQuestions) => {
return true;
};

const getSurveyData = useCallback(async () => {
if (!initialData.isActive) {
router.replace('/');
return;
} else {
setFormData(initialData);
}
}, [router, initialData]);

useEffect(() => {
if (surveyId) {
getSurveyData();
setFormData(initialData);
}
if (
process.env.NEXT_PUBLIC_BLOCK_MULTIPLE_ANSWERS &&
Expand Down Expand Up @@ -152,7 +143,13 @@ export const useSurveyAnswerManager = (initialData: SurveyWithQuestions) => {
await router.replace(`/survey/${surveyId}/thank-you`);
toast.success(t('successfullSubmit'));
} else {
await router.replace('/');
setFormData((prev) => {
if (!prev) return prev;
return {
...prev,
isActive: false,
};
});
toast.error(t('surveyInactive'));
}
} catch (error) {
Expand Down
21 changes: 20 additions & 1 deletion src/features/surveys/managers/surveyResultsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import toast from 'react-hot-toast';
import useCopyToClipboard from 'shared/hooks/useCopyToClipboard';

import useTranslation from 'next-translate/useTranslation';
import { getFetch } from '../../../../lib/axiosConfig';
import { getFetch, patchFetch } from '../../../../lib/axiosConfig';
import { SurveyWithAnswers } from 'types/SurveyWithAnswers';
import { QuestionType } from '@prisma/client';
import { MappedAnswers } from 'types/MappedAnswers';
Expand All @@ -16,6 +16,7 @@ export const useSurveyResultsManager = (initialData: SurveyWithAnswers) => {
const { surveyId } = router.query as { surveyId: string };

const [isDataLoading, setIsDataLoading] = useState<boolean>(false);
const [isStatusLoading, setIsStatusLoading] = useState<boolean>(false);
const [surveyData, setSurveyData] = useState<SurveyWithAnswers>();
const [mappedAnswersData, setMappedAnswersData] = useState<MappedAnswers>({});

Expand Down Expand Up @@ -74,6 +75,22 @@ export const useSurveyResultsManager = (initialData: SurveyWithAnswers) => {
toast.success(t('refreshSuccess'));
}, [surveyId, router, t, fillSurveyData]);

const updateSurveyStatus = useCallback(async () => {
setIsStatusLoading(true);
try {
const surveyResult = await patchFetch(`/api/survey/${surveyId}`, {
actionType: 'UPDATE_ACTIVE',
isActive: !surveyData?.isActive,
});
setSurveyData((prev) =>
prev ? { ...prev, isActive: !!surveyResult?.isActive } : prev
);
} catch (_err) {
toast.error(t('updateStatusFailure'));
}
setIsStatusLoading(false);
}, [setIsStatusLoading, setSurveyData, surveyData, surveyId, t]);

useEffect(() => {
if (!surveyId) {
router.replace('/');
Expand Down Expand Up @@ -101,6 +118,8 @@ export const useSurveyResultsManager = (initialData: SurveyWithAnswers) => {
surveyData,
mappedAnswersData,
isDataLoading,
isStatusLoading,
onRemoveSuccess,
updateSurveyStatus,
};
};
5 changes: 3 additions & 2 deletions src/pages/api/answer/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,16 @@ export default async function handler(

const { id } = req.query;

const survey = await getSurveyData(id as string);

switch (requestMethod) {
case 'GET': {
const survey = await getSurveyData(id as string);
return res.status(200).json(survey);
}
case 'POST': {
const { answersData } = req.body as AnswerData;

if (!isAnswerDataValid(req.body)) {
if (!isAnswerDataValid(req.body) || !survey?.isActive) {
return res.status(400).end();
}

Expand Down
55 changes: 53 additions & 2 deletions src/pages/api/survey/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import { NextApiRequest, NextApiResponse } from 'next';
import prismadb from '../../../../lib/prismadb';
import serverAuth from '../../../../lib/serverAuth';

export enum SurveyActionTypes {
UPDATE_ACTIVE = 'UPDATE_ACTIVE',
}
interface SurveyPatchPayloadI {
actionType: SurveyActionTypes;
}

export async function getSurveyWithAnswers(surveyId: string, userId: string) {
const survey = await prismadb.survey.findFirst({
where: {
Expand All @@ -24,7 +31,49 @@ export async function getSurveyWithAnswers(surveyId: string, userId: string) {

return survey;
}

export async function updateSurveyActiveStatus({
surveyId,
isActive,
}: {
surveyId: string;
isActive: boolean;
}) {
const survey = await prismadb.survey.update({
data: { isActive },
where: {
id: surveyId,
},
});
return survey;
}
export async function handlePatch(req: NextApiRequest, res: NextApiResponse) {
const surveyId = String(req.query.id);
const { actionType } = req.body as SurveyPatchPayloadI;
const session = await serverAuth(req, res);
const userId = session.currentUser.id;
const surveyFound = await prismadb.survey.findFirst({
where: { id: surveyId, userId },
});
if (!surveyFound?.id) {
return res.status(404).end();
}
switch (actionType) {
case SurveyActionTypes.UPDATE_ACTIVE: {
const isActive = !!req.body.isActive;
const survey = await updateSurveyActiveStatus({
surveyId,
isActive,
});
if (survey?.id) {
return res.status(200).json(survey);
}
return res.status(500).json({ message: 'Failed to change status' });
}
default: {
return res.status(400).json({ message: 'actionType is invalid' });
}
}
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
Expand Down Expand Up @@ -64,7 +113,9 @@ export default async function handler(

return res.status(200).end();
}

case 'PATCH': {
return handlePatch(req, res);
}
default:
return res.status(405).end();
}
Expand Down
2 changes: 2 additions & 0 deletions src/pages/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import { getSession } from 'next-auth/react';
import { NextPageContext } from 'next';

export async function getServerSideProps(context: NextPageContext) {

const session = await getSession(context);

if (session) {
return {
redirect: {
Expand Down
1 change: 1 addition & 0 deletions src/pages/signup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NextPageContext } from 'next';

export async function getServerSideProps(context: NextPageContext) {
const session = await getSession(context);

if (session) {
return {
redirect: {
Expand Down
13 changes: 2 additions & 11 deletions src/pages/survey/[surveyId]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import Head from 'next/head';
import { ButtonVariant } from 'shared/components/Button/Button';
import { useSurveyAnswerManager } from 'features/surveys/managers/surveyAnswerManager';
import ButtonLink from 'shared/components/ButtonLink/ButtonLink';
import useTranslation from 'next-translate/useTranslation';
import { InferGetServerSidePropsType, NextPageContext } from 'next';
import { getSurveyData } from 'pages/api/answer/[id]';
Expand Down Expand Up @@ -62,15 +60,8 @@ function AnswerPage({
)
) : (
<>
<h1 className="text-5xl">🙁</h1>
<h1 className="my-5 text-xl">{t('surveyNoLongerActive')}</h1>
<ButtonLink
href={'/'}
variant={ButtonVariant.PRIMARY}
className="w-full sm:w-auto"
>
{t('backHomeButton')}
</ButtonLink>
<div className="text-5xl">🙁</div>
<div className="my-5 text-xl">{t('surveyNoLongerActive')}</div>
</>
)}
</div>
Expand Down
21 changes: 16 additions & 5 deletions src/pages/survey/answer/[surveyId]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { RefreshIcon, ShareIcon, TrashIcon } from '@heroicons/react/outline';

import Toggle from 'shared/components/Toggle/Toggle';
import Head from 'next/head';
import withAnimation from 'shared/HOC/withAnimation';
import withProtectedRoute from 'shared/HOC/withProtectedRoute';
import AnswerHeader from 'features/surveys/components/AnswerHeader/AnswerHeader';
import { useSurveyResultsManager } from 'features/surveys/managers/surveyResultsManager';
import Button, { ButtonVariant } from 'shared/components/Button/Button';

import useTranslation from 'next-translate/useTranslation';
import { InferGetServerSidePropsType, NextPageContext } from 'next';
import { getSession } from 'next-auth/react';
Expand All @@ -31,7 +30,7 @@ export async function getServerSideProps(context: NextPageContext) {

const surveyData = (await getSurveyWithAnswers(
context.query.surveyId as string,
session.user.id
session.user?.id
)) as SurveyWithAnswers;

if (!surveyData) {
Expand Down Expand Up @@ -60,6 +59,8 @@ function SurveyResultsPage({
mappedAnswersData,
isDataLoading,
onRemoveSuccess,
updateSurveyStatus,
isStatusLoading,
} = useSurveyResultsManager(initialData);

const {
Expand Down Expand Up @@ -88,7 +89,17 @@ function SurveyResultsPage({
<h1 className="flex min-h-[38px] items-center border-indigo-200 pb-4 text-xl font-semibold sm:border-l-4 sm:pb-0 sm:pl-4 sm:text-left">
{surveyData?.title}
</h1>
<div className="flex w-full justify-center gap-2 sm:w-auto">
<div className="flex w-full flex-wrap justify-center gap-2 sm:w-auto sm:flex-nowrap">
<div className="flex w-full items-center justify-start">
<Toggle
classNames="mx-auto my-2 sm:my-0 sm:ml-0 sm:mr-2"
isEnabled={!!surveyData?.isActive}
onToggle={updateSurveyStatus}
label={t('isActive')}
isLoading={isStatusLoading}
/>
</div>

<Button
title={t('buttonCopyLinkTitle')}
onClick={openShareSurveyModal}
Expand Down Expand Up @@ -122,7 +133,7 @@ function SurveyResultsPage({
createDate={surveyData?.createdAt ?? ''}
/>

{surveyData?.answers.length === 0 && (
{surveyData?.answers?.length === 0 && (
<div className="mt-6">{t('noAnswers')}</div>
)}

Expand Down
11 changes: 9 additions & 2 deletions src/shared/components/Toggle/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Switch } from '@headlessui/react';
import clsx from 'clsx';
import Loader from 'shared/components/Loader/Loader';

interface ToggleProps {
isEnabled: boolean;
onToggle: (isEnabled: boolean) => void;
label?: string;
classNames?: string;
testId?: string;
isLoading?: boolean;
}

function Toggle({
Expand All @@ -15,17 +17,20 @@ function Toggle({
onToggle,
label,
testId,
isLoading,
}: ToggleProps) {
return (
<Switch.Group>
<div
className={clsx('flex items-center', classNames)}
className={clsx('relative flex items-center', classNames)}
data-test-id="toggle-wrapper"
>
<Switch.Label className="mr-2 text-sm">{label}</Switch.Label>

<Switch
checked={isEnabled}
data-test-id={testId}
disabled={isLoading}
onChange={onToggle}
className={`${
isEnabled ? 'bg-indigo-300' : 'bg-zinc-300'
Expand All @@ -35,7 +40,9 @@ function Toggle({
className={`${
isEnabled ? 'translate-x-5' : 'translate-x-1'
} inline-block h-3 w-3 transform rounded-full bg-white transition-transform`}
/>
>
<Loader className="h-3 w-3" isLoading={!!isLoading} />
</span>
</Switch>
</div>
</Switch.Group>
Expand Down

0 comments on commit a85b499

Please sign in to comment.