From d4c3a7125d5091da690ee773b409f7c5d4805af9 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Thu, 23 Mar 2023 17:29:59 +0300 Subject: [PATCH 01/12] create type and difficulty using switch selector --- .../SelectorFieldDifficulty.tsx | 44 +++++++++++++++++++ .../SwitchSelectorDifficulty.tsx | 42 ++++++++++++++++++ .../SelectorFieldNOQ.tsx} | 8 ++-- .../SwitchSelectorNOQ.tsx} | 28 ++++++------ .../SelectorFieldType/SelectorFieldType.tsx | 44 +++++++++++++++++++ .../SelectorFieldType/SwitchSelectorType.tsx | 41 +++++++++++++++++ .../create-test/create-question/index.tsx | 33 +++++++++----- .../create-quiz/CreateQuizContainer.tsx | 4 +- src/pages/testPage/index.tsx | 2 - src/store/reducers/quizzes-reducer.ts | 1 - src/store/selectors.ts | 2 - src/types/CreateQuizType.ts | 4 +- src/types/SelectorType.ts | 21 +++++++-- 13 files changed, 232 insertions(+), 42 deletions(-) create mode 100644 src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx create mode 100644 src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx rename src/pages/create-test/FieldsComponents/SelectorField/{SelectorField.tsx => SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx} (75%) rename src/pages/create-test/FieldsComponents/SelectorField/{SwitchSelector.tsx => SelectorFieldNumOfQuestion/SwitchSelectorNOQ.tsx} (57%) create mode 100644 src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx create mode 100644 src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx new file mode 100644 index 0000000..4f01db8 --- /dev/null +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx @@ -0,0 +1,44 @@ +import { Control, Controller, FieldPath, FieldValues } from 'react-hook-form'; +import React from 'react'; +import { Box } from '@mui/system'; +import { Typography } from '@mui/material'; +import { useTranslation } from 'next-i18next'; +import { TypeSwitchSelect } from '../../../../../types/SelectorType'; +import { SwitchSelectorDifficulty } from './SwitchSelectorDifficulty'; + +type SelectorFieldType = { + name: FieldPath; + type: TypeSwitchSelect; + label?: string | null; + rules?: object; + control: Control; +}; + +export const SelectorFieldDifficulty = ({ + name, + label, + type, + rules, + control, +}: SelectorFieldType) => { + const { t } = useTranslation('selectorField'); + return ( + + {label && ( + {t(`${label}`)} + )} + ( + + )} + /> + + ); +}; diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx new file mode 100644 index 0000000..e31b2ca --- /dev/null +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx @@ -0,0 +1,42 @@ +import { useMemo } from 'react'; +import SwitchSelector from 'react-switch-selector'; +import { useTranslation } from 'next-i18next'; +import { palette } from '../../../../../styles/theme/commonDefaultTheme'; +import { SelectorDifficultyType } from '../../../../../types/SelectorType'; + +export const SwitchSelectorDifficulty = ({ + onPressDifficulty, + type, + valueDifficulty, +}: SelectorDifficultyType) => { + const { t } = useTranslation('SwitchSelector'); + const SelectorsDataDifficulty = useMemo(() => { + if (type === 'difficulty') { + return [ + { label: `${t('light')}`, value: 'light' }, + { label: `${t('medium')}`, value: 'medium' }, + { label: `${t('hard')}`, value: 'hard' }, + ]; + } + return [ + { label: `${t('All')}`, value: 'All' }, + { label: `${t('My')}`, value: 'My' }, + ]; + }, [type]); + + return ( +
+ el.value === valueDifficulty + )} + onChange={onPressDifficulty} + selectedBackgroundColor={palette.primary.main} + backgroundColor={palette.background.border} + fontSize={15} + /> +
+ ); +}; diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorField.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx similarity index 75% rename from src/pages/create-test/FieldsComponents/SelectorField/SelectorField.tsx rename to src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx index e3aaed6..f7d0fb9 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorField.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx @@ -3,8 +3,8 @@ import React from 'react'; import { Box } from '@mui/system'; import { Typography } from '@mui/material'; import { useTranslation } from 'next-i18next'; -import { TypeSwitchSelect } from '../../../../types/SelectorType'; -import { SwitchSelectors } from './SwitchSelector'; +import { TypeSwitchSelect } from '../../../../../types/SelectorType'; +import { SwitchSelectorNOQ } from './SwitchSelectorNOQ'; type SelectorFieldType = { name: FieldPath; @@ -14,7 +14,7 @@ type SelectorFieldType = { control: Control; }; -export const SelectorField = ({ +export const SelectorFieldNOQ = ({ name, label, type, @@ -32,7 +32,7 @@ export const SelectorField = ({ name={name} rules={rules} render={({ field: { onChange, value } }) => ( - + )} /> diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SwitchSelector.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SwitchSelectorNOQ.tsx similarity index 57% rename from src/pages/create-test/FieldsComponents/SelectorField/SwitchSelector.tsx rename to src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SwitchSelectorNOQ.tsx index 25fe84d..927411a 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SwitchSelector.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SwitchSelectorNOQ.tsx @@ -1,21 +1,19 @@ import { useMemo } from 'react'; import SwitchSelector from 'react-switch-selector'; import { useTranslation } from 'next-i18next'; -import { palette } from '../../../../styles/theme/commonDefaultTheme'; -import { SelectorType } from '../../../../types/SelectorType'; +import { palette } from '../../../../../styles/theme/commonDefaultTheme'; +import { SelectorNOQType } from '../../../../../types/SelectorType'; -export const SwitchSelectors = ({ onPress, type, value }: SelectorType) => { +export const SwitchSelectorNOQ = ({ + onPressNOQ, + type, + valueNOQ, +}: SelectorNOQType) => { const { t } = useTranslation('SwitchSelector'); - const SelectorsData = useMemo(() => { - if (type === 'level') { - return [ - { label: `${t('Easy')}`, value: 'light' }, - { label: `${t('Medium')}`, value: 'medium' }, - { label: `${t('Hard')}`, value: 'hard' }, - ]; - } + const SelectorsDataNOQ = useMemo(() => { if (type === 'number') { return [ + { label: '5', value: '5' }, { label: '10', value: '10' }, { label: '15', value: '15' }, { label: '20', value: '20' }, @@ -32,12 +30,12 @@ export const SwitchSelectors = ({ onPress, type, value }: SelectorType) => { return (
el.value === value + forcedSelectedIndex={SelectorsDataNOQ.findIndex( + (el) => el.value === valueNOQ )} - onChange={onPress} + onChange={onPressNOQ} selectedBackgroundColor={palette.primary.main} backgroundColor={palette.primary.contrastText} fontSize={15} diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx new file mode 100644 index 0000000..6531b22 --- /dev/null +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx @@ -0,0 +1,44 @@ +import { Control, Controller, FieldPath, FieldValues } from 'react-hook-form'; +import React from 'react'; +import { Box } from '@mui/system'; +import { Typography } from '@mui/material'; +import { useTranslation } from 'next-i18next'; +import { TypeSwitchSelect } from '../../../../../types/SelectorType'; +import { SwitchSelectorType } from './SwitchSelectorType'; + +type SelectorFieldType = { + name: FieldPath; + type: TypeSwitchSelect; + label?: string | null; + rules?: object; + control: Control; +}; + +export const SelectorFieldType = ({ + name, + label, + type, + rules, + control, +}: SelectorFieldType) => { + const { t } = useTranslation('selectorField'); + return ( + + {label && ( + {t(`${label}`)} + )} + ( + + )} + /> + + ); +}; diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx new file mode 100644 index 0000000..20793f0 --- /dev/null +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx @@ -0,0 +1,41 @@ +import { useMemo } from 'react'; +import SwitchSelector from 'react-switch-selector'; +import { useTranslation } from 'next-i18next'; +import { palette } from '../../../../../styles/theme/commonDefaultTheme'; +import { SelectorTypeOfQuestionType } from '../../../../../types/SelectorType'; + +export const SwitchSelectorType = ({ + onPressType, + type, + valueType, +}: SelectorTypeOfQuestionType) => { + const { t } = useTranslation('SwitchSelector'); + const SelectorsDataType = useMemo(() => { + if (type === 'type') { + return [ + { label: `${t('single')}`, value: 'single' }, + { label: `${t('multi')}`, value: 'multi' }, + ]; + } + return [ + { label: `${t('All')}`, value: 'All' }, + { label: `${t('My')}`, value: 'My' }, + ]; + }, [type]); + + return ( +
+ el.value === valueType + )} + onChange={onPressType} + selectedBackgroundColor={palette.primary.main} + backgroundColor={palette.background.border} + fontSize={15} + /> +
+ ); +}; diff --git a/src/pages/create-test/create-question/index.tsx b/src/pages/create-test/create-question/index.tsx index 1fa8e0d..ac49e14 100644 --- a/src/pages/create-test/create-question/index.tsx +++ b/src/pages/create-test/create-question/index.tsx @@ -2,11 +2,9 @@ import React, { useState, useEffect, useMemo } from 'react'; import { Box, Button, Stack, Typography } from '@mui/material'; import { SubmitHandler, useForm } from 'react-hook-form'; import { useRouter } from 'next/router'; -import Link from 'next/link'; import { useTranslation } from 'next-i18next'; import { QuestionTabs } from '../../../components/common/Tabs/QuestionTabs/QuestionTabs'; import { InputField } from '../FieldsComponents/InputFieald'; -import { DropDownField } from '../FieldsComponents/DropDownField'; import { types } from '../../../Mocs/NewTestMoc'; import CreateAnswer from '../FieldsComponents/CreateAnswer/CreateAnswer'; import { quizesApi } from '../../../api/quizesApi'; @@ -16,6 +14,9 @@ import { ButtonBackHome } from '../../../components/common/ButtonBackHome'; import { Layout } from '../../../components/layout/Layout'; import { StylizedPaper } from '../../../components/common/StylizedPaper/StylizedPaper'; import { QuestionTimer } from '../FieldsComponents/QuestionTimer/QuestionTimer'; +import { TypeSwitchSelect } from '../../../types/SelectorType'; +import { SelectorFieldDifficulty } from '../FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty'; +import { SelectorFieldType } from '../FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType'; const CreateQuestion = () => { const { t } = useTranslation('create-question'); @@ -157,19 +158,31 @@ const CreateQuestion = () => { - */} + - */} + diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index 8df697b..8aa13df 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -6,10 +6,10 @@ import { ButtonBackHome } from '../../../components/common/ButtonBackHome'; import { StylizedPaper } from '../../../components/common/StylizedPaper/StylizedPaper'; import { InputField } from '../FieldsComponents/InputFieald'; import TopicSelect from '../FieldsComponents/CreateTopic/CreateTopic'; -import { SelectorField } from '../FieldsComponents/SelectorField/SelectorField'; import { TypeSwitchSelect } from '../../../types/SelectorType'; import { Layout } from '../../../components/layout/Layout'; import { CreateQuizType } from '../../../types/CreateQuizType'; +import { SelectorFieldNOQ } from '../FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ'; type CreateQuizContainerType = { onSubmit: SubmitHandler; @@ -56,7 +56,7 @@ export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { - {/* */} diff --git a/src/store/reducers/quizzes-reducer.ts b/src/store/reducers/quizzes-reducer.ts index 4db33be..a4fc896 100644 --- a/src/store/reducers/quizzes-reducer.ts +++ b/src/store/reducers/quizzes-reducer.ts @@ -3,7 +3,6 @@ import { HYDRATE } from 'next-redux-wrapper'; import { AxiosError } from 'axios'; import { quizesApi } from '../../api/quizesApi'; import { CardType } from '../../types/CardTypes'; -import { TopicType } from '../../types/CreateQuizType'; export const fetchQuizes = createAsyncThunk( 'quizes/getQuizesThunk', diff --git a/src/store/selectors.ts b/src/store/selectors.ts index cf96ea7..9f147bb 100644 --- a/src/store/selectors.ts +++ b/src/store/selectors.ts @@ -1,6 +1,4 @@ -import React from 'react'; import { AppState } from './store'; -import { createTopic } from './reducers/topic-reducer'; export const selectOneQuizes = (state: AppState) => state.quizes.oneQuizes; export const selectResulData = (state: AppState) => state.resultData.result; diff --git a/src/types/CreateQuizType.ts b/src/types/CreateQuizType.ts index a65df20..5cfec92 100644 --- a/src/types/CreateQuizType.ts +++ b/src/types/CreateQuizType.ts @@ -2,8 +2,8 @@ export type CreateQuizType = { title: string; description: string; comment: string; - topicId: any; - numberOfQuestions: any; + topicId: number; + numberOfQuestions: number; id?: number; }; export type TopicType = { diff --git a/src/types/SelectorType.ts b/src/types/SelectorType.ts index 650231d..5f4f3f4 100644 --- a/src/types/SelectorType.ts +++ b/src/types/SelectorType.ts @@ -1,11 +1,24 @@ -export type SelectorType = { - onPress?: (selectedOptionValue: T | unknown) => void; - value?: string | number; +export type SelectorDifficultyType = { + onPressDifficulty?: (selectedOptionValue: T | unknown) => void; + valueDifficulty?: string | number; + type: TypeSwitchSelect; +}; + +export type SelectorNOQType = { + onPressNOQ?: (selectedOptionValue: T | unknown) => void; + valueNOQ?: string | number; + type: TypeSwitchSelect; +}; + +export type SelectorTypeOfQuestionType = { + onPressType?: (selectedOptionValue: T | unknown) => void; + valueType?: string | number; type: TypeSwitchSelect; }; export enum TypeSwitchSelect { - LEVEL = 'level', + DIFFICULTY = 'difficulty', + TYPE = 'type', NUMBER = 'number', FILTER = 'filter', } From 140b60168da8b0ea19770241468e5d74e36c6113 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Thu, 23 Mar 2023 19:27:40 +0300 Subject: [PATCH 02/12] fix switch selector bugs --- src/Mocs/NewTestMoc.ts | 4 ++-- src/api/quizesApi.ts | 2 +- .../create-test/FieldsComponents/InputFieald.tsx | 11 +++++++++-- .../SelectorFieldDifficulty.tsx | 1 + .../SwitchSelectorDifficulty.tsx | 4 +++- .../SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx | 2 +- .../SelectorFieldType/SelectorFieldType.tsx | 1 + .../SelectorFieldType/SwitchSelectorType.tsx | 4 +++- src/types/SelectorType.ts | 2 ++ 9 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Mocs/NewTestMoc.ts b/src/Mocs/NewTestMoc.ts index 85756a5..a4fbd30 100644 --- a/src/Mocs/NewTestMoc.ts +++ b/src/Mocs/NewTestMoc.ts @@ -1,3 +1,3 @@ -export const types = ['Select type...', 'single', 'multi']; -export const difficulties = ['Select difficulty...', 'light', 'medium', 'hard']; +export const types = ['single', 'multi']; +export const difficulties = ['light', 'medium', 'hard']; export const numberQuestions = [10, 15, 20, 25, 30]; diff --git a/src/api/quizesApi.ts b/src/api/quizesApi.ts index e96b7d8..40a5c03 100644 --- a/src/api/quizesApi.ts +++ b/src/api/quizesApi.ts @@ -10,7 +10,7 @@ export const quizesApi = { getQuiz(cardId: number) { return instance.get(`quiz/${cardId}`); }, - postQuizes(quizData: CreateQuizType) { + postQuizes(quizData: { topicId: axios.AxiosResponse | number; description: string; comment: string; numberOfQuestions: null; id?: number; title: string }) { return instance.post('quiz', quizData); }, postQuestion(questionData: FieldValues) { diff --git a/src/pages/create-test/FieldsComponents/InputFieald.tsx b/src/pages/create-test/FieldsComponents/InputFieald.tsx index ea7c720..874069d 100644 --- a/src/pages/create-test/FieldsComponents/InputFieald.tsx +++ b/src/pages/create-test/FieldsComponents/InputFieald.tsx @@ -1,6 +1,6 @@ import { FormGroup, TextField, Typography } from '@mui/material'; import React from 'react'; -import { Controller } from 'react-hook-form'; +import { Control, Controller, FieldValues } from "react-hook-form"; import { useTranslation } from 'next-i18next'; type InputFieldType = { @@ -19,9 +19,16 @@ export function InputField({ {t(`${nameTitle}`)} } name={nameControl} + rules={{ required: true }} control={control} + render={({ field, fieldState: { error } }) => ( + + )} /> ); diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx index 4f01db8..b61f5d6 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SelectorFieldDifficulty.tsx @@ -36,6 +36,7 @@ export const SelectorFieldDifficulty = ({ type={type} onPressDifficulty={onChange} valueDifficulty={value} + name={name} /> )} /> diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx index e31b2ca..50ede23 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx @@ -8,6 +8,7 @@ export const SwitchSelectorDifficulty = ({ onPressDifficulty, type, valueDifficulty, + name }: SelectorDifficultyType) => { const { t } = useTranslation('SwitchSelector'); const SelectorsDataDifficulty = useMemo(() => { @@ -34,8 +35,9 @@ export const SwitchSelectorDifficulty = ({ )} onChange={onPressDifficulty} selectedBackgroundColor={palette.primary.main} - backgroundColor={palette.background.border} + backgroundColor={palette.background.paperAccent2} fontSize={15} + name={name} />
); diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx index f7d0fb9..1a269bb 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx @@ -32,7 +32,7 @@ export const SelectorFieldNOQ = ({ name={name} rules={rules} render={({ field: { onChange, value } }) => ( - + )} /> diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx index 6531b22..66fe51a 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx @@ -36,6 +36,7 @@ export const SelectorFieldType = ({ type={type} onPressType={onChange} valueType={value} + name={name} /> )} /> diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx index 20793f0..c672a8a 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx @@ -8,6 +8,7 @@ export const SwitchSelectorType = ({ onPressType, type, valueType, + name }: SelectorTypeOfQuestionType) => { const { t } = useTranslation('SwitchSelector'); const SelectorsDataType = useMemo(() => { @@ -33,8 +34,9 @@ export const SwitchSelectorType = ({ )} onChange={onPressType} selectedBackgroundColor={palette.primary.main} - backgroundColor={palette.background.border} + backgroundColor={palette.background.paperAccent2} fontSize={15} + name={name} /> ); diff --git a/src/types/SelectorType.ts b/src/types/SelectorType.ts index 5f4f3f4..65b7532 100644 --- a/src/types/SelectorType.ts +++ b/src/types/SelectorType.ts @@ -2,6 +2,7 @@ export type SelectorDifficultyType = { onPressDifficulty?: (selectedOptionValue: T | unknown) => void; valueDifficulty?: string | number; type: TypeSwitchSelect; + name: string }; export type SelectorNOQType = { @@ -14,6 +15,7 @@ export type SelectorTypeOfQuestionType = { onPressType?: (selectedOptionValue: T | unknown) => void; valueType?: string | number; type: TypeSwitchSelect; + name : string }; export enum TypeSwitchSelect { From 4b4af8cf5b501a30029c78a139b6b3dc319e08ca Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Thu, 23 Mar 2023 19:34:45 +0300 Subject: [PATCH 03/12] fix switch selector bugs --- .../FieldsComponents/QuestionTimer/QuestionTimer.tsx | 4 ++-- src/pages/create-test/create-question/index.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/QuestionTimer/QuestionTimer.tsx b/src/pages/create-test/FieldsComponents/QuestionTimer/QuestionTimer.tsx index 3ee4a84..7fad049 100644 --- a/src/pages/create-test/FieldsComponents/QuestionTimer/QuestionTimer.tsx +++ b/src/pages/create-test/FieldsComponents/QuestionTimer/QuestionTimer.tsx @@ -24,7 +24,7 @@ export const QuestionTimer: React.FC = ({ name, control }) => { InputProps={{ inputProps: { min: 0 } }} fullWidth /> - {t('Minutes')} + {t('Min')} )} /> @@ -40,7 +40,7 @@ export const QuestionTimer: React.FC = ({ name, control }) => { InputProps={{ inputProps: { min: 0, max: 59 } }} fullWidth /> - {t('Seconds')} + {t('Sec')} )} /> diff --git a/src/pages/create-test/create-question/index.tsx b/src/pages/create-test/create-question/index.tsx index ac49e14..9e4145a 100644 --- a/src/pages/create-test/create-question/index.tsx +++ b/src/pages/create-test/create-question/index.tsx @@ -157,7 +157,7 @@ const CreateQuestion = () => { - + {/* { type={TypeSwitchSelect.TYPE} /> - + {/* { type={TypeSwitchSelect.DIFFICULTY} /> - + {t('Timer :')} From 4bfe23613ee885e92bcf596bb2943f8614834616 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Sat, 25 Mar 2023 13:07:53 +0300 Subject: [PATCH 04/12] fix topic --- .../CreateTopic/CreateTopic.tsx | 169 +++++++++--------- .../FieldsComponents/InputFieald.tsx | 3 + .../create-quiz/CreateQuizContainer.tsx | 17 +- 3 files changed, 101 insertions(+), 88 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx index 2c5decd..642f093 100644 --- a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx +++ b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx @@ -1,108 +1,113 @@ -import React, { ChangeEvent, useState } from 'react'; -import { - Button, - FormControl, - Input, - InputLabel, - MenuItem, - Select, - Stack, - TextField, - Typography, -} from '@mui/material'; -import { Controller } from 'react-hook-form'; -import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; +import Autocomplete from '@mui/material/Autocomplete'; +import TextField from '@mui/material/TextField'; +import { useController } from 'react-hook-form'; +import { Box, Button, Stack, Typography } from '@mui/material'; import { useTranslation } from 'next-i18next'; -import { InputField } from '../InputFieald'; -import { useAppDispatch, useAppSelector } from '../../../../store/store'; -import { getOneQuizes } from '../../../../store/reducers/quizzes-reducer'; +import { useDispatch } from 'react-redux'; +import { useAppDispatch } from '../../../../store/store'; import { createTopic } from '../../../../store/reducers/topic-reducer'; -import { selectOneQuizes, selectTopic } from '../../../../store/selectors'; - -type Props = { - name: string; - control: any; -}; type Topic = { id: number; - name: string; + title: string; }; -const topicOptions: Topic[] = [ - { id: 1, name: 'Select topic...' }, - { id: 2, name: 'NodeJS' }, - { id: 3, name: 'React' }, - { id: 4, name: 'Angular' }, -]; +type AutocompleteProps = { + name: string; + control: any; +}; -export default function TopicSelect({ name, control }: Props) { - const [newTopicName, setNewTopicName] = useState(''); - const { t } = useTranslation('createTopic'); - const [showNewTopicInput, setShowNewTopicInput] = useState(false); - const [topics, setTopics] = useState(topicOptions); +const CreatableAutocomplete: React.FC = ({ + name, + control, +}) => { + const { + field: { value, onChange }, + } = useController({ + name, + control, + }); const dispatch = useAppDispatch(); - const topic = useAppSelector(selectTopic); + const { t } = useTranslation('Topic'); + const [topics, setTopics] = useState([]); + const [newTopicName, setNewTopicName] = useState(''); + + useEffect(() => { + fetch('http://localhost:5000/api/topic') + .then((response) => response.json()) + .then((data) => setTopics(data)); + }, []); const addNewTopicHandler = () => { dispatch(createTopic(newTopicName)); }; - const handleNewTopicNameChange = ( - event: React.ChangeEvent - ) => { - setNewTopicName(event.target.value); - }; - - const handleNewTopicButtonClick = () => { - setShowNewTopicInput(true); - }; - - const handleNewTopicCancel = () => { - setShowNewTopicInput(false); - setNewTopicName(''); + const handleNewTopicNameChange = (event: React.SyntheticEvent) => { + // setNewTopicName(event.target.value); }; - const handleNewTopicSave = () => { - const newId = topics.length + 1; - const newTopic = { id: newId, name: newTopicName }; - setTopics([...topics, newTopic]); - handleNewTopicCancel(); + const handleCreate = (newValue: string) => { + console.log(newValue); + // make a POST request to create new topic on the server + const newTopic = { id: topics.length + 1, title: newValue }; + // update topics with new topic + topics.push(newTopic); + onChange(newTopic); }; return ( - {t('Choose a topic :')} - - setNewTopicName(e.currentTarget.value)} - /> - - - {!showNewTopicInput && ( - - )} - - {showNewTopicInput && ( - <> - + {t('Test topic')} + setNewTopicName(e.currentTarget.value)} + filterOptions={(options, params) => { + const filtered = options.filter((option) => + option.title.toLowerCase().includes(params.inputValue.toLowerCase()) + ); + if (params.inputValue !== '') { + filtered.push({ + id: topics.length + 1, + title: params.inputValue, + }); + } + return filtered; + }} + selectOnFocus + clearOnBlur + handleHomeEndKeys + options={topics} + getOptionLabel={(option) => option.title} + renderOption={(props, option) =>
  • {option.title}
  • } + renderInput={(params) => ( + + - - - - )} + )} + freeSolo + onInputChange={(event, newInputValue) => { + if (newInputValue !== '') { + onChange({ + id: topics.length + 1, + title: newInputValue, + }); + } + }} + multiple={false} + limitTags={1} + fullWidth + />
    ); -} +}; + +export default CreatableAutocomplete; diff --git a/src/pages/create-test/FieldsComponents/InputFieald.tsx b/src/pages/create-test/FieldsComponents/InputFieald.tsx index 874069d..fa9ebfa 100644 --- a/src/pages/create-test/FieldsComponents/InputFieald.tsx +++ b/src/pages/create-test/FieldsComponents/InputFieald.tsx @@ -7,12 +7,14 @@ type InputFieldType = { nameTitle: string; nameControl: string; control: any; + placeholder: string }; export function InputField({ nameTitle, nameControl, control, + placeholder }: InputFieldType) { const { t } = useTranslation('SwitchSelector'); return ( @@ -26,6 +28,7 @@ export function InputField({ )} diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index 8aa13df..bca46e1 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -1,20 +1,25 @@ -import React from 'react'; +import React, { useEffect, useState } from "react"; import { SubmitHandler, useForm } from 'react-hook-form'; import { Box, Button, Stack } from '@mui/material'; import { useTranslation } from 'next-i18next'; import { ButtonBackHome } from '../../../components/common/ButtonBackHome'; import { StylizedPaper } from '../../../components/common/StylizedPaper/StylizedPaper'; import { InputField } from '../FieldsComponents/InputFieald'; -import TopicSelect from '../FieldsComponents/CreateTopic/CreateTopic'; import { TypeSwitchSelect } from '../../../types/SelectorType'; import { Layout } from '../../../components/layout/Layout'; import { CreateQuizType } from '../../../types/CreateQuizType'; import { SelectorFieldNOQ } from '../FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ'; +import AutocompleteComponent from '../FieldsComponents/CreateTopic/CreateTopic'; type CreateQuizContainerType = { onSubmit: SubmitHandler; }; +type Topic = { + id: number; + title: string; +} + export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { const { handleSubmit, control } = useForm(); const { t } = useTranslation('create-quiz'); @@ -37,14 +42,14 @@ export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { nameTitle={t('Test title')} nameControl='title' control={control} - /> + placeholder='Add title for test...'/>
    + placeholder='Add description for test...'/>
    { spacing={3} > - + { nameControl='comment' nameTitle={t('Comment')} control={control} - /> + placeholder='Add comment for test...'/> From e1fc116adcbb5d7a6c0073e576ef1493a6e3961c Mon Sep 17 00:00:00 2001 From: Zenater Date: Sat, 25 Mar 2023 13:50:35 +0300 Subject: [PATCH 05/12] fix : fixed creation topic --- src/api/quizesApi.ts | 9 +++- .../CreateTopic/CreateTopic.tsx | 46 +++++++++---------- .../FieldsComponents/InputFieald.tsx | 6 +-- .../SwitchSelectorDifficulty.tsx | 2 +- .../SelectorFieldNOQ.tsx | 6 ++- .../SelectorFieldType/SwitchSelectorType.tsx | 2 +- .../create-quiz/CreateQuizContainer.tsx | 15 +++--- src/types/SelectorType.ts | 4 +- 8 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/api/quizesApi.ts b/src/api/quizesApi.ts index 40a5c03..cd4b55a 100644 --- a/src/api/quizesApi.ts +++ b/src/api/quizesApi.ts @@ -10,7 +10,14 @@ export const quizesApi = { getQuiz(cardId: number) { return instance.get(`quiz/${cardId}`); }, - postQuizes(quizData: { topicId: axios.AxiosResponse | number; description: string; comment: string; numberOfQuestions: null; id?: number; title: string }) { + postQuizes(quizData: { + topicId: axios.AxiosResponse | number; + description: string; + comment: string; + numberOfQuestions: null; + id?: number; + title: string; + }) { return instance.post('quiz', quizData); }, postQuestion(questionData: FieldValues) { diff --git a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx index 642f093..061aa45 100644 --- a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx +++ b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { ChangeEvent, SyntheticEvent, useEffect, useState } from 'react'; import Autocomplete from '@mui/material/Autocomplete'; import TextField from '@mui/material/TextField'; import { useController } from 'react-hook-form'; @@ -43,8 +43,12 @@ const CreatableAutocomplete: React.FC = ({ dispatch(createTopic(newTopicName)); }; - const handleNewTopicNameChange = (event: React.SyntheticEvent) => { - // setNewTopicName(event.target.value); + const handleNewTopicNameChange = ( + event: ChangeEvent + ) => { + if (event.target.value !== '') { + setNewTopicName(event.target.value); + } }; const handleCreate = (newValue: string) => { @@ -55,27 +59,28 @@ const CreatableAutocomplete: React.FC = ({ topics.push(newTopic); onChange(newTopic); }; - + const cher = topics.filter( + (e) => (e.title && e.title !== '') === newTopicName + ); + console.log(cher, 'cher'); return ( {t('Test topic')} setNewTopicName(e.currentTarget.value)} filterOptions={(options, params) => { const filtered = options.filter((option) => option.title.toLowerCase().includes(params.inputValue.toLowerCase()) ); - if (params.inputValue !== '') { - filtered.push({ - id: topics.length + 1, - title: params.inputValue, - }); - } + // if (params.inputValue !== '') { + // filtered.push({ + // id: topics.length + 1, + // title: params.inputValue, + // }); + // } return filtered; }} selectOnFocus - clearOnBlur handleHomeEndKeys options={topics} getOptionLabel={(option) => option.title} @@ -87,21 +92,16 @@ const CreatableAutocomplete: React.FC = ({ placeholder='Choose topic or add your own...' size='small' value={newTopicName} + onChange={handleNewTopicNameChange} /> - + {cher && ( + + )} )} freeSolo - onInputChange={(event, newInputValue) => { - if (newInputValue !== '') { - onChange({ - id: topics.length + 1, - title: newInputValue, - }); - } - }} multiple={false} limitTags={1} fullWidth diff --git a/src/pages/create-test/FieldsComponents/InputFieald.tsx b/src/pages/create-test/FieldsComponents/InputFieald.tsx index fa9ebfa..9612d3c 100644 --- a/src/pages/create-test/FieldsComponents/InputFieald.tsx +++ b/src/pages/create-test/FieldsComponents/InputFieald.tsx @@ -1,20 +1,20 @@ import { FormGroup, TextField, Typography } from '@mui/material'; import React from 'react'; -import { Control, Controller, FieldValues } from "react-hook-form"; +import { Control, Controller, FieldValues } from 'react-hook-form'; import { useTranslation } from 'next-i18next'; type InputFieldType = { nameTitle: string; nameControl: string; control: any; - placeholder: string + placeholder: string; }; export function InputField({ nameTitle, nameControl, control, - placeholder + placeholder, }: InputFieldType) { const { t } = useTranslation('SwitchSelector'); return ( diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx index 50ede23..003c6aa 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldDifficulty/SwitchSelectorDifficulty.tsx @@ -8,7 +8,7 @@ export const SwitchSelectorDifficulty = ({ onPressDifficulty, type, valueDifficulty, - name + name, }: SelectorDifficultyType) => { const { t } = useTranslation('SwitchSelector'); const SelectorsDataDifficulty = useMemo(() => { diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx index 1a269bb..20bbfa4 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ.tsx @@ -32,7 +32,11 @@ export const SelectorFieldNOQ = ({ name={name} rules={rules} render={({ field: { onChange, value } }) => ( - + )} /> diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx index c672a8a..95a66d0 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SwitchSelectorType.tsx @@ -8,7 +8,7 @@ export const SwitchSelectorType = ({ onPressType, type, valueType, - name + name, }: SelectorTypeOfQuestionType) => { const { t } = useTranslation('SwitchSelector'); const SelectorsDataType = useMemo(() => { diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index bca46e1..fcb157a 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState } from 'react'; import { SubmitHandler, useForm } from 'react-hook-form'; import { Box, Button, Stack } from '@mui/material'; import { useTranslation } from 'next-i18next'; @@ -18,7 +18,7 @@ type CreateQuizContainerType = { type Topic = { id: number; title: string; -} +}; export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { const { handleSubmit, control } = useForm(); @@ -42,14 +42,16 @@ export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { nameTitle={t('Test title')} nameControl='title' control={control} - placeholder='Add title for test...'/> + placeholder='Add title for test...' + /> + placeholder='Add description for test...' + /> { spacing={3} > - + { nameControl='comment' nameTitle={t('Comment')} control={control} - placeholder='Add comment for test...'/> + placeholder='Add comment for test...' + /> diff --git a/src/types/SelectorType.ts b/src/types/SelectorType.ts index 65b7532..ea304c1 100644 --- a/src/types/SelectorType.ts +++ b/src/types/SelectorType.ts @@ -2,7 +2,7 @@ export type SelectorDifficultyType = { onPressDifficulty?: (selectedOptionValue: T | unknown) => void; valueDifficulty?: string | number; type: TypeSwitchSelect; - name: string + name: string; }; export type SelectorNOQType = { @@ -15,7 +15,7 @@ export type SelectorTypeOfQuestionType = { onPressType?: (selectedOptionValue: T | unknown) => void; valueType?: string | number; type: TypeSwitchSelect; - name : string + name: string; }; export enum TypeSwitchSelect { From 31da8ca86086705488581f21e84281b914f77131 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Sat, 25 Mar 2023 23:25:52 +0300 Subject: [PATCH 06/12] topic createAsyncThunk --- src/api/quizesApi.ts | 1 + src/api/topicApi.ts | 12 ++++ .../common/Tabs/QuestionTabs/QuestionTabs.tsx | 2 +- .../CreateTopic/CreateTopic.tsx | 64 +++++++++++++------ .../create-test/create-question/index.tsx | 7 +- .../create-quiz/CreateQuizContainer.tsx | 4 +- src/store/reducers/topic-reducer.ts | 26 ++++++++ 7 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 src/api/topicApi.ts diff --git a/src/api/quizesApi.ts b/src/api/quizesApi.ts index cd4b55a..7297b1c 100644 --- a/src/api/quizesApi.ts +++ b/src/api/quizesApi.ts @@ -1,4 +1,5 @@ import { FieldValues } from 'react-hook-form'; +import axios from 'axios'; import { instance } from './Instance/instance'; import { CardType } from '../types/CardTypes'; import { CreateQuizType, TopicType } from '../types/CreateQuizType'; diff --git a/src/api/topicApi.ts b/src/api/topicApi.ts new file mode 100644 index 0000000..32e06bb --- /dev/null +++ b/src/api/topicApi.ts @@ -0,0 +1,12 @@ +import { instance } from "./Instance/instance"; +import { TopicType } from "../types/CreateQuizType"; + + +export const topicApi = { + postTopic(title: string) { + return instance.post(`/topic`, { title }); + }, + getTopic() { + return instance.get(`/topic`); + }, +}; \ No newline at end of file diff --git a/src/components/common/Tabs/QuestionTabs/QuestionTabs.tsx b/src/components/common/Tabs/QuestionTabs/QuestionTabs.tsx index 89f5b22..ba8bd3e 100644 --- a/src/components/common/Tabs/QuestionTabs/QuestionTabs.tsx +++ b/src/components/common/Tabs/QuestionTabs/QuestionTabs.tsx @@ -57,7 +57,7 @@ export const QuestionTabs = ({ ); return ( - + {amountOfQuestionsTabs.map((id) => ( = ({ const { t } = useTranslation('Topic'); const [topics, setTopics] = useState([]); const [newTopicName, setNewTopicName] = useState(''); + const [isLoading, setIsLoading] = useState(false); - useEffect(() => { - fetch('http://localhost:5000/api/topic') - .then((response) => response.json()) - .then((data) => setTopics(data)); - }, []); + // useEffect(() => { + // getTopics(); + // }, []); + + console.log(topics); const addNewTopicHandler = () => { dispatch(createTopic(newTopicName)); @@ -50,25 +58,27 @@ const CreatableAutocomplete: React.FC = ({ setNewTopicName(event.target.value); } }; - - const handleCreate = (newValue: string) => { - console.log(newValue); - // make a POST request to create new topic on the server - const newTopic = { id: topics.length + 1, title: newValue }; - // update topics with new topic - topics.push(newTopic); - onChange(newTopic); + const getTopicTitles = () => { + const allTopicsTitle = []; + for (const topic of topics) { + const topicTitles = topic.title; + allTopicsTitle.push(topicTitles); + } + return allTopicsTitle; }; + console.log(getTopicTitles()); const cher = topics.filter( (e) => (e.title && e.title !== '') === newTopicName ); console.log(cher, 'cher'); return ( - + {t('Test topic')} { + setIsLoading(true) const filtered = options.filter((option) => option.title.toLowerCase().includes(params.inputValue.toLowerCase()) ); @@ -78,7 +88,11 @@ const CreatableAutocomplete: React.FC = ({ // title: params.inputValue, // }); // } + setTimeout(() => { + setIsLoading(false); + }, 500); return filtered; + }} selectOnFocus handleHomeEndKeys @@ -86,17 +100,31 @@ const CreatableAutocomplete: React.FC = ({ getOptionLabel={(option) => option.title} renderOption={(props, option) =>
  • {option.title}
  • } renderInput={(params) => ( - + + {isLoading ? ( + + ) : null} + {params.InputProps.endAdornment} + + ), + }} /> - {cher && ( - )} diff --git a/src/pages/create-test/create-question/index.tsx b/src/pages/create-test/create-question/index.tsx index 9e4145a..86db180 100644 --- a/src/pages/create-test/create-question/index.tsx +++ b/src/pages/create-test/create-question/index.tsx @@ -54,8 +54,8 @@ const CreateQuestion = () => { defaultValues: { title: currentQuestion.title, description: currentQuestion.description, - difficulty: currentQuestion.difficulty, - type: currentQuestion.type, + difficulty: currentQuestion.difficulty[0], + type: currentQuestion.type[0], content: { options: [], correctAnswer: [], @@ -148,11 +148,12 @@ const CreateQuestion = () => { nameTitle={t('Question :')} nameControl='title' control={control} - /> + placeholder='Add question title...'/>
    diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index fcb157a..0a3ec9c 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -59,10 +59,10 @@ export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { flexWrap='wrap' spacing={3} > - + - + { + try { + const response = await topicApi.getTopic(); + return response.data; + } catch (e) { + const err = e as AxiosError; + return rejectWithValue(err.message); + } + } +); + +// const getOptions = async () => { +// setIsLoading(true); +// try { +// const response = await fetch('http://localhost:5000/api/topic'); +// const getTopics = await response.json(); +// setTopics(getTopics); +// } catch (error) { +// console.error(error); +// } +// setIsLoading(false); +// }; + export const slice = createSlice({ name: 'topic', initialState: { From 4568ed80ad66847455d242f274c4954670e04109 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Sun, 26 Mar 2023 12:42:39 +0300 Subject: [PATCH 07/12] fix limit create answer --- .../CreateAnswer/CreateAnswer.tsx | 146 ++++++++++-------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx b/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx index 84626c8..2b076bf 100644 --- a/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx +++ b/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx @@ -33,80 +33,92 @@ const CreateAnswer = ({ control, name, }); - const handleAppendNewAnswer = () => append({ name: '', checked: false }); + const handleAppendNewAnswer = () => { + if (fields.length < 4) { + append({ name: '', checked: false }); + } + }; return ( {t('Answer choice :')} - {fields.map((field, index) => ( - - - {t(`${index + 1}.`)} - - ( - - + {fields.map((field, index) => { + if (index < 4) { + return ( + + + {t(`${index + 1}.`)} - )} - /> - ( - - ( + + - } - label='' - /> + + )} + /> + ( + + + } + label='' + /> + + )} + /> + + - )} - /> - - - - - ))} + + ); + } + return null; + })} - + {fields.length < 4 ? ( + + + + ) : + Maximum 4 answers ! + } ); }; From 205db918f33259015471f0380bd044973aec5644 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Sun, 26 Mar 2023 13:01:09 +0300 Subject: [PATCH 09/12] add default values for numberOfQuestions --- src/pages/create-test/create-quiz/CreateQuizContainer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index 0a3ec9c..5c4f35a 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -21,7 +21,7 @@ type Topic = { }; export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { - const { handleSubmit, control } = useForm(); + const { handleSubmit, control } = useForm({defaultValues: {numberOfQuestions: 5}}); const { t } = useTranslation('create-quiz'); return ( From 65e54077deab107236959fc691e9f103fad2fda4 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Sun, 26 Mar 2023 16:46:23 +0300 Subject: [PATCH 10/12] add topic validation and rewrite to thunk --- .../CreateTopic/CreateTopic.tsx | 107 ++++++++++-------- .../create-quiz/CreateQuizContainer.tsx | 4 +- src/store/reducers/topic-reducer.ts | 20 +--- src/store/selectors.ts | 4 +- 4 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx index 77866cd..d5cb8d6 100644 --- a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx +++ b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx @@ -1,19 +1,16 @@ import React, { ChangeEvent, SyntheticEvent, useEffect, useState } from 'react'; import Autocomplete from '@mui/material/Autocomplete'; import TextField from '@mui/material/TextField'; -import { useController } from 'react-hook-form'; -import { - Box, - Button, - Stack, - Typography, -} from '@mui/material'; +import { Controller, useController } from 'react-hook-form'; +import { Box, Button, Stack, Typography } from '@mui/material'; import { useTranslation } from 'next-i18next'; -import { useDispatch } from 'react-redux'; -import CircularProgress from "@mui/material/CircularProgress"; -import { useAppDispatch } from '../../../../store/store'; -import { createTopic } from '../../../../store/reducers/topic-reducer'; -import { PlusIcon } from "../../../../assets/icons/PlusIcon"; +import CircularProgress from '@mui/material/CircularProgress'; +import { useAppDispatch, useAppSelector } from '../../../../store/store'; +import { + createTopic, + getAllTopics, +} from '../../../../store/reducers/topic-reducer'; +import { PlusIcon } from '../../../../assets/icons/PlusIcon'; type Topic = { id: number; @@ -25,7 +22,7 @@ type AutocompleteProps = { control: any; }; -const CreatableAutocomplete: React.FC = ({ +const CreateTopicComponent: React.FC = ({ name, control, }) => { @@ -37,13 +34,14 @@ const CreatableAutocomplete: React.FC = ({ }); const dispatch = useAppDispatch(); const { t } = useTranslation('Topic'); - const [topics, setTopics] = useState([]); + const topics = useAppSelector((state) => state.topics.topicData); + // const [topics, setTopics] = useState([]); const [newTopicName, setNewTopicName] = useState(''); const [isLoading, setIsLoading] = useState(false); - // useEffect(() => { - // getTopics(); - // }, []); + useEffect(() => { + dispatch(getAllTopics()); + }, []); console.log(topics); @@ -72,13 +70,13 @@ const CreatableAutocomplete: React.FC = ({ ); console.log(cher, 'cher'); return ( - + {t('Test topic')} { - setIsLoading(true) + setIsLoading(true); const filtered = options.filter((option) => option.title.toLowerCase().includes(params.inputValue.toLowerCase()) ); @@ -92,7 +90,6 @@ const CreatableAutocomplete: React.FC = ({ setIsLoading(false); }, 500); return filtered; - }} selectOnFocus handleHomeEndKeys @@ -100,34 +97,48 @@ const CreatableAutocomplete: React.FC = ({ getOptionLabel={(option) => option.title} renderOption={(props, option) =>
  • {option.title}
  • } renderInput={(params) => ( - - - {isLoading ? ( - - ) : null} - {params.InputProps.endAdornment} - - ), - }} - /> - {!getTopicTitles().includes(newTopicName) && ( - + ( + + + {isLoading ? ( + + ) : null} + {params.InputProps.endAdornment} + + ), + }} + /> + {!getTopicTitles().includes(newTopicName) && ( + + )} + )} - + /> )} freeSolo multiple={false} @@ -138,4 +149,4 @@ const CreatableAutocomplete: React.FC = ({ ); }; -export default CreatableAutocomplete; +export default CreateTopicComponent; diff --git a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx index 5c4f35a..9673ce4 100644 --- a/src/pages/create-test/create-quiz/CreateQuizContainer.tsx +++ b/src/pages/create-test/create-quiz/CreateQuizContainer.tsx @@ -9,7 +9,7 @@ import { TypeSwitchSelect } from '../../../types/SelectorType'; import { Layout } from '../../../components/layout/Layout'; import { CreateQuizType } from '../../../types/CreateQuizType'; import { SelectorFieldNOQ } from '../FieldsComponents/SelectorField/SelectorFieldNumOfQuestion/SelectorFieldNOQ'; -import AutocompleteComponent from '../FieldsComponents/CreateTopic/CreateTopic'; +import CreateTopicComponent from "../FieldsComponents/CreateTopic/CreateTopic"; type CreateQuizContainerType = { onSubmit: SubmitHandler; @@ -60,7 +60,7 @@ export const CreateQuizContainer = ({ onSubmit }: CreateQuizContainerType) => { spacing={3} > - + { try { @@ -31,18 +31,6 @@ export const getTopics = createAsyncThunk( } ); -// const getOptions = async () => { -// setIsLoading(true); -// try { -// const response = await fetch('http://localhost:5000/api/topic'); -// const getTopics = await response.json(); -// setTopics(getTopics); -// } catch (error) { -// console.error(error); -// } -// setIsLoading(false); -// }; - export const slice = createSlice({ name: 'topic', initialState: { @@ -57,11 +45,15 @@ export const slice = createSlice({ extraReducers: { [HYDRATE]: (state, action) => ({ ...state, - ...action.payload.topic, + ...action.payload.topicData, + }), [createTopic.fulfilled.type]: (state, action) => { state.topic = action.payload; }, + [getAllTopics.fulfilled.type]: (state, action) => { + state.topicData = action.payload; + } }, }); diff --git a/src/store/selectors.ts b/src/store/selectors.ts index 9f147bb..5cc5175 100644 --- a/src/store/selectors.ts +++ b/src/store/selectors.ts @@ -1,5 +1,5 @@ -import { AppState } from './store'; +import { AppState } from "./store"; export const selectOneQuizes = (state: AppState) => state.quizes.oneQuizes; export const selectResulData = (state: AppState) => state.resultData.result; -export const selectTopic = (state: AppState) => state.topics.topic; +export const selectTopic = (state: AppState) => state.topics.topic; \ No newline at end of file From 0411c8ac7f7b48cbbe3f9c2c9cfcdce3ecd68c72 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Mon, 27 Mar 2023 15:06:55 +0300 Subject: [PATCH 11/12] topic validation --- .../FieldsComponents/CreateTopic/CreateTopic.tsx | 6 +----- src/pages/create-test/create-question/index.tsx | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx index d5cb8d6..8753a19 100644 --- a/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx +++ b/src/pages/create-test/FieldsComponents/CreateTopic/CreateTopic.tsx @@ -99,15 +99,11 @@ const CreateTopicComponent: React.FC = ({ renderInput={(params) => ( ( + render={() => ( { - + From 8ec18884dd67ff7b72d79f96bfc99a575cd41ab4 Mon Sep 17 00:00:00 2001 From: nikitakukharchuk Date: Mon, 27 Mar 2023 17:30:39 +0300 Subject: [PATCH 12/12] multi single --- .../CreateAnswer/CreateAnswer.tsx | 38 ++++++++++++++++--- .../SelectorFieldType/SelectorFieldType.tsx | 2 +- .../create-test/create-question/index.tsx | 13 ++++++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx b/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx index 286893a..4acbba7 100644 --- a/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx +++ b/src/pages/create-test/FieldsComponents/CreateAnswer/CreateAnswer.tsx @@ -15,29 +15,52 @@ import { TextField, Typography, } from '@mui/material'; -import React from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'next-i18next'; import { BasketIcon } from '../../../../assets/icons/BasketIcon'; type CreateAnswerPropsType = { control: any; - name: any; + name: string; + // typeOfQuestion: string; // for single multi }; const CreateAnswer = ({ control, name, + // typeOfQuestion // for single multi }: CreateAnswerPropsType) => { const { t } = useTranslation('createAnswer'); + // const [correctAnswers, setCorrectAnswers] = useState([]); // for single multi const { fields, append, remove } = useFieldArray({ control, name, }); + const handleAppendNewAnswer = () => { if (fields.length < 4) { append({ name: '', checked: false }); } }; + // const handleCheckboxChange = (index: number) => { // for single multi + // const questionAnswer = fields[index].id; + // if (correctAnswers.includes(questionAnswer)) { + // setCorrectAnswers((prevAnswers) => + // prevAnswers.filter((answer) => answer !== questionAnswer) + // ); + // } else { + // setCorrectAnswers((prevAnswers) => [...prevAnswers, questionAnswer]); + // } + // }; + // const checkCorrect = () => { + // if (typeOfQuestion === 'single' && correctAnswers.length === 1) { // for single multi + // return true + // } + // if (typeOfQuestion === 'multi' && correctAnswers.length === 2) { + // return true + // } + // return false; + // }; return ( {t('Answer choice :')} @@ -96,6 +119,9 @@ const CreateAnswer = ({ handleCheckboxChange(index)} checked={value} onChange={onChange} /> @@ -129,9 +155,11 @@ const CreateAnswer = ({ {t('Add Answer')}
    - ) : - Maximum 4 answers ! - } + ) : ( + + Maximum 4 answers ! + + )} ); }; diff --git a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx index 66fe51a..71818bc 100644 --- a/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx +++ b/src/pages/create-test/FieldsComponents/SelectorField/SelectorFieldType/SelectorFieldType.tsx @@ -31,7 +31,7 @@ export const SelectorFieldType = ({ control={control} name={name} rules={rules} - render={({ field: { onChange, value } }) => ( + render={({ field: { value, onChange } }) => ( { }); const [questions, setQuestions] = useState([{ ...getNewQuestion() }]); + // const [selectedTypeOfQuestion, setTypeOfQuestion] = useState(''); // for single && multi + // const onChangeSelectType = (e: any) => { + // setTypeOfQuestion(e.currentTarget.value); + // }; const currentQuestion = useMemo( () => questions[currentQuestionIndex] || { @@ -148,7 +152,8 @@ const CreateQuestion = () => { nameTitle={t('Question :')} nameControl='title' control={control} - placeholder='Add question title...'/> + placeholder='Add question title...' + /> {
    - +