From f48ce0e397d8e093a913f81ab82f150d33cf30e8 Mon Sep 17 00:00:00 2001 From: Artem Balanovskyi <108689551+abalanovsky@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:23:25 +0200 Subject: [PATCH] Implemented settings tab for Quiz (#1384) * Implemented settings tab for Quiz * Created reusable component * Refactored code * Changed to match design updates --- .../setting-item/SettingItem.styles.ts | 17 +++ src/components/setting-item/SettingItem.tsx | 25 ++++ src/constants/translations/en/common.json | 1 + .../translations/en/my-resources-page.json | 26 ++-- src/constants/translations/ua/common.json | 1 + .../translations/ua/my-resources-page.json | 14 ++- .../QuizSettingsContainer.styles.ts | 53 ++++++++ .../QuizSettingsContainer.tsx | 115 +++++++++++++++++- src/styles/app-theme/app.pallete.ts | 4 +- .../my-quizzes/QuizSettingsContainer.spec.jsx | 58 +++++++++ 10 files changed, 302 insertions(+), 12 deletions(-) create mode 100644 src/components/setting-item/SettingItem.styles.ts create mode 100644 src/components/setting-item/SettingItem.tsx create mode 100644 src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.styles.ts create mode 100644 tests/unit/containers/my-quizzes/QuizSettingsContainer.spec.jsx diff --git a/src/components/setting-item/SettingItem.styles.ts b/src/components/setting-item/SettingItem.styles.ts new file mode 100644 index 000000000..131aad78a --- /dev/null +++ b/src/components/setting-item/SettingItem.styles.ts @@ -0,0 +1,17 @@ +import { TypographyVariantEnum } from '~/types' +export const styles = { + title: { + typography: TypographyVariantEnum.Subtitle2 + }, + subtitle: { + typography: TypographyVariantEnum.Subtitle2, + fontWeight: 400, + color: 'basic.blueGray' + }, + settingContainer: { + mt: '24px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center' + } +} diff --git a/src/components/setting-item/SettingItem.tsx b/src/components/setting-item/SettingItem.tsx new file mode 100644 index 000000000..86f4a5437 --- /dev/null +++ b/src/components/setting-item/SettingItem.tsx @@ -0,0 +1,25 @@ +import { ReactNode, FC } from 'react' +import { Box } from '@mui/material' +import Typography from '@mui/material/Typography' + +import { styles } from '~/components/setting-item/SettingItem.styles' + +interface SettingItemProps { + title: string + subtitle: string + children: ReactNode +} + +const SettingItem: FC = ({ title, subtitle, children }) => { + return ( + + + {title} + {subtitle} + + {children} + + ) +} + +export default SettingItem diff --git a/src/constants/translations/en/common.json b/src/constants/translations/en/common.json index 109da4358..cec0e0cd4 100644 --- a/src/constants/translations/en/common.json +++ b/src/constants/translations/en/common.json @@ -27,6 +27,7 @@ "aboutOffer": "About Offer", "goToName": "Go to {{name}}", "save": "Save", + "apply": "Apply", "cancel": "Cancel", "discard": "Discard", "add": "Add", diff --git a/src/constants/translations/en/my-resources-page.json b/src/constants/translations/en/my-resources-page.json index 2aeb6f639..37517d0ea 100644 --- a/src/constants/translations/en/my-resources-page.json +++ b/src/constants/translations/en/my-resources-page.json @@ -41,14 +41,24 @@ "questions": "Questions", "updated": "Last updates", "emptyItems": "You have no quizzes yet", - "confirmDeletionTitle": "Do you confirm quiz deletion?", - "successDeletion": "Quiz was deleted successfully", - "defaultNewTitle": "Untitled", - "defaultNewDescription": "Description...", - "createNewQuestion": "Create new question", + "confirmDeletionTitle":"Do you confirm quiz deletion?", + "successDeletion":"Quiz was deleted successfully", "editQuestion": "Edit question", - "addQuestion": "Add question", - "successAddedOuiz": "Ouiz was successtully created" + "successAddedOuiz": "Quiz was successfully created", + "defaultNewTitle":"Untitled", + "defaultNewDescription":"Description...", + "createNewQuestion":"Create new question", + "addQuestion":"Add question", + "settingsPointsAndAnswers": "Settings: Points and answers", + "pointValues": "Point values", + "pointValuesDesc": "Respondents can see total points and points received for each question", + "scoredUnscoredResponses": "Scored / Unscored responses", + "scoredUnscoredResponsesDesc": "Respondents can see which questions were answered correctly or incorrectly", + "correctAnswers": "Correct answers", + "correctAnswersDesc": "Respondents can see correct answers after grades are released", + "settingsQuiz": "Settings: Quiz", + "questionsShuffle": "Questions shuffle", + "questionsShuffleDesc": "Questions will be shuffled with every attempt" }, "questions": { "addBtn": "New question", @@ -74,4 +84,4 @@ "confirmDeletionTitle": "Do you confirm category deletion?" }, "confirmDeletionMessage": "This action is permanent and will remove all related content. Please review your decision before proceeding." -} \ No newline at end of file +} diff --git a/src/constants/translations/ua/common.json b/src/constants/translations/ua/common.json index 85cd5563d..86e49546e 100644 --- a/src/constants/translations/ua/common.json +++ b/src/constants/translations/ua/common.json @@ -24,6 +24,7 @@ "uahSlashHour": "ГРН/годину", "beginner": "Початковий", "save": "Зберегти", + "apply": "Застосувати", "cancel": "Відмінити", "discard": "Відмовитись", "add": "Додати", diff --git a/src/constants/translations/ua/my-resources-page.json b/src/constants/translations/ua/my-resources-page.json index 077dad2ae..eac15b813 100644 --- a/src/constants/translations/ua/my-resources-page.json +++ b/src/constants/translations/ua/my-resources-page.json @@ -48,8 +48,18 @@ "defaultNewDescription": "Опис...", "createNewQuestion": "Створити нове питання", "editQuestion": "Редагувати питання", - "addQuestion": "Додати питання", - "successAddedOuiz": "Тест успішно створено" + "successAddedOuiz": "Тест успішно створено", + "addQuestion":"Додати питання", + "settingsPointsAndAnswers": "Налаштування: Бали та відповіді", + "pointValues": "Значення балів", + "pointValuesDesc": "Респонденти можуть бачити загальну кількість балів і бали, отримані за кожне запитання", + "scoredUnscoredResponses": "Оцінені / не оцінені відповіді", + "scoredUnscoredResponsesDesc": "Респонденти можуть бачити, на які запитання було надано правильні чи неправильні відповіді", + "correctAnswers": "Правильні відповіді", + "correctAnswersDesc": "Респонденти можуть бачити правильні відповіді після оприлюднення оцінок", + "settingsQuiz": "Налаштування: Тест", + "questionsShuffle": "Питання перемішуються", + "questionsShuffleDesc": "Запитання будуть перемішуватися при кожній спробі" }, "questions": { "addBtn": "Нове запитання", diff --git a/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.styles.ts b/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.styles.ts new file mode 100644 index 000000000..1f8815433 --- /dev/null +++ b/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.styles.ts @@ -0,0 +1,53 @@ +import { TypographyVariantEnum } from '~/types' +export const styles = { + topTitle: { + mt: '8px' + }, + title: { + typography: TypographyVariantEnum.H6, + color: 'basic.blueGray', + mt: '40px' + }, + select: { + width: '160px', + height: '40px', + flex: 'none' + }, + buttonContainer: { + display: 'flex', + justifyContent: 'flex-end', + mt: '32px' + }, + switch: { + width: '50px', + height: '24px', + padding: 0, + '& .MuiSwitch-switchBase': { + padding: '4px', + '&.Mui-checked': { + transform: 'translateX(26px)', + color: 'basic.white', + '& + .MuiSwitch-track': { + opacity: 1, + backgroundColor: 'basic.white' + }, + '& .MuiSwitch-thumb': { + backgroundColor: 'primary.900' + } + } + }, + '& .MuiSwitch-thumb': { + width: '16px', + height: '16px', + backgroundColor: 'basic.gray' + }, + '& .MuiSwitch-track': { + borderRadius: '28px', + opacity: 1, + border: '2px solid', + borderColor: 'primary.100', + backgroundColor: 'basic.white', + boxSizing: 'border-box' + } + } +} diff --git a/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.tsx b/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.tsx index 5a372f846..a6a408aaa 100644 --- a/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.tsx +++ b/src/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.tsx @@ -1,7 +1,120 @@ +import { useTranslation } from 'react-i18next' import { Box } from '@mui/material' +import Typography from '@mui/material/Typography' +import Switch from '@mui/material/Switch' +import { ButtonTypeEnum } from '~/types' +import useForm from '~/hooks/use-form' +import { spliceSx } from '~/utils/helper-functions' + +import SettingItem from '~/components/setting-item/SettingItem' +import AppSelect from '~/components/app-select/AppSelect' +import AppButton from '~/components/app-button/AppButton' + +import { styles } from '~/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer.styles' + +const quizViewFields = [ + { + value: 'scroll', + title: 'Scroll' + }, + { + value: 'stepper', + title: 'Stepper' + } +] const QuizSettingsContainer = () => { - return Quiz settings + const { t } = useTranslation() + const { data, handleInputChange, handleNonInputValueChange } = useForm({ + initialValues: { + pointValues: false, + scoredUnscoredResponses: false, + correctAnswers: false, + shuffleQuestions: false, + quizView: 'scroll' + } + }) + + return ( + + + + {t('myResourcesPage.quizzes.settingsQuiz')} + + + + handleNonInputValueChange('quizView', value)} + sx={styles.select} + value={data.quizView} + /> + + + + + + + + + + {t('myResourcesPage.quizzes.settingsPointsAndAnswers')} + + + + + + + + + + + + + + + + + {t('common.apply')} + + + + ) } export default QuizSettingsContainer diff --git a/src/styles/app-theme/app.pallete.ts b/src/styles/app-theme/app.pallete.ts index 917d8b977..94b3429bb 100644 --- a/src/styles/app-theme/app.pallete.ts +++ b/src/styles/app-theme/app.pallete.ts @@ -6,6 +6,7 @@ const palette = { imageOverlay: 'rgba(38, 50, 56, 0.7)', basic: { black: '#000000', + gray: '#B0BEC5', blue: '#0B8AF8', white: '#FFFFFF', grey: '#ECEFF1', @@ -19,7 +20,8 @@ const palette = { lime: '#99CC00', turquoise: '#489DA0', turquoiseDark: '#3B8587', - turquoiseChat: '#A0F0F2' + turquoiseChat: '#A0F0F2', + blueGray: '#607D8B' }, companyBlue: 'rgba(0, 167, 167, 0.2)', error: { diff --git a/tests/unit/containers/my-quizzes/QuizSettingsContainer.spec.jsx b/tests/unit/containers/my-quizzes/QuizSettingsContainer.spec.jsx new file mode 100644 index 000000000..5357e0077 --- /dev/null +++ b/tests/unit/containers/my-quizzes/QuizSettingsContainer.spec.jsx @@ -0,0 +1,58 @@ +import QuizSettingsContainer from '~/containers/my-quizzes/quiz-settings-container/QuizSettingsContainer' +import { renderWithProviders } from '~tests/test-utils' +import { screen, fireEvent } from '@testing-library/react' + +describe('QuizSettingsContainer', () => { + beforeEach(() => { + renderWithProviders() + }) + + it('should render two settings titles', () => { + const title1 = screen.getByText( + 'myResourcesPage.quizzes.settingsPointsAndAnswers' + ) + const title2 = screen.getByText('myResourcesPage.quizzes.settingsQuiz') + expect(title1).toBeInTheDocument() + expect(title2).toBeInTheDocument() + }) + + it('should toggle the "pointValues" switch and update data', () => { + const switchElement = screen.getByTestId('pointValues-switch').firstChild + + fireEvent.click(switchElement) + + expect(switchElement).toBeChecked() + expect(screen.getByTestId('pointValues-switch').firstChild.checked).toBe( + true + ) + }) + + it('should toggle the "scoredUnscoredResponses" switch and update data', () => { + const switchElement = screen.getByTestId('responses-switch').firstChild + + fireEvent.click(switchElement) + + expect(switchElement).toBeChecked() + expect(screen.getByTestId('responses-switch').firstChild.checked).toBe(true) + }) + + it('should toggle the "correctAnswers" switch and update data', () => { + const switchElement = screen.getByTestId('correctAnswers-switch').firstChild + + fireEvent.click(switchElement) + + expect(switchElement).toBeChecked() + expect(screen.getByTestId('correctAnswers-switch').firstChild.checked).toBe( + true + ) + }) + + it('should toggle the "shuffleQuestions" switch and update data', () => { + const switchElement = screen.getByTestId('shuffle-switch').firstChild + + fireEvent.click(switchElement) + + expect(switchElement).toBeChecked() + expect(screen.getByTestId('shuffle-switch').firstChild.checked).toBe(true) + }) +})