From 23a1ff18bc68b45f26d92c2e671f8453b829489d Mon Sep 17 00:00:00 2001
From: Nikita Mashchenko
Date: Tue, 4 Jul 2023 22:57:16 -0500
Subject: [PATCH 1/2] Finished logic for updating
---
client/src/assets/LanguageLogo/CSS.js | 12 +
client/src/assets/LanguageLogo/Kotlin.js | 12 +
client/src/assets/LanguageLogo/Lua.js | 20 ++
client/src/assets/LanguageLogo/R.js | 18 ++
client/src/assets/LanguageLogo/Rust.js | 14 +
client/src/assets/LanguageLogo/TS.js | 16 +
.../src/components/NavBar/Profile/Profile.jsx | 2 -
client/src/components/Profile/Profile.jsx | 12 +-
.../EditingComponentEducation.jsx | 299 ------------------
.../EditingComponentEducation.jsx | 152 +++++++++
.../States/Adding.jsx | 104 ++++++
.../States/Editing.jsx | 120 +++++++
.../EditingComponentEducation/States/Main.jsx | 99 ++++++
.../EditingComponents/EditingComponentJob.jsx | 279 ----------------
.../EditingComponentJob.jsx | 149 +++++++++
.../EditingComponentJob/States/Adding.jsx | 83 +++++
.../EditingComponentJob/States/Editing.jsx | 103 ++++++
.../EditingComponentJob/States/Main.jsx | 92 ++++++
.../EditingComponentProfile.jsx | 13 +-
.../components/ResumeInfo/ResumeInfo.jsx | 4 +-
.../UserEducationForm/UserEducationForm.jsx | 2 +-
.../UserJobForm/UserJobForm.jsx | 6 +-
client/src/constants/concentrations.js | 48 ++-
client/src/constants/frameworkColors.js | 64 ++--
client/src/constants/frameworks.js | 18 +-
client/src/constants/programmingLanguages.js | 22 +-
client/src/http/index.js | 2 -
client/src/schemas/index.js | 137 ++++++++
.../CheckboxWithLabel/CheckboxWithLabel.js | 0
.../CheckboxWithLabel.styles.js | 0
.../Formik/CustomInput/CustomInput.jsx | 4 +
client/src/utils/convertStringToDate.js | 14 +-
server/src/maintenance/maintenance.service.ts | 30 +-
33 files changed, 1315 insertions(+), 635 deletions(-)
create mode 100644 client/src/assets/LanguageLogo/CSS.js
create mode 100644 client/src/assets/LanguageLogo/Kotlin.js
create mode 100644 client/src/assets/LanguageLogo/Lua.js
create mode 100644 client/src/assets/LanguageLogo/R.js
create mode 100644 client/src/assets/LanguageLogo/Rust.js
create mode 100644 client/src/assets/LanguageLogo/TS.js
delete mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Adding.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Editing.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Main.jsx
delete mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Adding.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Editing.jsx
create mode 100644 client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
rename client/src/{components/RegistrationPipeline => shared}/components/CheckboxWithLabel/CheckboxWithLabel.js (100%)
rename client/src/{components/RegistrationPipeline => shared}/components/CheckboxWithLabel/CheckboxWithLabel.styles.js (100%)
diff --git a/client/src/assets/LanguageLogo/CSS.js b/client/src/assets/LanguageLogo/CSS.js
new file mode 100644
index 000000000..1c3d992d9
--- /dev/null
+++ b/client/src/assets/LanguageLogo/CSS.js
@@ -0,0 +1,12 @@
+function CSS() {
+ return (
+
+ )
+}
+
+export default CSS
diff --git a/client/src/assets/LanguageLogo/Kotlin.js b/client/src/assets/LanguageLogo/Kotlin.js
new file mode 100644
index 000000000..808d18953
--- /dev/null
+++ b/client/src/assets/LanguageLogo/Kotlin.js
@@ -0,0 +1,12 @@
+function Kotlin() {
+ return (
+
+ )
+}
+
+export default Kotlin
diff --git a/client/src/assets/LanguageLogo/Lua.js b/client/src/assets/LanguageLogo/Lua.js
new file mode 100644
index 000000000..f3a8f71d9
--- /dev/null
+++ b/client/src/assets/LanguageLogo/Lua.js
@@ -0,0 +1,20 @@
+function Lua() {
+ return (
+
+ )
+}
+
+export default Lua
diff --git a/client/src/assets/LanguageLogo/R.js b/client/src/assets/LanguageLogo/R.js
new file mode 100644
index 000000000..6de2f3cf7
--- /dev/null
+++ b/client/src/assets/LanguageLogo/R.js
@@ -0,0 +1,18 @@
+function R() {
+ return (
+
+ )
+}
+
+export default R
diff --git a/client/src/assets/LanguageLogo/Rust.js b/client/src/assets/LanguageLogo/Rust.js
new file mode 100644
index 000000000..c6fd44f60
--- /dev/null
+++ b/client/src/assets/LanguageLogo/Rust.js
@@ -0,0 +1,14 @@
+function Rust() {
+ return (
+
+ )
+}
+
+export default Rust
diff --git a/client/src/assets/LanguageLogo/TS.js b/client/src/assets/LanguageLogo/TS.js
new file mode 100644
index 000000000..bab55baec
--- /dev/null
+++ b/client/src/assets/LanguageLogo/TS.js
@@ -0,0 +1,16 @@
+function TS() {
+ return (
+
+ )
+}
+
+export default TS
diff --git a/client/src/components/NavBar/Profile/Profile.jsx b/client/src/components/NavBar/Profile/Profile.jsx
index 5297d2417..d8fdfb7ee 100644
--- a/client/src/components/NavBar/Profile/Profile.jsx
+++ b/client/src/components/NavBar/Profile/Profile.jsx
@@ -14,8 +14,6 @@ let defaultData = {
}
const changeData = (data) => {
- console.log(data)
-
return {
userRealName: data.fullName,
userUsername: data.username,
diff --git a/client/src/components/Profile/Profile.jsx b/client/src/components/Profile/Profile.jsx
index 0650a1411..68bcca2e2 100644
--- a/client/src/components/Profile/Profile.jsx
+++ b/client/src/components/Profile/Profile.jsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
-import { Formik, useFormikContext } from 'formik'
+import { Formik } from 'formik'
import { useCheckAuth } from '../../api/hooks/auth/useCheckAuth'
import { useUpdateAvatar } from '../../api/hooks/shared/useUpdateAvatar'
@@ -12,6 +12,7 @@ import { usePrompt } from '../../hooks/usePrompt'
import { editProfileValidation } from '../../schemas'
import Loader from '../../shared/components/Loader/Loader'
import ModalComponent from '../../shared/components/Modal/Modal'
+import { formatDateString } from '../../utils/convertStringToDate'
import Page404Form from '../Forms/Page404Form/Page404Form'
import ProfileInfo from './components/ProfileInfo/ProfileInfo'
@@ -46,6 +47,7 @@ const Profile = () => {
github,
telegram,
linkedIn,
+ behance,
programmingLanguages,
frameworks,
dateOfBirth,
@@ -54,6 +56,9 @@ const Profile = () => {
universityData,
file,
} = values
+
+ const formattedDOB = formatDateString(dateOfBirth)
+
const modifiedUserData = {
email: showingUser.email,
fullName,
@@ -65,10 +70,11 @@ const Profile = () => {
github,
telegram,
linkedIn,
+ behance,
},
programmingLanguages,
frameworks,
- dateOfBirth,
+ dateOfBirth: formattedDOB,
projectData,
jobData,
universityData,
@@ -95,6 +101,7 @@ const Profile = () => {
github: showingUser?.links?.github,
linkedIn: showingUser?.links?.linkedIn,
telegram: showingUser?.links?.telegram,
+ behance: showingUser?.links?.behance,
description: showingUser?.description,
concentration: showingUser?.concentration,
country: showingUser?.country,
@@ -112,6 +119,7 @@ const Profile = () => {
onSubmit={handleSubmit}
>
{({ values, errors, dirty }) => {
+ console.log(values, dirty)
usePrompt('You have unsaved changes. Do you want to discard them?', dirty)
return (
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation.jsx
deleted file mode 100644
index 78b61e3e3..000000000
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation.jsx
+++ /dev/null
@@ -1,299 +0,0 @@
-import { useState } from 'react'
-import { ThreeDots } from 'react-loader-spinner'
-import { FieldArray, useFormikContext } from 'formik'
-
-import { useEditUserDetails } from '../../../../../api/hooks/user/useEditUserDetails'
-import LongArrowLeft from '../../../../../assets/Arrows/LongArrowLeft'
-import CrossIcon from '../../../../../assets/UserProfile/CrossIcon'
-import EditIcon from '../../../../../assets/UserProfile/EditIcon'
-import PlusIconWhite from '../../../../../assets/UserProfile/PlusIconWhite'
-import FlexWrapper from '../../../../../shared/components/FlexWrapper/FlexWrapper'
-import CustomInput from '../../../../../shared/components/Formik/CustomInput/CustomInput'
-import ModalComponent from '../../../../../shared/components/Modal/Modal'
-import { ActionButton, EditIconContainer, Text } from '../ResumeInfo.styles'
-
-function EditingComponentEducation({ handleBack, showingUser }) {
- const [modalActive, setModalActive] = useState('')
- const { values, setFieldValue, resetForm } = useFormikContext()
- const [currentAction, setCurrentAction] = useState('main') // 'main', 'editing', 'adding'
- const [index, setIndex] = useState(0)
-
- const handleReset = () => {
- setModalActive('')
- setCurrentAction('main')
- }
-
- const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
-
- const handleRemoveUniversity = () => {
- const universities = [...values.universityData]
-
- const updatedUniversityData = universities.filter((_, i) => i !== index)
-
- setFieldValue('universityData', updatedUniversityData)
-
- editUserDetails({ email: showingUser.email, universityData: updatedUniversityData })
- }
-
- const handleEditUniversity = (index) => {
- setIndex(index)
- setCurrentAction('editing')
- }
-
- const submitEditUniversity = () => {
- editUserDetails({ email: showingUser.email, universityData: values.universityData })
- }
-
- const handleOpenModal = (index) => {
- setModalActive('DeleteUniversity')
- setIndex(index)
- }
-
- const handleClose = () => {
- setModalActive('')
- }
-
- const handleCancel = () => {
- setCurrentAction('main')
- resetForm()
- }
-
- return (
- <>
-
-
-
- Education
-
- {currentAction === 'main' && (
-
- {({ push, remove }) => (
- <>
- {values?.universityData?.length > 0 ? (
- values?.universityData.map((university, index) => (
-
-
-
- {university.degree} - {university.major}
-
-
- {university.university}
-
-
- {university?.addmissionDate?.split('-')[0]} -{' '}
- {university?.graduationDate?.split('-')[0]}
-
-
-
- handleEditUniversity(index)}
- >
-
-
- handleOpenModal(index)}
- >
-
-
-
-
- ))
- ) : (
-
- No universities added yet.
-
- )}
-
-
-
- Back
-
- {
- push({
- university: '',
- degree: ``,
- major: '',
- addmissionDate: '',
- graduationDate: '',
- })
- setCurrentAction('adding')
- }}
- type="button"
- disabled={values.universityData.length === 2 ? true : false}
- >
- Add new
-
-
-
- >
- )}
-
- )}
-
- {currentAction === 'editing' && (
- <>
-
-
-
-
-
-
-
-
-
-
- Cancel
-
-
- {isLoading ? (
-
- ) : (
- 'Save'
- )}
-
-
-
- >
- )}
-
- {currentAction === 'adding' && (
- <>
-
-
-
-
-
-
-
-
-
-
- Cancel
-
-
- {isLoading ? (
-
- ) : (
- 'Save'
- )}
-
-
-
- >
- )}
-
- >
- )
-}
-
-export default EditingComponentEducation
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
new file mode 100644
index 000000000..b5f0a556a
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
@@ -0,0 +1,152 @@
+import { useEffect, useState } from 'react'
+import { useFormikContext } from 'formik'
+import { cloneDeep } from 'lodash'
+
+import { useEditUserDetails } from '../../../../../../api/hooks/user/useEditUserDetails'
+import FlexWrapper from '../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import ModalComponent from '../../../../../../shared/components/Modal/Modal'
+import { errorToaster } from '../../../../../../shared/components/Toasters/Error.toaster'
+import { Text } from '../../ResumeInfo.styles'
+
+import Adding from './States/Adding'
+import Editing from './States/Editing'
+import Main from './States/Main'
+
+function EditingComponentEducation({ handleBack, showingUser }) {
+ const [modalActive, setModalActive] = useState('')
+ const { values, setFieldValue, resetForm, validateForm, setErrors } = useFormikContext()
+ const [currentAction, setCurrentAction] = useState('main') // 'main', 'editing', 'adding'
+ const [index, setIndex] = useState(0)
+ const [checkbox, setCheckbox] = useState(false)
+
+ useEffect(() => {
+ values && values?.universityData[index]?.graduationDate === null
+ ? setCheckbox(true)
+ : setCheckbox(false)
+ }, [index])
+
+ const handleReset = () => {
+ setModalActive('')
+ setCurrentAction('main')
+ }
+
+ const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
+
+ const handleRemoveUniversity = () => {
+ const universities = [...values.universityData]
+
+ const updatedUniversityData = universities.filter((_, i) => i !== index)
+
+ setFieldValue('universityData', updatedUniversityData)
+ setIndex((prev) => prev - 1)
+
+ editUserDetails({ email: showingUser.email, universityData: updatedUniversityData })
+ }
+
+ const handleEditUniversity = (index) => {
+ setIndex(index)
+ setCurrentAction('editing')
+ }
+
+ const submitEditUniversity = async () => {
+ const validation = await validateForm()
+
+ console.log(validation)
+
+ if (!validation?.universityData) {
+ const initialObject = cloneDeep(values.universityData)
+
+ initialObject[index].addmissionDate = new Date(
+ String(initialObject[index].addmissionDate),
+ ).toISOString()
+ initialObject[index].graduationDate = initialObject[index].graduationDate
+ ? new Date(String(initialObject[index].graduationDate)).toISOString()
+ : null
+
+ setFieldValue(`universityData[${index}].addmissionDate`, initialObject[index].addmissionDate)
+ setFieldValue(`universityData[${index}].graduationDate`, initialObject[index].graduationDate)
+
+ editUserDetails({ email: showingUser.email, universityData: initialObject })
+ } else {
+ setErrors({ universityData: validation.universityData[index] })
+ errorToaster('Fill in data before submission!')
+ }
+ }
+
+ const handleOpenModal = (index) => {
+ setModalActive('DeleteUniversity')
+ setIndex(index)
+ }
+
+ const handleClose = () => {
+ setModalActive('')
+ }
+
+ const handleCancel = () => {
+ setCurrentAction('main')
+ resetForm()
+ setIndex(0)
+ }
+
+ const handleClick = () => {
+ if (checkbox) {
+ setCheckbox(false)
+ setFieldValue(`universityData[${index}].graduationDate`, '')
+ } else {
+ setCheckbox(true)
+ setFieldValue(`universityData[${index}].graduationDate`, null)
+ }
+ }
+
+ return (
+ <>
+
+
+
+ Education
+
+ {currentAction === 'main' && (
+
+ )}
+
+ {currentAction === 'editing' && (
+
+ )}
+
+ {currentAction === 'adding' && (
+
+ )}
+
+ >
+ )
+}
+
+export default EditingComponentEducation
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Adding.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Adding.jsx
new file mode 100644
index 000000000..b7d8b1360
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Adding.jsx
@@ -0,0 +1,104 @@
+import { ThreeDots } from 'react-loader-spinner'
+import { useFormikContext } from 'formik'
+
+import { degrees } from '../../../../../../../constants/degrees'
+import { majors } from '../../../../../../../constants/majors'
+import CheckboxWithLabel from '../../../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import CustomInput from '../../../../../../../shared/components/Formik/CustomInput/CustomInput'
+import CustomSelectAutocomplete from '../../../../../../../shared/components/Formik/CustomSelectAutocomplete/CustomSelectAutocomplete'
+import { ActionButton } from '../../../ResumeInfo.styles'
+
+const Adding = ({
+ handleCancel,
+ submitEditUniversity,
+ isLoading,
+ handleClick,
+ checkbox,
+ index,
+}) => {
+ const { values, errors } = useFormikContext()
+
+ return (
+
+
+
+
+
+
+
+ {!checkbox && (
+
+ )}
+
+
+
+
+
+ Cancel
+
+
+ {isLoading ? (
+
+ ) : (
+ 'Save'
+ )}
+
+
+
+ )
+}
+
+export default Adding
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Editing.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Editing.jsx
new file mode 100644
index 000000000..681b13936
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Editing.jsx
@@ -0,0 +1,120 @@
+import { useEffect } from 'react'
+import { ThreeDots } from 'react-loader-spinner'
+import { useFormikContext } from 'formik'
+
+import { degrees } from '../../../../../../../constants/degrees'
+import CheckboxWithLabel from '../../../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import CustomInput from '../../../../../../../shared/components/Formik/CustomInput/CustomInput'
+import CustomSelectAutocomplete from '../../../../../../../shared/components/Formik/CustomSelectAutocomplete/CustomSelectAutocomplete'
+import { ActionButton } from '../../../ResumeInfo.styles'
+
+const Editing = ({
+ index,
+ isLoading,
+ handleCancel,
+ submitEditUniversity,
+ checkbox,
+ handleClick,
+}) => {
+ const { setFieldValue, errors, values } = useFormikContext()
+
+ useEffect(() => {
+ setFieldValue(
+ `universityData[${index}].addmissionDate`,
+ Number(values?.universityData[index]?.addmissionDate?.slice(0, 4)),
+ )
+
+ if (values?.universityData[index]?.graduationDate) {
+ setFieldValue(
+ `universityData[${index}].graduationDate`,
+ Number(values?.universityData[index]?.graduationDate.slice(0, 4)),
+ )
+ }
+ }, [])
+
+ return (
+
+
+
+
+
+
+
+ {!checkbox && (
+
+ )}
+
+
+
+
+
+
+ Cancel
+
+
+ {isLoading ? (
+
+ ) : (
+ 'Save'
+ )}
+
+
+
+ )
+}
+
+export default Editing
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Main.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Main.jsx
new file mode 100644
index 000000000..7831e36df
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/States/Main.jsx
@@ -0,0 +1,99 @@
+import { FieldArray } from 'formik'
+
+import LongArrowLeft from '../../../../../../../assets/Arrows/LongArrowLeft'
+import CrossIcon from '../../../../../../../assets/UserProfile/CrossIcon'
+import EditIcon from '../../../../../../../assets/UserProfile/EditIcon'
+import PlusIconWhite from '../../../../../../../assets/UserProfile/PlusIconWhite'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import { ActionButton, EditIconContainer, Text } from '../../../ResumeInfo.styles'
+
+const Main = ({
+ values,
+ handleEditUniversity,
+ handleOpenModal,
+ handleBack,
+ setCurrentAction,
+ setIndex,
+ index,
+}) => {
+ return (
+
+ {({ push, remove }) => (
+ <>
+ {values?.universityData?.length > 0 ? (
+ values?.universityData.map((university, index) => (
+
+
+
+ {university.degree} - {university.major}
+
+
+ {university.university}
+
+
+ {university?.addmissionDate?.split('-')[0]} -{' '}
+ {university?.addmissionDate && university?.graduationDate === null
+ ? 'Present'
+ : university?.graduationDate?.split('-')[0]}
+
+
+
+ handleEditUniversity(index)}
+ >
+
+
+ handleOpenModal(index)}
+ >
+
+
+
+
+ ))
+ ) : (
+
+ No universities added yet.
+
+ )}
+
+
+
+ Back
+
+ {
+ values.universityData.length !== 0 && setIndex((prev) => prev + 1)
+ push({
+ university: '',
+ degree: ``,
+ major: '',
+ addmissionDate: '',
+ graduationDate: '',
+ })
+ setCurrentAction('adding')
+ }}
+ type="button"
+ disabled={values.universityData.length === 2 ? true : false}
+ >
+ Add new
+
+
+
+ >
+ )}
+
+ )
+}
+
+export default Main
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob.jsx
deleted file mode 100644
index 65d5c2c5a..000000000
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob.jsx
+++ /dev/null
@@ -1,279 +0,0 @@
-import { useState } from 'react'
-import { ThreeDots } from 'react-loader-spinner'
-import { FieldArray, useFormikContext } from 'formik'
-
-import { useEditUserDetails } from '../../../../../api/hooks/user/useEditUserDetails'
-import LongArrowLeft from '../../../../../assets/Arrows/LongArrowLeft'
-import CrossIcon from '../../../../../assets/UserProfile/CrossIcon'
-import EditIcon from '../../../../../assets/UserProfile/EditIcon'
-import PlusIconWhite from '../../../../../assets/UserProfile/PlusIconWhite'
-import FlexWrapper from '../../../../../shared/components/FlexWrapper/FlexWrapper'
-import CustomInput from '../../../../../shared/components/Formik/CustomInput/CustomInput'
-import ModalComponent from '../../../../../shared/components/Modal/Modal'
-import { ActionButton, EditIconContainer, Text } from '../ResumeInfo.styles'
-
-function EditingComponentJob({ handleBack, showingUser }) {
- const [modalActive, setModalActive] = useState('')
- const { values, setFieldValue, resetForm } = useFormikContext()
- const [currentAction, setCurrentAction] = useState('main') // 'main', 'editing', 'adding'
- const [index, setIndex] = useState(0)
-
- const handleReset = () => {
- setModalActive('')
- setCurrentAction('main')
- }
-
- const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
-
- const handleRemoveUniversity = () => {
- const jobs = [...values.jobData]
-
- const updatedJobData = jobs.filter((_, i) => i !== index)
-
- setFieldValue('jobData', updatedJobData)
-
- editUserDetails({ email: showingUser.email, jobData: updatedJobData })
- }
-
- const handleEditJob = (index) => {
- setIndex(index)
- setCurrentAction('editing')
- }
-
- const submitEditJob = () => {
- editUserDetails({ email: showingUser.email, jobData: values.jobData })
- }
-
- const handleOpenModal = (index) => {
- setModalActive('DeleteJob')
- setIndex(index)
- }
-
- const handleClose = () => {
- setModalActive('')
- }
-
- const handleCancel = () => {
- setCurrentAction('main')
- resetForm()
- }
-
- return (
- <>
-
-
-
- Work Experience
-
- {currentAction === 'main' && (
-
- {({ push, remove }) => (
- <>
- {values?.jobData?.length > 0 ? (
- values?.jobData.map((job, index) => (
-
-
-
- {job.title} - {job.company}
-
-
- {job.startDate.split('-')[0]} - {job.endDate.split('-')[0]}
-
-
-
- handleEditJob(index)}
- >
-
-
- handleOpenModal(index)}
- >
-
-
-
-
- ))
- ) : (
-
- No jobs added yet.
-
- )}
-
-
-
- Back
-
- {
- push({
- title: '',
- company: ``,
- startDate: '',
- endDate: '',
- })
- setCurrentAction('adding')
- }}
- type="button"
- disabled={values.jobData.length === 2 ? true : false}
- >
- Add new
-
-
-
- >
- )}
-
- )}
-
- {currentAction === 'editing' && (
- <>
-
-
-
-
-
-
-
-
-
- Cancel
-
-
- {isLoading ? (
-
- ) : (
- 'Save'
- )}
-
-
-
- >
- )}
-
- {currentAction === 'adding' && (
- <>
-
-
-
-
-
-
-
-
-
- Cancel
-
-
- {isLoading ? (
-
- ) : (
- 'Save'
- )}
-
-
-
- >
- )}
-
- >
- )
-}
-
-export default EditingComponentJob
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
new file mode 100644
index 000000000..97030261c
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
@@ -0,0 +1,149 @@
+import { useEffect, useState } from 'react'
+import { useFormikContext } from 'formik'
+import { cloneDeep } from 'lodash'
+
+import { useEditUserDetails } from '../../../../../../api/hooks/user/useEditUserDetails'
+import FlexWrapper from '../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import ModalComponent from '../../../../../../shared/components/Modal/Modal'
+import { errorToaster } from '../../../../../../shared/components/Toasters/Error.toaster'
+import { Text } from '../../ResumeInfo.styles'
+
+import Adding from './States/Adding'
+import Editing from './States/Editing'
+import Main from './States/Main'
+
+function EditingComponentJob({ handleBack, showingUser }) {
+ const [modalActive, setModalActive] = useState('')
+ const { values, setFieldValue, resetForm, validateForm, setErrors } = useFormikContext()
+ const [currentAction, setCurrentAction] = useState('main') // 'main', 'editing', 'adding'
+ const [index, setIndex] = useState(0)
+ const [checkbox, setCheckbox] = useState(false)
+
+ useEffect(() => {
+ console.log(index)
+ values && values?.jobData[index]?.endDate === null ? setCheckbox(true) : setCheckbox(false)
+ }, [index])
+
+ const handleReset = () => {
+ setModalActive('')
+ setCurrentAction('main')
+ }
+
+ const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
+
+ const handleRemoveJob = () => {
+ const jobs = [...values.jobData]
+
+ const updatedJobData = jobs.filter((_, i) => i !== index)
+
+ setFieldValue('jobData', updatedJobData)
+ setIndex((prev) => prev - 1)
+
+ editUserDetails({ email: showingUser.email, jobData: updatedJobData })
+ }
+
+ const handleEditJob = (index) => {
+ setIndex(index)
+ setCurrentAction('editing')
+ }
+
+ const submitEditJob = async () => {
+ const validation = await validateForm()
+
+ if (!validation?.jobData) {
+ const initialObject = cloneDeep(values.jobData)
+
+ initialObject[index].startDate = new Date(
+ String(initialObject[index].startDate),
+ ).toISOString()
+ initialObject[index].endDate = initialObject[index].endDate
+ ? new Date(String(initialObject[index].endDate)).toISOString()
+ : null
+
+ setFieldValue(`jobData[${index}].startDate`, initialObject[index].startDate)
+ setFieldValue(`jobData[${index}].endDate`, initialObject[index].endDate)
+
+ editUserDetails({ email: showingUser.email, jobData: initialObject })
+ } else {
+ setErrors({ jobData: validation.jobData[index] })
+ errorToaster('Fill in data before submission!')
+ }
+ }
+
+ const handleOpenModal = (index) => {
+ setModalActive('DeleteJob')
+ setIndex(index)
+ }
+
+ const handleClose = () => {
+ setModalActive('')
+ }
+
+ const handleCancel = () => {
+ setCurrentAction('main')
+ resetForm()
+ setIndex(0)
+ }
+
+ const handleClick = () => {
+ if (checkbox) {
+ setCheckbox(false)
+ setFieldValue(`jobData[${index}].endDate`, '')
+ } else {
+ setCheckbox(true)
+ setFieldValue(`jobData[${index}].endDate`, null)
+ }
+ }
+
+ return (
+ <>
+
+
+
+ Work Experience
+
+ {currentAction === 'main' && (
+
+ )}
+
+ {currentAction === 'editing' && (
+
+ )}
+
+ {currentAction === 'adding' && (
+
+ )}
+
+ >
+ )
+}
+
+export default EditingComponentJob
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Adding.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Adding.jsx
new file mode 100644
index 000000000..9f2a94158
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Adding.jsx
@@ -0,0 +1,83 @@
+import { ThreeDots } from 'react-loader-spinner'
+import { useFormikContext } from 'formik'
+
+import CheckboxWithLabel from '../../../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import CustomInput from '../../../../../../../shared/components/Formik/CustomInput/CustomInput'
+import { ActionButton } from '../../../ResumeInfo.styles'
+
+const Adding = ({ handleCancel, submitEditJob, isLoading, handleClick, checkbox }) => {
+ const { values, errors } = useFormikContext()
+
+ return (
+
+
+
+
+
+ {!checkbox && (
+
+ )}
+
+
+
+
+ Cancel
+
+
+ {isLoading ? (
+
+ ) : (
+ 'Save'
+ )}
+
+
+
+ )
+}
+
+export default Adding
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Editing.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Editing.jsx
new file mode 100644
index 000000000..7090ab1f4
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Editing.jsx
@@ -0,0 +1,103 @@
+import { useEffect } from 'react'
+import { ThreeDots } from 'react-loader-spinner'
+import { useFormikContext } from 'formik'
+
+import CheckboxWithLabel from '../../../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import CustomInput from '../../../../../../../shared/components/Formik/CustomInput/CustomInput'
+import { ActionButton } from '../../../ResumeInfo.styles'
+
+const Editing = ({ index, checkbox, handleCancel, handleClick, submitEditJob, isLoading }) => {
+ const { setFieldValue, errors, values } = useFormikContext()
+
+ useEffect(() => {
+ setFieldValue(
+ `jobData[${index}].startDate`,
+ Number(values?.jobData[index]?.startDate?.slice(0, 4)),
+ )
+
+ if (values?.jobData[index]?.endDate) {
+ setFieldValue(
+ `jobData[${index}].endDate`,
+ Number(values?.jobData[index]?.endDate.slice(0, 4)),
+ )
+ }
+ }, [])
+
+ return (
+
+
+
+
+
+
+ {!checkbox && (
+
+ )}
+
+
+
+
+ Cancel
+
+
+ {isLoading ? (
+
+ ) : (
+ 'Save'
+ )}
+
+
+
+ )
+}
+
+export default Editing
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
new file mode 100644
index 000000000..b8c950d9d
--- /dev/null
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
@@ -0,0 +1,92 @@
+import { FieldArray } from 'formik'
+
+import LongArrowLeft from '../../../../../../../assets/Arrows/LongArrowLeft'
+import CrossIcon from '../../../../../../../assets/UserProfile/CrossIcon'
+import EditIcon from '../../../../../../../assets/UserProfile/EditIcon'
+import PlusIconWhite from '../../../../../../../assets/UserProfile/PlusIconWhite'
+import FlexWrapper from '../../../../../../../shared/components/FlexWrapper/FlexWrapper'
+import { ActionButton, EditIconContainer, Text } from '../../../ResumeInfo.styles'
+
+const Main = ({
+ values,
+ handleEditJob,
+ handleOpenModal,
+ handleBack,
+ setCurrentAction,
+ setIndex,
+ index,
+}) => {
+ return (
+
+ {({ push, remove }) => (
+ <>
+ {values?.jobData?.length > 0 ? (
+ values?.jobData.map((job, index) => (
+
+
+
+ {job.title} - {job.company}
+
+
+ {job?.startDate?.split('-')[0]} -{' '}
+ {job?.startDate && job?.endDate === null
+ ? 'Present'
+ : job?.endDate?.split('-')[0]}
+
+
+
+ handleEditJob(index)}>
+
+
+ handleOpenModal(index)}
+ >
+
+
+
+
+ ))
+ ) : (
+
+ No jobs added yet.
+
+ )}
+
+
+
+ Back
+
+ {
+ values.jobData.length !== 0 && setIndex((prev) => prev + 1)
+ push({
+ title: '',
+ company: ``,
+ startDate: '',
+ endDate: '',
+ })
+ setCurrentAction('adding')
+ }}
+ type="button"
+ disabled={values?.jobData?.length === 2 ? true : false}
+ >
+ Add new
+
+
+
+ >
+ )}
+
+ )
+}
+
+export default Main
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentProfile.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentProfile.jsx
index 57e443354..ada47aea1 100644
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentProfile.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentProfile.jsx
@@ -1,7 +1,7 @@
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import { useFormikContext } from 'formik'
-import concentrationOptions from '../../../../../constants/concentrations'
+import { concentrationOptions } from '../../../../../constants/concentrations'
import { countries } from '../../../../../constants/countries'
import { userExperienceOptions } from '../../../../../constants/finishRegistrationData'
import FlexWrapper from '../../../../../shared/components/FlexWrapper/FlexWrapper'
@@ -12,7 +12,11 @@ import { ResumePartBox, ResumePartBtn } from '../ResumeInfo.styles'
function EditingComponentProfile() {
const [isActive, setIsActive] = useState('general')
- const { values } = useFormikContext()
+ const { values, setFieldValue } = useFormikContext()
+
+ useEffect(() => {
+ setFieldValue('dateOfBirth', '')
+ }, [])
return (
@@ -38,6 +42,7 @@ function EditingComponentProfile() {
name="country"
options={countries}
placeholder="Select country"
+ value={values['country']}
/>
>
)}
diff --git a/client/src/components/Profile/components/ResumeInfo/ResumeInfo.jsx b/client/src/components/Profile/components/ResumeInfo/ResumeInfo.jsx
index 305a67beb..73911406b 100644
--- a/client/src/components/Profile/components/ResumeInfo/ResumeInfo.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/ResumeInfo.jsx
@@ -7,9 +7,9 @@ import { ProfileSection } from '../../Profile.styles'
import EditingComponentAvatar from './EditingComponents/EditingComponentAvatar'
import EditingComponentDefault from './EditingComponents/EditingComponentDefault'
import EditingComponentDescription from './EditingComponents/EditingComponentDescription'
-import EditingComponentEducation from './EditingComponents/EditingComponentEducation'
+import EditingComponentEducation from './EditingComponents/EditingComponentEducation/EditingComponentEducation'
import EditingComponentFrameworks from './EditingComponents/EditingComponentFrameworks'
-import EditingComponentJob from './EditingComponents/EditingComponentJob'
+import EditingComponentJob from './EditingComponents/EditingComponentJob/EditingComponentJob'
import EditingComponentLanguages from './EditingComponents/EditingComponentLanguages'
import EditingComponentProfile from './EditingComponents/EditingComponentProfile'
import EditingComponentProjects from './EditingComponents/EditingComponentProjects'
diff --git a/client/src/components/RegistrationPipeline/components/RegistrationForms/UserEducationForm/UserEducationForm.jsx b/client/src/components/RegistrationPipeline/components/RegistrationForms/UserEducationForm/UserEducationForm.jsx
index f6bac0b78..4359c88ba 100644
--- a/client/src/components/RegistrationPipeline/components/RegistrationForms/UserEducationForm/UserEducationForm.jsx
+++ b/client/src/components/RegistrationPipeline/components/RegistrationForms/UserEducationForm/UserEducationForm.jsx
@@ -3,9 +3,9 @@ import { useFormikContext } from 'formik'
import { degrees } from '../../../../../constants/degrees'
import { majors } from '../../../../../constants/majors'
+import CheckboxWithLabel from '../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
import CustomInput from '../../../../../shared/components/Formik/CustomInput/CustomInput'
import CustomSelectAutocomplete from '../../../../../shared/components/Formik/CustomSelectAutocomplete/CustomSelectAutocomplete'
-import CheckboxWithLabel from '../../CheckboxWithLabel/CheckboxWithLabel'
import { ContentContainer } from '../../MultiStepRegistration/MultiStepRegistration.styles'
import { GroupItems, InputWrapper } from './UserEducationForm.styles'
diff --git a/client/src/components/RegistrationPipeline/components/RegistrationForms/UserJobForm/UserJobForm.jsx b/client/src/components/RegistrationPipeline/components/RegistrationForms/UserJobForm/UserJobForm.jsx
index 839baaf64..02381dbc9 100644
--- a/client/src/components/RegistrationPipeline/components/RegistrationForms/UserJobForm/UserJobForm.jsx
+++ b/client/src/components/RegistrationPipeline/components/RegistrationForms/UserJobForm/UserJobForm.jsx
@@ -1,8 +1,8 @@
import React, { useEffect, useState } from 'react'
import { useFormikContext } from 'formik'
+import CheckboxWithLabel from '../../../../../shared/components/CheckboxWithLabel/CheckboxWithLabel'
import CustomInput from '../../../../../shared/components/Formik/CustomInput/CustomInput'
-import CheckboxWithLabel from '../../CheckboxWithLabel/CheckboxWithLabel'
import { ContentContainer } from '../../MultiStepRegistration/MultiStepRegistration.styles'
import { InputWrapper } from '../UserEducationForm/UserEducationForm.styles'
@@ -10,10 +10,6 @@ const UserJobForm = () => {
const [checkbox, setCheckbox] = useState(false)
const { setFieldValue, values } = useFormikContext()
- useEffect(() => {
- values && values.jobData[0].endDate === '0' ? setCheckbox(true) : setCheckbox(false)
- }, [])
-
const handleClick = () => {
if (checkbox) {
setCheckbox(false)
diff --git a/client/src/constants/concentrations.js b/client/src/constants/concentrations.js
index cd118f12a..fa7beddba 100644
--- a/client/src/constants/concentrations.js
+++ b/client/src/constants/concentrations.js
@@ -1,51 +1,75 @@
export const concentrationOptions = [
{
label: 'Mobile Developer',
- value: 'Mobile',
+ value: 'mobile',
},
{
label: 'Frontend/UI Developer',
- value: 'Frontend',
+ value: 'frontend',
},
{
label: 'Backend Developer',
- value: 'Backend',
+ value: 'backend',
},
{
label: 'Full-Stack Developer',
- value: 'Fullstack',
+ value: 'fullstack',
},
{
label: 'Desktop Applications Developer',
- value: 'Desktop',
+ value: 'desktop',
},
{
label: 'Embedded Systems Developer',
- value: 'Embedded',
+ value: 'embedded',
},
{
label: 'Machine Learning Engineer',
- value: 'ML',
+ value: 'ml',
},
{
label: 'Data Scientist',
- value: 'DataScience',
+ value: 'datascience',
},
{
label: 'DevOps Engineer',
- value: 'DevOps',
+ value: 'devops',
},
{
label: 'Data Engineer',
- value: 'DataEngineer',
+ value: 'dataengineer',
},
{
label: 'QA/Test Engineer',
- value: 'QA',
+ value: 'qa',
+ },
+ {
+ label: 'Designer',
+ value: 'designer',
+ },
+ {
+ label: 'Project Manager',
+ value: 'projectmanager',
+ },
+ {
+ label: 'Cyber Security',
+ value: 'cybersecurity',
+ },
+ {
+ label: 'Web Developer',
+ value: 'webdeveloper',
+ },
+ {
+ label: 'Database Developer',
+ value: 'databasedeveloper',
+ },
+ {
+ label: 'No-code Developer',
+ value: 'nocodedeveloper',
},
{
label: 'Other',
- value: 'Other',
+ value: 'other',
},
]
diff --git a/client/src/constants/frameworkColors.js b/client/src/constants/frameworkColors.js
index 15a1e428b..957d1b11f 100644
--- a/client/src/constants/frameworkColors.js
+++ b/client/src/constants/frameworkColors.js
@@ -1,28 +1,40 @@
const frameworkColors = Object.freeze({
- NodeJS: '#5A9E54',
- Ruby: '#900E04',
- Angular: '#C3002F',
- AndroidSDK: '#06B75D',
- IOS: '#F2F2F2',
- Hadoop: '#E4E017',
- Ember: '#E24B31',
- Django: '#194838',
- Redux: '#6333AA',
- React: '#00A4D3',
- Spring: '#66C229',
- Spark: '#E67609',
- Backbone: '#00619C',
- Figma: '#8D3DF5',
- Photoshop: '#2C97E6',
+ NodeJS: '#73B212',
+ Ruby: '#BF2626',
+ Angular: '#BF2626',
+ Hadoop: '#0AA6BF',
+ Ember: '#BF2626',
+ Django: '#08A642',
+ Redux: '#6836D9',
+ React: '#0AA6BF',
+ Spring: '#73B212',
+ Spark: '#D9790B',
+ Backbone: '#225FE5',
+ Figma: '#6836D9',
+ Photoshop: '#225FE5',
+ jQuery: '#225FE5',
+ MUI: '#225FE5',
+ 'ASP.NET': '#225FE5',
+ NumPy: '#225FE5',
+ Flutter: '#0AA6BF',
+ 'React N.': '#0AA6BF',
+ Flask: '#0AA6BF',
+ VueJS: '#08A642',
+ Bootstrap: '#6836D9',
+ KMM: '#CC1FC3',
+ GraphQL: '#CC1FC3',
+ Laravel: '#BF2626',
+ PyTorch: '#D9790B',
+ 'Tensor F.': '#D9790B',
+ Express: '#FAFAFA',
+ Illustrator: '#D9790B',
})
const frameworkTextColors = Object.freeze({
NodeJS: 'white',
Ruby: 'white',
Angular: 'white',
- AndroidSDK: 'white',
- IOS: '#1E1E1E',
- Hadoop: '#1E1E1E',
+ Hadoop: 'white',
Ember: 'white',
Django: 'white',
Redux: 'white',
@@ -32,6 +44,22 @@ const frameworkTextColors = Object.freeze({
Backbone: 'white',
Figma: 'white',
Photoshop: 'white',
+ jQuery: 'white',
+ MUI: 'white',
+ 'ASP.NET': 'white',
+ NumPy: 'white',
+ Flutter: 'white',
+ 'React N.': 'white',
+ Flask: 'white',
+ VueJS: 'white',
+ Bootstrap: 'white',
+ KMM: 'white',
+ GraphQL: 'white',
+ Laravel: 'white',
+ PyTorch: 'white',
+ 'Tensor F.': 'white',
+ Express: '#1E1E1E',
+ Illustrator: 'white',
})
export { frameworkColors, frameworkTextColors }
diff --git a/client/src/constants/frameworks.js b/client/src/constants/frameworks.js
index e13854b6a..8bd07a992 100644
--- a/client/src/constants/frameworks.js
+++ b/client/src/constants/frameworks.js
@@ -2,8 +2,6 @@ const frameworkOptions = [
{ label: 'NodeJS', value: 'nodejs' },
{ label: 'Ruby', value: 'ruby' },
{ label: 'Angular', value: 'angular' },
- { label: 'AndroidSDK', value: 'android' },
- { label: 'IOS', value: 'ios' },
{ label: 'Hadoop', value: 'hadoop' },
{ label: 'Ember', value: 'ember' },
{ label: 'Django', value: 'django' },
@@ -14,6 +12,22 @@ const frameworkOptions = [
{ label: 'Backbone', value: 'backbone' },
{ label: 'Figma', value: 'figma' },
{ label: 'Photoshop', value: 'photoshop' },
+ { label: 'jQuery', value: 'jquery' },
+ { label: 'MUI', value: 'mui' },
+ { label: 'ASP.NET', value: 'aspnet' },
+ { label: 'NumPy', value: 'numpy' },
+ { label: 'Flutter', value: 'flutter' },
+ { label: 'React N.', value: 'reactnative' },
+ { label: 'Flask', value: 'flask' },
+ { label: 'VueJS', value: 'vuejs' },
+ { label: 'Bootstrap', value: 'bootstrap' },
+ { label: 'KMM', value: 'kotlinmultiplatformmobile' },
+ { label: 'GraphQL', value: 'graphql' },
+ { label: 'Laravel', value: 'laravel' },
+ { label: 'PyTorch', value: 'pytorch' },
+ { label: 'Tensor F.', value: 'tensorflow' },
+ { label: 'Express', value: 'express' },
+ { label: 'Illustrator', value: 'illustrator' },
]
export default frameworkOptions
diff --git a/client/src/constants/programmingLanguages.js b/client/src/constants/programmingLanguages.js
index e609534b8..e09609a72 100644
--- a/client/src/constants/programmingLanguages.js
+++ b/client/src/constants/programmingLanguages.js
@@ -2,18 +2,24 @@
import C from '../assets/LanguageLogo/C'
import Cplusplus from '../assets/LanguageLogo/Cplusplus'
import Csharp from '../assets/LanguageLogo/Csharp'
+import CSS from '../assets/LanguageLogo/CSS'
import Dart from '../assets/LanguageLogo/Dart'
import GO from '../assets/LanguageLogo/GO'
import Html from '../assets/LanguageLogo/Html'
import Java from '../assets/LanguageLogo/Java'
import JS from '../assets/LanguageLogo/JS'
+import Kotlin from '../assets/LanguageLogo/Kotlin'
+import Lua from '../assets/LanguageLogo/Lua'
import Perl from '../assets/LanguageLogo/Perl'
import Php from '../assets/LanguageLogo/Php'
import Python from '../assets/LanguageLogo/Python'
+import R from '../assets/LanguageLogo/R'
import Ruby from '../assets/LanguageLogo/Ruby'
+import Rust from '../assets/LanguageLogo/Rust'
import Scala from '../assets/LanguageLogo/Scala'
import SQL from '../assets/LanguageLogo/SQL'
import Swift from '../assets/LanguageLogo/Swift'
+import TS from '../assets/LanguageLogo/TS'
const programmingLanguageOptions = [
{ label: 'JS', value: 'js' },
@@ -27,10 +33,16 @@ const programmingLanguageOptions = [
{ label: 'Go', value: 'go' },
{ label: 'C#', value: 'c#' },
{ label: 'Java', value: 'java' },
- { label: 'HTML/CSS', value: 'html/css' },
+ { label: 'HTML', value: 'html' },
+ { label: 'CSS', value: 'css' },
{ label: 'Dart', value: 'dart' },
{ label: 'Perl', value: 'perl' },
{ label: 'SQL', value: 'sql' },
+ { label: 'TS', value: 'ts' },
+ { label: 'Kotlin', value: 'kotlin' },
+ { label: 'Rust', value: 'rust' },
+ { label: 'R', value: 'r' },
+ { label: 'Lua', value: 'lua' },
]
const languageOptions = Object.freeze({
@@ -45,10 +57,16 @@ const languageOptions = Object.freeze({
Go: ,
'C#': ,
Java: ,
- 'HTML/CSS': ,
+ HTML: ,
+ CSS: ,
Dart: ,
Perl: ,
SQL: ,
+ TS: ,
+ Kotlin: ,
+ Rust: ,
+ R: ,
+ Lua: ,
})
export { languageOptions, programmingLanguageOptions }
diff --git a/client/src/http/index.js b/client/src/http/index.js
index 1108344ce..0285f5d00 100644
--- a/client/src/http/index.js
+++ b/client/src/http/index.js
@@ -31,8 +31,6 @@ api.interceptors.response.use(
try {
const response = await axios.get(`${API_URL}/auth/refresh`, { withCredentials: true })
- console.log(response)
-
localStorage.setItem('token', response.data.accessToken)
return api.request(originalRequest)
diff --git a/client/src/schemas/index.js b/client/src/schemas/index.js
index 9c6291181..4e124e587 100644
--- a/client/src/schemas/index.js
+++ b/client/src/schemas/index.js
@@ -6,6 +6,14 @@ const regMatch =
const SUPPORTED_FORMATS = ['image/jpg', 'image/jpeg', 'image/gif', 'image/png']
+const isDate = (_date) => {
+ const _regExp = new RegExp(
+ '^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$',
+ )
+
+ return _regExp.test(_date)
+}
+
const userFileValidation = yup.object().shape({
file: yup
.mixed()
@@ -382,6 +390,22 @@ export const editProfileValidation = yup.object().shape(
return yup.string().notRequired()
}
}),
+ dateOfBirth: yup
+ .string()
+ .matches(
+ /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/(19\d\d|20[01][0-9]|202[0-3])$/,
+ 'Invalid date format. Please enter a date in the format dd/mm/yyyy',
+ )
+ .test('valid-year', 'Year must be between 1901 and current year', function (value) {
+ if (value) {
+ const year = parseInt(value.split('/')[2])
+
+ return year >= 1901 && year <= new Date().getFullYear()
+ }
+
+ return true
+ })
+ .required('Please input your birthday'),
experience: yup.string().required('Please choose your experience'),
programmingLanguages: yup
.array()
@@ -438,6 +462,119 @@ export const editProfileValidation = yup.object().shape(
)
.min(0)
.max(5),
+ jobData: yup
+ .array()
+ .of(
+ yup.object().shape({
+ title: yup
+ .string()
+ .matches(/^[a-zA-Z0-9\s]+$/, {
+ message: 'Only alphabets and numbers are allowed for this field',
+ excludeEmptyString: true,
+ })
+ .required('Input your title!'),
+ company: yup
+ .string()
+ .matches(/^[a-zA-Z0-9\s]+$/, {
+ message: 'Only alphabets and numbers are allowed for this field',
+ excludeEmptyString: true,
+ })
+ .required('Input your company!'),
+ startDate: yup
+ .string()
+ .test('valid-year', 'Year must be between 1901 and current year', function (value) {
+ /* Check if value is Date type that we got from backend */
+ if (typeof value === 'string' && isDate(value)) {
+ return true
+ }
+
+ /* Check if number is between specific range */
+ return value >= 1901 && value <= new Date().getFullYear()
+ })
+ .required('Date is required'),
+ endDate: yup
+ .string()
+ .test(
+ 'valid-year',
+ 'Year must be from 1901 and bigger than start date',
+ function (value) {
+ let { startDate } = this.parent
+
+ /* Check if value is Date type that we got from backend */
+ if (typeof value === 'string' && isDate(value)) {
+ return true
+ }
+
+ /* If startDate is of type string (and not number), convert it to number */
+ if (isDate(startDate)) {
+ startDate = Number(startDate.slice(0, 4))
+ }
+
+ /* If startDate is of type null, return true as input might be empty */
+ if (value === null) {
+ return true
+ }
+
+ /* Finally check if number is between specific range */
+ return value >= 1901 && startDate <= value
+ },
+ )
+ .nullable(),
+ }),
+ )
+ .min(0)
+ .max(2),
+ universityData: yup
+ .array()
+ .of(
+ yup.object().shape({
+ major: yup.string().required('Input your major!'),
+ degree: yup.string().required('Input your degree!'),
+ university: yup.string().required('Input your university!'),
+ addmissionDate: yup
+ .string()
+ .test('valid-year', 'Year must be between 1901 and current year', function (value) {
+ /* Check if value is Date type that we got from backend */
+ if (typeof value === 'string' && isDate(value)) {
+ return true
+ }
+
+ /* Check if number is between specific range */
+ return value >= 1901 && value <= new Date().getFullYear()
+ })
+ .required('Date is required'),
+ graduationDate: yup
+ .string()
+ .test(
+ 'valid-year',
+ 'Year must be from 1901 and bigger than start date',
+ function (value) {
+ let { addmissionDate } = this.parent
+
+ /* Check if value is Date type that we got from backend */
+ if (typeof value === 'string' && isDate(value)) {
+ return true
+ }
+
+ /* If startDate is of type string (and not number), convert it to number */
+ if (isDate(addmissionDate)) {
+ addmissionDate = Number(addmissionDate.slice(0, 4))
+ }
+
+ /* If startDate is of type null, return true as input might be empty */
+ if (value === null) {
+ return true
+ }
+
+ /* Finally check if number is between specific range */
+ return value >= 1901 && addmissionDate <= value
+ },
+ )
+ .nullable(),
+ }),
+ )
+ .min(0)
+ .max(2),
},
[
['description', 'description'],
diff --git a/client/src/components/RegistrationPipeline/components/CheckboxWithLabel/CheckboxWithLabel.js b/client/src/shared/components/CheckboxWithLabel/CheckboxWithLabel.js
similarity index 100%
rename from client/src/components/RegistrationPipeline/components/CheckboxWithLabel/CheckboxWithLabel.js
rename to client/src/shared/components/CheckboxWithLabel/CheckboxWithLabel.js
diff --git a/client/src/components/RegistrationPipeline/components/CheckboxWithLabel/CheckboxWithLabel.styles.js b/client/src/shared/components/CheckboxWithLabel/CheckboxWithLabel.styles.js
similarity index 100%
rename from client/src/components/RegistrationPipeline/components/CheckboxWithLabel/CheckboxWithLabel.styles.js
rename to client/src/shared/components/CheckboxWithLabel/CheckboxWithLabel.styles.js
diff --git a/client/src/shared/components/Formik/CustomInput/CustomInput.jsx b/client/src/shared/components/Formik/CustomInput/CustomInput.jsx
index 4efe10cda..15f4379d9 100644
--- a/client/src/shared/components/Formik/CustomInput/CustomInput.jsx
+++ b/client/src/shared/components/Formik/CustomInput/CustomInput.jsx
@@ -18,6 +18,7 @@ const CustomInput = ({
shouldFormatDate = false,
shouldFormatYear = false,
isOptional = false,
+ maxLength = 524288,
...props
}) => {
const [field, meta, helpers] = useField(props)
@@ -25,6 +26,7 @@ const CustomInput = ({
const handleChange = (event) => {
const { value } = event.target
+
let formattedValue = value
if (shouldFormatDate) {
@@ -34,6 +36,7 @@ const CustomInput = ({
}
helpers.setValue(formattedValue) // Manually set the value of the field
+ console.log(field, props)
if (onInputChange) {
onInputChange(formattedValue) // Pass the input value to the callback
@@ -47,6 +50,7 @@ const CustomInput = ({
{
- const [day, month, year] = inputValue.split('/')
+ const pattern = /^\d{2}\/\d{2}\/\d{4}$/
- // Create a new Date object in JavaScript (months start from 0)
- const birthday = new Date(year, month - 1, day, 0, 0, 0).toISOString()
+ if (pattern.test(inputValue)) {
+ const [day, month, year] = inputValue.split('/')
- return birthday
+ // Create a new Date object in JavaScript (months start from 0)
+ const birthday = new Date(year, month - 1, day, 0, 0, 0).toISOString()
+
+ return birthday
+ }
+
+ return inputValue
}
diff --git a/server/src/maintenance/maintenance.service.ts b/server/src/maintenance/maintenance.service.ts
index 9282635a0..f7d24431a 100644
--- a/server/src/maintenance/maintenance.service.ts
+++ b/server/src/maintenance/maintenance.service.ts
@@ -57,14 +57,17 @@ export class MaintenanceService {
'Dart',
'Perl',
'SQL',
+ 'TS',
+ 'Kotlin',
+ 'Rust',
+ 'R',
+ 'Lua',
];
frameworks: string[] = [
'NodeJS',
'Ruby',
'Angular',
- 'AndroidSDK',
- 'IOS',
'Hadoop',
'Ember',
'Django',
@@ -75,6 +78,22 @@ export class MaintenanceService {
'Backbone',
'Figma',
'Photoshop',
+ 'jQuery',
+ 'MUI',
+ 'ASP.NET',
+ 'NumPy',
+ 'Flutter',
+ 'React N.',
+ 'Flask',
+ 'VueJS',
+ 'Bootstrap',
+ 'KMM',
+ 'GraphQL',
+ 'Laravel',
+ 'PyTorch',
+ 'Tensor F.',
+ 'Express',
+ 'Illustrator',
];
concentrations: string[] = [
@@ -89,6 +108,13 @@ export class MaintenanceService {
'DevOps Engineer',
'Data Engineer',
'QA/Test Engineer',
+ 'Designer',
+ 'Project Manager',
+ 'Cyber Security',
+ 'Web Developer',
+ 'Database Developer',
+ 'No-code Developer',
+ 'Other',
];
images: string[] = [
From 87350ef438e6668223a9458347b0d22cda19bb96 Mon Sep 17 00:00:00 2001
From: Nikita Mashchenko
Date: Wed, 5 Jul 2023 14:46:24 -0500
Subject: [PATCH 2/2] final fixes
---
client/src/components/Profile/Profile.jsx | 2 +-
.../EditingComponentEducation.jsx | 9 ++--
.../EditingComponentJob.jsx | 9 ++--
.../EditingComponentJob/States/Main.jsx | 1 -
.../ProjectsSkills/ProjectsSkills.jsx | 10 +++-
client/src/schemas/index.js | 53 +++++++++++++------
.../Formik/CustomInput/CustomInput.jsx | 1 -
7 files changed, 57 insertions(+), 28 deletions(-)
diff --git a/client/src/components/Profile/Profile.jsx b/client/src/components/Profile/Profile.jsx
index 68bcca2e2..3b74c82be 100644
--- a/client/src/components/Profile/Profile.jsx
+++ b/client/src/components/Profile/Profile.jsx
@@ -119,7 +119,7 @@ const Profile = () => {
onSubmit={handleSubmit}
>
{({ values, errors, dirty }) => {
- console.log(values, dirty)
+ console.log(errors)
usePrompt('You have unsaved changes. Do you want to discard them?', dirty)
return (
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
index b5f0a556a..8b64b7df3 100644
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentEducation/EditingComponentEducation.jsx
@@ -23,11 +23,12 @@ function EditingComponentEducation({ handleBack, showingUser }) {
values && values?.universityData[index]?.graduationDate === null
? setCheckbox(true)
: setCheckbox(false)
- }, [index])
+ }, [index, values?.universityData[index]?.graduationDate])
const handleReset = () => {
setModalActive('')
setCurrentAction('main')
+ setIndex(0)
}
const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
@@ -38,9 +39,9 @@ function EditingComponentEducation({ handleBack, showingUser }) {
const updatedUniversityData = universities.filter((_, i) => i !== index)
setFieldValue('universityData', updatedUniversityData)
- setIndex((prev) => prev - 1)
editUserDetails({ email: showingUser.email, universityData: updatedUniversityData })
+ setIndex(0)
}
const handleEditUniversity = (index) => {
@@ -51,8 +52,6 @@ function EditingComponentEducation({ handleBack, showingUser }) {
const submitEditUniversity = async () => {
const validation = await validateForm()
- console.log(validation)
-
if (!validation?.universityData) {
const initialObject = cloneDeep(values.universityData)
@@ -67,6 +66,7 @@ function EditingComponentEducation({ handleBack, showingUser }) {
setFieldValue(`universityData[${index}].graduationDate`, initialObject[index].graduationDate)
editUserDetails({ email: showingUser.email, universityData: initialObject })
+ setIndex(0)
} else {
setErrors({ universityData: validation.universityData[index] })
errorToaster('Fill in data before submission!')
@@ -80,6 +80,7 @@ function EditingComponentEducation({ handleBack, showingUser }) {
const handleClose = () => {
setModalActive('')
+ setIndex(0)
}
const handleCancel = () => {
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
index 97030261c..71ab75a24 100644
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/EditingComponentJob.jsx
@@ -20,13 +20,13 @@ function EditingComponentJob({ handleBack, showingUser }) {
const [checkbox, setCheckbox] = useState(false)
useEffect(() => {
- console.log(index)
values && values?.jobData[index]?.endDate === null ? setCheckbox(true) : setCheckbox(false)
- }, [index])
+ }, [index, values?.jobData[index]?.endDate])
const handleReset = () => {
setModalActive('')
setCurrentAction('main')
+ setIndex(0)
}
const { mutate: editUserDetails, isLoading } = useEditUserDetails(handleReset)
@@ -37,9 +37,9 @@ function EditingComponentJob({ handleBack, showingUser }) {
const updatedJobData = jobs.filter((_, i) => i !== index)
setFieldValue('jobData', updatedJobData)
- setIndex((prev) => prev - 1)
editUserDetails({ email: showingUser.email, jobData: updatedJobData })
+ setIndex(0)
}
const handleEditJob = (index) => {
@@ -64,6 +64,7 @@ function EditingComponentJob({ handleBack, showingUser }) {
setFieldValue(`jobData[${index}].endDate`, initialObject[index].endDate)
editUserDetails({ email: showingUser.email, jobData: initialObject })
+ setIndex(0)
} else {
setErrors({ jobData: validation.jobData[index] })
errorToaster('Fill in data before submission!')
@@ -77,6 +78,7 @@ function EditingComponentJob({ handleBack, showingUser }) {
const handleClose = () => {
setModalActive('')
+ setIndex(0)
}
const handleCancel = () => {
@@ -116,7 +118,6 @@ function EditingComponentJob({ handleBack, showingUser }) {
handleBack={handleBack}
setCurrentAction={setCurrentAction}
setIndex={setIndex}
- index={index}
/>
)}
diff --git a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
index b8c950d9d..f1832352b 100644
--- a/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/EditingComponents/EditingComponentJob/States/Main.jsx
@@ -14,7 +14,6 @@ const Main = ({
handleBack,
setCurrentAction,
setIndex,
- index,
}) => {
return (
diff --git a/client/src/components/Profile/components/ResumeInfo/ProjectsSkills/ProjectsSkills.jsx b/client/src/components/Profile/components/ResumeInfo/ProjectsSkills/ProjectsSkills.jsx
index 6718f895f..ca7135b9d 100644
--- a/client/src/components/Profile/components/ResumeInfo/ProjectsSkills/ProjectsSkills.jsx
+++ b/client/src/components/Profile/components/ResumeInfo/ProjectsSkills/ProjectsSkills.jsx
@@ -31,7 +31,13 @@ const ProjectsSkills = ({ showingUser, setIsEditing, userStatus }) => {
)}
{showingUser?.description ? (
-
+
) : (