Skip to content

[PROD RELEASE] - Copilot Portal fixes #1137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8d20c30
fix: redirect to requests page once request is created
hentrymartin Jul 8, 2025
258c6da
fix: redirect to requests page once request is created
hentrymartin Jul 8, 2025
2df6c37
fix: redirect to requests page once request is created
hentrymartin Jul 8, 2025
a818130
fix: used router to navigate
hentrymartin Jul 9, 2025
51634fb
fix: used router to navigate
hentrymartin Jul 9, 2025
fa09b18
fix: used router to navigate
hentrymartin Jul 9, 2025
9f88d4a
fix: implemented client side infinite scroll
hentrymartin Jul 9, 2025
3c10762
fix: implemented client side infinite scroll
hentrymartin Jul 9, 2025
fd517ed
fix: make notes mandatory
hentrymartin Jul 9, 2025
e621c94
fix: modified the scroll event
hentrymartin Jul 10, 2025
d565783
fix: modified the scroll event
hentrymartin Jul 10, 2025
75aa8cb
fix: lint
hentrymartin Jul 10, 2025
248914c
Merge pull request #1131 from topcoder-platform/pm-1448_in-scroll
hentrymartin Jul 10, 2025
d67e5ae
fix: added hover actions for application icons
hentrymartin Jul 10, 2025
f4cee24
Merge pull request #1132 from topcoder-platform/pm-1468
hentrymartin Jul 10, 2025
80720e7
Merge pull request #1129 from topcoder-platform/pm-1322
hentrymartin Jul 10, 2025
4da42fa
fix: show applications count in tab
hentrymartin Jul 10, 2025
bcf7098
fix: lint
hentrymartin Jul 10, 2025
429f44b
fix: lint
hentrymartin Jul 10, 2025
1bc239f
fix: undefined error in profile picture component
hentrymartin Jul 11, 2025
bb10a8f
fix: qa feedbacks
hentrymartin Jul 11, 2025
01975d5
fix: qa feedbacks
hentrymartin Jul 11, 2025
1d6825c
fix: qa feedbacks
hentrymartin Jul 11, 2025
e929c29
fix: qa feedbacks
hentrymartin Jul 11, 2025
343ff82
Merge pull request #1136 from topcoder-platform/pm-1448_1
hentrymartin Jul 11, 2025
b546384
Merge pull request #1135 from topcoder-platform/pm-1470
hentrymartin Jul 11, 2025
53accf4
Merge pull request #1134 from topcoder-platform/pm-1469
hentrymartin Jul 11, 2025
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ workflows:
- LVT-256
- CORE-635
- feat/system-admin
- pm-1464
- pm-1448_1

- deployQa:
context: org-global
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ApplyOpportunityModal: FC<ApplyOpportunityModalProps> = props => {
buttons={
!success ? (
<>
<Button primary onClick={onApply} label='Apply' />
<Button disabled={!notes?.trim()} primary onClick={onApply} label='Apply' />

Choose a reason for hiding this comment

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

The disabled attribute is conditionally set based on notes?.trim(). Ensure that notes is properly initialized and defined in the component to avoid potential runtime errors if notes is undefined or null.

<Button secondary onClick={props.onClose} label='Cancel' />
</>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ const CopilotOpportunityDetails: FC<{}> = () => {
<TabsNavbar
defaultActive={activeTab}
onChange={handleTabChange}
tabs={getCopilotDetailsTabsConfig(isAdminOrPM)}
tabs={getCopilotDetailsTabsConfig(isAdminOrPM, copilotApplications?.length || 0)}

Choose a reason for hiding this comment

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

The function getCopilotDetailsTabsConfig now takes an additional parameter copilotApplications?.length || 0. Ensure that this function is updated to handle the new parameter correctly and that it does not break existing functionality. Verify that the logic inside getCopilotDetailsTabsConfig properly utilizes this parameter.

/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ export enum CopilotDetailsTabViews {
applications = '1',
}

export const getCopilotDetailsTabsConfig = (isAdminOrPM: boolean): TabsNavItem[] => (isAdminOrPM ? [
export const getCopilotDetailsTabsConfig = (isAdminOrPM: boolean, count: number): TabsNavItem[] => (isAdminOrPM ? [

Choose a reason for hiding this comment

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

The function getCopilotDetailsTabsConfig now takes an additional parameter count, but there is no validation or default value handling for this parameter. Consider adding validation to ensure count is a non-negative integer.

{
id: CopilotDetailsTabViews.details,
title: 'Details',
},
{
badges: [{
count,
type: 'info',
}],
id: CopilotDetailsTabViews.applications,
title: 'Applications',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ const CopilotApplicationAction = (
!isInvited
&& copilotApplication.status === CopilotApplicationStatus.PENDING
&& copilotApplication.opportunityStatus === 'active' && (
<IconSolid.UserAddIcon />
<Tooltip content='Send Invitation'>
<IconSolid.UserAddIcon />
</Tooltip>
)
}

{
copilotApplication.status === CopilotApplicationStatus.ACCEPTED && (
<IconSolid.BadgeCheckIcon />
<Tooltip content='Application Accepted'>
<IconSolid.BadgeCheckIcon />
</Tooltip>
)
}
</div>
Expand Down
6 changes: 6 additions & 0 deletions src/apps/copilots/src/pages/copilot-request-form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FC, useContext, useMemo, useState } from 'react'
import { bind, debounce, isEmpty } from 'lodash'
import { toast } from 'react-toastify'
import { useNavigate } from 'react-router-dom'

Choose a reason for hiding this comment

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

Consider adding useNavigate to the list of hooks used in this component, if not already done, to ensure consistency and clarity in the usage of hooks.

import classNames from 'classnames'

import { profileContext, ProfileContextData } from '~/libs/core'
Expand All @@ -16,6 +17,7 @@ import styles from './styles.module.scss'
// eslint-disable-next-line
const CopilotRequestForm: FC<{}> = () => {
const { profile }: ProfileContextData = useContext(profileContext)
const navigate = useNavigate()

const [formValues, setFormValues] = useState<any>({})

Choose a reason for hiding this comment

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

Consider specifying a more precise type for formValues instead of using any to improve type safety and maintainability.

const [isFormChanged, setIsFormChanged] = useState(false)
Expand Down Expand Up @@ -217,6 +219,10 @@ const CopilotRequestForm: FC<{}> = () => {
setIsFormChanged(false)
setFormErrors({})
setPaymentType('')
// Added a small timeout for the toast to be visible properly to the users
setTimeout(() => {

Choose a reason for hiding this comment

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

Consider extracting the timeout duration (1000 ms) into a constant with a descriptive name to improve code readability and maintainability.

navigate('/requests')
}, 1000)
})
.catch(e => {
toast.error(e.message)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useCallback, useState } from 'react'
import { FC, useCallback, useEffect, useState } from 'react'
import classNames from 'classnames'

import { Button, ContentLayout, LinkButton, LoadingCircles } from '~/libs/ui'
Expand All @@ -17,6 +17,9 @@ import styles from './SearchResultsPage.module.scss'
const SearchResultsPage: FC = () => {
const [showSkillsModal, setShowSkillsModal] = useState(false)

const [currentPage, setCurrentPage] = useState(1)
const itemsPerPage = 10

const [skills, setSkills] = useUrlQuerySearchParms('q')
const {
loading,
Expand All @@ -25,6 +28,27 @@ const SearchResultsPage: FC = () => {
hasNext,
total,
}: InfiniteTalentMatchesResposne = useInfiniteTalentMatches(skills)
const paginatedMatches = matches.slice(0, currentPage * itemsPerPage)

useEffect(() => {
const handleScroll: () => void = () => {
const scrollY = window.scrollY
const visibleHeight = window.innerHeight
const fullHeight = document.body.scrollHeight
const footerElem = document.getElementById('footer-nav-el')
const footerHeight = (footerElem && footerElem.offsetHeight) || 650

Choose a reason for hiding this comment

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

Consider using a more reliable method to get the footer height, as relying on a default value of 650 may not be accurate across different screen sizes or if the footer content changes.

if (scrollY + visibleHeight >= fullHeight - (footerHeight + 100)) {

Choose a reason for hiding this comment

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

The condition scrollY + visibleHeight >= fullHeight - (footerHeight + 100) could be extracted into a well-named variable for better readability and maintainability.

// Scroll near bottom
setCurrentPage(prev => {
const maxPages = Math.ceil(matches.length / itemsPerPage)

Choose a reason for hiding this comment

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

Consider adding a check to ensure itemsPerPage is not zero to prevent potential division by zero errors when calculating maxPages.

return prev < maxPages ? prev + 1 : prev
})
}
}

window.addEventListener('scroll', handleScroll)
return () => window.removeEventListener('scroll', handleScroll)
}, [matches])

const toggleSkillsModal = useCallback(() => setShowSkillsModal(s => !s), [])

Expand Down Expand Up @@ -100,7 +124,7 @@ const SearchResultsPage: FC = () => {
)}
</div>
<div className={styles.resultsWrap}>
{matches.map(member => (
{paginatedMatches.map(member => (
<TalentCard
queriedSkills={skills}
member={member}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const ProfilePicture: FC<ProfilePictureProps> = props => {
>
{!loaded && (
<span className={styles.profileInitials}>
{props.member.firstName.slice(0, 1)}
{props.member.lastName.slice(0, 1)}
{props.member?.firstName?.slice(0, 1)}
{props.member?.lastName?.slice(0, 1)}
</span>
)}
{props.member.photoURL && !error && (
Expand Down