Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
aa4b5c9
PM-3357 - profile completeness messaging
vas3a Jan 13, 2026
c0ee28c
lint fixes
vas3a Jan 13, 2026
6cf84b5
feat: added download button in profile page
hentrymartin Jan 13, 2026
905c256
fix: lint
hentrymartin Jan 13, 2026
b33b925
fix: smaller improvements
hentrymartin Jan 13, 2026
f8f7de9
fix styling
vas3a Jan 14, 2026
8d2c316
fix: lint
hentrymartin Jan 14, 2026
b530246
Minor tweaks to legend view based on user feedback
jmgasper Jan 15, 2026
fa871ac
Legend wording
jmgasper Jan 15, 2026
440c14c
Merge pull request #1401 from topcoder-platform/leave-tracker
jmgasper Jan 15, 2026
5e1dd7f
Merge pull request #1395 from topcoder-platform/PM-3357_profile-compl…
vas3a Jan 15, 2026
1422386
For approvers show final score if available
vas3a Jan 15, 2026
16c640c
Merge pull request #1403 from topcoder-platform/PM-2663_approvers-fin…
vas3a Jan 15, 2026
49eea51
PM-3357 - make sure to filter out profileCompleteness categories
vas3a Jan 15, 2026
5bafaef
PM-3397 Add email to profiles UI
himaniraghav3 Jan 15, 2026
cc66789
Merge pull request #1404 from topcoder-platform/PM-3357_profile-compl…
vas3a Jan 15, 2026
7cf6173
Merge pull request #1405 from topcoder-platform/PM-3397
himaniraghav3 Jan 15, 2026
17c4257
removed console log
hentrymartin Jan 15, 2026
e149a45
fix: review comments
hentrymartin Jan 15, 2026
c3ca9bc
fix: review comments
hentrymartin Jan 15, 2026
b90b66f
fix: review comments
hentrymartin Jan 15, 2026
64edac4
fix: lint
hentrymartin Jan 15, 2026
afbe389
fix: lint
hentrymartin Jan 15, 2026
0d36298
Merge pull request #1398 from topcoder-platform/pm-3398
hentrymartin Jan 15, 2026
9b889f1
Merge pull request #1396 from topcoder-platform/pm-3319
hentrymartin Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/apps/calendar/src/lib/utils/calendar.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const statusColorMap: Record<LeaveStatus, string> = {

const statusLabelMap: Record<LeaveStatus, string> = {
[LeaveStatus.LEAVE]: 'Leave',
[LeaveStatus.HOLIDAY]: 'Personal Holiday',
[LeaveStatus.HOLIDAY]: 'Holiday',
[LeaveStatus.WIPRO_HOLIDAY]: 'Wipro Holiday',
[LeaveStatus.WEEKEND]: 'Weekend',
[LeaveStatus.AVAILABLE]: 'Available',
Expand All @@ -22,7 +22,6 @@ export const legendStatusOrder: LeaveStatus[] = [
LeaveStatus.AVAILABLE,
LeaveStatus.LEAVE,
LeaveStatus.HOLIDAY,
LeaveStatus.WIPRO_HOLIDAY,
LeaveStatus.WEEKEND,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ correctness]
Removing LeaveStatus.WIPRO_HOLIDAY from legendStatusOrder may affect any functionality that relies on the order of statuses. Ensure that this change is intentional and does not break any dependent logic.

]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const PersonalCalendarPage: FC = () => {
onClick={handleSetAsHoliday}
disabled={!selectedDates.size || isUpdating}
>
Set as Personal Holiday
Set as Holiday
</Button>
<Button
secondary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

.navigation {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
justify-content: center;
margin: 14px 0 10px;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { addMonths, endOfMonth, startOfMonth, subMonths } from 'date-fns'
import { FC, useCallback, useEffect, useMemo, useState } from 'react'

import { MonthNavigation, TeamCalendar } from '../../lib/components'
import { CalendarLegend, MonthNavigation, TeamCalendar } from '../../lib/components'
import { useFetchTeamLeave } from '../../lib/hooks'

import styles from './TeamCalendarPage.module.scss'
Expand Down Expand Up @@ -57,6 +57,7 @@ const TeamCalendarPage: FC = () => {
onNextMonth={handleNextMonth}
onPrevMonth={handlePrevMonth}
/>
<CalendarLegend />
</section>

<section className={styles.calendarSection}>
Expand Down
4 changes: 4 additions & 0 deletions src/apps/profiles/src/config/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// import { EnvironmentConfig } from '~/config'

import { UserRole } from '~/libs/core'

export enum TRACKS_PROFILE_MAP {
DEVELOP = 'Developer',
DESIGN = 'Designer',
Expand All @@ -26,3 +28,5 @@ export enum profileEditModes {
// (removed) CES Survey/Userflow integrations

export const MAX_PRINCIPAL_SKILLS_COUNT = 10

export const ADMIN_ROLES = [UserRole.administrator]
38 changes: 37 additions & 1 deletion src/apps/profiles/src/lib/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable complexity */
import { UserProfile } from '~/libs/core'
import { UserProfile, UserRole } from '~/libs/core'

import { ADMIN_ROLES } from '../config'

declare global {
interface Window { tcUniNav: any }
Expand Down Expand Up @@ -125,3 +127,37 @@ export function isValidURL(urlToValidate: string): boolean {
export function formatPlural(count: number, baseWord: string): string {
return `${baseWord}${count === 1 ? '' : 's'}`
}

/**
* Check if the user can download the profile
* @param authProfile - The authenticated user profile
* @param profile - The profile to check if the user can download
* @returns {boolean} - Whether the user can download the profile
*/
export function canDownloadProfile(authProfile: UserProfile | undefined, profile: UserProfile): boolean {
if (!authProfile) {
return false
}

// Check if user is viewing their own profile
if (authProfile.handle === profile.handle) {
return true
}

// Check if user has admin roles
if (authProfile.roles?.some(role => ADMIN_ROLES.includes(role.toLowerCase() as UserRole))) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The use of toLowerCase() on roles might lead to unexpected behavior if ADMIN_ROLES contains roles with mixed casing. Consider ensuring ADMIN_ROLES is consistently cased or adjust the logic to handle casing more robustly.

return true
}

// Check if user has PM or Talent Manager roles
const allowedRoles = ['Project Manager', 'Talent Manager']
if (authProfile
.roles?.some(
role => allowedRoles.some(allowed => role.toLowerCase() === allowed.toLowerCase()),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
The allowedRoles array is defined within the function and used only once. Consider moving it outside the function to avoid redefining it on each function call, which can slightly improve performance.

)
) {
return true
}

return false
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@
padding: $sp-4 $sp-4 $sp-4 0;
}
}

.titleWrap {
margin-top: $sp-8;
}

.email {
display: flex;
align-items: center;
}

.emailText {
margin-top: $sp-2;
}
13 changes: 13 additions & 0 deletions src/apps/profiles/src/member-profile/about-me/AboutMe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { KeyedMutator } from 'swr'
import classNames from 'classnames'

import { NamesAndHandleAppearance, useMemberTraits, UserProfile, UserTraitIds, UserTraits } from '~/libs/core'
import { CopyButton } from '~/apps/admin/src/lib/components/CopyButton'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ maintainability]
The CopyButton component is imported from the admin app's library. Ensure that this component is intended to be shared across different apps and that there are no unintended dependencies or side effects. Consider moving shared components to a common library if they are used across multiple apps.


import { AddButton, EditMemberPropertyBtn, EmptySection } from '../../components'
import { EDIT_MODE_QUERY_PARAM, profileEditModes } from '../../config'
Expand Down Expand Up @@ -119,6 +120,18 @@ const AboutMe: FC<AboutMeProps> = (props: AboutMeProps) => {
/>
)
}

{props.profile?.email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[❗❗ security]
Displaying the user's email address directly in the UI may have privacy implications. Ensure that displaying the email is compliant with privacy policies and consider adding user consent or a privacy notice if necessary.

&& (
<div className={styles.titleWrap}>
<p className='body-main-bold'>Contact</p>
<div className={styles.email}>
<p className={styles.emailText}>{props.profile.email}</p>
<CopyButton className={styles.copyButton} text={props.profile.email} />
</div>
</div>
)}

</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,68 @@
height: 100%;

.profileHeaderWrap {
position: relative;
background: url('../../lib/assets/profile-header-bg.png') no-repeat right top / auto, linear-gradient(#0d83c5, #0e89d5);

@include ltelg {
background: url('../../lib/assets/profile-header-bg-mobile.png') no-repeat right top /100% 100%;
}

.downloadButtonWrap {
position: absolute;
top: $sp-4;
right: calc((100% - #{$xxl-min}) / 2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The calculation for right using calc((100% - #{$xxl-min}) / 2) may lead to unexpected layout issues if $xxl-min is larger than the container width. Consider verifying the value of $xxl-min or using a different approach to ensure consistent alignment.

max-width: $xxl-min;
width: 100%;
display: flex;
justify-content: flex-end;
padding-right: $sp-8;
z-index: 10;

@include ltexl {
right: $sp-8;
}

@include ltemd {
padding-right: $sp-6;
right: $sp-6;
}

@include ltesm {
padding-right: $sp-4;
right: $sp-4;
}

@include ltelg {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 maintainability]
The @include ltelg block redefines several properties that are already set outside of this block. This could lead to redundancy and potential maintenance issues. Consider consolidating these styles to avoid duplication.

position: absolute;
top: $sp-4;
right: $sp-4;
left: auto;
max-width: none;
width: auto;
padding: 0;
pointer-events: auto;
}

> * {
pointer-events: auto;
}
}

.downloadButton {
color: $tc-white;
padding: $sp-2 $sp-4;
border-radius: 4px;
font-weight: $font-weight-bold;
font-family: $font-roboto;
font-size: 16px;

&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}

.profileHeaderContent {
padding: 0;
max-height: 260px;
Expand Down
Loading
Loading