Repository: Space2Study-UA-1355-02/Client-02
Pull request #31: Feature/76 subjects step UI
Author: login: Sergij95
Created: 2025-04-25T12:06:46Z | Merged: 2025-05-02T11:56:13Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Introduced a dynamic subject selection interface for tutors, allowing users to select, add, and remove subjects with an expandable list and category filtering.
- **Bug Fixes**
	- Improved translation files by adding missing keys and correcting formatting issues.
- **Style**
	- Cleaned up formatting and removed redundant code in several components for improved readability.
- **Refactor**
	- Simplified event handlers and refactored conditional logic for better code clarity without changing functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/src/components/info-general-step/InfoGeneralStep.tsx b/src/components/info-general-step/InfoGeneralStep.tsx
index bdd692bd..92636b60 100644
--- a/src/components/info-general-step/InfoGeneralStep.tsx
+++ b/src/components/info-general-step/InfoGeneralStep.tsx
@@ -27,8 +27,9 @@ const UserStepsModal = ({ role = 'tutor' }) => {
   const [open, setOpen] = useState(true)
   const [openConfirm, setOpenConfirm] = useState(false)
   const [isUserFetched, setIsUserFetched] = useState(false)
-  const imageArr = [generalImg, interestImg, languageImg] // Add the images for each step here
+  const imageArr = [generalImg, interestImg, languageImg]
   const [activeStep, setActiveStep] = useState(0)
+
   const childrenArr = [
     <GeneralInfoStep
       isUserFetched={isUserFetched}
@@ -39,6 +40,7 @@ const UserStepsModal = ({ role = 'tutor' }) => {
     <LanguageStep key='3' />,
     <AddPhotoStep key='4' />
   ]
+
   const childrenArrStud = [
     <GeneralInfoStep
       isUserFetched={isUserFetched}
@@ -49,6 +51,7 @@ const UserStepsModal = ({ role = 'tutor' }) => {
     <LanguageStep key='3' />,
     <AddPhotoStep key='4' />
   ]
+
   let tempChildrenArr = []
   let tempStepLabels = []
   if (role === 'tutor') {
@@ -58,6 +61,7 @@ const UserStepsModal = ({ role = 'tutor' }) => {
     tempChildrenArr = childrenArrStud
     tempStepLabels = studentStepLabels
   }
+
   const handleClose = () => {
     setOpenConfirm(true)
   }
@@ -79,8 +83,6 @@ const UserStepsModal = ({ role = 'tutor' }) => {
             />
           )}
 
-          {/* Right: Stepper form */}
-
           <StepProvider
             initialValues={initialValues}
             stepLabels={tempStepLabels}
diff --git a/src/constants/translations/en/become-tutor.json b/src/constants/translations/en/become-tutor.json
index 16e134b5..4cb6c33e 100644
--- a/src/constants/translations/en/become-tutor.json
+++ b/src/constants/translations/en/become-tutor.json
@@ -22,7 +22,8 @@
     "subjectLabel": "Subject",
     "btnText": "Add one more subject",
     "emptyFields": "All fields must be filled",
-    "sameSubject": "You have the same subject"
+    "sameSubject": "You have the same subject",
+    "collapse": "Collapse" 
   },
   "photo": {
     "imageAlt": "Your photo",
diff --git a/src/constants/translations/ua/become-tutor.json b/src/constants/translations/ua/become-tutor.json
index 0a656748..a97256ed 100644
--- a/src/constants/translations/ua/become-tutor.json
+++ b/src/constants/translations/ua/become-tutor.json
@@ -1,7 +1,7 @@
 {
   "stepLabels": {
-    "generalInfo": "Загальне", 
-    "language": "Мова", 
+    "generalInfo": "Загальне",
+    "language": "Мова",
     "subjects": "Предмети",
     "photo": "Фото"
   },
@@ -27,15 +27,16 @@
     "subjectLabel": "Предмет",
     "btnText": "Додайте ще один предмет",
     "emptyFields": "Усі поля мають бути заповнені",
-    "sameSubject": "Ви вже маєте такий предмет"
+    "sameSubject": "Ви вже маєте такий предмет",
+    "collapse": "Згорнути"
   },
   "photo": {
-	"imageAlt": "Ваша фотографія",
-	"button": "Завантажте свою фотографію профілю",
-	"placeholder":"Попередній перегляд фотографій",
-	"description":"Будь ласка, завантажте фотографію, яка відображає вас і допомагає іншим вас впізнати.",
-	"typeError": "Неправильний тип файлу. Дозволяються лише файли .png/.jpg/.jpeg.",
-	"fileSizeError": "Розмір одного файлу не може перевищувати 10 Мб."
+    "imageAlt": "Ваша фотографія",
+    "button": "Завантажте свою фотографію профілю",
+    "placeholder": "Попередній перегляд фотографій",
+    "description": "Будь ласка, завантажте фотографію, яка відображає вас і допомагає іншим вас впізнати.",
+    "typeError": "Неправильний тип файлу. Дозволяються лише файли .png/.jpg/.jpeg.",
+    "fileSizeError": "Розмір одного файлу не може перевищувати 10 Мб."
   },
   "successMessage": "Успішно! Ваші дані додано."
 }
diff --git a/src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx b/src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
index 25327d66..4091c4a8 100644
--- a/src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
+++ b/src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
@@ -44,6 +44,7 @@ const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
     setErrors(newErrors)
     onErrorChange(Object.values(newErrors).includes(true))
   }
+
   const handleDescriptionChange = (e) => {
     const { value } = e.target
     if (value.length <= 100) {
@@ -60,12 +61,10 @@ const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
         <TextField
           error={errors.firstName}
           fullWidth
-          helperText={
-            errors.firstName && t('becomeTutor.generalInfo.firstNameLabelReq')
-          }
+          helperText={errors.firstName && t('becomeTutor.generalInfo.firstNameLabelReq')}
           label={t('common.labels.firstName')}
           name='firstName'
-          onBlur={() => validateForm()}
+          onBlur={validateForm}
           onChange={handleChange}
           required
           value={form.firstName}
@@ -73,12 +72,10 @@ const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
         <TextField
           error={errors.lastName}
           fullWidth
-          helperText={
-            errors.lastName && t('becomeTutor.generalInfo.lastNameLabelReq')
-          }
+          helperText={errors.lastName && t('becomeTutor.generalInfo.lastNameLabelReq')}
           label={t('common.labels.lastName')}
           name='lastName'
-          onBlur={() => validateForm()}
+          onBlur={validateForm}
           onChange={handleChange}
           required
           value={form.lastName}
@@ -126,7 +123,6 @@ const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
         rows={3}
         value={form.description}
       />
-
       <FormControlLabel
         control={
           <Checkbox
@@ -137,7 +133,6 @@ const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
         }
         label={t('becomeTutor.generalInfo.ageComfir')}
       />
-
       <Typography sx={styles.assign} variant='caption'>
         {t('becomeTutor.generalInfo.helperText')}
       </Typography>
diff --git a/src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx b/src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
index 5106feb4..d02bf1f7 100644
--- a/src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
+++ b/src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
@@ -6,6 +6,9 @@ import Chip from '@mui/material/Chip'
 import Stack from '@mui/material/Stack'
 import TextField from '@mui/material/TextField'
 import Typography from '@mui/material/Typography'
+import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'
+import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
+import Button from '@mui/material/Button'
 
 import AppButton from '~/components/app-button/AppButton'
 import { ButtonVariantEnum } from '~/types'
@@ -13,30 +16,40 @@ import { ButtonVariantEnum } from '~/types'
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
 import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
 
-const SubjectsStep = ({ btnsBox }) => {
+const SubjectsStep = ({ btnsBox, onSubjectsChange }) => {
   const { t } = useTranslation()
+
   const [mainCategory, setMainCategory] = useState(null)
   const [selectedSubject, setSelectedSubject] = useState(null)
   const [subjects, setSubjects] = useState([])
+  const [showAllSubjects, setShowAllSubjects] = useState(false)
 
-  const addSubject = () => {
-    if (!selectedSubject) {
-      alert(t('becomeTutor.categories.emptyFields'))
-      return
-    }
+  const isAddDisabled =
+    !selectedSubject || subjects.some((s) => s.name === selectedSubject.name)
 
-    const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
-    if (isDuplicate) {
-      alert(t('becomeTutor.categories.sameSubject'))
-      return
+  const updateSubjects = (newSubjects) => {
+    setSubjects(newSubjects)
+    if (typeof onSubjectsChange === 'function') {
+      onSubjectsChange(newSubjects)
     }
+  }
 
-    setSubjects([...subjects, { name: selectedSubject.name }])
+  const addSubject = () => {
+    if (isAddDisabled || !selectedSubject) return
+    const updated = [...subjects, { name: selectedSubject.name }]
+    updateSubjects(updated)
     setSelectedSubject(null)
   }
 
-  const displayedSubjects = subjects.slice(0, 2)
-  const hiddenCount = subjects.length - displayedSubjects.length
+  const removeSubject = (name) => {
+    const updated = subjects.filter((s) => s.name !== name)
+    updateSubjects(updated)
+  }
+
+  const toggleShowAll = () => setShowAllSubjects((prev) => !prev)
+
+  const displayedSubjects = showAllSubjects ? subjects : subjects.slice(0, 2)
+  const hiddenCount = subjects.length - 2
 
   return (
     <Box sx={styles.container}>
@@ -76,21 +89,46 @@ const SubjectsStep = ({ btnsBox }) => {
             value={selectedSubject}
           />
 
-          <AppButton onClick={addSubject} variant={ButtonVariantEnum.Outlined}>
+          <AppButton
+            disabled={isAddDisabled}
+            onClick={addSubject}
+            variant={ButtonVariantEnum.Outlined}
+          >
             {t('becomeTutor.categories.btnText')}
           </AppButton>
 
           <Stack direction='row' flexWrap='wrap' spacing={1}>
             {displayedSubjects.map((subject, index) => (
               <Chip
-                key={index}
+                key={`${subject.name}-${index}`}
                 label={subject.name}
-                onDelete={() =>
-                  setSubjects(subjects.filter((s) => s.name !== subject.name))
-                }
+                onDelete={() => removeSubject(subject.name)}
               />
             ))}
-            {hiddenCount > 0 && <Chip label={`+${hiddenCount}`} />}
+
+            {hiddenCount > 0 && !showAllSubjects && (
+              <Chip
+                clickable
+                icon={<ArrowDropDownIcon />}
+                label={`+${hiddenCount}`}
+                onClick={toggleShowAll}
+              />
+            )}
+
+            {showAllSubjects && (
+              <Button
+                onClick={toggleShowAll}
+                startIcon={<ArrowDropUpIcon />}
+                sx={{
+                  fontSize: '14px',
+                  padding: '6px 16px',
+                  textTransform: 'none'
+                }}
+                variant='outlined'
+              >
+                {t('becomeTutor.categories.collapse')}
+              </Button>
+            )}
           </Stack>
 
           {btnsBox}
diff --git a/src/pages/guest-home-page/GuestHome.tsx b/src/pages/guest-home-page/GuestHome.tsx
index 7465f8f4..7c1bf883 100644
--- a/src/pages/guest-home-page/GuestHome.tsx
+++ b/src/pages/guest-home-page/GuestHome.tsx
@@ -24,7 +24,8 @@ const GuestHomePage = () => {
   useEffect(() => {
     const confirmToken = searchParams.get('confirmToken')
     const resetToken = searchParams.get('resetToken')
-    confirmToken &&
+
+    if (confirmToken) {
       openModal({
         component: (
           <EmailConfirmModal
@@ -33,14 +34,19 @@ const GuestHomePage = () => {
           />
         )
       })
-    resetToken &&
+    }
+
+    if (resetToken) {
       openModal({
         component: (
           <ResetPassword openModal={openModal} resetToken={resetToken} />
         )
       })
-    searchParams.get('login') !== null &&
+    }
+
+    if (searchParams.get('login') !== null) {
       openModal({ component: <LoginDialog /> })
+    }
 
     setSearchParams([])
   }, [searchParams, setSearchParams, openModal])
@@ -58,4 +64,5 @@ const GuestHomePage = () => {
     </Box>
   )
 }
+
 export default GuestHomePage


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 6**

<details>
<summary>🧹 Nitpick comments (10)</summary><blockquote>

<details>
<summary>src/components/step-wrapper/StepWrapper.styles.js (1)</summary><blockquote>

`47-49`: **Consider content overflow handling**

The maxHeight constraint on stepContent might cause content clipping issues if the content exceeds 100px.

Consider adding overflow handling (like `overflow-y: auto`) or using a more flexible approach to height constraints to ensure all content remains accessible.

</blockquote></details>
<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (1)</summary><blockquote>

`14-14`: **Consider providing a default value for onStepChange prop**

The onStepChange prop is currently optional but doesn't have a default value in the function parameters.

Consider providing a default value for better robustness:
```diff
-const StepWrapper = ({ children, steps, onStepChange }) => {
+const StepWrapper = ({ children, steps, onStepChange = () => {} }) => {
```

</blockquote></details>
<details>
<summary>src/components/info-general-step/InfoGeneralStep.styles.ts (2)</summary><blockquote>

`1-38`: **Styles look clean, but consider more semantic naming and consistent pattern**

The styles are well-structured and implement responsive design patterns, but there's a naming inconsistency - the file is named `InfoGeneralStep.styles.ts` but actually contains styles for what appears to be the `UserStepsModal` component. Consider renaming for better alignment with the component it styles.

Additionally, consider using theme breakpoints directly for consistency with your other styling across the application.

```diff
- width: '70vw',
- height: '80vh',
+ width: { xs: '95vw', sm: '85vw', md: '70vw' },
+ height: { xs: '95vh', sm: '90vh', md: '80vh' },
```

---

`26-32`: **Review the image display settings for better responsiveness**

The `padding: 'auto'` property doesn't have an effect and should be removed. Also, `objectFit` should be applied to the `<img>` element directly in the component properties rather than in the container style.

```diff
  imageBox: {
    flex: 1,
    width: '30vw',
    height: 'auto',
-   padding: 'auto',
-   objectFit: 'scale-down',
    display: { xs: 'none', md: 'block' }
  },
```

</blockquote></details>
<details>
<summary>src/components/info-general-step/InfoGeneralStep.tsx (4)</summary><blockquote>

`1-20`: **Align component name with filename for better maintainability**

The filename `InfoGeneralStep.tsx` doesn't match the component name `UserStepsModal`, which creates confusion. Consider renaming either the file to match the component or vice versa to maintain a consistent pattern across your codebase.

```diff
- // File: InfoGeneralStep.tsx
+ // File: UserStepsModal.tsx
```

---

`22-37`: **Add initialization and cleanup effects**

The modal is set to be always open without an external trigger. Consider adding a prop to control the visibility or initializing data fetching effects. Also, implement a cleanup effect to avoid memory leaks when unmounting.

```diff
- const UserStepsModal = () => {
+ const UserStepsModal = ({ initialOpen = true }) => {
-  const [open, setOpen] = useState(true)
+  const [open, setOpen] = useState(initialOpen)
  const [openConfirm, setOpenConfirm] = useState(false)
  const [isUserFetched, setIsUserFetched] = useState(false)
  const imageArr = [generalImg, interestImg, languageImg] // Add the images for each step here
  const [activeStep, setActiveStep] = useState(0)
+ 
+ useEffect(() => {
+   // Initialize any data or effects
+   return () => {
+     // Cleanup when unmounting
+   }
+ }, [])
```

---

`51-56`: **Improve image accessibility and loading**

The `alt` attribute is specified in the Box props but isn't being used because the component is rendered as an img. Additionally, consider adding loading optimization for images.

```diff
  <Box
-   alt='Stepper illustration'
    component='img'
+   alt={`Step ${activeStep + 1} illustration`}
    src={imageArr[activeStep]}
+   loading="lazy"
    sx={styles.imageBox}
  />
```

---

`71-81`: **Improve confirmation dialog UX**

The confirmation dialog has minimal messaging. Consider enhancing it with more descriptive information about the consequences of exiting, especially if there's unsaved data.

```diff
  <ConfirmDialog
-   message='Are you sure you want exit?'
+   message='Are you sure you want to exit? Any unsaved information will be lost.'
    onConfirm={() => {
      setOpenConfirm(false)
      setOpen(false)
    }}
    onDismiss={() => {
      setOpenConfirm(false)
    }}
    open={openConfirm}
-   title='Confirmation'
+   title='Exit Confirmation'
  />
```

</blockquote></details>
<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx (1)</summary><blockquote>

`36-44`: **Validate form on component mount and optimize validation**

The form validation is only triggered on blur events. For a better user experience, consider validating the form on component mount and after dependency changes.

```diff
+ // Add a useEffect to validate the form when dependencies change
+ useEffect(() => {
+   validateForm()
+ }, [form.firstName, form.lastName, form.description])

  const validateForm = () => {
    const newErrors = {
      firstName: form.firstName === '',
      lastName: form.lastName === '',
      description: form.description.length > 100
    }
    setErrors(newErrors)
    onErrorChange(Object.values(newErrors).includes(true))
  }
```

</blockquote></details>
<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (1)</summary><blockquote>

`80-91`: **Improve selected subjects display**

Currently, the component only shows the first two selected subjects with a count chip for the rest. Consider adding a toggle to show all subjects or using a more interactive way to browse all selections.

```diff
+ const [showAllSubjects, setShowAllSubjects] = useState(false)
+ const displayedSubjects = showAllSubjects ? subjects : subjects.slice(0, 2)
- const displayedSubjects = subjects.slice(0, 2)
  const hiddenCount = subjects.length - displayedSubjects.length

  <Stack direction='row' flexWrap='wrap' spacing={1}>
    {displayedSubjects.map((subject, index) => (
      <Chip
        key={index}
        label={subject.name}
        onDelete={() =>
          setSubjects(subjects.filter((s) => s.name !== subject.name))
        }
      />
    ))}
-   {hiddenCount > 0 && <Chip label={`+${hiddenCount}`} />}
+   {hiddenCount > 0 && (
+     <Chip 
+       label={`+${hiddenCount}`} 
+       onClick={() => setShowAllSubjects(!showAllSubjects)}
+       clickable
+     />
+   )}
  </Stack>
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 73b54f473f9cc92b6c13fa2bb746feaf767df5c4 and 2b9217782722d725f24ccab8180f9e0128bdb56f.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `src/components/info-general-step/InfoGeneralStep.styles.ts` (1 hunks)
* `src/components/info-general-step/InfoGeneralStep.tsx` (1 hunks)
* `src/components/step-wrapper/StepWrapper.jsx` (6 hunks)
* `src/components/step-wrapper/StepWrapper.styles.js` (2 hunks)
* `src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx` (1 hunks)
* `src/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles.js` (1 hunks)
* `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx` (1 hunks)
* `src/pages/guest-home-page/GuestHome.tsx` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx (2)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles.js (2)</summary>

* `styles` (3-22)
* `styles` (3-22)

</details>
<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (1)</summary>

* `btnsBox` (66-80)

</details>

</blockquote></details>
<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (1)</summary><blockquote>

<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (1)</summary>

* `btnsBox` (66-80)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Run Tests

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles.js (1)</summary>

`11-21`: **Clean style additions for the form layout**

The new style definitions for `inputs` and `assign` use flexbox effectively to create organized layouts for form elements. These additions will improve the visual structure of the General Info step.

</details>
<details>
<summary>src/components/step-wrapper/StepWrapper.styles.js (3)</summary>

`5-9`: **Good button styling improvements**

The button style enhancements with flex properties and minimum dimensions ensure consistent button sizing while maintaining flexibility.

---

`54-56`: **Good constraint for button wrapper**

Setting a maxHeight for the button wrapper helps maintain consistent spacing in the UI.

---

`57-63`: **Clean button style organization**

Breaking out the button styles into separate btnLeft and btnRight objects improves code organization and makes it easier to maintain specific button styling.

</details>
<details>
<summary>src/pages/guest-home-page/GuestHome.tsx (2)</summary>

`18-19`: **LGTM: Clean component imports**

The imports for the new confirmation and onboarding step components are well-organized.

---

`56-58`: **LGTM: Component integration**

Good integration of the EmailConfirmationInfo and InfoGeneralStep components into the page structure.

</details>
<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (4)</summary>

`21-26`: **Good implementation of step change notification**

The step error state tracking and the useEffect hook for notifying parent components about step changes improve the component's reusability.

---

`28-28`: **Clean solution for button disabling logic**

The isNextDisabled variable cleanly combines both local and global error states to control the next button.

---

`43-64`: **Good button state management improvements**

The button state management improvements with proper disabled states enhance user experience by preventing progression when there are errors.

---

`87-90`: **Good child component communication**

Passing stepLabel and onErrorChange to child components enables better communication between the wrapper and its children, allowing for step-specific validation and error reporting.

</details>
<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (1)</summary>

`13-14`: <details>
<summary>❌ Incorrect review comment</summary>

**Verify data sources for categories**

You're importing both mock data and translation constants for categories. Ensure you're using the correct data source for your needs and consider consolidating these imports.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check structure of categoriesMock and translation categories
grep -A 10 "export const categoriesMock" src/containers/tutor-home-page/subjects-step/constants.js
echo "---"
grep -A 10 "categories" src/constants/translations/en/become-tutor.json
```

Length of output: 1088

---



</details>

**Remove unnecessary consolidation suggestion**

The `categoriesMock` array provides domain data (the list of subjects), while the imported `categories` object contains UI translation strings (titles, labels, error messages). They serve distinct purposes and should remain separate—no consolidation is needed. 

> Likely an incorrect or invalid review comment.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-25T12:10:57Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (4)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (4)</summary><blockquote>

`62-75`: **Filter subjects based on selected category**

The subjects dropdown should be filtered based on the selected main category, but currently shows all options from `categoriesMock`. This reduces usability and could lead to invalid subject selections.


```diff
<Autocomplete
  fullWidth
  getOptionLabel={(option) => option.name}
  onChange={(_, newValue) => setSelectedSubject(newValue)}
-  options={categoriesMock}
+  options={mainCategory ? categoriesMock.filter(item => 
+    item.parentCategoryId === mainCategory.id || 
+    item.category === mainCategory.name
+  ) : []}
+  disabled={!mainCategory}
  renderInput={(params) => (
    <TextField
      {...params}
      label={categories.subjectLabel}
      variant='outlined'
+     helperText={!mainCategory ? 'Please select a main category first' : ''}
    />
  )}
  value={selectedSubject}
/>
```

---

`47-60`: _🛠️ Refactor suggestion_

**Add error state to main category field**

The main category field should display error state and message when validation fails.


```diff
<Autocomplete
  fullWidth
  getOptionLabel={(option) => option.name}
  onChange={(_, newValue) => setMainCategory(newValue)}
  options={categoriesMock}
  renderInput={(params) => (
    <TextField
      {...params}
      label={categories.mainSubjectsLabel}
      variant='outlined'
+     error={errors.mainCategory}
+     helperText={errors.mainCategory ? 'Please select a main category' : ''}
    />
  )}
  value={mainCategory}
/>
```

---

`19-24`: _🛠️ Refactor suggestion_

**Add proper validation and error handling**

The component lacks proper form validation and error handling, which could lead to incorrect data submission.


```diff
const SubjectsStep = ({ btnsBox }) => {
  const [mainCategory, setMainCategory] = useState(null)
  const [selectedSubject, setSelectedSubject] = useState(null)
  const [subjects, setSubjects] = useState([])
  const [showAllSubjects, setShowAllSubjects] = useState(false)
+ const [errors, setErrors] = useState({
+   mainCategory: false,
+   selectedSubject: false,
+ })
```

---

`28-33`: _🛠️ Refactor suggestion_

**Enhance subject addition logic with validation**

The current implementation of `addSubject` lacks proper validation and error state management. It should validate inputs and provide feedback to users.


```diff
const addSubject = () => {
-  if (isAddDisabled) return
+  // Reset errors first
+  setErrors({ mainCategory: false, selectedSubject: false })
+  
+  // Validate inputs
+  if (!mainCategory) {
+    setErrors(prev => ({ ...prev, mainCategory: true }))
+    return
+  }
+  
+  if (!selectedSubject) {
+    setErrors(prev => ({ ...prev, selectedSubject: true }))
+    return
+  }
+  
+  // Check for duplicates
+  const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
+  if (isDuplicate) {
+    setErrors(prev => ({ ...prev, selectedSubject: true }))
+    return
+  }

  setSubjects([...subjects, { name: selectedSubject.name }])
  setSelectedSubject(null)
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (3)</summary><blockquote>

`106-118`: **Use AppButton component for consistency**

The component uses both MUI's Button and your custom AppButton component. Prefer using AppButton throughout for UI consistency.


```diff
-<Button
-  onClick={toggleShowAll}
-  startIcon={<ArrowDropUpIcon />}
-  sx={{
-    fontSize: '14px',
-    padding: '6px 16px',
-    textTransform: 'none'
-  }}
-  variant='outlined'
->
-  Collapse
-</Button>
+<AppButton
+  onClick={toggleShowAll}
+  startIcon={<ArrowDropUpIcon />}
+  variant={ButtonVariantEnum.Outlined}
+>
+  Collapse
+</AppButton>
```

---

`85-119`: **Add accessibility improvements to the subject chips section**

The subject chips section lacks proper accessibility attributes, which could make it difficult for screen reader users.


```diff
-<Stack direction='row' flexWrap='wrap' spacing={1}>
+<Stack 
+  direction='row' 
+  flexWrap='wrap' 
+  spacing={1}
+  aria-label="Selected subjects"
+  role="list"
+>
  {displayedSubjects.map((subject, index) => (
    <Chip
      key={index}
      label={subject.name}
+     role="listitem"
+     aria-label={`Remove ${subject.name}`}
      onDelete={() =>
        setSubjects(subjects.filter((s) => s.name !== subject.name))
      }
    />
  ))}

  {hiddenCount > 0 && !showAllSubjects && (
    <Chip
      clickable
      icon={<ArrowDropDownIcon />}
      label={`+${hiddenCount}`}
+     aria-label={`Show ${hiddenCount} more subjects`}
      onClick={toggleShowAll}
    />
  )}

  {showAllSubjects && (
    <Button
      onClick={toggleShowAll}
      startIcon={<ArrowDropUpIcon />}
+     aria-label="Hide additional subjects"
      sx={{
        fontSize: '14px',
        padding: '6px 16px',
        textTransform: 'none'
      }}
      variant='outlined'
    >
      Collapse
    </Button>
  )}
</Stack>
```

---

`25-26`: **Simplify isAddDisabled logic**

The current implementation of `isAddDisabled` will still be active after validation errors are corrected. Consider updating its logic.


```diff
-const isAddDisabled =
-  !selectedSubject || subjects.some((s) => s.name === selectedSubject.name)
+const isAddDisabled =
+  !mainCategory ||
+  !selectedSubject ||
+  subjects.some((s) => s.name === selectedSubject.name)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2b9217782722d725f24ccab8180f9e0128bdb56f and 31e008761189f4913b68c554470744ea0603821f.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (1)</summary><blockquote>

<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (1)</summary>

* `btnsBox` (66-80)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Run Tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-28T16:46:41Z
user: login: Kryzhanivsky
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T19:14:11Z
user: login: Don-de-padlo
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T05:47:23Z
user: login: Don-de-padlo
body: dont merge to develop
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T05:48:12Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (3)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (3)</summary><blockquote>

`53-81`: **Filter subjects based on selected category**

Currently, both dropdowns show the same options from `categoriesMock`. This makes it difficult for users to select relevant subjects.


```diff
  <Autocomplete
    fullWidth
    getOptionLabel={(option) => option.name}
    onChange={(_, newValue) => setMainCategory(newValue)}
    options={categoriesMock}
    renderInput={(params) => (
      <TextField
        {...params}
        label={categoriesTranslations.mainSubjectsLabel}
        variant='outlined'
+       error={!mainCategory && subjects.length === 0}
+       helperText={!mainCategory && subjects.length === 0 ? 'Please select a main category' : ''}
      />
    )}
    value={mainCategory}
  />

  <Autocomplete
    fullWidth
    getOptionLabel={(option) => option.name}
    onChange={(_, newValue) => setSelectedSubject(newValue)}
-   options={categoriesMock}
+   options={mainCategory ? categoriesMock.filter(item => 
+     item.categoryId === mainCategory.id || // Adjust based on your data structure
+     item.parentCategory === mainCategory.name
+   ) : []}
+   disabled={!mainCategory}
    renderInput={(params) => (
      <TextField
        {...params}
        label={categoriesTranslations.subjectLabel}
        variant='outlined'
+       error={!selectedSubject && subjects.length === 0}
+       helperText={!selectedSubject && subjects.length === 0 ? 'Please select a subject' : ''}
      />
    )}
    value={selectedSubject}
  />
```

---

`126-128`: **Add required subject validation before proceeding**

Currently, there's no validation to ensure at least one subject is added before proceeding to the next step.


```diff
  </Stack>

+ {subjects.length === 0 && (
+   <Typography color="error" variant="caption">
+     {categoriesTranslations.subjectsRequired || 'Please add at least one subject to continue'}
+   </Typography>
+ )}

  {btnsBox}
```

Make sure to add this message to your translation file as well, and consider integrating with the step-wrapper's validation API if available.

---

`31-36`: _🛠️ Refactor suggestion_

**Improve the addSubject function with error feedback**

The current implementation lacks proper error feedback when a subject can't be added.


```diff
  const addSubject = () => {
-   if (isAddDisabled) return
+   if (!selectedSubject) {
+     // Show error feedback
+     return
+   }
+   
+   if (subjects.some((s) => s.name === selectedSubject.name)) {
+     // Show duplicate subject error (could use a snackbar or inline message)
+     return
+   }

    setSubjects([...subjects, { name: selectedSubject.name }])
    setSelectedSubject(null)
  }
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (2)</summary><blockquote>

`91-100`: **Use unique identifier for Chip keys instead of array indices**

Using array indices as keys can cause rendering issues when the array changes (such as when removing items). Use a more stable, unique identifier instead.


```diff
  {displayedSubjects.map((subject, index) => (
    <Chip
-     key={index}
+     key={subject.name} // Assuming subject names are unique
      label={subject.name}
      onDelete={() =>
        setSubjects(subjects.filter((s) => s.name !== subject.name))
      }
    />
  ))}
```

---

`122-123`: **Use translation strings for UI text**

The "Collapse" text is hardcoded instead of using a translation key like other text in the component.


```diff
- Collapse
+ {categoriesTranslations.collapse || 'Collapse'}
```

Add the translation key to your translation file as well.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 31e008761189f4913b68c554470744ea0603821f and 7345b2a37b011b428abd298c999d9de1b27b6e22.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (1)</summary><blockquote>

<details>
<summary>src/components/step-wrapper/StepWrapper.jsx (1)</summary>

* `btnsBox` (66-80)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Run Tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-29T07:05:25Z
user: login: Kryzhanivsky
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T07:53:01Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>♻️ Duplicate comments (5)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (5)</summary><blockquote>

`77-90`: _🛠️ Refactor suggestion_

**Filter subjects based on selected category**

The subject dropdown should only show subjects related to the selected main category. This improves user experience by limiting choices to relevant options.

```diff
          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setSelectedSubject(newValue)}
-           options={categoriesMock}
+           options={mainCategory 
+             ? categoriesMock.filter(item => 
+                item.categoryId === mainCategory.id || 
+                item.parentId === mainCategory.id)
+             : []}
+           disabled={!mainCategory}
            renderInput={(params) => (
              <TextField
                {...params}
                label={t('become-tutor.categories.subjectLabel')}
                variant='outlined'
+               error={!mainCategory}
+               helperText={!mainCategory ? t('become-tutor.categories.selectMainFirst') : ''}
              />
            )}
            value={selectedSubject}
          />
```

---

`27-42`: _🛠️ Refactor suggestion_

**Improve validation and error handling**

The current implementation lacks proper form validation and error handling. Users should receive visual feedback about validation errors.

```diff
  const [mainCategory, setMainCategory] = useState(null)
  const [selectedSubject, setSelectedSubject] = useState(null)
  const [subjects, setSubjects] = useState([])
  const [showAllSubjects, setShowAllSubjects] = useState(false)
+  const [errors, setErrors] = useState({
+    mainCategory: false,
+    selectedSubject: false,
+    subjectsList: false
+  })

-  const isAddDisabled =
-    !selectedSubject || subjects.some((s) => s.name === selectedSubject.name)
+  const isAddDisabled = !mainCategory || !selectedSubject || 
+    subjects.some((s) => s.name === selectedSubject.name)

  // ...

  const addSubject = () => {
-    if (isAddDisabled || !selectedSubject) return
+    // Validate inputs
+    const newErrors = {
+      mainCategory: !mainCategory,
+      selectedSubject: !selectedSubject,
+      subjectsList: false
+    }
+    setErrors(newErrors)
+    
+    if (newErrors.mainCategory || newErrors.selectedSubject || isAddDisabled) return
    
     const updated = [...subjects, { name: selectedSubject.name }]
     updateSubjects(updated)
     setSelectedSubject(null)
+    setErrors({...errors, subjectsList: false})
  }
```

---

`134-135`: _⚠️ Potential issue_

**Add validation for empty subjects list**

Users should not be able to proceed if they haven't added any subjects. Add validation to ensure at least one subject is added.

```diff
          </Stack>

+          {subjects.length === 0 && (
+            <Typography color="error" variant="caption">
+              {t('become-tutor.categories.atLeastOneSubject')}
+            </Typography>
+          )}

          {btnsBox}
```

---

`59-60`: _⚠️ Potential issue_

**Translation key format correction required**

The translation key format should be consistent throughout the application. Based on the reviewer comments, keys should use dot notation without camelCase.

```diff
-            {t('becomeTutor.categories.title')}
+            {t('become-tutor.categories.title')}
```

---

`62-75`: _🛠️ Refactor suggestion_

**Add error handling to main category selection**

Add validation feedback to the main category dropdown to improve form usability.

```diff
          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setMainCategory(newValue)}
            options={categoriesMock}
            renderInput={(params) => (
              <TextField
                {...params}
                label={t('become-tutor.categories.mainSubjectsLabel')}
                variant='outlined'
+               error={errors.mainCategory}
+               helperText={errors.mainCategory ? t('become-tutor.categories.mainCategoryRequired') : ''}
              />
            )}
            value={mainCategory}
          />
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx (3)</summary><blockquote>

`101-107`: **Use more semantic keys for list items**

Using array index with subject name as key isn't ideal when items can be removed. Use a more unique identifier if available.

```diff
-              <Chip
-                key={`${subject.name}-${index}`}
+              <Chip
+                key={subject.id || `subject-${index}`}
                label={subject.name}
                onDelete={() => removeSubject(subject.name)}
              />
```

---

`49-52`: **Consider memoizing derived values**

The `displayedSubjects` and `hiddenCount` are recalculated on every render. Consider using `useMemo` for better performance.

```diff
+import { useState, useMemo } from 'react'
// ...

  const toggleShowAll = () => setShowAllSubjects((prev) => !prev)

-  const displayedSubjects = showAllSubjects ? subjects : subjects.slice(0, 2)
-  const hiddenCount = subjects.length - 2
+  const { displayedSubjects, hiddenCount } = useMemo(() => ({
+    displayedSubjects: showAllSubjects ? subjects : subjects.slice(0, 2),
+    hiddenCount: subjects.length - 2
+  }), [subjects, showAllSubjects])
```

---

`118-131`: **Use consistent component for collapse button**

You're using `Chip` for the expand button but `Button` for the collapse button. Consider using the same component type for better UI consistency.

```diff
            {showAllSubjects && (
-              <Button
+              <Chip
                onClick={toggleShowAll}
-                startIcon={<ArrowDropUpIcon />}
+                icon={<ArrowDropUpIcon />}
-                sx={{
-                  fontSize: '14px',
-                  padding: '6px 16px',
-                  textTransform: 'none'
-                }}
-                variant='outlined'
+                clickable
              >
                {t('become-tutor.categories.collapse')}
-              </Button>
+              </Chip>
            )}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7345b2a37b011b428abd298c999d9de1b27b6e22 and 3384e73f61cc781dbdcda54b58d80bba4ec0ec18.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `src/constants/translations/en/become-tutor.json` (1 hunks)
* `src/constants/translations/ua/become-tutor.json` (2 hunks)
* `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (2)</summary>

* src/constants/translations/ua/become-tutor.json
* src/constants/translations/en/become-tutor.json

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Run Tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-01T06:25:37Z
user: login: Kryzhanivsky
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T06:25:51Z
user: login: olena-kuziaieva
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T08:45:54Z
user: login: vlad-khrychov
state: APPROVED
author_association: NONE
submitted_at: 2025-05-01T18:25:41Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx (1)</summary><blockquote>

`64-64`: **Nitpick: Wrap conditional `helperText` in JSX expression for Prettier**  
Prettier is flagging the inline conditional. Wrapping it across multiple lines improves readability and satisfies the formatter:

```diff
-helperText={errors.firstName && t('becomeTutor.generalInfo.firstNameLabelReq')}
+helperText={
+  errors.firstName &&
+  t('becomeTutor.generalInfo.firstNameLabelReq')
+}
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 ESLint</summary>

[error] 64-64: Replace `errors.firstName·&&·t('becomeTutor.generalInfo.firstNameLabelReq')` with `⏎············errors.firstName·&&·t('becomeTutor.generalInfo.firstNameLabelReq')⏎··········`

(prettier/prettier)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3384e73f61cc781dbdcda54b58d80bba4ec0ec18 and f18a66b75fbbb2a96b0c5e16a1718f2cc3066f9b.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `src/components/info-general-step/InfoGeneralStep.tsx` (4 hunks)
* `src/constants/translations/en/become-tutor.json` (1 hunks)
* `src/constants/translations/ua/become-tutor.json` (2 hunks)
* `src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx` (2 hunks)
* `src/pages/guest-home-page/GuestHome.tsx` (3 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* src/components/info-general-step/InfoGeneralStep.tsx

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* src/constants/translations/en/become-tutor.json
* src/constants/translations/ua/become-tutor.json
* src/pages/guest-home-page/GuestHome.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 ESLint</summary>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx</summary>

[error] 64-64: Replace `errors.firstName·&&·t('becomeTutor.generalInfo.firstNameLabelReq')` with `⏎············errors.firstName·&&·t('becomeTutor.generalInfo.firstNameLabelReq')⏎··········`

(prettier/prettier)

---

[error] 75-75: Replace `errors.lastName·&&·t('becomeTutor.generalInfo.lastNameLabelReq')` with `⏎············errors.lastName·&&·t('becomeTutor.generalInfo.lastNameLabelReq')⏎··········`

(prettier/prettier)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Run Tests

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx (3)</summary>

`46-47`: **Skip: formatting-only change**  
Removal of an extraneous blank line after the `validateForm` declaration has no impact on functionality or readability.

---

`67-67`: **Approve: Simplify `onBlur` handler**  
Passing `validateForm` directly to `onBlur` removes an unnecessary arrow wrapper and is more concise.

---

`79-79`: **Approve: Simplify `onBlur` handler**  
Consistently passing `validateForm` directly to `onBlur` improves readability and matches the first name field.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T11:52:08Z

Review comments:
diff_hunk: @@ -0,0 +1,86 @@
+import { useState } from 'react'
+import { Box, Modal, IconButton } from '@mui/material'
+import CloseIcon from '@mui/icons-material/Close'
+
+import StepWrapper from '~/components/step-wrapper/StepWrapper'
+import { StepProvider } from '~/context/step-context'
+
+import GeneralInfoStep from '~/containers/tutor-home-page/general-info-step/GeneralInfoStep'
+import AddPhotoStep from '~/containers/tutor-home-page/add-photo-step/AddPhotoStep'
+import SubjectsStep from '~/containers/tutor-home-page/subjects-step/SubjectsStep'
+import LanguageStep from '~/containers/tutor-home-page/language-step/LanguageStep'
+import generalImg from '~/assets/img/tutor-home-page/become-tutor/general-info.svg'
+import interestImg from '~/assets/img/tutor-home-page/become-tutor/study-category.svg'
+import languageImg from '~/assets/img/tutor-home-page/become-tutor/languages.svg'
+import {
+  tutorStepLabels,
+  initialValues
+} from '~/components/user-steps-wrapper/constants'
+import { styles } from './InfoGeneralStep.styles'
+import ConfirmDialog from '~/components/confirm-dialog/ConfirmDialog'
+
+const UserStepsModal = () => {
+  const [open, setOpen] = useState(true)
+  const [openConfirm, setOpenConfirm] = useState(false)
+  const [isUserFetched, setIsUserFetched] = useState(false)
+  const imageArr = [generalImg, interestImg, languageImg] // Add the images for each step here
+  const [activeStep, setActiveStep] = useState(0)
+  const childrenArr = [
+    <GeneralInfoStep
+      isUserFetched={isUserFetched}
+      key='1'
+      setIsUserFetched={setIsUserFetched}
+    />,
+    <SubjectsStep key='2' />,
+    <LanguageStep key='3' />,
+    <AddPhotoStep key='4' />
+  ]
+
+  const handleClose = () => {
+    setOpenConfirm(true)
+  }
+
+  return (
+    <>
+      <Modal onClose={handleClose} open={open} sx={styles.modalBox}>
+        <Box sx={styles.modalBox}>
+          <IconButton onClick={handleClose} sx={styles.closeButton}>
+            <CloseIcon />
+          </IconButton>
+
+          <Box
+            alt='Stepper illustration'
+            component='img'
+            src={imageArr[activeStep]}
+            sx={styles.imageBox}
+          />
+
+          {/* Right: Stepper form */}
+
+          <StepProvider
+            initialValues={initialValues}
+            stepLabels={tutorStepLabels}
+          >
+            <StepWrapper onStepChange={setActiveStep} steps={tutorStepLabels}>
+              {childrenArr}
+            </StepWrapper>
path: src/components/info-general-step/InfoGeneralStep.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Pass error state handling to StepWrapper**

The component doesn't appear to handle or track the error state of individual steps. Consider adding error state tracking to properly disable/enable navigation between steps.

```diff
- <StepWrapper onStepChange={setActiveStep} steps={tutorStepLabels}>
+ <StepWrapper 
+   onStepChange={setActiveStep} 
+   steps={tutorStepLabels}
+   onStepError={(stepIndex, hasError) => {
+     // Track errors for each step
+   }}
+ >
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
            <StepWrapper
              onStepChange={setActiveStep}
              steps={tutorStepLabels}
              onStepError={(stepIndex, hasError) => {
                // Track errors for each step
              }}
            >
              {childrenArr}
            </StepWrapper>
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,143 @@
+import React, { useState } from 'react'
 import Box from '@mui/material/Box'
+import Typography from '@mui/material/Typography'
+import TextField from '@mui/material/TextField'
+import MenuItem from '@mui/material/MenuItem'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import Checkbox from '@mui/material/Checkbox'
 
 import { styles } from '~/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles'
 
-const GeneralInfoStep = ({ btnsBox }) => {
+const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
+  const countries = ['USA', 'Canada', 'UK']
+  const cities = ['New York', 'Toronto', 'London']
+  const [form, setForm] = useState({
+    firstName: '',
+    lastName: '',
+    country: '',
+    city: '',
+    description: '',
+    confirmAge: false
+  })
+  const [errors, setErrors] = useState({
+    firstName: false,
+    lastName: false,
+    description: false
+  })
path: src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Enhance form data structure and validation**

The component relies on hardcoded country and city lists which aren't linked. Consider using a more dynamic approach with nested data that links cities to countries. Also, the form's state initialization and validation could be more robust.

```diff
- const countries = ['USA', 'Canada', 'UK']
- const cities = ['New York', 'Toronto', 'London']
+ const countryData = {
+   'USA': ['New York', 'Los Angeles', 'Chicago'],
+   'Canada': ['Toronto', 'Vancouver', 'Montreal'],
+   'UK': ['London', 'Manchester', 'Birmingham']
+ }
+ const countries = Object.keys(countryData)
  const [form, setForm] = useState({
    firstName: '',
    lastName: '',
    country: '',
    city: '',
    description: '',
    confirmAge: false
  })
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
  const countryData = {
    'USA': ['New York', 'Los Angeles', 'Chicago'],
    'Canada': ['Toronto', 'Vancouver', 'Montreal'],
    'UK': ['London', 'Manchester', 'Birmingham']
  }
  const countries = Object.keys(countryData)
  const [form, setForm] = useState({
    firstName: '',
    lastName: '',
    country: '',
    city: '',
    description: '',
    confirmAge: false
  })
  const [errors, setErrors] = useState({
    firstName: false,
    lastName: false,
    description: false
  })
  // …rest of component
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,143 @@
+import React, { useState } from 'react'
 import Box from '@mui/material/Box'
+import Typography from '@mui/material/Typography'
+import TextField from '@mui/material/TextField'
+import MenuItem from '@mui/material/MenuItem'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import Checkbox from '@mui/material/Checkbox'
 
 import { styles } from '~/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles'
 
-const GeneralInfoStep = ({ btnsBox }) => {
+const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
+  const countries = ['USA', 'Canada', 'UK']
+  const cities = ['New York', 'Toronto', 'London']
+  const [form, setForm] = useState({
+    firstName: '',
+    lastName: '',
+    country: '',
+    city: '',
+    description: '',
+    confirmAge: false
+  })
+  const [errors, setErrors] = useState({
+    firstName: false,
+    lastName: false,
+    description: false
+  })
+
+  const handleChange = (e) => {
+    const { name, value, type, checked } = e.target
+    setForm((prev) => ({
+      ...prev,
+      [name]: type === 'checkbox' ? checked : value
+    }))
+  }
+
+  const validateForm = () => {
+    const newErrors = {
+      firstName: form.firstName === '',
+      lastName: form.lastName === '',
+      description: form.description.length > 100
+    }
+    setErrors(newErrors)
+    onErrorChange(Object.values(newErrors).includes(true))
+  }
+  const handleDescriptionChange = (e) => {
+    const { value } = e.target
+    if (value.length <= 100) {
+      setForm((prev) => ({ ...prev, description: value }))
+    }
+  }
+
   return (
-    <Box sx={styles.container}>
-      GeneralInfo step
-      {btnsBox}
-    </Box>
+    <>
+      <Typography variant='body1'>
+        Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet
+        sint.
+      </Typography>
+      <Box sx={styles.inputs}>
+        <TextField
+          error={errors.firstName}
+          fullWidth
+          helperText={errors.firstName && 'First name is required'}
+          label='First Name'
+          name='firstName'
+          onBlur={() => validateForm()}
+          onChange={handleChange}
+          required
+          value={form.firstName}
+        />
+        <TextField
+          error={errors.lastName}
+          fullWidth
+          helperText={errors.lastName && 'Last name is required'}
+          label='Last Name'
+          name='lastName'
+          onBlur={() => validateForm()}
+          onChange={handleChange}
+          required
+          value={form.lastName}
+        />
+      </Box>
+      <Box sx={styles.inputs}>
+        <TextField
+          fullWidth
+          label='Country'
+          name='country'
+          onChange={handleChange}
+          select
+          value={form.country}
+        >
+          {countries.map((c) => (
+            <MenuItem key={c} value={c}>
+              {c}
+            </MenuItem>
+          ))}
+        </TextField>
+        <TextField
+          fullWidth
+          label='City'
+          name='city'
+          onChange={handleChange}
+          select
+          value={form.city}
+        >
+          {cities.map((c) => (
+            <MenuItem key={c} value={c}>
+              {c}
+            </MenuItem>
+          ))}
+        </TextField>
+      </Box>
path: src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Link city dropdown options to selected country**

Currently, the city dropdown shows the same options regardless of the country selected. Update to show only cities from the selected country.

```diff
  <TextField
    fullWidth
    label='Country'
    name='country'
-   onChange={handleChange}
+   onChange={(e) => {
+     handleChange(e);
+     // Reset city when country changes
+     setForm(prev => ({...prev, city: ''}));
+   }}
    select
    value={form.country}
  >
    {countries.map((c) => (
      <MenuItem key={c} value={c}>
        {c}
      </MenuItem>
    ))}
  </TextField>
  <TextField
    fullWidth
    label='City'
    name='city'
    onChange={handleChange}
    select
+   disabled={!form.country}
    value={form.city}
  >
-   {cities.map((c) => (
+   {form.country && countryData[form.country].map((c) => (
      <MenuItem key={c} value={c}>
        {c}
      </MenuItem>
    ))}
  </TextField>
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
      <Box sx={styles.inputs}>
        <TextField
          fullWidth
          label='Country'
          name='country'
          onChange={(e) => {
            handleChange(e);
            // Reset city when country changes
            setForm(prev => ({ ...prev, city: '' }));
          }}
          select
          value={form.country}
        >
          {countries.map((c) => (
            <MenuItem key={c} value={c}>
              {c}
            </MenuItem>
          ))}
        </TextField>
        <TextField
          fullWidth
          label='City'
          name='city'
          onChange={handleChange}
          select
          disabled={!form.country}
          value={form.city}
        >
          {form.country &&
            countryData[form.country].map((c) => (
              <MenuItem key={c} value={c}>
                {c}
              </MenuItem>
            ))}
        </TextField>
      </Box>
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,143 @@
+import React, { useState } from 'react'
 import Box from '@mui/material/Box'
+import Typography from '@mui/material/Typography'
+import TextField from '@mui/material/TextField'
+import MenuItem from '@mui/material/MenuItem'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import Checkbox from '@mui/material/Checkbox'
 
 import { styles } from '~/containers/tutor-home-page/general-info-step/GeneralInfoStep.styles'
 
-const GeneralInfoStep = ({ btnsBox }) => {
+const GeneralInfoStep = ({ btnsBox, onErrorChange }) => {
+  const countries = ['USA', 'Canada', 'UK']
+  const cities = ['New York', 'Toronto', 'London']
+  const [form, setForm] = useState({
+    firstName: '',
+    lastName: '',
+    country: '',
+    city: '',
+    description: '',
+    confirmAge: false
+  })
+  const [errors, setErrors] = useState({
+    firstName: false,
+    lastName: false,
+    description: false
+  })
+
+  const handleChange = (e) => {
+    const { name, value, type, checked } = e.target
+    setForm((prev) => ({
+      ...prev,
+      [name]: type === 'checkbox' ? checked : value
+    }))
+  }
+
+  const validateForm = () => {
+    const newErrors = {
+      firstName: form.firstName === '',
+      lastName: form.lastName === '',
+      description: form.description.length > 100
+    }
+    setErrors(newErrors)
+    onErrorChange(Object.values(newErrors).includes(true))
+  }
+  const handleDescriptionChange = (e) => {
+    const { value } = e.target
+    if (value.length <= 100) {
+      setForm((prev) => ({ ...prev, description: value }))
+    }
+  }
+
   return (
-    <Box sx={styles.container}>
-      GeneralInfo step
-      {btnsBox}
-    </Box>
+    <>
+      <Typography variant='body1'>
+        Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet
+        sint.
+      </Typography>
+      <Box sx={styles.inputs}>
+        <TextField
+          error={errors.firstName}
+          fullWidth
+          helperText={errors.firstName && 'First name is required'}
+          label='First Name'
+          name='firstName'
+          onBlur={() => validateForm()}
+          onChange={handleChange}
+          required
+          value={form.firstName}
+        />
+        <TextField
+          error={errors.lastName}
+          fullWidth
+          helperText={errors.lastName && 'Last name is required'}
+          label='Last Name'
+          name='lastName'
+          onBlur={() => validateForm()}
+          onChange={handleChange}
+          required
+          value={form.lastName}
+        />
+      </Box>
+      <Box sx={styles.inputs}>
+        <TextField
+          fullWidth
+          label='Country'
+          name='country'
+          onChange={handleChange}
+          select
+          value={form.country}
+        >
+          {countries.map((c) => (
+            <MenuItem key={c} value={c}>
+              {c}
+            </MenuItem>
+          ))}
+        </TextField>
+        <TextField
+          fullWidth
+          label='City'
+          name='city'
+          onChange={handleChange}
+          select
+          value={form.city}
+        >
+          {cities.map((c) => (
+            <MenuItem key={c} value={c}>
+              {c}
+            </MenuItem>
+          ))}
+        </TextField>
+      </Box>
+      <TextField
+        error={errors.description}
+        fullWidth
+        helperText={`${form.description.length}/100`}
+        inputProps={{ maxLength: 100 }}
+        label='Describe in short your professional status'
+        multiline
+        name='description'
+        onChange={handleDescriptionChange}
+        rows={3}
+        value={form.description}
+      />
+
+      <FormControlLabel
+        control={
+          <Checkbox
+            checked={form.confirmAge}
+            name='confirmAge'
+            onChange={handleChange}
+          />
+        }
+        label='I confirm that I am over 18 years old'
+      />
path: src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Add validation for the age confirmation checkbox**

The age confirmation checkbox is required but lacks validation in the `validateForm` function. Add it to the validation logic to prevent proceeding without confirming age.

```diff
  const validateForm = () => {
    const newErrors = {
      firstName: form.firstName === '',
      lastName: form.lastName === '',
-     description: form.description.length > 100
+     description: form.description.length > 100,
+     confirmAge: !form.confirmAge
    }
    setErrors(newErrors)
    onErrorChange(Object.values(newErrors).includes(true))
  }
  
  // And in the checkbox:
  <FormControlLabel
    control={
      <Checkbox
        checked={form.confirmAge}
        name='confirmAge'
        onChange={handleChange}
+       required
      />
    }
+   error={errors.confirmAge}
+   helperText={errors.confirmAge && 'You must confirm your age to continue'}
    label='I confirm that I am over 18 years old'
  />
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  const validateForm = () => {
    const newErrors = {
      firstName: form.firstName === '',
      lastName: form.lastName === '',
      description: form.description.length > 100,
      confirmAge: !form.confirmAge
    }
    setErrors(newErrors)
    onErrorChange(Object.values(newErrors).includes(true))
  }

  // …

      <FormControlLabel
        control={
          <Checkbox
            checked={form.confirmAge}
            name="confirmAge"
            onChange={handleChange}
            required
          />
        }
        error={errors.confirmAge}
        helperText={errors.confirmAge && 'You must confirm your age to continue'}
        label="I confirm that I am over 18 years old"
      />
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,97 @@
+import { useState } from 'react'
+import Autocomplete from '@mui/material/Autocomplete'
 import Box from '@mui/material/Box'
+import Chip from '@mui/material/Chip'
+import Stack from '@mui/material/Stack'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+
+import AppButton from '~/components/app-button/AppButton'
+import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
+import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
+import { categories } from '~/constants/translations/en/become-tutor.json'
 
 const SubjectsStep = ({ btnsBox }) => {
+  const [mainCategory, setMainCategory] = useState(null)
+  const [selectedSubject, setSelectedSubject] = useState(null)
+  const [subjects, setSubjects] = useState([])
+
+  const addSubject = () => {
+    if (!selectedSubject) {
+      alert(categories.emptyFields)
+      return
+    }
+
+    const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
+    if (isDuplicate) {
+      alert(categories.sameSubject)
+      return
+    }
+
+    setSubjects([...subjects, { name: selectedSubject.name }])
+    setSelectedSubject(null)
+  }
+
+  const displayedSubjects = subjects.slice(0, 2)
+  const hiddenCount = subjects.length - displayedSubjects.length
+
   return (
     <Box sx={styles.container}>
       <Box sx={styles.rigthBox}>
-        Subjects step
-        {btnsBox}
+        <Stack spacing={2}>
+          <Typography variant='body1'>{categories.title}</Typography>
+
+          <Autocomplete
+            fullWidth
+            getOptionLabel={(option) => option.name}
+            onChange={(_, newValue) => setMainCategory(newValue)}
+            options={categoriesMock}
+            renderInput={(params) => (
+              <TextField
+                {...params}
+                label={categories.mainSubjectsLabel}
+                variant='outlined'
+              />
+            )}
+            value={mainCategory}
+          />
+
+          <Autocomplete
+            fullWidth
+            getOptionLabel={(option) => option.name}
+            onChange={(_, newValue) => setSelectedSubject(newValue)}
+            options={categoriesMock}
+            renderInput={(params) => (
+              <TextField
+                {...params}
+                label={categories.subjectLabel}
+                variant='outlined'
+              />
+            )}
+            value={selectedSubject}
+          />
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Filter subjects based on selected category**

Currently, both dropdowns show the same options from `categoriesMock`. Filter the subject options based on the main category selection to improve user experience.

```diff
  <Autocomplete
    fullWidth
    getOptionLabel={(option) => option.name}
    onChange={(_, newValue) => setMainCategory(newValue)}
    options={categoriesMock}
    renderInput={(params) => (
      <TextField
        {...params}
        label={categories.mainSubjectsLabel}
        variant='outlined'
+       error={errors.mainCategory}
+       helperText={errors.mainCategory ? 'Please select a main category' : ''}
      />
    )}
    value={mainCategory}
  />

  <Autocomplete
    fullWidth
    getOptionLabel={(option) => option.name}
    onChange={(_, newValue) => setSelectedSubject(newValue)}
-   options={categoriesMock}
+   options={mainCategory ? categoriesMock.filter(item => 
+     item.categoryId === mainCategory.id || // Adjust based on your data structure
+     item.category === mainCategory.name
+   ) : []}
+   disabled={!mainCategory}
    renderInput={(params) => (
      <TextField
        {...params}
        label={categories.subjectLabel}
        variant='outlined'
+       error={errors.selectedSubject}
+       helperText={errors.selectedSubject ? 'Please select a valid subject' : ''}
      />
    )}
    value={selectedSubject}
  />
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setMainCategory(newValue)}
            options={categoriesMock}
            renderInput={(params) => (
              <TextField
                {...params}
                label={categories.mainSubjectsLabel}
                variant='outlined'
                error={errors.mainCategory}
                helperText={errors.mainCategory ? 'Please select a main category' : ''}
              />
            )}
            value={mainCategory}
          />

          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setSelectedSubject(newValue)}
            options={
              mainCategory
                ? categoriesMock.filter(item =>
                    item.categoryId === mainCategory.id ||
                    item.category === mainCategory.name
                  )
                : []
            }
            disabled={!mainCategory}
            renderInput={(params) => (
              <TextField
                {...params}
                label={categories.subjectLabel}
                variant='outlined'
                error={errors.selectedSubject}
                helperText={errors.selectedSubject ? 'Please select a valid subject' : ''}
              />
            )}
            value={selectedSubject}
          />
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,97 @@
+import { useState } from 'react'
+import Autocomplete from '@mui/material/Autocomplete'
 import Box from '@mui/material/Box'
+import Chip from '@mui/material/Chip'
+import Stack from '@mui/material/Stack'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+
+import AppButton from '~/components/app-button/AppButton'
+import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
+import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
+import { categories } from '~/constants/translations/en/become-tutor.json'
 
 const SubjectsStep = ({ btnsBox }) => {
+  const [mainCategory, setMainCategory] = useState(null)
+  const [selectedSubject, setSelectedSubject] = useState(null)
+  const [subjects, setSubjects] = useState([])
+
+  const addSubject = () => {
+    if (!selectedSubject) {
+      alert(categories.emptyFields)
+      return
+    }
+
+    const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
+    if (isDuplicate) {
+      alert(categories.sameSubject)
+      return
+    }
+
+    setSubjects([...subjects, { name: selectedSubject.name }])
+    setSelectedSubject(null)
+  }
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Improve subject selection validation**

The current implementation only prevents adding empty or duplicate subjects, but there are other validation concerns to address:
1. The main category should be required before selecting a subject
2. Filtering subjects based on the selected main category
3. Error feedback should use proper UI components instead of `alert()`

```diff
  const [mainCategory, setMainCategory] = useState(null)
  const [selectedSubject, setSelectedSubject] = useState(null)
  const [subjects, setSubjects] = useState([])
+ const [errors, setErrors] = useState({
+   mainCategory: false,
+   selectedSubject: false
+ })

  const addSubject = () => {
+   const newErrors = {
+     mainCategory: !mainCategory,
+     selectedSubject: !selectedSubject
+   }
+   setErrors(newErrors)
+   
+   if (newErrors.mainCategory || newErrors.selectedSubject) {
+     return
+   }

-   if (!selectedSubject) {
-     alert(categories.emptyFields)
-     return
-   }

    const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
    if (isDuplicate) {
-     alert(categories.sameSubject)
+     setErrors(prev => ({...prev, selectedSubject: true}))
      return
    }

    setSubjects([...subjects, { name: selectedSubject.name }])
    setSelectedSubject(null)
  }
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  const [mainCategory, setMainCategory] = useState(null)
  const [selectedSubject, setSelectedSubject] = useState(null)
  const [subjects, setSubjects] = useState([])
  const [errors, setErrors] = useState({
    mainCategory: false,
    selectedSubject: false
  })

  const addSubject = () => {
    const newErrors = {
      mainCategory: !mainCategory,
      selectedSubject: !selectedSubject
    }
    setErrors(newErrors)

    if (newErrors.mainCategory || newErrors.selectedSubject) {
      return
    }

    const isDuplicate = subjects.some((s) => s.name === selectedSubject.name)
    if (isDuplicate) {
      setErrors(prev => ({ ...prev, selectedSubject: true }))
      return
    }

    setSubjects([...subjects, { name: selectedSubject.name }])
    setSelectedSubject(null)
  }
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-25T12:10:56Z
author_association: NONE
diff_hunk: @@ -1,13 +1,125 @@
+import { useState } from 'react'
+import Autocomplete from '@mui/material/Autocomplete'
 import Box from '@mui/material/Box'
+import Chip from '@mui/material/Chip'
+import Stack from '@mui/material/Stack'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'
+import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
+import Button from '@mui/material/Button'
+
+import AppButton from '~/components/app-button/AppButton'
+import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
+import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
+import { categories } from '~/constants/translations/en/become-tutor.json'
 
 const SubjectsStep = ({ btnsBox }) => {
+  const [mainCategory, setMainCategory] = useState(null)
+  const [selectedSubject, setSelectedSubject] = useState(null)
+  const [subjects, setSubjects] = useState([])
+  const [showAllSubjects, setShowAllSubjects] = useState(false)
+
+  const isAddDisabled =
+    !selectedSubject || subjects.some((s) => s.name === selectedSubject.name)
+
+  const addSubject = () => {
+    if (isAddDisabled) return
+
+    setSubjects([...subjects, { name: selectedSubject.name }])
+    setSelectedSubject(null)
+  }
+
+  const displayedSubjects = showAllSubjects ? subjects : subjects.slice(0, 2)
+  const hiddenCount = subjects.length - 2
+
+  const toggleShowAll = () => {
+    setShowAllSubjects((prev) => !prev)
+  }
+
   return (
     <Box sx={styles.container}>
       <Box sx={styles.rigthBox}>
-        Subjects step
-        {btnsBox}
+        <Stack spacing={2}>
+          <Typography variant='body1'>{categories.title}</Typography>
+          <Autocomplete
+            fullWidth
+            getOptionLabel={(option) => option.name}
+            onChange={(_, newValue) => setMainCategory(newValue)}
+            options={categoriesMock}
+            renderInput={(params) => (
+              <TextField
+                {...params}
+                label={categories.mainSubjectsLabel}
+                variant='outlined'
+              />
+            )}
+            value={mainCategory}
+          />
+
+          <Autocomplete
+            fullWidth
+            getOptionLabel={(option) => option.name}
+            onChange={(_, newValue) => setSelectedSubject(newValue)}
+            options={categoriesMock}
+            renderInput={(params) => (
+              <TextField
+                {...params}
+                label={categories.subjectLabel}
+                variant='outlined'
+              />
+            )}
+            value={selectedSubject}
+          />
+
+          <AppButton
+            disabled={isAddDisabled}
+            onClick={addSubject}
+            variant={ButtonVariantEnum.Outlined}
+          >
+            {categories.btnText}
+          </AppButton>
+
+          <Stack direction='row' flexWrap='wrap' spacing={1}>
+            {displayedSubjects.map((subject, index) => (
+              <Chip
+                key={index}
+                label={subject.name}
+                onDelete={() =>
+                  setSubjects(subjects.filter((s) => s.name !== subject.name))
+                }
+              />
+            ))}
+
+            {hiddenCount > 0 && !showAllSubjects && (
+              <Chip
+                clickable
+                icon={<ArrowDropDownIcon />}
+                label={`+${hiddenCount}`}
+                onClick={toggleShowAll}
+              />
+            )}
+
+            {showAllSubjects && (
+              <Button
+                onClick={toggleShowAll}
+                startIcon={<ArrowDropUpIcon />}
+                sx={{
+                  fontSize: '14px',
+                  padding: '6px 16px',
+                  textTransform: 'none'
+                }}
+                variant='outlined'
+              >
+                Collapse
+              </Button>
+            )}
+          </Stack>
+
+          {btnsBox}
+        </Stack>
       </Box>
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Add check for empty subjects array before submission**

The component doesn't validate whether any subjects have been added before allowing users to proceed to the next step. This could lead to incomplete tutor profiles.


Add validation to ensure at least one subject is selected before the user can proceed to the next step:

```diff
return (
  <Box sx={styles.container}>
    <Box sx={styles.rigthBox}>
      <Stack spacing={2}>
        <Typography variant='body1'>{categories.title}</Typography>
        {/* ... existing code ... */}
        
+       {subjects.length === 0 && (
+         <Typography color="error" variant="caption">
+           Please add at least one subject to continue
+         </Typography>
+       )}
        
        {btnsBox}
      </Stack>
    </Box>
  </Box>
)
```

Let's check if this validation is handled in the parent component:

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if the parent component handles subject validation
rg -A 5 -B 5 "SubjectsStep" --glob "*.{jsx,tsx,js}" | grep -v "SubjectsStep\.jsx"
```

Length of output: 4165

---

🏁 Script executed:

```shell
#!/bin/bash
# Print the first 200 lines of SubjectsStep.jsx for context
sed -n '1,200p' src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
```

Length of output: 4094

---

```bash
#!/bin/bash
# Locate StepWrapper files
echo "Finding StepWrapper component files..."
rg -l "StepWrapper" --glob "*.{tsx,jsx}"

# Print first 200 lines of the StepWrapper implementation
STEP_WRAPPER_PATH=$(rg -l "StepWrapper" --glob "*.{tsx,jsx}" | grep -v ".test." | head -n1)
echo "StepWrapper path: $STEP_WRAPPER_PATH"
if [ -n "$STEP_WRAPPER_PATH" ]; then
  echo "Displaying contents of $STEP_WRAPPER_PATH..."
  sed -n '1,200p' "$STEP_WRAPPER_PATH"
else
  echo "StepWrapper file not found."
fi
```

---



</details>

**Add required subject validation in SubjectsStep**

Currently, neither `SubjectsStep` nor its parent enforces that at least one subject is selected before moving on—users can advance with zero subjects. Let’s ensure we both show an error and prevent submission until `subjects.length > 0`.

• File: `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx`  
• Around the bottom of the render (just before `{btnsBox}`):

```diff
           </Stack>

+          {subjects.length === 0 && (
+            <Typography color="error" variant="caption">
+              Please add at least one subject to continue
+            </Typography>
+          )}

           {btnsBox}
```

If you’re using the step-wrapper’s Next button, also hook into its validation API (e.g. via `useStepContext().setCanContinue(subjects.length > 0)`) so “Next” is disabled until a subject is added.  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  return (
    <Box sx={styles.container}>
      <Box sx={styles.rigthBox}>
        <Stack spacing={2}>
          <Typography variant='body1'>{categories.title}</Typography>
          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setMainCategory(newValue)}
            options={categoriesMock}
            renderInput={(params) => (
              <TextField
                {...params}
                label={categories.mainSubjectsLabel}
                variant='outlined'
              />
            )}
            value={mainCategory}
          />

          <Autocomplete
            fullWidth
            getOptionLabel={(option) => option.name}
            onChange={(_, newValue) => setSelectedSubject(newValue)}
            options={categoriesMock}
            renderInput={(params) => (
              <TextField
                {...params}
                label={categories.subjectLabel}
                variant='outlined'
              />
            )}
            value={selectedSubject}
          />

          <AppButton
            disabled={isAddDisabled}
            onClick={addSubject}
            variant={ButtonVariantEnum.Outlined}
          >
            {categories.btnText}
          </AppButton>

          <Stack direction='row' flexWrap='wrap' spacing={1}>
            {displayedSubjects.map((subject, index) => (
              <Chip
                key={index}
                label={subject.name}
                onDelete={() =>
                  setSubjects(subjects.filter((s) => s.name !== subject.name))
                }
              />
            ))}

            {hiddenCount > 0 && !showAllSubjects && (
              <Chip
                clickable
                icon={<ArrowDropDownIcon />}
                label={`+${hiddenCount}`}
                onClick={toggleShowAll}
              />
            )}

            {showAllSubjects && (
              <Button
                onClick={toggleShowAll}
                startIcon={<ArrowDropUpIcon />}
                sx={{
                  fontSize: '14px',
                  padding: '6px 16px',
                  textTransform: 'none'
                }}
                variant='outlined'
              >
                Collapse
              </Button>
            )}
          </Stack>

+         {subjects.length === 0 && (
+           <Typography color="error" variant="caption">
+             Please add at least one subject to continue
+           </Typography>
+         )}

          {btnsBox}
        </Stack>
      </Box>
    </Box>
  )
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-28T16:46:40Z
author_association: NONE
diff_hunk: @@ -14,7 +14,10 @@ import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
 import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
-import { categories } from '~/constants/translations/en/become-tutor.json'
+
+import categoriesTranslationsRaw from '~/constants/translations/en/become-tutor.json'
+
+const categoriesTranslations = categoriesTranslationsRaw.categories
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: This is incorrect
created_at: 2025-04-30T07:49:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -14,7 +14,10 @@ import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
 import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
-import { categories } from '~/constants/translations/en/become-tutor.json'
+
+import categoriesTranslationsRaw from '~/constants/translations/en/become-tutor.json'
+
+const categoriesTranslations = categoriesTranslationsRaw.categories
 
 const SubjectsStep = ({ btnsBox }) => {
   const [mainCategory, setMainCategory] = useState(null)
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: You need to use "const { t } = useTranslation()"
created_at: 2025-04-30T07:50:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -52,7 +58,7 @@ const SubjectsStep = ({ btnsBox }) => {
             renderInput={(params) => (
               <TextField
                 {...params}
-                label={categories.mainSubjectsLabel}
+                label={categoriesTranslations.mainSubjectsLabel}
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: Then you shoud use t function like t("become-tutor.categories.title")
created_at: 2025-04-30T07:51:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -43,7 +46,10 @@ const SubjectsStep = ({ btnsBox }) => {
     <Box sx={styles.container}>
       <Box sx={styles.rigthBox}>
         <Stack spacing={2}>
-          <Typography variant='body1'>{categories.title}</Typography>
+          <Typography variant='body1'>
+            {categoriesTranslations.title}
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: Here you need to use the "t" function
created_at: 2025-04-30T07:52:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,7 +73,7 @@ const SubjectsStep = ({ btnsBox }) => {
             renderInput={(params) => (
               <TextField
                 {...params}
-                label={categories.subjectLabel}
+                label={categoriesTranslations.subjectLabel}
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: Here you need to use the "t" function
created_at: 2025-04-30T07:52:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,7 +85,7 @@ const SubjectsStep = ({ btnsBox }) => {
             onClick={addSubject}
             variant={ButtonVariantEnum.Outlined}
           >
-            {categories.btnText}
+            {categoriesTranslations.btnText}
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: Kryzhanivsky
body: Here you need to use the "t" function
created_at: 2025-04-30T07:52:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,138 @@
+import { useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import Autocomplete from '@mui/material/Autocomplete'
 import Box from '@mui/material/Box'
+import Chip from '@mui/material/Chip'
+import Stack from '@mui/material/Stack'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'
+import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
+import Button from '@mui/material/Button'
+
+import AppButton from '~/components/app-button/AppButton'
+import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
+import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
+
+const SubjectsStep = ({ btnsBox, onSubjectsChange }) => {
+  const { t } = useTranslation()
+
+  const [mainCategory, setMainCategory] = useState(null)
+  const [selectedSubject, setSelectedSubject] = useState(null)
+  const [subjects, setSubjects] = useState([])
+  const [showAllSubjects, setShowAllSubjects] = useState(false)
+
+  const isAddDisabled =
+    !selectedSubject || subjects.some((s) => s.name === selectedSubject.name)
+
+  const updateSubjects = (newSubjects) => {
+    setSubjects(newSubjects)
+    if (typeof onSubjectsChange === 'function') {
+      onSubjectsChange(newSubjects)
+    }
+  }
+
+  const addSubject = () => {
+    if (isAddDisabled || !selectedSubject) return
+    const updated = [...subjects, { name: selectedSubject.name }]
+    updateSubjects(updated)
+    setSelectedSubject(null)
+  }
+
+  const removeSubject = (name) => {
+    const updated = subjects.filter((s) => s.name !== name)
+    updateSubjects(updated)
+  }
+
+  const toggleShowAll = () => setShowAllSubjects((prev) => !prev)
+
+  const displayedSubjects = showAllSubjects ? subjects : subjects.slice(0, 2)
+  const hiddenCount = subjects.length - 2
 
-const SubjectsStep = ({ btnsBox }) => {
   return (
     <Box sx={styles.container}>
       <Box sx={styles.rigthBox}>
-        Subjects step
-        {btnsBox}
+        <Stack spacing={2}>
+          <Typography variant='body1'>
+            {t('becomeTutor.categories.title')}
+          </Typography>
+
+          <Autocomplete
+            fullWidth
+            getOptionLabel={(option) => option.name}
+            onChange={(_, newValue) => setMainCategory(newValue)}
+            options={categoriesMock}
+            renderInput={(params) => (
+              <TextField
+                {...params}
+                label={t('becomeTutor.categories.mainSubjectsLabel')}
+                variant='outlined'
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix all translation key formats**

All translation keys need to be updated to match the expected format with hyphenated paths instead of camelCase.

```diff
-                label={t('becomeTutor.categories.mainSubjectsLabel')}
+                label={t('become-tutor.categories.mainSubjectsLabel')}

-                label={t('becomeTutor.categories.subjectLabel')}
+                label={t('become-tutor.categories.subjectLabel')}

-            {t('becomeTutor.categories.btnText')}
+            {t('become-tutor.categories.btnText')}

-                {t('becomeTutor.categories.collapse')}
+                {t('become-tutor.categories.collapse')}
```



Also applies to: 85-86, 97-98, 129-130

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-01T06:25:36Z
author_association: NONE
diff_hunk: @@ -1,13 +1,138 @@
+import { useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import Autocomplete from '@mui/material/Autocomplete'
 import Box from '@mui/material/Box'
+import Chip from '@mui/material/Chip'
+import Stack from '@mui/material/Stack'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'
+import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
+import Button from '@mui/material/Button'
+
+import AppButton from '~/components/app-button/AppButton'
+import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
+import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
+
+const SubjectsStep = ({ btnsBox, onSubjectsChange }) => {
+  const { t } = useTranslation()
+
+  const [mainCategory, setMainCategory] = useState(null)
+  const [selectedSubject, setSelectedSubject] = useState(null)
+  const [subjects, setSubjects] = useState([])
+  const [showAllSubjects, setShowAllSubjects] = useState(false)
+
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Component prop validation needed**

The component doesn't validate its props. Add PropTypes or TypeScript definitions to ensure proper usage.

```diff
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
+import PropTypes from 'prop-types'
import Autocomplete from '@mui/material/Autocomplete'
// ... other imports

const SubjectsStep = ({ btnsBox, onSubjectsChange }) => {
  // ... component code
}

+SubjectsStep.propTypes = {
+  btnsBox: PropTypes.node,
+  onSubjectsChange: PropTypes.func
+}
+
+SubjectsStep.defaultProps = {
+  btnsBox: null,
+  onSubjectsChange: null
+}

export default SubjectsStep
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import PropTypes from 'prop-types'
import Autocomplete from '@mui/material/Autocomplete'
// ... other imports

const SubjectsStep = ({ btnsBox, onSubjectsChange }) => {
  const { t } = useTranslation()

  const [mainCategory, setMainCategory] = useState(null)
  const [selectedSubject, setSelectedSubject] = useState(null)
  const [subjects, setSubjects] = useState([])
  const [showAllSubjects, setShowAllSubjects] = useState(false)

  // ... rest of component code
}

SubjectsStep.propTypes = {
  btnsBox: PropTypes.node,
  onSubjectsChange: PropTypes.func
}

SubjectsStep.defaultProps = {
  btnsBox: null,
  onSubjectsChange: null
}

export default SubjectsStep
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-01T06:25:36Z
author_association: NONE
diff_hunk: @@ -14,7 +14,10 @@ import { ButtonVariantEnum } from '~/types'
 
 import { styles } from '~/containers/tutor-home-page/subjects-step/SubjectsStep.styles'
 import { categoriesMock } from '~/containers/tutor-home-page/subjects-step/constants'
-import { categories } from '~/constants/translations/en/become-tutor.json'
+
+import categoriesTranslationsRaw from '~/constants/translations/en/become-tutor.json'
+
+const categoriesTranslations = categoriesTranslationsRaw.categories
 
 const SubjectsStep = ({ btnsBox }) => {
   const [mainCategory, setMainCategory] = useState(null)
path: src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx
user: login: vlad-khrychov
body: If you say about `mainCategory`, we should not front end translation for them 
created_at: 2025-05-01T18:25:26Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-25T12:06:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This set of changes primarily updates the UI and logic for the subject selection step in the tutor onboarding flow, replacing a static placeholder with a dynamic, interactive subject picker. It introduces state management for main category and subject selection, supports adding and removing subjects, and provides a toggle to expand or collapse the list of selected subjects. Additional minor changes include translation string updates, code formatting improvements, and small refactors for clarity in modal handling and form validation logic. No changes were made to the logic or structure of other components.

## Changes

| File(s)                                                                                      | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|---------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `src/containers/tutor-home-page/subjects-step/SubjectsStep.jsx`                             | Replaced static placeholder with a dynamic subject selection UI using MUI Autocomplete, Chips, and Stack. Added state for main category, selected subject, subject list, and show/collapse toggle. Added subject addition/removal logic, subject count chip, and callback for subject changes. Significantly refactored component structure and props.                                                                                                                      |
| `src/constants/translations/en/become-tutor.json`,<br>`src/constants/translations/ua/become-tutor.json` | Added `"collapse"` translation key to the categories section in both English and Ukrainian. Minor whitespace and indentation cleanup in Ukrainian file.                                                                                                                                                                                                                                                                                                                                                                                                            |
| `src/components/info-general-step/InfoGeneralStep.tsx`                                      | Removed commented-out label and adjusted whitespace. No changes to logic or structure.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `src/containers/tutor-home-page/general-info-step/GeneralInfoStep.jsx`                      | Simplified `onBlur` handlers by removing redundant arrow functions. Cleaned up extraneous blank lines. No functional changes.                                                                                                                                                                                                                                                                                                                                                                                               |
| `src/pages/guest-home-page/GuestHome.tsx`                                                   | Refactored conditional modal opening logic from short-circuit expressions to explicit `if` statements for clarity. No change in behavior.                                                                                                                                                                                                                                                                                                                                                                                  |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant SubjectsStep
    participant UI
    participant ParentComponent

    User->>SubjectsStep: Selects main category
    SubjectsStep->>SubjectsStep: Updates mainCategory state

    User->>SubjectsStep: Selects subject
    SubjectsStep->>SubjectsStep: Updates selectedSubject state

    User->>SubjectsStep: Clicks "Add Subject"
    SubjectsStep->>SubjectsStep: Adds subject if valid and not duplicate
    SubjectsStep->>UI: Updates Chips display
    SubjectsStep->>ParentComponent: Calls onSubjectsChange (if provided)

    User->>SubjectsStep: Clicks Chip delete icon
    SubjectsStep->>SubjectsStep: Removes subject from list
    SubjectsStep->>UI: Updates Chips display
    SubjectsStep->>ParentComponent: Calls onSubjectsChange (if provided)

    User->>SubjectsStep: Clicks "Show all" or "Collapse"
    SubjectsStep->>SubjectsStep: Toggles showAllSubjects state
    SubjectsStep->>UI: Expands/collapses subject chips
```

## Possibly related PRs

- [Space2Study-UA-1355-02/Client-02#32](https://github.com/Space2Study-UA-1355-02/Client-02/pull/32): Introduces a new `UserStepsModal` component and styles in the same file as some of the formatting changes here, indicating related work on the onboarding or stepper flow.

## Suggested reviewers

- Don-de-padlo
- ruslansymonenko
- Kryzhanivsky
- olena-kuziaieva

## Poem

> In the garden of code, new subjects now bloom,  
> With chips and selections, there’s plenty of room.  
> Categories sorted, collapse with a click,  
> UI now dances—so lively, so slick!  
> A bunny approves, with a hop and a cheer,  
> For subjects and languages, springtime is here!  
> 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEejqANiS4AxEtWwUSAegDsANkiJsw0bmSINNyQAKoAkgYActjMApRcAMwAjAYhiPGQAMqURPBCAJwArEb6xuBQZPT4AGY4BMRkyjT0TKzsXLz8vmKS0pByCkpUqupaOqUmUHCoqJh1hKTkVM0KbRickFQA7l4xzGgU8gNMQypqmtq6YIZlpgaIFAzOrdz45OuIzvAY1QuNVBYwIESNxnGEfvgAOL/NAWTJBDT+AAeHAMACIMQYAMRYyAAQTCDSW1Dou1YB3kNUYsEwpEQZlgJEgtHg1VqTmY+CkyDQqzY6zoYHweEgFm+TNwNNwopUJCs9ElTOB3G4lEgvwozC8fngb3QyDRACV4ERYBt4SDVXwNcw0egMPQlFYaDysCRmNxcPIxeR+iQNRLGZAAAbAC3cAAKFC58CGemDq1e700+NoLPEb1hFlkABpIMxvvg+FsEC7uGgGEy0LQhNhAvz/JAtpQmfslOho9gHR2qPIlAwLAdqLqMK6Wm90yPYf0LPgGABrRB5gQijD4am0vrNpz56sS9eK0X4XIMPOBEm7jBoUgNvNFxNvdheXAUbBiRwkDQwIPVLs9TMWH6NISLqFB5t8A7YCyGBEPmijTjSDo+kQZ5BJslSUN8KH2uOPzwJqw56iysLHnmHLaKOkB/ohpC0BoRhGDi+IWDQywjsgBCQIe/aDmxbzIFSJBIq8FArPe3A+GKDCQOw6jwNIRiRI+6KYgYEBgEYDxPEw6wUZQny4HgRZgLALAkGA5akM4izKIC3y/ECQTONCxIWOCvzhhoQiICiKlotiuIEkSTSkt45KHPwtQMDRCkGHATLRZuyAclyTJOLQXa0Jg0oHNGOy/hg/5YFsVAqvpHbCt2h7BhIsKxiSNhFswCYMFmyDfFxQbBm8ABCFiOAmiG0FYFACbUh7VPhgSQFebA4TK02zUywbQEJuA2PJFi0C1LBJuwS5ePAHpitUshYZ17pceuLJOGI6HVC2hXSF+eJpnJAHZnma1UOQwoyIOGDzqK4rINuTJOiQKxoNUrEXSGtVillNCNZqCYFUVzL+t870YHm0Ow4ezDYCx8A+uD0gMBQ8CeiOIarUi62bdtePdvjaqHteCVvJNBEZlg0WiPOAj4EiD7JmR0jE+IMEoFgBZrtaTXUNLsEDvYGDYMEWzqKZIrQw9PQy+jfN1V69EMUxeIsU07FXXDPFDnzY0ycJRZiXwEkCFJMnrHJsVKeQfklHcWnPG8uB6aNziGQQFAmWZFmc843jdP4jkgs4mQ+CIYiIJ53m+Ri/mW4SNnLKFewUpFG4wbF8Uhlnqd50EO0eo+6xNmgyC/hY2boSV6g0FgnFONwg6Vugz7DtJY8ViQplbWq2uSpPtCyLN8DSSnOfSukVgY98rHVHPX5hNKa47HWfSGvYd3njQkCmfgi52/sV6kCG+zfAAwiSRBFrIYMeZgx7z8HQRuO8gEhm3n4RACYAAUcxcpoEpLUasSh6AwNzgAShZvQEBpkthWzhNnWBCDeQECIEQKw6p7wskQLPM6Mssy7Cbtgr80AtjrgALLhBDHiIyLxnQkFbntD46Be74EvukUadtQF3V5F/fmf8AHzV5Fg6U1Roxal5LwOgWNyD0DFNNeBwZWo0H/lTaQ3C5zzmDOw/EWBgzoIgX4NGf4+boDTBxIM8iVgaLttVDRcDgbTVZCgaUqA1w5QsE4as8g9HpA7pgBUvi5Q6j1KgBGsY8z0JUMhOG6D+h4AIFgfAioKDa3SBwoMLx26701iJRsKUQIy2CZAECvJgzfwQNwUR9TQY60xsIlAOlECn2lPQxhyBNaBK4dqfe/jSG536H2f0aApZ5mXrASeA5N7znyQlXpXhCHnUPEwLs0oqQIDTGQVhO92q1E5DuSUcxcDzIOEqdJYg6AvSulQmhK5cClIkbOLYyAhLlgdOde8TBe5oG4IgM5P5iaAWMVc2owSalMj0SBP6zJ8J+HQg6TCMsqTBgELgUcPURYJiiVI2WFjy70GoHDYWwKWDV0POQHYgRXzvnSjKWQwppR1nOrwsIDcI4LigStWQrwiClVgIAvB/CVQ9RKW8fpyZxnfi5m3ZMEjEDrlar3V0/AaYARDG8VxucembhalmAQFYgYlkaFIPgh52noprnSc2jFArWz4pRTi3FRC8UIpRQSrtRKknEpJTePtxDiFilAGwHjaZ1MNcGW1/hwx0qcaHHSEdxRRxjsZUybBE5WWCenUEubm4gi8j5BMWwu5wRZJNUknEKyVk9PaLxk4rW8HwMEbqGAG32trgmFJdsIL9XbDyqeD9apU0OcgUxSjf4WIAbKvx4Dlm4D3YeuBwDECEOIQ2+x80l2H0oFeQCxtbamJcYe2VLSSC5tlZQ6hn6L291lZrJGn6T32LPCaDArJN7ZT7olGC511DtQFBQB9R4TzzT4U4ElVMYL0SLsHDS9xHjOEstIay2BpC4HjlW0jzkKOBAABJmURD5VE+GS7BWZWSfYEUqRwbpAyLm0KTaAW+BIOckbnbdVVBgGxWULAJmdekKoWAQiGgADLagONFHgQ42CsWQGY7m+FmDQGfmQd90hIZmfnBZ1VwZZy5AwDOncThj5iCLKSLRnKxVtNMqJMADB8IMGwOoND0HAJ4kiAAERdokpF/E7aQqkmF4MrIEz33dPtGpqB+NMkPtGDKlZkBq0+XwYt0ZH1gtWU2Uq3Bzq3x2ZyeTQoZPnUc4mr2tjZZIvbIh/gWwnHpeXVl9Y2LwvSVnXEYCoF0JKPVBmj68gSAAEdQsI3YFsoZa5fV9E4pQaMfAhoFPvL1pk/oDb+HG04aaVJzm7XqeBQqC7zoAClMgAA1iVDHOrOp+L86ycwlkomZhUYp0QDcxViknAlBgdsG52kK3Zxo9gm6SskU30iiMpfDakQ7EbGRHD40cfqIEHE7ZwZBnBxFaOZctFBm1vDY5iDjZcSSYMrrxqKMUsf1xfJgMnkbIDvYAPKRFoZ6oMaIacJ3p3aUjncZncGA/QAY6DfszRIDsWzsgwAIwo7p/CIY0RwsHIikgaIuBom/vgeF5u0QJkyuzLqJuVFWMQA77URUcs8jep47wKorANh8edpESAVaQB14MyUIqO2siYbBe8LTfsYGW2HwIDX1ju/NpbINMPQ1w/DY7W20amko54GjpNfssdQFehgyeS7+ejnJ7THXxvTcIvSJbyA1vbdm67wWuGwZXc7vd57wQO9ZbQIJ/xIn/gScC5b/xSnGBqeiFl0ZBn3ktV4dUupTSM/Rxz4MqTpfo5nDYDQGv2nYB6eM4wMz4ugVS4wiWeFVBu3ee1J53N1KXEqCkznQMJzw8gwzO5Mhohs5uQQh2izpogAxECX6kB2hR5T6HhojKjqaygWAe5e58x/KN6n5C5t4m596d4W5NhDKHj64QGADoIIAMwggAfCCAACIIALwggAwiCABCIIABwgdoswty9ATukuEB5iJAli8kuB6Q3ukA4IcMaI3ApkBAdoUhfMT2Sguknis6wBQWzCO4TAFAt0KwGooKkeJAsg0eus0o/GKe8gNADMCgAoY2kASk/AFScek05itsoaRB/uL4WEAkfAfKb4hkO4nyu4SgOega0OTssO5MA4xeiWpeyOVQqOXsiaGOEhikj442k0NCbwsG4cFEHEPhtMfK/hN664SOsaKRFeaR0kJw52vsmOu+/keONwkwPsVQaCRknG7OfI7QmwaAvKnORw8gDRww5wYwVwhgHRrQBYuAAA+rGIgAsU4CBFrnQAseeKJNMbcFAAAEwCD5D7FJCuCuAAAc+xrg+x+xtA1xhQ1Q+xAALAwK1AIOcUkOcQAAzVD5AkBfFJD7HnECC0ACCFDuC1ATDlCQDJD/FfHnEeBJCfH5DVBPH5BJAJACDuDnEMCFCFBPFPGuBfGuAEn2BfHuBfEJCXFJCQnXAGAdGuAJBPGFACD7FoAJCuACAAlJACBPFAkqC0D7H5A4n5Cim0D5BKA8lXFYkkA3G7EdEJBUlPEkCMnVDuBJCvEXFJCgm0AMBZT4lgnnG0DfGqBoDKkMBfGiCfHynQnVCfFoDuDuACCuAPGqCsloD5BOlfG4kkBJDuBoCnGfGPGvEJDkkQn5ACC7H0nQlzHqBLG0ArFrHyTNi0ALGVDTFAA= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Space2Study-UA-1355-02/Client-02&utm_content=31):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-02T11:53:15Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=Space2Study-UA-1355-02_Client-02&pullRequest=31) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=Space2Study-UA-1355-02_Client-02&pullRequest=31&metric=new_coverage&view=list) (required ≥ 80%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Space2Study-UA-1355-02_Client-02&pullRequest=31)


author_association: NONE