Skip to content

Commit

Permalink
Implemented settings tab for Quiz (#1384)
Browse files Browse the repository at this point in the history
* Implemented settings tab for Quiz

* Created reusable component

* Refactored code

* Changed to match design updates
  • Loading branch information
abalanovsky authored Nov 20, 2023
1 parent 5d4f5e8 commit f48ce0e
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 12 deletions.
17 changes: 17 additions & 0 deletions src/components/setting-item/SettingItem.styles.ts
Original file line number Diff line number Diff line change
@@ -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'
}
}
25 changes: 25 additions & 0 deletions src/components/setting-item/SettingItem.tsx
Original file line number Diff line number Diff line change
@@ -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<SettingItemProps> = ({ title, subtitle, children }) => {
return (
<Box sx={styles.settingContainer}>
<Box>
<Typography sx={styles.title}>{title}</Typography>
<Typography sx={styles.subtitle}>{subtitle}</Typography>
</Box>
{children}
</Box>
)
}

export default SettingItem
1 change: 1 addition & 0 deletions src/constants/translations/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"aboutOffer": "About Offer",
"goToName": "Go to {{name}}",
"save": "Save",
"apply": "Apply",
"cancel": "Cancel",
"discard": "Discard",
"add": "Add",
Expand Down
26 changes: 18 additions & 8 deletions src/constants/translations/en/my-resources-page.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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."
}
}
1 change: 1 addition & 0 deletions src/constants/translations/ua/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"uahSlashHour": "ГРН/годину",
"beginner": "Початковий",
"save": "Зберегти",
"apply": "Застосувати",
"cancel": "Відмінити",
"discard": "Відмовитись",
"add": "Додати",
Expand Down
14 changes: 12 additions & 2 deletions src/constants/translations/ua/my-resources-page.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,18 @@
"defaultNewDescription": "Опис...",
"createNewQuestion": "Створити нове питання",
"editQuestion": "Редагувати питання",
"addQuestion": "Додати питання",
"successAddedOuiz": "Тест успішно створено"
"successAddedOuiz": "Тест успішно створено",
"addQuestion":"Додати питання",
"settingsPointsAndAnswers": "Налаштування: Бали та відповіді",
"pointValues": "Значення балів",
"pointValuesDesc": "Респонденти можуть бачити загальну кількість балів і бали, отримані за кожне запитання",
"scoredUnscoredResponses": "Оцінені / не оцінені відповіді",
"scoredUnscoredResponsesDesc": "Респонденти можуть бачити, на які запитання було надано правильні чи неправильні відповіді",
"correctAnswers": "Правильні відповіді",
"correctAnswersDesc": "Респонденти можуть бачити правильні відповіді після оприлюднення оцінок",
"settingsQuiz": "Налаштування: Тест",
"questionsShuffle": "Питання перемішуються",
"questionsShuffleDesc": "Запитання будуть перемішуватися при кожній спробі"
},
"questions": {
"addBtn": "Нове запитання",
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
}
}
}
Original file line number Diff line number Diff line change
@@ -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 <Box>Quiz settings</Box>
const { t } = useTranslation()
const { data, handleInputChange, handleNonInputValueChange } = useForm({
initialValues: {
pointValues: false,
scoredUnscoredResponses: false,
correctAnswers: false,
shuffleQuestions: false,
quizView: 'scroll'
}
})

return (
<Box>
<Box>
<Typography sx={spliceSx(styles.title, styles.topTitle)}>
{t('myResourcesPage.quizzes.settingsQuiz')}
</Typography>

<SettingItem
subtitle={t('myResourcesPage.quizzes.questionsShuffleDesc')}
title={t('myResourcesPage.quizzes.questionsShuffle')}
>
<AppSelect
fields={quizViewFields}
setValue={(value) => handleNonInputValueChange('quizView', value)}
sx={styles.select}
value={data.quizView}
/>
</SettingItem>

<SettingItem
subtitle={t('myResourcesPage.quizzes.questionsShuffleDesc')}
title={t('myResourcesPage.quizzes.questionsShuffle')}
>
<Switch
checked={data.shuffleQuestions}
data-testid='shuffle-switch'
onChange={handleInputChange('shuffleQuestions')}
sx={styles.switch}
/>
</SettingItem>
</Box>

<Box>
<Typography sx={styles.title}>
{t('myResourcesPage.quizzes.settingsPointsAndAnswers')}
</Typography>

<SettingItem
subtitle={t('myResourcesPage.quizzes.pointValuesDesc')}
title={t('myResourcesPage.quizzes.pointValues')}
>
<Switch
checked={data.pointValues}
data-testid='pointValues-switch'
onChange={handleInputChange('pointValues')}
sx={styles.switch}
/>
</SettingItem>

<SettingItem
subtitle={t('myResourcesPage.quizzes.scoredUnscoredResponsesDesc')}
title={t('myResourcesPage.quizzes.scoredUnscoredResponses')}
>
<Switch
checked={data.scoredUnscoredResponses}
data-testid='responses-switch'
onChange={handleInputChange('scoredUnscoredResponses')}
sx={styles.switch}
/>
</SettingItem>

<SettingItem
subtitle={t('myResourcesPage.quizzes.correctAnswersDesc')}
title={t('myResourcesPage.quizzes.correctAnswers')}
>
<Switch
checked={data.correctAnswers}
data-testid='correctAnswers-switch'
onChange={handleInputChange('correctAnswers')}
sx={styles.switch}
/>
</SettingItem>
</Box>
<Box sx={styles.buttonContainer}>
<AppButton disabled type={ButtonTypeEnum.Submit}>
{t('common.apply')}
</AppButton>
</Box>
</Box>
)
}

export default QuizSettingsContainer
4 changes: 3 additions & 1 deletion src/styles/app-theme/app.pallete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const palette = {
imageOverlay: 'rgba(38, 50, 56, 0.7)',
basic: {
black: '#000000',
gray: '#B0BEC5',
blue: '#0B8AF8',
white: '#FFFFFF',
grey: '#ECEFF1',
Expand All @@ -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: {
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/containers/my-quizzes/QuizSettingsContainer.spec.jsx
Original file line number Diff line number Diff line change
@@ -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(<QuizSettingsContainer />)
})

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)
})
})

0 comments on commit f48ce0e

Please sign in to comment.