diff --git a/src/apps/onboarding/src/components/modal-add-work/index.tsx b/src/apps/onboarding/src/components/modal-add-work/index.tsx deleted file mode 100644 index f90ca7086..000000000 --- a/src/apps/onboarding/src/components/modal-add-work/index.tsx +++ /dev/null @@ -1,261 +0,0 @@ -import { FC, useEffect, useState } from 'react' -import _ from 'lodash' -import classNames from 'classnames' -import moment from 'moment' - -import { Button, IconSolid, InputDatePicker, InputSelect, InputText, Tooltip } from '~/libs/ui' -import { getIndustryOptionsWithOthersLast, INDUSTRIES_OPTIONS } from '~/libs/shared' - -import FormInputCheckbox from '../form-input-checkbox' -import OnboardingBaseModal from '../onboarding-base-modal' -import WorkInfo, { emptyWorkInfo } from '../../models/WorkInfo' - -import styles from './styles.module.scss' - -const FormInputCheckboxMiddleware: any = FormInputCheckbox as any - -interface ModalAddWorkProps { - onClose?: () => void - editingWork?: WorkInfo | null - onAdd?: (workInfo: WorkInfo) => void - onEdit?: (workInfo: WorkInfo) => void -} - -const industryOptions: any = getIndustryOptionsWithOthersLast(INDUSTRIES_OPTIONS) - -const ModalAddWork: FC = (props: ModalAddWorkProps) => { - const [workInfo, setWorkInfo] = useState(emptyWorkInfo()) - const [formErrors, setFormErrors] = useState({ - companyName: undefined, - endDate: undefined, - otherIndustry: undefined, - position: undefined, - startDate: undefined, - }) - - const validateDate: any = (startDate: Date | undefined, endDate: Date | undefined) => { - const isInValid: any = endDate - && startDate - && moment(endDate) - .isSameOrBefore(startDate) - return !isInValid - } - - const validateField: any = () => { - const errorTmp: any = {} - if (!workInfo.companyName) { - errorTmp.companyName = 'Required' - } - - if (!workInfo.position) { - errorTmp.position = 'Required' - } - - if (!workInfo.startDate) { - errorTmp.startDate = 'Required' - } else if (!validateDate(workInfo.startDate, workInfo.endDate)) { - errorTmp.startDate = 'Start Date should be before End Date' - } - - if (!workInfo.endDate && !workInfo.currentlyWorking) { - errorTmp.endDate = 'Required' - } - - if (workInfo.industry === 'Other' && !workInfo.otherIndustry?.trim()) { - errorTmp.otherIndustry = 'Please specify your industry' - } - - setFormErrors(errorTmp) - return _.isEmpty(errorTmp) - } - - useEffect(() => { - if (props.editingWork) { - setWorkInfo(props.editingWork) - } - }, [props.editingWork]) - - const endDateUI = ( - - ) - - return ( - - + + + ))} ) : undefined} @@ -157,27 +226,26 @@ export const PageWorksContent: FC<{ next - {showAddWorkModal ? ( - (w.id !== editWork.id ? w : editWork)), + (works || []) + .map(w => (w.id !== editingWork.id ? w : userTraitToWorkInfo(trait, editingWork.id))), ) - }} - /> - ) : undefined} + } else { + const newId = workId + 1 + setWorks([...(works || []), userTraitToWorkInfo(trait, newId)]) + setWorkId(newId) + } + }} + /> ) } diff --git a/src/apps/onboarding/src/pages/works/styles.module.scss b/src/apps/onboarding/src/pages/works/styles.module.scss index a22a37a44..0f20d6a37 100644 --- a/src/apps/onboarding/src/pages/works/styles.module.scss +++ b/src/apps/onboarding/src/pages/works/styles.module.scss @@ -1,3 +1,5 @@ +@import '@libs/ui/styles/includes'; + .container { min-height: 100%; } @@ -6,6 +8,34 @@ margin-bottom: 40px; } +.workCardWrap { + display: flex; + align-items: flex-start; + border: 1px solid $black-20; + border-radius: 8px; + padding: $sp-4; +} + +.workCardActions { + display: flex; + align-items: center; + gap: 8px; + margin-left: $sp-15; + + :global(button) { + padding: $sp-2; + color: $turq-160; + background: none; + border: none; + cursor: pointer; + } + + svg { + width: 24px; + height: 24px; + } +} + .ProgressBar { margin-top: auto; width: 100%; diff --git a/src/apps/onboarding/src/redux/actions/member.ts b/src/apps/onboarding/src/redux/actions/member.ts index f80485f9a..1fc61d884 100644 --- a/src/apps/onboarding/src/redux/actions/member.ts +++ b/src/apps/onboarding/src/redux/actions/member.ts @@ -126,14 +126,18 @@ export const fetchMemberTraits: any = () => async (dispatch: any) => { if (workExpValue) { // workExpValue is array of works. fill it to state const works: WorkInfo[] = workExpValue.map((j: any, index: number) => { - const startDate: Date | undefined = dateTimeToDate(j.startDate) - const endDate: Date | undefined = dateTimeToDate(j.endDate) + const startDate: Date | undefined = dateTimeToDate(j.startDate || j.timePeriodFrom) + const endDate: Date | undefined = dateTimeToDate(j.endDate || j.timePeriodTo) return ({ - companyName: j.companyName, + associatedSkills: Array.isArray(j.associatedSkills) ? j.associatedSkills : undefined, + city: j.cityName || j.cityTown || j.city, + companyName: j.companyName || j.company, currentlyWorking: j.working, + description: j.description, endDate, id: index + 1, industry: j.industry, + otherIndustry: j.otherIndustry, position: j.position, startDate, }) @@ -207,18 +211,26 @@ export const fetchMemberTraits: any = () => async (dispatch: any) => { const createWorksPayloadData: any = (works: WorkInfo[]) => { const data: any = works.map(work => { const { - company, + companyName, position, industry, + otherIndustry, startDate, endDate, currentlyWorking, + description, + city, + associatedSkills, }: any = work return { - companyName: company || '', + associatedSkills: Array.isArray(associatedSkills) ? associatedSkills : undefined, + cityName: city, + companyName: companyName || '', + description: description || undefined, // eslint-disable-next-line unicorn/no-null endDate: endDate ? endDate.toISOString() : null, industry, + otherIndustry: otherIndustry || undefined, position, // eslint-disable-next-line unicorn/no-null startDate: startDate ? startDate.toISOString() : null, diff --git a/src/apps/profiles/src/member-profile/work-expirence/ModifyWorkExpirenceModal/ModifyWorkExpirenceModal.tsx b/src/apps/profiles/src/member-profile/work-expirence/ModifyWorkExpirenceModal/ModifyWorkExpirenceModal.tsx index 519b6f616..998ee40a6 100644 --- a/src/apps/profiles/src/member-profile/work-expirence/ModifyWorkExpirenceModal/ModifyWorkExpirenceModal.tsx +++ b/src/apps/profiles/src/member-profile/work-expirence/ModifyWorkExpirenceModal/ModifyWorkExpirenceModal.tsx @@ -1,10 +1,10 @@ /* eslint-disable complexity */ -import { ChangeEvent, Dispatch, FC, MutableRefObject, SetStateAction, useEffect, useRef, useState } from 'react' -import { bind, trim } from 'lodash' +import { Dispatch, FC, SetStateAction, useEffect, useRef, useState } from 'react' +import { bind } from 'lodash' import { toast } from 'react-toastify' import classNames from 'classnames' -import { BaseModal, Button, IconOutline, InputDatePicker, InputSelect, InputText } from '~/libs/ui' +import { BaseModal, Button, IconOutline } from '~/libs/ui' import { updateDeleteOrCreateMemberTraitAsync, UserProfile, UserTrait, @@ -12,15 +12,12 @@ import { UserTraitIds, } from '~/libs/core' import { - FieldHtmlEditor, - getIndustryOptionsWithOthersLast, - INDUSTRIES_OPTIONS, - InputSkillSelector, + AddEditWorkExperienceForm, + WorkExperienceCard, } from '~/libs/shared' +import type { AddEditWorkExperienceFormRef } from '~/libs/shared/lib/components/add-edit-work-experience-form' import { fetchSkillsByIds } from '~/libs/shared/lib/services/standard-skills' -import { WorkExpirenceCard } from '../WorkExpirenceCard' - import styles from './ModifyWorkExpirenceModal.module.scss' interface ModifyWorkExpirenceModalProps { @@ -37,20 +34,6 @@ const ModifyWorkExpirenceModal: FC = (props: Modi const [addingNewItem, setAddingNewItem]: [boolean, Dispatch>] = useState(props.workExpirence?.length === 0 || false) - const [formValues, setFormValues]: [ - { [key: string]: string | boolean | Date | any[] | undefined }, - Dispatch> - ] - = useState<{ [key: string]: string | boolean | Date | any[] | undefined }>({}) - - const [formErrors, setFormErrors]: [ - { [key: string]: string }, - Dispatch> - ] - = useState<{ [key: string]: string }>({}) - - const formElRef: MutableRefObject = useRef() - const [editedItemIndex, setEditedItemIndex]: [ number | undefined, Dispatch> @@ -65,6 +48,7 @@ const ModifyWorkExpirenceModal: FC = (props: Modi const [skillNamesMap, setSkillNamesMap] = useState>({}) const [loadingSkills, setLoadingSkills] = useState(false) const fetchedSkillIdsRef = useRef>(new Set()) + const formRef = useRef(null) useEffect(() => { if (!workExpirence) { @@ -126,7 +110,6 @@ const ModifyWorkExpirenceModal: FC = (props: Modi setLoadingSkills(false) } } else { - // No skills to fetch setLoadingSkills(false) } }, [workExpirence]) @@ -142,12 +125,9 @@ const ModifyWorkExpirenceModal: FC = (props: Modi }) } - const industryOptions: any = getIndustryOptionsWithOthersLast(INDUSTRIES_OPTIONS) - function handleModifyWorkExpirenceSave(): void { if (addingNewItem || editedItemIndex !== undefined) { - handleFormAction() - + formRef.current?.submit() return } @@ -171,199 +151,25 @@ const ModifyWorkExpirenceModal: FC = (props: Modi }) } - function handleFormValueChange( - key: string, - event: React.ChangeEvent, - ): void { - let value: string | boolean | Date | undefined - const oldFormValues = { ...formValues } - - switch (key) { - case 'currentlyWorking': - value = (event.target as HTMLInputElement).checked - if (value) { - oldFormValues.endDate = undefined - } - - break - case 'startDate': - case 'endDate': - value = event as unknown as Date - break - case 'industry': - value = event.target.value - if (value !== 'Other') { - oldFormValues.otherIndustry = undefined - } - - break - default: - value = event.target.value - break - } - - setFormValues({ - ...oldFormValues, - [key]: value, - }) - } - - function handleDescriptionChange(value: string): void { - setFormValues({ - ...formValues, - description: value, - }) - } - - function handleSkillsChange(event: ChangeEvent): void { - const selectedSkills = (event.target as any).value || [] - setFormValues({ - ...formValues, - associatedSkills: selectedSkills.map((skill: any) => ({ - id: skill.value || skill.id, - name: skill.label || skill.name, - })), - }) - } - - function resetForm(): void { - setFormValues({}) - setFormErrors({}) - formElRef.current.reset() - setEditedItemIndex(undefined) - setAddingNewItem(false) - } - - function handleFormAction(): void { - setFormErrors({}) - - if (!trim(formValues.company as string)) { - setFormErrors({ - company: 'Company is required', - }) - return - } - - if (!trim(formValues.position as string)) { - setFormErrors({ - position: 'Position is required', - }) - return - } - - if (formValues.endDate && formValues.startDate && formValues.endDate <= formValues.startDate) { - setFormErrors({ - endDate: 'End date must be greater than start date', - }) - return - } - - if (formValues.endDate || formValues.startDate) { - if (formValues.endDate && !formValues.startDate && !formValues.currentlyWorking) { - setFormErrors({ - startDate: 'Start date is required when end date is given', - }) - return - } - - if (formValues.startDate && !formValues.endDate && !formValues.currentlyWorking) { - setFormErrors({ - endDate: 'End date is required when start date is given', - }) - return - } - } - - if (formValues.industry === 'Other' && !trim(formValues.otherIndustry as string)) { - setFormErrors({ - otherIndustry: 'Please specify your industry', - }) - return - } - - const companyName: string | undefined = formValues.company as string | undefined - const startDateIso: string | undefined = formValues.startDate - ? (formValues.startDate as Date).toISOString() - : undefined - const endDateIso: string | undefined = formValues.endDate - ? (formValues.endDate as Date).toISOString() - : undefined - - const updatedWorkExpirence: UserTrait = { - associatedSkills: (formValues.associatedSkills as any[])?.map((s: any) => s.id || s) || [], - company: companyName, - companyName, - description: (formValues.description as string) || undefined, - endDate: endDateIso, - industry: formValues.industry, - otherIndustry: formValues.industry === 'Other' ? (formValues.otherIndustry as string) : undefined, - position: formValues.position, - startDate: startDateIso, - timePeriodFrom: startDateIso, - timePeriodTo: endDateIso, - working: formValues.currentlyWorking, - } - + function handleFormSave(work: UserTrait): void { if (editedItemIndex !== undefined && workExpirence) { - workExpirence[editedItemIndex] = updatedWorkExpirence - - setWorkExpirence([ - ...workExpirence, - ]) + const updated = [...workExpirence] + updated[editedItemIndex] = work + setWorkExpirence(updated) } else { - setWorkExpirence( - [...workExpirence || [], updatedWorkExpirence], - ) + setWorkExpirence([...(workExpirence || []), work]) } - resetForm() + setEditedItemIndex(undefined) + setAddingNewItem(false) } - async function handleWorkExpirenceEdit(indx: number): Promise { - const work: UserTrait = workExpirence ? workExpirence[indx] : {} - + function handleWorkExpirenceEdit(indx: number): void { setEditedItemIndex(indx) - - let associatedSkills: any[] = [] - if (work.associatedSkills && Array.isArray(work.associatedSkills) && work.associatedSkills.length > 0) { - try { - const skills = await fetchSkillsByIds( - work.associatedSkills.filter((id): id is string => typeof id === 'string'), - ) - const skillsMap = new Map(skills.map(s => [s.id, s.name])) - - associatedSkills = work.associatedSkills.map((skillId: string) => ({ - id: skillId, - name: skillsMap.get(skillId) || '', - })) - } catch { - associatedSkills = work.associatedSkills.map((skillId: string) => ({ - id: skillId, - name: skillNamesMap[skillId] || '', - })) - } - } - - setFormValues({ - associatedSkills, - company: (work.company || work.companyName || '') as string, - currentlyWorking: work.working || false, - description: work.description || '', - endDate: work.timePeriodTo - ? new Date(work.timePeriodTo) - : (work.endDate ? new Date(work.endDate) : undefined), - industry: work.industry || '', - otherIndustry: work.otherIndustry || '', - position: (work.position || '') as string, - startDate: work.timePeriodFrom - ? new Date(work.timePeriodFrom) - : (work.startDate ? new Date(work.startDate) : undefined), - }) } function handleWorkExpirenceDelete(indx: number): void { const updatedWorkExpirence: UserTrait[] = [...workExpirence || []] - updatedWorkExpirence.splice(indx, 1) setWorkExpirence(updatedWorkExpirence) } @@ -376,7 +182,6 @@ const ModifyWorkExpirenceModal: FC = (props: Modi if (addingNewItem || editedItemIndex !== undefined) { setAddingNewItem(false) setEditedItemIndex(undefined) - resetForm() } else { props.onClose() } @@ -427,7 +232,7 @@ const ModifyWorkExpirenceModal: FC = (props: Modi className={styles.workExpirenceCardWrap} key={uniqueKey || `${work.position}-${indx}`} > - = (props: Modi