Skip to content
Merged
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ type TalentSearchSortOption = 'alphabetical' | 'matching-index'

export const TalentSearchPage: FC = () => {
const skipNextAutoSearchRef = useRef<boolean>(false)
const searchGenerationRef = useRef<number>(0) // ← add this
const searchGenerationRef = useRef<number>(0)
const toggleDebounceTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
const pendingToggleAutoSearchRef = useRef<boolean>(false)
const hasMountedRef = useRef<boolean>(false)

const [lastSearchedDescription, setLastSearchedDescription] = useState<string>('')
const countryLookup: CountryLookup[] | undefined = useCountryLookup()
Expand Down Expand Up @@ -91,20 +94,8 @@ export const TalentSearchPage: FC = () => {
[hasSkillSearch],
)

const filteredResults = useMemo(() => results.filter(talent => {
if (onlyActive && !talent.isRecentlyActive) {
return false
}

if (onlyOpenToWork && !talent.openToWork) {
return false
}

return true
}), [onlyActive, onlyOpenToWork, results])

// Order comes from reports-api (sortBy/sortOrder on each request) so pagination stays globally consistent.
const displayedResults = filteredResults
const displayedResults = results

const foundMembersCount = totalResults || displayedResults.length
const displayedResultsWithCountryName = useMemo(
Expand Down Expand Up @@ -162,6 +153,7 @@ export const TalentSearchPage: FC = () => {
},
): Promise<boolean> => {
const append = overrides?.append === true

const countries = (overrides?.countries ?? selectedCountryCodesList)
.filter(Boolean)
const generation = overrides?.generation
Expand Down Expand Up @@ -345,15 +337,72 @@ export const TalentSearchPage: FC = () => {

useEffect(() => {
if ((shouldShowIntroState) || isExtractingSkills) {
if (toggleDebounceTimerRef.current) {
clearTimeout(toggleDebounceTimerRef.current)
toggleDebounceTimerRef.current = undefined
}

pendingToggleAutoSearchRef.current = false

return
}

if (!hasMountedRef.current) {
hasMountedRef.current = true

if (skipNextAutoSearchRef.current) {
skipNextAutoSearchRef.current = false
pendingToggleAutoSearchRef.current = false
if (toggleDebounceTimerRef.current) {
clearTimeout(toggleDebounceTimerRef.current)
toggleDebounceTimerRef.current = undefined
}

return
}

runMemberSearch(selectedSkills, { generation: searchGenerationRef.current, page: 1 })
return
}

if (skipNextAutoSearchRef.current) {
skipNextAutoSearchRef.current = false
if (toggleDebounceTimerRef.current) {
clearTimeout(toggleDebounceTimerRef.current)
toggleDebounceTimerRef.current = undefined
}

pendingToggleAutoSearchRef.current = false

return
}

runMemberSearch(selectedSkills, { generation: searchGenerationRef.current, page: 1 })
const runSearch = (): void => {
runMemberSearch(selectedSkills, {
generation: searchGenerationRef.current,
page: 1,
})
}

const shouldDebounce = pendingToggleAutoSearchRef.current || Boolean(toggleDebounceTimerRef.current)

if (shouldDebounce) {
pendingToggleAutoSearchRef.current = false
if (toggleDebounceTimerRef.current) {
clearTimeout(toggleDebounceTimerRef.current)
toggleDebounceTimerRef.current = undefined
}

toggleDebounceTimerRef.current = setTimeout(() => {
toggleDebounceTimerRef.current = undefined
runSearch()
}, 800)
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
return
}

// No debounce requested and no pending timer: execute immediately.
pendingToggleAutoSearchRef.current = false
runSearch()
}, [
hasSearched,
hasActiveFilters,
Expand All @@ -366,6 +415,14 @@ export const TalentSearchPage: FC = () => {
shouldShowIntroState,
])

// Cleanup any pending debounced request on unmount.
useEffect(() => (): void => {
if (toggleDebounceTimerRef.current) {
clearTimeout(toggleDebounceTimerRef.current)
toggleDebounceTimerRef.current = undefined
}
}, [])

const handleLoadMore = useCallback((): void => {
if (isLoadingMore || isSearchingMembers || !hasMoreResults) {
return
Expand Down Expand Up @@ -472,24 +529,13 @@ export const TalentSearchPage: FC = () => {
placeholder='Select country'
/>
</div>
<label className={styles.checkboxRow}>
<input
type='checkbox'
checked={onlyProfileComplete}
className={styles.checkboxInput}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setOnlyProfileComplete(event.target.checked)
}}
/>
<span className={styles.toggleControl} />
<span>100% Profile complete</span>
</label>
<label className={styles.checkboxRow}>
<input
type='checkbox'
checked={onlyOpenToWork}
className={styles.checkboxInput}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
pendingToggleAutoSearchRef.current = true
setOnlyOpenToWork(event.target.checked)
}}
/>
Expand All @@ -502,6 +548,7 @@ export const TalentSearchPage: FC = () => {
checked={onlyActive}
className={styles.checkboxInput}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
pendingToggleAutoSearchRef.current = true
setOnlyActive(event.target.checked)
}}
/>
Expand All @@ -525,6 +572,19 @@ export const TalentSearchPage: FC = () => {
</Tooltip>
</span>
</label>
<label className={styles.checkboxRow}>
<input
type='checkbox'
checked={onlyProfileComplete}
className={styles.checkboxInput}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
pendingToggleAutoSearchRef.current = true
setOnlyProfileComplete(event.target.checked)
}}
/>
<span className={styles.toggleControl} />
<span>100% Profile complete</span>
</label>
<div className={styles.clearFiltersWrap}>
<Button secondary onClick={clearAllFilters}>
Clear Filters
Expand Down
Loading