Skip to content

Commit

Permalink
[#32] Navigate to survey completion screen after submitting the surve…
Browse files Browse the repository at this point in the history
…y successfully
  • Loading branch information
manh-t committed Jul 24, 2023
1 parent 762934a commit 1ee2681
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 62 deletions.
5 changes: 4 additions & 1 deletion src/adapters/Survey/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { getAuth, postAuth } from 'adapters/BaseAuth';
import { JSONObject } from 'helpers/json';
import { SurveySubmitRequest } from 'types/request/surveySubmitRequest';

export const getSurveys = () => getAuth('surveys?page[number]=1&page[size]=10');

export const getSurvey = (surveyId: string) => getAuth(`surveys/${surveyId}`);

export const submitSurvey = (surveySubmitRequest: SurveySubmitRequest) => postAuth('responses', surveySubmitRequest);
export const submitSurvey = (surveySubmitRequest: SurveySubmitRequest) => {
return postAuth('responses', surveySubmitRequest as unknown as JSONObject);
};
61 changes: 55 additions & 6 deletions src/components/Answer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import Nps from 'components/Nps';
import Rating from 'components/Rating';
import TextArea from 'components/TextArea';
import { DisplayType, Question, getDisplayTypeEnum } from 'types/question';
import { AnswerRequest } from 'types/request/surveySubmitRequest';

interface AnswerProps {
question: Question;
onAnswerChanged?: (answers: AnswerRequest[]) => void;
'data-test-id'?: string;
}
const Answer = ({ question, ...rest }: AnswerProps): JSX.Element => {
const Answer = ({ question, onAnswerChanged, ...rest }: AnswerProps): JSX.Element => {
const displayTypeEnum = getDisplayTypeEnum(question);

switch (displayTypeEnum) {
Expand All @@ -27,6 +29,7 @@ const Answer = ({ question, ...rest }: AnswerProps): JSX.Element => {
items={question.answers}
displayType={displayTypeEnum}
data-test-id={rest['data-test-id']}
onValueChanged={(answer) => onAnswerChanged?.([{ id: answer.id }])}
/>
);
case DisplayType.Choice:
Expand All @@ -36,18 +39,64 @@ const Answer = ({ question, ...rest }: AnswerProps): JSX.Element => {
items={question.answers}
isPickOne={question?.pick === 'one'}
data-test-id={rest['data-test-id']}
onValuesChanged={(answers) => {
const answerRequests: AnswerRequest[] = answers.map((answer) => ({
id: answer.id,
}));
return onAnswerChanged?.(answerRequests);
}}
/>
);
case DisplayType.Nps:
return <Nps questionId={question.id} items={question.answers} data-test-id={rest['data-test-id']} />;
return (
<Nps
questionId={question.id}
items={question.answers}
data-test-id={rest['data-test-id']}
onValuesChanged={(answers) => {
const answerRequests: AnswerRequest[] = answers.map((answer) => ({
id: answer.id,
}));
return onAnswerChanged?.(answerRequests);
}}
/>
);
case DisplayType.Textarea:
return <TextArea questionId={question.id} items={question.answers} data-test-id={rest['data-test-id']} />;
return (
<TextArea
questionId={question.id}
items={question.answers}
data-test-id={rest['data-test-id']}
onValueChange={(answerRequest) => onAnswerChanged?.([answerRequest])}
/>
);
case DisplayType.Textfield:
return <MultiInputs questionId={question.id} items={question.answers} data-test-id={rest['data-test-id']} />;
return (
<MultiInputs
questionId={question.id}
items={question.answers}
data-test-id={rest['data-test-id']}
onValuesChanged={(answerRequests) => onAnswerChanged?.(answerRequests)}
/>
);
case DisplayType.Dropdown:
return <Dropdown questionId={question.id} items={question.answers} data-test-id={rest['data-test-id']} />;
return (
<Dropdown
questionId={question.id}
items={question.answers}
data-test-id={rest['data-test-id']}
onValueChanged={(answer) => onAnswerChanged?.([{ id: answer.id }])}
/>
);
case DisplayType.Slider:
return <AppSlider questionId={question.id} items={question.answers} data-test-id={rest['data-test-id']} />;
return (
<AppSlider
questionId={question.id}
items={question.answers}
data-test-id={rest['data-test-id']}
onValueChanged={(answer) => onAnswerChanged?.([{ id: answer.id }])}
/>
);
case DisplayType.Unknown:
case DisplayType.Intro:
case DisplayType.Outro:
Expand Down
25 changes: 8 additions & 17 deletions src/components/MultiInputs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';

import TextInput from 'components/TextInput';
import { Answer } from 'types/answer';
Expand All @@ -14,26 +14,17 @@ const MultiInputs = ({ questionId, items, onValuesChanged, ...rest }: MultiInput
const [selectedValues, setSelectedValues] = useState<AnswerRequest[]>([]);

const handleValuesChanged = (answer: Answer, content: string) => {
const newSelectedValues = selectedValues;
const itemIndex = newSelectedValues.findIndex((value) => value.id === answer.id);
if (itemIndex !== -1) {
newSelectedValues[itemIndex].answer = content;
}
const newSelectedValues = [
...selectedValues.filter((value) => value.id !== answer.id),
{
id: answer.id,
answer: content,
},
];
setSelectedValues(newSelectedValues);
onValuesChanged?.(newSelectedValues);
};

useEffect(() => {
const newSelectedValues: AnswerRequest[] = [];
for (let i = 0; i < items.length; i++) {
newSelectedValues.push({
id: items[i].id,
answer: '',
});
}
setSelectedValues(newSelectedValues);
}, [questionId, items]);

return (
<div id={`multi-inputs-${questionId}`} {...rest}>
{items.map((item) => (
Expand Down
20 changes: 5 additions & 15 deletions src/components/TextArea/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React from 'react';

import { Answer } from 'types/answer';
import { AnswerRequest } from 'types/request/surveySubmitRequest';
Expand All @@ -11,24 +11,14 @@ interface TextAreaProps {
}

const TextArea = ({ questionId, items, onValueChange, ...rest }: TextAreaProps): JSX.Element => {
const [selectedValue, setSelectedValue] = useState<AnswerRequest>({
id: items[0].id,
answer: '',
});
const handleOnChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
event.preventDefault();
const answerRequest: AnswerRequest = selectedValue;
answerRequest.answer = event.target.value;
setSelectedValue(answerRequest);
onValueChange?.(answerRequest);
};

useEffect(() => {
setSelectedValue({
onValueChange?.({
id: items[0].id,
answer: '',
answer: event.target.value,
});
}, [questionId, items]);
};

return (
<textarea
id={`text-area-${questionId}`}
Expand Down
11 changes: 11 additions & 0 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RouteObject } from 'react-router-dom';

import DashBoardScreen from 'screens/Dashboard';
import QuestionScreen from 'screens/Question';
import QuestionCompleteScreen from 'screens/Question/Complete';
import SignInScreen from 'screens/SignIn';
import SurveyScreen from 'screens/Survey';

Expand All @@ -13,13 +14,19 @@ export const paths = {
signIn: '/sign-in',
survey: '/surveys/:id',
question: '/surveys/:id/questions',
questionComplete: '/surveys/:id/questions/complete',
};

export const questionPath = (): string => {
const questionPaths = paths.question.split('/');
return questionPaths[questionPaths.length - 1];
};

export const questionCompletePath = (): string => {
const questionCompletePaths = paths.questionComplete.split('/');
return questionCompletePaths[questionCompletePaths.length - 1];
};

const routes: RouteObject[] = [
{
element: <ProtectedRoute />,
Expand All @@ -36,6 +43,10 @@ const routes: RouteObject[] = [
path: paths.question,
element: <QuestionScreen />,
},
{
path: paths.questionComplete,
element: <QuestionCompleteScreen />,
},
],
},
{
Expand Down
7 changes: 7 additions & 0 deletions src/screens/Question/Complete/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const QuestionCompleteScreen = (): JSX.Element => {
return <div>Complete</div>;
};

export default QuestionCompleteScreen;
35 changes: 33 additions & 2 deletions src/screens/Question/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import { act, render, screen } from '@testing-library/react';

import { useAppDispatch, useAppSelector } from 'hooks';
import { paths } from 'routes';
import { SurveyState } from 'store/reducers/Survey';
import TestWrapper from 'tests/TestWrapper';

Expand Down Expand Up @@ -71,6 +72,8 @@ describe('QuestionScreen', () => {
},
isLoading: true,
isError: false,
questionRequests: [],
isSubmitSuccess: false,
},
};

Expand Down Expand Up @@ -120,7 +123,7 @@ describe('QuestionScreen', () => {
});

describe('given the close button is clicked', () => {
it('navigates back to the previous screen', () => {
it('navigates back to the Home screen', () => {
render(<TestComponent />);

const closeButton = screen.getByTestId(questionScreenTestIds.closeButton);
Expand All @@ -129,7 +132,35 @@ describe('QuestionScreen', () => {
closeButton.click();
});

expect(mockUseNavigate).toHaveBeenCalledWith(-1);
expect(mockDispatch).toHaveBeenCalledWith({ type: 'survey/resetQuestions' });
expect(mockUseNavigate).toHaveBeenCalledWith(paths.root, { replace: true });
});
});

describe('given the submit button is clicked', () => {
it('submits the survey', () => {
render(<TestComponent />);

const nextButton = screen.getByTestId(questionScreenTestIds.nextButton);

act(() => {
nextButton.click();
});

act(() => {
nextButton.click();
});

const submitButton = screen.getByTestId(questionScreenTestIds.submitButton);

act(() => {
submitButton.click();
});

expect(mockDispatch).toHaveBeenCalledWith({
type: 'survey/fillAnswers',
payload: { id: 'question 2', answers: [{ id: 'answer 1' }] },
});
});
});
});
Loading

0 comments on commit 1ee2681

Please sign in to comment.