solution, But I think I made some mistakes.#1823
Conversation
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
I am requesting changes because a few core checklist requirements are still not met, and they will likely cause tests and required behaviors to fail.
Critical issues that must be fixed before this can pass:
queryparam must be removed when the input is empty ([CHECKLIST ITEM #8, #18]). InPeopleFilters.tsx,PeoplePage.tsx, andPeopleTable.tsxyou always doparams.set('query', event.target.value), so when the input is cleared the URL becomes?query=instead of having noquerykey. Update the change handlers so that whenevent.target.value.trim()is empty you callparams.delete('query'), and onlyset('query', value)when it is non‑empty.- Search params must be preserved when navigating within the People page ([CHECKLIST ITEM #4, #16]). The
NavbarPeoplelink (src/components/Navbar.tsx) usesto="/people", andPersonLink(src/components/PersonLink.tsx) usesto={/people/${person.slug}}, both of which drop existing?query=...¢uries=...&sort=...&order=.... Replace these with yourSearchLinkhelper (or build atoobject that keeps the currentlocation.search) so that filters and sort remain in the URL when clickingPeopleor a specific person.
Minor/structural suggestions (not blockers, but worth improving):
- You currently have both
PeopleFiltersandPeopleTablecallingonFilter, which makes the visible list depend on two sources (URL params and internal state). Consider centralizing filtering/sorting in one place derived solely frompeoples + searchParamsto keep the URL as the single source of truth.
Your implementation of the filters, multi-century support, and sorting logic is otherwise very solid; once you fix the query clearing and navigation search-param preservation, it should align well with the task requirements.
✨ 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
| 'has-background-grey-lighter': isActive, | ||
| }); | ||
| }} | ||
| to="/people" |
There was a problem hiding this comment.
According to checklist items #4 and #16, when the user clicks the People navigation, existing search parameters must be preserved; using a plain to="/people" will drop any current ?query=...¢uries=... filters. Consider using your SearchLink wrapper (or useSearchParams with a composed to) here so the search string is carried over.
| function hangeChangeQuery(event: React.ChangeEvent<HTMLInputElement>) { | ||
| const params = new URLSearchParams(serchParams); | ||
|
|
||
| params.set('query', event.target.value); | ||
| setSerchParams(params); |
There was a problem hiding this comment.
| useEffect(() => { | ||
| let filtered = [...peoples]; | ||
|
|
||
| if (centuries.length > 0) { | ||
| filtered = filtered.filter(person => { | ||
| const century = Math.ceil(person.born / 100); | ||
|
|
||
| return centuries.includes(String(century)); | ||
| }); | ||
| } | ||
|
|
||
| if (sex) { | ||
| filtered = filtered.filter(person => person.sex === sex); | ||
| } | ||
|
|
||
| if (query) { | ||
| filtered = filtered.filter( | ||
| person => | ||
| person.name.toLowerCase().includes(query.trim().toLowerCase()) || | ||
| person.fatherName | ||
| ?.toLowerCase() | ||
| .includes(query.trim().toLowerCase()) || | ||
| person.motherName?.toLowerCase().includes(query.trim().toLowerCase()), | ||
| ); | ||
| } | ||
|
|
||
| onFilter(filtered); | ||
| }, [peoples, serchParams, sex, query, onFilter]); |
There was a problem hiding this comment.
This effect recalculates filtered based on peoples and search params and then calls onFilter(filtered), while PeopleTable also calls onFilter when sorting. That double responsibility makes the visible list depend on both URL params and internal state, which conflicts with the requirement that filters/sort be controlled by URL search params. Consider centralizing filtering/sorting logic so that it derives solely from peoples + search params in one place.
|
|
||
| if (n === 'All') { | ||
| params.delete('centuries'); | ||
|
|
||
| return setSerchParams(params); | ||
| } | ||
|
|
||
| const newCenturies = centuries.includes(n) | ||
| ? centuries.filter(centurie => centurie !== n) | ||
| : [...centuries, n]; | ||
|
|
||
| params.delete('centuries'); | ||
| newCenturies.forEach(ages => params.append('centuries', ages)); | ||
|
|
||
| return setSerchParams(params); | ||
| } | ||
|
|
||
| const handleClearAll = () => { | ||
| setSerchParams({}); | ||
| }; | ||
|
|
||
| useEffect(() => { | ||
| let filtered = [...peoples]; | ||
|
|
||
| if (centuries.length > 0) { | ||
| filtered = filtered.filter(person => { |
There was a problem hiding this comment.
sortPeople both updates local masPeople and calls onFilter(sorted), which then changes visiblePeoples in the parent. Since sorted is already stored locally in masPeople and the sort criteria are in the URL, propagating the sorted list upwards is redundant and can make state harder to reason about. Consider relying on URL params plus local state here, or centralizing the sort in the parent, but avoid two independent sorted states.
| .then(peopleFromServer => { | ||
| setPeoples(peopleFromServer); | ||
| setVisiblePeoples(peopleFromServer); | ||
| if (!peopleFromServer || peopleFromServer.length === 0) { | ||
| setChekError(TypeErroros.noPeople); |
There was a problem hiding this comment.
According to checklist items #6, #17, and especially #8/#18, when the search input is empty the query param should be removed from the URL, not set to an empty string. Here you always do params.set('query', event.target.value), so query= remains in the URL. Consider checking for an empty trimmed value and calling params.delete('query') when it’s empty, only set when it’s non-empty.
| if (typeof valA === 'number' && typeof valB === 'number') { | ||
| return order !== null ? valB - valA : valA - valB; |
There was a problem hiding this comment.
Calling setSerchParams({}) here clears all search params, which is good for a full reset. Just be aware that this also clears sort / order if they’re set, which is consistent with a “Reset all filters” button but goes beyond only filters; confirm this matches the desired UX.
| return 0; | ||
| }); | ||
|
|
||
| setMasPeople(sorted); | ||
| onFilter(sorted); | ||
| } | ||
|
|
||
| function hangelSort(sor: string) { | ||
| const params = new URLSearchParams(serchParams); | ||
|
|
||
| if (currentSort === sor && currentOrder === 'desc') { | ||
| params.delete('sort'); | ||
| params.delete('order'); | ||
| } else if (currentSort === sor) { | ||
| params.set('order', 'desc'); | ||
| } else { | ||
| params.set('sort', sor); | ||
| params.delete('order'); | ||
| } | ||
|
|
||
| currentSort = params.get('sort') as keyof Person | null; | ||
| currentOrder = params.get('order') as 'desc' | null; | ||
| setSerchParams(params); | ||
| sortPeople(currentSort, currentOrder); | ||
|
|
||
| return; | ||
| } | ||
|
|
There was a problem hiding this comment.
This effect correctly applies all filters based on URL params, but using serchParams as a dependency means the effect will re-run on any param change (including unrelated ones). That’s generally fine here, but if you later add extra search params not related to filtering, you might want to derive only the needed values instead of depending on the whole serchParams object.
| function sortPeople(field: keyof Person | null, order: 'desc' | null) { | ||
| const sorted = [...peoples]; | ||
|
|
||
| if (field === null) { | ||
| return setMasPeople([...peoples]); | ||
| } | ||
|
|
||
| sorted.sort((a, b) => { | ||
| const valA = a[field]; | ||
| const valB = b[field]; | ||
|
|
||
| if (typeof valA === 'string' && typeof valB === 'string') { | ||
| return order !== null | ||
| ? valB.localeCompare(valA) | ||
| : valA.localeCompare(valB); | ||
| } | ||
|
|
||
| if (typeof valA === 'number' && typeof valB === 'number') { | ||
| return order !== null ? valB - valA : valA - valB; | ||
| } | ||
|
|
||
| return 0; | ||
| }); | ||
|
|
||
| setMasPeople(sorted); | ||
| onFilter(sorted); |
There was a problem hiding this comment.
sortPeople derives the sorted list from the peoples prop (the parent’s visible array) and then calls onFilter(sorted). This makes sorting update the parent’s filtered state. While not forbidden, it couples sorting and filtering: you might prefer to leave onFilter responsible for filtering only and keep sorted state local to this table, especially since sort state is already stored in search params.
| <Link | ||
| className={classNames({ 'has-text-danger': person.sex === 'f' })} | ||
| to={`/people/${person.slug}`} |
There was a problem hiding this comment.
This Link navigates to /people/${person.slug} without preserving any existing search params (like ?query=...¢uries=...&sort=...). Checklist items #4 and #16 require keeping search params when navigating within the People page (including when selecting a person). Consider replacing this with your SearchLink component or building a to object that keeps the current location.search.
|
|
||
| /** | ||
| * SearchLink updates the given `params` in the search keeping the `pathname` | ||
| * and the other existing search params (see `getSearchWith`) | ||
| * SearchLink оновлює задані `params` у пошуку, зберігаючи `pathname` |
There was a problem hiding this comment.
The requirement says that search params must be preserved when navigating within the People page, including when selecting a person (checklist #4, #16). Here you use a plain to={/people/${person.slug}}, which drops existing ?query, centuries, sort, and order from the URL. Consider replacing this with your SearchLink component or building a to object that reuses the current location.search so these params are kept.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
I am requesting changes because one core requirement is still not satisfied: search params are not preserved when clicking the People link in the navbar, which is explicitly required for correct behavior of the People page. Currently, src/components/Navbar.tsx uses a plain NavLink with to="/people", so any active filters or sorting in the URL (like ?query=¢uries=&sort=&order=) are lost when the user navigates via that link, breaking the shareable/filter-preserving navigation requirement.
The critical issue to fix is:
- In
Navbar.tsx, update thePeoplenavigation item to preserve the current search string when going to/people. For example, you can either useuseLocationand setto={{ pathname: '/people', search: location.search }}for that link, or reuse your existingSearchLinkhelper withto="/people"andparams={{}}so it keeps all current search params intact.
All other major requirements (URL-backed filters, multi-century selection, case-insensitive name/mother/father search, and the 3-click sort behavior with correct sort/order handling) are implemented well, and your PersonLink already preserves search params when selecting a person. Once you adjust the navbar People link to keep the search params, your solution will align fully with the task description. You’re very close; this is a small but important change to complete the functionality.
✨ 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
| 'has-background-grey-lighter': isActive, | ||
| }); | ||
| }} | ||
| to="/people" |
There was a problem hiding this comment.
The People NavLink navigates to /people without preserving the current location.search, so any active filters (query, centuries, sort, order, etc.) are dropped when clicking this link. The description explicitly requires "Keep search params when navigating within the People page", and this was also flagged in the previous review. Consider switching this to a link that includes the existing search (e.g., using useLocation with a to={{ pathname: '/people', search: location.search }} or your SearchLink helper) so that URL search params remain intact.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
I am approving your solution because the People page behavior and URL-backed filters/sorting are implemented correctly and match the checklist requirements (name/century filters, multi-century selection, 3-click sorting, and search-param preservation on navigation like [CHECKLIST ITEM #1–#3, #9–#27, #31]). Your use of useSearchParams to drive both filters and sorting is solid, and the conditional rendering of the sidebar only when people are successfully loaded shows good attention to UX and state management. Navigation via Navbar and PersonLink correctly keeps location.search, so filters and sort stay intact when moving within the People section.
One small improvement opportunity is the sex filter: instead of keeping sex as an empty string for “All”, you could delete the sex param entirely to keep the URL cleaner and more explicit about “no sex filter” being active, but this is a refinement rather than a requirement. Overall, your code is coherent, meets the functional goals, and demonstrates a strong grasp of React Router and search-param handling. Your solution is approved—nice work continuing to refine the behavior around filters, sorting, and navigation.
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
DEMO LINK