From 4ca2fcc578ac23d4c1305b08fb0c95d396f1d439 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Wed, 12 Jul 2023 15:05:46 +0700 Subject: [PATCH 01/21] [CHORE] Bump version to 0.6.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0bafecc..94f618b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "manh-react-survey", - "version": "0.5.0", + "version": "0.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "manh-react-survey", - "version": "0.5.0", + "version": "0.6.0", "dependencies": { "@reduxjs/toolkit": "1.9.5", "@travelperksl/fabricator": "7.0.1", diff --git a/package.json b/package.json index 588ef3b..d520f62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "manh-react-survey", - "version": "0.5.0", + "version": "0.6.0", "private": true, "dependencies": { "@reduxjs/toolkit": "1.9.5", From 96b2be5fee84028c4183e40599de2e563e2c8af4 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Thu, 13 Jul 2023 15:03:56 +0700 Subject: [PATCH 02/21] [#29] Create Slider component --- package-lock.json | 36 ++++++++++++++++ package.json | 1 + src/components/AppSlider/index.test.tsx | 15 +++++++ src/components/AppSlider/index.tsx | 55 +++++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/components/AppSlider/index.test.tsx create mode 100644 src/components/AppSlider/index.tsx diff --git a/package-lock.json b/package-lock.json index 94f618b..628bb7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "classnames": "2.3.2", "date-fns": "2.30.0", "lodash": "4.17.21", + "rc-slider": "10.2.1", "react": "18.2.0", "react-dom": "18.2.0", "react-redux": "8.1.0", @@ -21259,6 +21260,41 @@ "node": ">=0.10.0" } }, + "node_modules/rc-slider": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.2.1.tgz", + "integrity": "sha512-l355C/65iV4UFp7mXq5xBTNX2/tF2g74VWiTVlTpNp+6vjE/xaHHNiQq5Af+Uu28uUiqCuH/QXs5HfADL9KJ/A==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.27.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.34.1.tgz", + "integrity": "sha512-SqiUT8Ssgh5C+hu4y887xwCrMNcxLm6ScOo8AFlWYYF3z9uNNiPpwwSjvicqOlWd79rNw1g44rnP7tz9MrO1ZQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", diff --git a/package.json b/package.json index d520f62..e4fec65 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "classnames": "2.3.2", "date-fns": "2.30.0", "lodash": "4.17.21", + "rc-slider": "10.2.1", "react": "18.2.0", "react-dom": "18.2.0", "react-redux": "8.1.0", diff --git a/src/components/AppSlider/index.test.tsx b/src/components/AppSlider/index.test.tsx new file mode 100644 index 0000000..5bab514 --- /dev/null +++ b/src/components/AppSlider/index.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import { render, screen } from '@testing-library/react'; + +import AppSlider, { appSliderDataTestIds } from '.'; + +describe('AppSlider', () => { + it('renders AppSlider component', () => { + render(); + + const appSlider = screen.getByTestId(appSliderDataTestIds.base); + + expect(appSlider).toBeVisible(); + }); +}); diff --git a/src/components/AppSlider/index.tsx b/src/components/AppSlider/index.tsx new file mode 100644 index 0000000..f410115 --- /dev/null +++ b/src/components/AppSlider/index.tsx @@ -0,0 +1,55 @@ +import React from 'react'; + +import Slider from 'rc-slider'; +import 'rc-slider/assets/index.css'; + +export const appSliderDataTestIds = { + base: 'app-slider__base', +}; + +interface SliderProps { + min?: number; + max?: number; + step?: number; + onValueChanged: (position: number) => void; +} + +const AppSlider = ({ min = 1, max = 100, step = 1, onValueChanged }: SliderProps): JSX.Element => { + const handleOnChange = (value: number) => { + onValueChanged(value); + }; + + return ( +
+ handleOnChange(value as number)} + /> +
+ ); +}; + +export default AppSlider; From f28464a2b6a672290fdd06f0b355d2770f6188d7 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Thu, 31 Aug 2023 10:30:19 +0700 Subject: [PATCH 03/21] [#29] Move rc-slider css to App --- src/App.tsx | 1 + src/components/AppSlider/index.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 0d5cf81..7bacb1d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useRoutes } from 'react-router-dom'; import 'dummy.scss'; import 'assets/stylesheets/application.scss'; +import 'rc-slider/assets/index.css'; import { ToastContainer } from 'react-toastify'; import routes from './routes'; diff --git a/src/components/AppSlider/index.tsx b/src/components/AppSlider/index.tsx index f410115..3eb2217 100644 --- a/src/components/AppSlider/index.tsx +++ b/src/components/AppSlider/index.tsx @@ -1,7 +1,6 @@ import React from 'react'; import Slider from 'rc-slider'; -import 'rc-slider/assets/index.css'; export const appSliderDataTestIds = { base: 'app-slider__base', From f8f451ff28862d6ec842acbf93981ccb03eca1dd Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Thu, 31 Aug 2023 11:47:28 +0700 Subject: [PATCH 04/21] [#29] Add slider test id and verify slider component --- src/components/AppSlider/index.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/AppSlider/index.test.tsx b/src/components/AppSlider/index.test.tsx index 5bab514..680fe17 100644 --- a/src/components/AppSlider/index.test.tsx +++ b/src/components/AppSlider/index.test.tsx @@ -9,7 +9,9 @@ describe('AppSlider', () => { render(); const appSlider = screen.getByTestId(appSliderDataTestIds.base); + const slider = screen.getByRole('slider'); expect(appSlider).toBeVisible(); + expect(slider).toBeVisible(); }); }); From 05fe83352706c43e0e98d2bed5924e663fcebf6c Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Fri, 14 Jul 2023 17:02:46 +0700 Subject: [PATCH 05/21] [#21] Create the UI for Question page --- src/assets/images/icons/close-btn-white.svg | 14 ++++++ src/routes/index.tsx | 11 +++++ src/screens/Question/index.test.tsx | 31 ++++++++++++ src/screens/Question/index.tsx | 53 +++++++++++++++++++++ src/screens/Survey/index.tsx | 11 +++-- 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/assets/images/icons/close-btn-white.svg create mode 100644 src/screens/Question/index.test.tsx create mode 100644 src/screens/Question/index.tsx diff --git a/src/assets/images/icons/close-btn-white.svg b/src/assets/images/icons/close-btn-white.svg new file mode 100644 index 0000000..ff633ba --- /dev/null +++ b/src/assets/images/icons/close-btn-white.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/routes/index.tsx b/src/routes/index.tsx index fa7b901..ab4b42b 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { RouteObject } from 'react-router-dom'; import DashBoardScreen from 'screens/Dashboard'; +import QuestionScreen from 'screens/Question'; import SignInScreen from 'screens/SignIn'; import SurveyScreen from 'screens/Survey'; @@ -11,6 +12,12 @@ export const paths = { root: '/', signIn: '/sign-in', survey: '/surveys/:id', + question: '/surveys/:id/questions', +}; + +export const questionPath = (): string => { + const questionPaths = paths.question.split('/'); + return questionPaths[questionPaths.length - 1]; }; const routes: RouteObject[] = [ @@ -25,6 +32,10 @@ const routes: RouteObject[] = [ path: paths.survey, element: , }, + { + path: paths.question, + element: , + }, ], }, { diff --git a/src/screens/Question/index.test.tsx b/src/screens/Question/index.test.tsx new file mode 100644 index 0000000..d831dcc --- /dev/null +++ b/src/screens/Question/index.test.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import { render, screen } from '@testing-library/react'; + +import TestWrapper from 'tests/TestWrapper'; + +import QuestionScreen, { questionScreenTestIds } from '.'; + +describe('QuestionScreen', () => { + const TestComponent = (): JSX.Element => { + return ( + + + + ); + }; + + it('renders Question screen and its components', () => { + render(); + + const currentIndex = screen.getByTestId(questionScreenTestIds.index); + const questionTitle = screen.getByTestId(questionScreenTestIds.title); + const closeButton = screen.getByTestId(questionScreenTestIds.closeButton); + const nextButton = screen.getByTestId(questionScreenTestIds.nextButton); + + expect(currentIndex).toBeVisible(); + expect(questionTitle).toBeVisible(); + expect(closeButton).toBeVisible(); + expect(nextButton).toBeVisible(); + }); +}); diff --git a/src/screens/Question/index.tsx b/src/screens/Question/index.tsx new file mode 100644 index 0000000..489e13f --- /dev/null +++ b/src/screens/Question/index.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +import { ReactComponent as ArrowRight } from 'assets/images/icons/arrow-right.svg'; +import { ReactComponent as CloseButton } from 'assets/images/icons/close-btn-white.svg'; +import AppSlider from 'components/AppSlider'; +import MainView from 'components/MainView'; + +export const questionScreenTestIds = { + index: 'question__index', + title: 'question__title', + closeButton: 'question__close-button', + nextButton: 'question__next-button', +}; + +const QuestionScreen = (): JSX.Element => { + return ( + +
+ +
+

+ 1/5 +

+

+ How fulfilled did you feel during this WFH period? +

+ { + // TODO + }} + /> +
+ +
+
+ ); +}; + +export default QuestionScreen; diff --git a/src/screens/Survey/index.tsx b/src/screens/Survey/index.tsx index 035f3cb..4396992 100644 --- a/src/screens/Survey/index.tsx +++ b/src/screens/Survey/index.tsx @@ -1,5 +1,5 @@ import React, { useEffect } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Link, useNavigate, useParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import { ReactComponent as ArrowBack } from 'assets/images/icons/arrow-back.svg'; @@ -7,6 +7,7 @@ import ElevatedButton from 'components/ElevatedButton'; import LoadingDialog from 'components/LoadingDialog'; import MainView from 'components/MainView'; import { useAppDispatch, useAppSelector } from 'hooks'; +import { questionPath } from 'routes'; import { getSurveyAsyncThunk } from 'store/reducers/Survey'; export const surveyScreenTestIds = { @@ -71,9 +72,11 @@ const SurveyScreen = (): JSX.Element => { {survey?.description}

- - Start Survey - + + + Start Survey + +
From cf449ddc877e55d3fd751f3393ec3d644c023942 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Tue, 5 Sep 2023 14:24:47 +0700 Subject: [PATCH 06/21] [#21] Fix question path and apply currentColor to close-btn --- .../images/icons/{close-btn-white.svg => close-btn.svg} | 2 +- src/routes/index.tsx | 9 +++------ src/screens/Question/index.tsx | 4 ++-- src/screens/Survey/index.tsx | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) rename src/assets/images/icons/{close-btn-white.svg => close-btn.svg} (93%) diff --git a/src/assets/images/icons/close-btn-white.svg b/src/assets/images/icons/close-btn.svg similarity index 93% rename from src/assets/images/icons/close-btn-white.svg rename to src/assets/images/icons/close-btn.svg index ff633ba..04b9f73 100644 --- a/src/assets/images/icons/close-btn-white.svg +++ b/src/assets/images/icons/close-btn.svg @@ -1,7 +1,7 @@ - + diff --git a/src/routes/index.tsx b/src/routes/index.tsx index ab4b42b..1f9418d 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -8,16 +8,13 @@ import SurveyScreen from 'screens/Survey'; import ProtectedRoute from './ProtectedRoute'; +export const questionPath = 'questions'; + export const paths = { root: '/', signIn: '/sign-in', survey: '/surveys/:id', - question: '/surveys/:id/questions', -}; - -export const questionPath = (): string => { - const questionPaths = paths.question.split('/'); - return questionPaths[questionPaths.length - 1]; + question: `/surveys/:id/${questionPath}`, }; const routes: RouteObject[] = [ diff --git a/src/screens/Question/index.tsx b/src/screens/Question/index.tsx index 489e13f..cd5d7bb 100644 --- a/src/screens/Question/index.tsx +++ b/src/screens/Question/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { ReactComponent as ArrowRight } from 'assets/images/icons/arrow-right.svg'; -import { ReactComponent as CloseButton } from 'assets/images/icons/close-btn-white.svg'; +import { ReactComponent as CloseButton } from 'assets/images/icons/close-btn.svg'; import AppSlider from 'components/AppSlider'; import MainView from 'components/MainView'; @@ -16,7 +16,7 @@ const QuestionScreen = (): JSX.Element => { return (
-
diff --git a/src/screens/Survey/index.tsx b/src/screens/Survey/index.tsx index 4396992..b85d463 100644 --- a/src/screens/Survey/index.tsx +++ b/src/screens/Survey/index.tsx @@ -72,7 +72,7 @@ const SurveyScreen = (): JSX.Element => { {survey?.description}

- + Start Survey From 2c7ee56d35cce159f76615da2faa18e97fe6e8c3 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Mon, 17 Jul 2023 15:30:13 +0700 Subject: [PATCH 07/21] [#28] Create TextArea component --- src/components/TextArea/index.test.tsx | 15 +++++++++++++++ src/components/TextArea/index.tsx | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/components/TextArea/index.test.tsx create mode 100644 src/components/TextArea/index.tsx diff --git a/src/components/TextArea/index.test.tsx b/src/components/TextArea/index.test.tsx new file mode 100644 index 0000000..bb805d1 --- /dev/null +++ b/src/components/TextArea/index.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import { render, screen } from '@testing-library/react'; + +import TextArea, { textAreaDataTestIds } from '.'; + +describe('TextArea', () => { + it('renders a text area component', () => { + render(