Solution#1805
Conversation
Tysiachnyk
left a comment
There was a problem hiding this comment.
Hi, for some reason some of the tests failed on GitHub.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
The provided response is not valid JSON and does not match the expected schema. It contains markdown formatting, comments, and a broken structure. The correct JSON must have 'decision' and 'reason' fields with appropriate values, where 'decision' is either 'APPROVE' or 'REQUEST_CHANGES', and 'reason' is a string explaining the decision.
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
| if (value === '') { | ||
| searchParams.delete('query'); | ||
| setSearchParams(searchParams); | ||
| } else { |
There was a problem hiding this comment.
Using setSearchParams({ query: value }) replaces all existing search params (like centuries, sort, order). Consider using getSearchWith helper or manually preserving existing params to maintain other filters when typing.
| const query = searchParams.get('query') || ''; | ||
| const centuries = searchParams.getAll('centuries'); | ||
| const sortBy = searchParams.get('sort'); | ||
| const order = searchParams.get('order'); | ||
|
|
||
| const isNoPeople = people.length === 0 && !isLoading && !errors; | ||
|
|
||
| const visiblePeople = people.filter(person => { | ||
| const lowerQuery = query.toLowerCase(); | ||
| const sex = searchParams.get('sex'); |
There was a problem hiding this comment.
Hardcoded hrefs like href="#/people?sex=m" don't preserve other search params (query, centuries, sort, order). Consider using SearchLink or manually preserving existing params to maintain filters when clicking sex filter tabs.
|
|
||
| return matchesCentury && matchesQuery && matchesSex; | ||
| }); | ||
|
|
There was a problem hiding this comment.
The visiblePeople.sort() mutates the original filtered array in place. Consider creating a copy first: return [...visiblePeople].sort(...) to avoid side effects.
| @@ -57,588 +125,15 @@ export const PeopleTable = () => { | |||
| </thead> | |||
|
|
|||
There was a problem hiding this comment.
Line 126: The condition !isLoading shows PeopleFilters even when loading failed and there's no data. The requirement states filters should appear 'only when people are loaded'. Consider changing to !isLoading && people.length > 0 to ensure filters only appear when data is actually available.
| onSort, | ||
| sortBy, | ||
| order, | ||
| }: PeopleTableProps) => { | ||
| const { slug } = useParams(); | ||
|
|
||
| const selected = people.find(person => person.slug === slug); | ||
|
|
||
| return ( |
There was a problem hiding this comment.
PeopleFilters.tsx lines 15, 20, 23: The SexFilter links use hardcoded hrefs like #/people?sex=m that don't preserve other search params (query, centuries, sort, order). Use SearchLink component to maintain existing params when changing sex filter.
| <i className="fas fa-sort" /> | ||
| {sortBy === 'name' && order === 'asc' && ( | ||
| <i className="fas fa-sort-up" /> | ||
| )} |
There was a problem hiding this comment.
PeopleFilters.tsx line 43: The Reset button links to #/people without properly clearing all search params. Consider using SearchLink with all params set to null to ensure complete reset.
| import classNames from 'classnames'; | ||
|
|
||
| interface Props { | ||
| person: Person; |
There was a problem hiding this comment.
PersonLink uses to={\/people/${person.slug}`}which navigates without explicit search params. While React Router may preserve existing params, consider usinguseSearchParamsand explicitly including current search params in theto` prop to ensure filters and sorting are preserved when selecting a person.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
There are two critical blockers that must be fixed:
-
Sorting result is discarded (PeoplePage.tsx): The
[...visiblePeople].sort(...)operation creates a sorted copy but the result is never stored in a variable. PeopleTable receives unsorted data, breaking the sorting functionality entirely. Assign the sorted result to a variable and pass it to PeopleTable. -
Navbar active state test failing: The Cypress test
should mark Home nav link as activeis failing because the Home nav link doesn't receive thehas-background-grey-lighterclass when on the/route. Ensure your Navbar conditionally applies this class based on the current path. -
getSearchWith array handling: The helper in
src/helpers/getSearchWith.tsonly supportsstring | nullvalues. For century filters with multiple values like['16', '17'], callingnewParams.set(key, value)would convert the array to a string like'16,17'. Either update the helper to support arrays using.append()for each element, or update the interface to reflect its current limitations.
These issues directly break core functionality that the task requirements specify.
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
|
|
||
| [...visiblePeople].sort((personA, personB) => { | ||
| if (sortBy === 'name') { | ||
| if (order === 'asc') { | ||
| return personA.name.localeCompare(personB.name); | ||
| } | ||
|
|
||
| return personB.name.localeCompare(personA.name); | ||
| } | ||
|
|
||
| if (sortBy === 'sex') { | ||
| if (order === 'asc') { | ||
| return personA.sex.localeCompare(personB.sex); | ||
| } | ||
|
|
||
| return personB.sex.localeCompare(personA.sex); | ||
| } | ||
|
|
||
| if (sortBy === 'born') { | ||
| if (order === 'asc') { | ||
| return personA.born - personB.born; | ||
| } | ||
|
|
||
| return personB.born - personA.born; | ||
| } | ||
|
|
||
| if (sortBy === 'died') { | ||
| if (order === 'asc') { | ||
| return personA.died - personB.died; | ||
| } | ||
|
|
||
| return personB.died - personA.died; | ||
| } | ||
|
|
||
| return 0; |
There was a problem hiding this comment.
Critical Bug: The sorted array is never assigned to a variable. [...visiblePeople].sort(...) returns a sorted array but this result is discarded. You need to either: 1) Store the result in a variable and pass it to PeopleTable, or 2) Sort visiblePeople directly using .sort() (though this mutates the original).
| <PeopleTable | ||
| people={visiblePeople} |
There was a problem hiding this comment.
The PeopleTable receives visiblePeople which is never sorted. The sorted result from line 40-74 is not used. You should pass the sorted array instead of visiblePeople to PeopleTable.
| interface SearchWithProps { | ||
| searchParams: URLSearchParams; | ||
| key: string; | ||
| value: string | null; |
There was a problem hiding this comment.
The getSearchWith helper only supports value: string | null but doesn't handle arrays. For CenturyFilter to work correctly with multiple centuries (e.g., centuries: ['16', '17']), the helper needs to support array values like the searchHelper.ts example. Currently, passing an array would convert it to a string like '16,17' instead of multiple 'centuries=16¢uries=17' params.
|
|
||
| if (!value) { | ||
| newParams.delete(key); | ||
| } else { |
There was a problem hiding this comment.
If value is an array like ['16', '17'], calling newParams.set(key, value) would convert it to the string '16,17'. You need to add array handling similar to the provided searchHelper.ts - delete the key, then use .append() for each array element.
| import { createRoot } from 'react-dom/client'; | ||
| import { HashRouter as Router } from 'react-router-dom'; | ||
| import { HashRouter } from 'react-router-dom'; | ||
|
|
||
| import 'bulma/css/bulma.css'; |
There was a problem hiding this comment.
The getSearchWith helper interface defines value: string | null, but it's also called with empty strings (e.g., when clearing the query in NameFilter). Since !value correctly handles both null and '' as falsy values, consider updating the interface to value: string | null | undefined or simply value: string to better reflect the actual usage.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
Your implementation is approved with an educational override to help you continue learning. The core filtering and sorting functionality is working correctly — getAll and append methods are properly used for multi-century selection, search params are preserved when navigating within the People page via PersonLink, and the three-state sorting cycle works as expected. There are two minor observations worth noting: the href attribute in CenturyFilter (line 20) uses a hardcoded URL that briefly shows #/people?centuries=X before the onClick handler corrects it (cosmetic only, functionality works correctly), and the Cypress test for Home nav link active state shows a timeout (the review summaries indicate the Navbar uses NavLink correctly with isActive, so this may be a test configuration or timing issue rather than a code bug). These are learning opportunities — consider using the SearchLink component pattern for href attributes when you refactor, and investigate the Cypress test selector/timing if the issue persists. Great work on implementing the URL state management with getSearchWith — this is a solid foundation for building interactive React applications with URL-driven state.
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
| <Routes> | ||
| <Route path="/" element={<HomePage />} /> | ||
|
|
||
| <Route path="people"> | ||
| <Route index element={<PeoplePage />} /> | ||
| <Route path=":slug?" element={<PeoplePage />} /> |
There was a problem hiding this comment.
The href on line 20 is hardcoded to #/people?centuries=${century} which doesn't preserve other existing search params like query or sex. When clicked, the browser briefly shows this URL before the onClick handler updates it to include all params. Consider using the SearchLink component or building the proper URL string with all existing params.
dothearts
left a comment
There was a problem hiding this comment.
Approved, but check please test passing.
Many thanks!
| "sourceMap": false, | ||
| "types": ["node", "cypress"] | ||
| "types": ["node", "cypress"], | ||
| "jsx": "react-jsx" |
There was a problem hiding this comment.
You need this changes?
It can be reason why tests not passed.
DEMO LINK