Skip to content

Commit

Permalink
Merge pull request #1643 from zetkin/survey-404
Browse files Browse the repository at this point in the history
Load survey in getServerSideProps and add API downtime + 404 handling
  • Loading branch information
henrycatalinismith authored Nov 12, 2023
2 parents 5e5fe7f + 55a6384 commit b2cd619
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
14 changes: 14 additions & 0 deletions src/features/surveys/components/surveyForm/ErrorMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Box from '@mui/material/Box';
import { FC } from 'react';
import messageIds from 'features/surveys/l10n/messageIds';
import { Msg } from 'core/i18n';

const ErrorMessage: FC = () => {
return (
<Box bgcolor="#ee878a" mx={4} my={4} p={2} sx={{ borderRadius: '5px' }}>
<Msg id={messageIds.surveyForm.error} />
</Box>
);
};

export default ErrorMessage;
3 changes: 3 additions & 0 deletions src/features/surveys/l10n/messageIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ export default makeMessages('feat.surveys', {
authenticatedOption: m<{ email: string; person: string }>(
'Sign as {person} with email {email}'
),
error: m(
'Something went wrong when submitting your answers. Please try again later.'
),
nameEmailOption: m('Sign with name and email'),
policy: {
link: m('https://zetkin.org/privacy'),
Expand Down
72 changes: 44 additions & 28 deletions src/pages/o/[orgId]/surveys/[surveyId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import { parse } from 'querystring';
import { scaffold } from 'utils/next';
import useCurrentUser from 'features/user/hooks/useCurrentUser';
import {
ZetkinSurveyExtended,
ZetkinSurveyOptionsQuestionElement,
ZetkinSurveyTextElement,
ZetkinSurveyTextQuestionElement,
} from 'utils/types/zetkin';

import ErrorMessage from 'features/surveys/components/surveyForm/ErrorMessage';
import OptionsQuestion from 'features/surveys/components/surveyForm/OptionsQuestion';
import TextBlock from 'features/surveys/components/surveyForm/TextBlock';
import TextQuestion from 'features/surveys/components/surveyForm/TextQuestion';
import useSurvey from 'features/surveys/hooks/useSurvey';
import useSurveyElements from 'features/surveys/hooks/useSurveyElements';
import ZUIAvatar from 'zui/ZUIAvatar';
import { FC, useState } from 'react';

Expand Down Expand Up @@ -54,6 +54,17 @@ function parseRequest(
export const getServerSideProps = scaffold(async (ctx) => {
const { req, res } = ctx;
const { surveyId, orgId } = ctx.params!;
let status: FormStatus = 'editing';

const apiClient = new BackendApiClient(req.headers);
let survey: ZetkinSurveyExtended;
try {
survey = await apiClient.get<ZetkinSurveyExtended>(
`/api/orgs/${orgId}/surveys/${surveyId}`
);
} catch (e) {
return { notFound: true };
}

if (req.method === 'POST') {
const form = await parseRequest(req);
Expand Down Expand Up @@ -111,46 +122,49 @@ export const getServerSideProps = scaffold(async (ctx) => {
};
}

const apiClient = new BackendApiClient(req.headers);
const requestUrl = `/api/orgs/${orgId}/surveys/${surveyId}/submissions`;
try {
await apiClient.post(requestUrl, {
responses: Object.values(responses),
signature,
});
await apiClient.post(
`/api/orgs/${orgId}/surveys/${surveyId}/submissions`,
{
responses: Object.values(responses),
signature,
}
);
} catch (e) {
// eslint-disable-next-line no-console
console.log(e);
status = 'error';
}
if (status !== 'error') {
status = 'submitted';
}

res.writeHead(302, {
Location: `/o/${orgId}/surveys/${surveyId}/submitted`,
});
res.end();
if (status === 'submitted') {
res.writeHead(302, {
Location: `/o/${orgId}/surveys/${surveyId}/submitted`,
});
res.end();
}
}

return {
props: {
orgId,
surveyId,
status,
survey,
},
};
}, scaffoldOptions);

type PageProps = {
orgId: string;
surveyId: string;
status: FormStatus;
survey: ZetkinSurveyExtended;
};

type FormStatus = 'editing' | 'invalid' | 'error' | 'submitted';
type SignatureOption = 'authenticated' | 'email' | 'anonymous';

const Page: FC<PageProps> = ({ orgId, surveyId }) => {
const elements = useSurveyElements(
parseInt(orgId, 10),
parseInt(surveyId, 10)
);
const Page: FC<PageProps> = ({ orgId, status, survey }) => {
const messages = useMessages(messageIds);
const survey = useSurvey(parseInt(orgId, 10), parseInt(surveyId, 10));

const [selectedOption, setSelectedOption] = useState<null | SignatureOption>(
null
Expand All @@ -164,17 +178,19 @@ const Page: FC<PageProps> = ({ orgId, surveyId }) => {

return (
<>
<h1>{survey.data?.title}</h1>
<h1>{survey.title}</h1>

{status === 'error' && <ErrorMessage />}

{survey.data?.info_text && <p>{survey.data?.info_text}</p>}
{survey.info_text && <p>{survey.info_text}</p>}

<Box alignItems="center" columnGap={1} display="flex" flexDirection="row">
<ZUIAvatar size="md" url={`/api/orgs/${orgId}/avatar`} />
{survey.data?.organization.title}
{survey.organization.title}
</Box>

<form method="post">
{(elements.data || []).map((element) => (
{survey.elements.map((element) => (
<div key={element.id}>
{element.type === 'question' && (
<>
Expand Down Expand Up @@ -238,7 +254,7 @@ const Page: FC<PageProps> = ({ orgId, surveyId }) => {
}
value="email"
/>
{survey.data?.signature === 'allow_anonymous' && (
{survey.signature === 'allow_anonymous' && (
<FormControlLabel
control={<Radio />}
label={
Expand All @@ -260,7 +276,7 @@ const Page: FC<PageProps> = ({ orgId, surveyId }) => {
<Typography>
<Msg
id={messageIds.surveyForm.termsDescription}
values={{ organization: survey.data?.organization.title ?? '' }}
values={{ organization: survey.organization.title ?? '' }}
/>
</Typography>
<Typography>
Expand Down

0 comments on commit b2cd619

Please sign in to comment.