diff --git a/src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/HowSkillsWorkModal.tsx b/src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/HowSkillsWorkModal.tsx deleted file mode 100644 index 56649d21b..000000000 --- a/src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/HowSkillsWorkModal.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { FC } from 'react' - -import { BaseModal, IconOutline } from '~/libs/ui' - -import styles from './HowSkillsWorkModal.module.scss' - -interface HowSkillsWorkModalProps { - onClose: () => void - isTalentSearch?: boolean - canEdit?: boolean -} - -const HowSkillsWorkModal: FC = (props: HowSkillsWorkModalProps) => ( - - { - !!props.canEdit && ( -
-

- Topcoder Proven Skills -

-

- Look for the proven - - next to skills. -

-

Here’s how it works:

-
    -
  • You perform specific Topcoder opportunities
  • -
  • Each opportunity has associated skills (ex: javascript, HTML)
  • -
  • - You can prove you are proficient in these skills - by completing opportunities on the platform -
  • -
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • -
  • The more opportunities you complete the higher you rate for associated skills
  • -
-

- You can also self-proclaim skills that have not yet been proven. - These will display as skills without a checkmark. -

-
- ) - } - - { - !props.canEdit && props.isTalentSearch && ( -
-

- Topcoder Skill Matching -

-

Topcoder identifies experts that will best match the skills you are searching for.

-

- Look for the proven - - next to skills. -

-

Here’s how it works:

-
    -
  • Experts perform specific Topcoder opportunities
  • -
  • Each task has associated skills (ex: javascript, HTML)
  • -
  • - Experts prove they are proficient in these skills - by completing opportunities on the platform -
  • -
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • -
  • The more opportunities our experts complete the higher they rate for associated skills
  • -
-

- Experts can also self-proclaim skills that have not yet been proven. - These will display as skills without a checkmark. -

-
- ) - } - - { - !props.canEdit && !props.isTalentSearch && ( -
-

- Topcoder Proven Skills -

-

Our experts work hard to prove their skills through Topcoder opportunities.

-

- Look for the proven - - next to skills. -

-

Here’s how it works:

-
    -
  • Experts perform specific Topcoder opportunities
  • -
  • Each opportunity has associated skills (ex: javascript, HTML)
  • -
  • - Experts prove they are proficient in these skills - by completing opportunities on the platform -
  • -
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • -
  • The more opportunities our experts complete the higher they rate for associated skills
  • -
-

- Experts can also self-proclaim skills that have not yet been proven. - These will display as skills without a checkmark. -

-
- ) - } -
-) - -export default HowSkillsWorkModal diff --git a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx index a0f90a617..f40f437da 100644 --- a/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx +++ b/src/apps/profiles/src/member-profile/skills/MemberSkillsInfo.tsx @@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom' import { orderBy } from 'lodash' import { UserEMSISkill, UserProfile } from '~/libs/core' -import { ExpandableList, isSkillVerified, Skill, SkillPill } from '~/libs/shared' +import { ExpandableList, HowSkillsWorkModal, isSkillVerified, Skill, SkillPill } from '~/libs/shared' import { Button } from '~/libs/ui' import { AddButton, EditMemberPropertyBtn, EmptySection } from '../../components' @@ -11,7 +11,6 @@ import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config' import { MemberProfileContextValue, useMemberProfileContext } from '../MemberProfile.context' import { ModifySkillsModal } from './ModifySkillsModal' -import { HowSkillsWorkModal } from './HowSkillsWorkModal' import styles from './MemberSkillsInfo.module.scss' interface MemberSkillsInfoProps { @@ -141,7 +140,7 @@ const MemberSkillsInfo: FC = (props: MemberSkillsInfoProp ) } diff --git a/src/apps/talent-search/src/components/match-bar/index.ts b/src/apps/talent-search/src/components/match-bar/index.ts deleted file mode 100644 index c67f75cbc..000000000 --- a/src/apps/talent-search/src/components/match-bar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as MatchBar } from './MatchBar' diff --git a/src/apps/talent-search/src/components/match-bar/MatchBar.module.scss b/src/apps/talent-search/src/components/profile-match/ProfileMatch.module.scss similarity index 69% rename from src/apps/talent-search/src/components/match-bar/MatchBar.module.scss rename to src/apps/talent-search/src/components/profile-match/ProfileMatch.module.scss index 5842b6775..9bee73d1a 100644 --- a/src/apps/talent-search/src/components/match-bar/MatchBar.module.scss +++ b/src/apps/talent-search/src/components/profile-match/ProfileMatch.module.scss @@ -5,12 +5,13 @@ align-items: center; justify-content: center; color: $tc-white; - font-family: $font-barlow; - - gap: $sp-2; + font-family: $font-roboto; + flex-direction: column; border-radius: 100px; padding-bottom: 2px; + width: 100%; + aspect-ratio: 1 / 1; background: rgb(130,234,207); background: linear-gradient( @@ -26,13 +27,17 @@ background-size: 100% 3000px; background-position: 0 0; + font-size: 16px; + line-height: 26px; + font-weight: $font-weight-bold; + &:global(.dark) { color: $black-100; } strong { - font-size: 26px; - font-weight: $font-weight-medium; - line-height: $sp-8; + font-size: 23px; + line-height: 27px; + font-weight: 900; } } diff --git a/src/apps/talent-search/src/components/match-bar/MatchBar.tsx b/src/apps/talent-search/src/components/profile-match/ProfileMatch.tsx similarity index 76% rename from src/apps/talent-search/src/components/match-bar/MatchBar.tsx rename to src/apps/talent-search/src/components/profile-match/ProfileMatch.tsx index 2de8d66e1..a6a568be6 100644 --- a/src/apps/talent-search/src/components/match-bar/MatchBar.tsx +++ b/src/apps/talent-search/src/components/profile-match/ProfileMatch.tsx @@ -1,14 +1,14 @@ import { FC } from 'react' import classNames from 'classnames' -import styles from './MatchBar.module.scss' +import styles from './ProfileMatch.module.scss' -interface MatchBarProps { +interface ProfileMatchProps { className?: string percent?: number } -const MatchBar: FC = props => { +const ProfileMatch: FC = props => { const value = Math.round((props.percent ?? 0) * 100) return ( @@ -25,4 +25,4 @@ const MatchBar: FC = props => { ) } -export default MatchBar +export default ProfileMatch diff --git a/src/apps/talent-search/src/components/profile-match/index.ts b/src/apps/talent-search/src/components/profile-match/index.ts new file mode 100644 index 000000000..6508c84e9 --- /dev/null +++ b/src/apps/talent-search/src/components/profile-match/index.ts @@ -0,0 +1 @@ +export { default as ProfileMatch } from './ProfileMatch' diff --git a/src/apps/talent-search/src/components/talent-card/TalentCard.module.scss b/src/apps/talent-search/src/components/talent-card/TalentCard.module.scss index 3d9630ef7..f3ae7e033 100644 --- a/src/apps/talent-search/src/components/talent-card/TalentCard.module.scss +++ b/src/apps/talent-search/src/components/talent-card/TalentCard.module.scss @@ -1,7 +1,7 @@ @import "@libs/ui/styles/includes"; .wrap { - padding: $sp-55 $sp-8; + padding: $sp-6; border-radius: $sp-4; background: $tc-white; @@ -12,20 +12,20 @@ .topWrap { display: flex; - gap: $sp-10; + gap: $sp-6; } .profilePic { - width: 200px; - max-width: 200px; + width: 188px; + max-width: 188px; } .detailsContainer { flex: 1 1 auto; - padding: $sp-5 $sp-45 $sp-45 0; + padding: $sp-5 0 $sp-45; display: flex; - flex-direction: column; + gap: $sp-4; } .talentInfo { @@ -34,6 +34,7 @@ align-items: flex-start; gap: $sp-3; margin-bottom: $sp-45; + flex: 1 1 auto; &Name { font-size: 30px; @@ -55,9 +56,9 @@ } -.matchBar { - max-width: 330px; - margin-top: auto; +.profileMatch { + width: 83px; + flex: 0 0 auto; } .skillsContainer { diff --git a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx index 4e40d6077..5c335022f 100644 --- a/src/apps/talent-search/src/components/talent-card/TalentCard.tsx +++ b/src/apps/talent-search/src/components/talent-card/TalentCard.tsx @@ -7,7 +7,7 @@ import codes from 'country-calling-code' import { IconSolid } from '~/libs/ui' import { isSkillVerified, ProfilePicture, Skill, SkillPill } from '~/libs/shared' -import { MatchBar } from '../match-bar' +import { ProfileMatch } from '../profile-match' import { Member } from '../../lib/models' import { TALENT_SEARCH_PATHS } from '../../talent-search.routes' import { useIsMatchingSkill } from '../../lib/utils' @@ -35,12 +35,12 @@ const TalentCard: FC = props => { const matchedSkills = orderBy( props.member.emsiSkills, - isSkillVerified, - 'desc', + [isSkillVerified, a => a.name], + ['desc', 'asc'], ) .filter(isMatchingSkill) - const limitMatchedSkills = matchedSkills.slice(0, 10) + const limitMatchedSkills = matchedSkills.slice(0, 7) const provenSkills = limitMatchedSkills.filter(isSkillVerified) const selfSkills = limitMatchedSkills.filter(s => !isSkillVerified(s)) @@ -48,7 +48,7 @@ const TalentCard: FC = props => { const restLabel = restSkills > 0 && (
- {`+${restSkills} more skill${restSkills > 1 ? 's' : ''}`} + {`+${restSkills} more matched skill${restSkills > 1 ? 's' : ''}`}
) @@ -85,41 +85,32 @@ const TalentCard: FC = props => { ))} - +
+ +
-
Matched skills
- {provenSkills.length > 0 && ( - <> -
Proven skills
-
- {provenSkills.map(skill => ( - - ))} - {!selfSkills.length && restLabel} -
- - )} - {selfSkills.length > 0 && ( - <> -
Self-selected skills
-
- {selfSkills.map(skill => ( - - ))} - {restLabel} -
- - )} +
+ {`${matchedSkills.length} Matched skills`} +
+
+ {provenSkills.length > 0 && provenSkills.map(skill => ( + + ))} + {selfSkills.length > 0 && selfSkills.map(skill => ( + + ))} + {restLabel} +
) diff --git a/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.module.scss b/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.module.scss index ad203f037..823e89372 100644 --- a/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.module.scss +++ b/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.module.scss @@ -21,11 +21,32 @@ margin: $sp-4 0 $sp-5; text-align: center; color: $black-60; + + display: flex; + align-items: center; + justify-content: center; + > span { + display: block; + margin: 0 auto; + flex: 1 1 auto; + } + + :global(.highlighting) { color: $black-100; } } +.skillsPill { + flex: 0 0 auto; + + &:first-child { + opacity: 0; + visibility: hidden; + pointer-events: none; + } +} + .searchInput { margin-top: $sp-10; } diff --git a/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.tsx b/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.tsx index 1709928aa..c49916412 100644 --- a/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.tsx +++ b/src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.tsx @@ -1,8 +1,9 @@ -import { FC, useContext, useEffect, useRef } from 'react' +import { FC, useCallback, useContext, useEffect, useRef, useState } from 'react' import classNames from 'classnames' import { profileContext, ProfileContextData } from '~/libs/core' import { Button, ContentLayout, LoadingCircles } from '~/libs/ui' +import { EmsiSkillSources, HowSkillsWorkModal, SkillPill } from '~/libs/shared' import { TalentCard } from '../../components/talent-card' import { SearchInput } from '../../components/search-input' @@ -17,6 +18,7 @@ import styles from './SearchResultsPage.module.scss' const SearchResultsPage: FC = () => { const sprigFlag = useRef(false) + const [showSkillsModal, setShowSkillsModal] = useState(false) const { profile }: ProfileContextData = useContext(profileContext) const [skills, setSkills] = useUrlQuerySearchParms('q') @@ -28,6 +30,17 @@ const SearchResultsPage: FC = () => { total, }: InfiniteTalentMatchesResposne = useInfiniteTalentMatches(skills) + const toggleSkillsModal = useCallback(() => setShowSkillsModal(s => !s), []) + + const skillsModalTriggerBtn = ( +
+ +
+ ) + useEffect(() => { if (profile?.userId && matches?.length && !sprigFlag.current) { sprigFlag.current = true @@ -61,12 +74,16 @@ const SearchResultsPage: FC = () => { ) : ( <> - We found  - - {total} -  Experts + {skillsModalTriggerBtn} + + We found  + + {total} +  Experts + +  that match your search -  that match your search + {skillsModalTriggerBtn} )} @@ -87,6 +104,9 @@ const SearchResultsPage: FC = () => { )} + {showSkillsModal && ( + + )} ) diff --git a/src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/HowSkillsWorkModal.module.scss b/src/libs/shared/lib/components/modals/how-skills-work-modal/HowSkillsWorkModal.module.scss similarity index 100% rename from src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/HowSkillsWorkModal.module.scss rename to src/libs/shared/lib/components/modals/how-skills-work-modal/HowSkillsWorkModal.module.scss diff --git a/src/libs/shared/lib/components/modals/how-skills-work-modal/HowSkillsWorkModal.tsx b/src/libs/shared/lib/components/modals/how-skills-work-modal/HowSkillsWorkModal.tsx new file mode 100644 index 000000000..317fe8820 --- /dev/null +++ b/src/libs/shared/lib/components/modals/how-skills-work-modal/HowSkillsWorkModal.tsx @@ -0,0 +1,108 @@ +import { FC } from 'react' + +import { BaseModal, IconOutline } from '~/libs/ui' + +import styles from './HowSkillsWorkModal.module.scss' + +interface HowSkillsWorkModalProps { + onClose: () => void + isTalentSearch?: boolean + iseSelfView?: boolean +} + +const HowSkillsWorkModal: FC = (props: HowSkillsWorkModalProps) => ( + + {!!props.iseSelfView && ( +
+

+ Topcoder Proven Skills +

+

+ Look for the proven + + next to skills. +

+

Here’s how it works:

+
    +
  • You perform specific Topcoder opportunities
  • +
  • Each opportunity has associated skills (ex: javascript, HTML)
  • +
  • + You can prove you are proficient in these skills + by completing opportunities on the platform +
  • +
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • +
  • The more opportunities you complete the higher you rate for associated skills
  • +
+

+ You can also self-proclaim skills that have not yet been proven. + These will display as skills without a checkmark. +

+
+ )} + + {!props.iseSelfView && props.isTalentSearch && ( +
+

+ Topcoder Skill Matching +

+

Topcoder identifies experts that will best match the skills you are searching for.

+

+ Look for the proven + + next to skills. +

+

Here’s how it works:

+
    +
  • Experts perform specific Topcoder opportunities
  • +
  • Each task has associated skills (ex: javascript, HTML)
  • +
  • + Experts prove they are proficient in these skills + by completing opportunities on the platform +
  • +
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • +
  • The more opportunities our experts complete the higher they rate for associated skills
  • +
+

+ Experts can also self-proclaim skills that have not yet been proven. + These will display as skills without a checkmark. +

+
+ )} + + {!props.iseSelfView && !props.isTalentSearch && ( +
+

+ Topcoder Proven Skills +

+

Our experts work hard to prove their skills through Topcoder opportunities.

+

+ Look for the proven + + next to skills. +

+

Here’s how it works:

+
    +
  • Experts perform specific Topcoder opportunities
  • +
  • Each opportunity has associated skills (ex: javascript, HTML)
  • +
  • + Experts prove they are proficient in these skills + by completing opportunities on the platform +
  • +
  • Topcoder tracks and labels these skills, displaying what skills have been proven
  • +
  • The more opportunities our experts complete the higher they rate for associated skills
  • +
+

+ Experts can also self-proclaim skills that have not yet been proven. + These will display as skills without a checkmark. +

+
+ )} +
+) + +export default HowSkillsWorkModal diff --git a/src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/index.ts b/src/libs/shared/lib/components/modals/how-skills-work-modal/index.ts similarity index 100% rename from src/apps/profiles/src/member-profile/skills/HowSkillsWorkModal/index.ts rename to src/libs/shared/lib/components/modals/how-skills-work-modal/index.ts diff --git a/src/libs/shared/lib/components/modals/index.ts b/src/libs/shared/lib/components/modals/index.ts index 89930fa59..2b65b1e3a 100644 --- a/src/libs/shared/lib/components/modals/index.ts +++ b/src/libs/shared/lib/components/modals/index.ts @@ -2,3 +2,4 @@ export * from './contact-support-modal' export * from './order-contract-modal' export * from './privacy-policy-modal' export * from './terms-modal' +export * from './how-skills-work-modal'