Skip to content
Open
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ implement the ability to filter and sort people in the table.
- Implement a solution following the [React task guideline](https://github.com/mate-academy/react_task-guideline#react-tasks-guideline).
- Use the [React TypeScript cheat sheet](https://mate-academy.github.io/fe-program/js/extra/react-typescript).
- Open one more terminal and run tests with `npm test` to ensure your solution is correct.
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://<your_account>.github.io/react_people-table-advanced/) and add it to the PR description.
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://azesmmisha.github.io/react_people-table-advanced/) and add it to the PR description.
28 changes: 21 additions & 7 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import { PeoplePage } from './components/PeoplePage';
import { Navbar } from './components/Navbar';
import { Navbar } from './components/NavBar/Navbar';

import './App.scss';
import { Navigate, Route, Routes } from 'react-router-dom';
import { HomePage } from './pages/HomePage/HomePage';
import { NotFoundPage } from './pages/NotFoundPage/NotFoundPage';
import { PeoplePage } from './pages/PeoplePage/PeoplePage';
import { PeopleProvider } from './store/PeopleContext';

export const App = () => {
return (
<div data-cy="app">
<Navbar />

<div className="section">
<main className="section">
<div className="container">
<h1 className="title">Home Page</h1>
<h1 className="title">Page not found</h1>
<PeoplePage />
<Routes>
<Route path="/home" element={<Navigate to="/" replace />} />
<Route path="/" element={<HomePage />} />
Comment on lines 13 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This link navigates to /people/${person.slug} but does not include the current search params from the URL, so filters and sorting are lost when selecting a person. The description requires that search params be kept when selecting a person within the People page; consider using SearchLink or useSearchParams to construct a to object that preserves the existing search string while changing only the pathname.

<Route
path="/people/:slug?"
Comment on lines +20 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The route setup is fine, but when PeoplePage is rendered via /people/:slug?, internal navigation to this route (from Navbar or person links) must preserve existing search params as per the description. Right now, the Navbar and PersonLink use plain paths without including current searchParams, so filters/sort are lost when navigating.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This NavLink to /people drops any existing search params (filters/sort) when users click the "People" link. The requirements (checklist #4, #16) say search params must be kept when navigating within the People page, so consider using SearchLink or useSearchParams here to include the current query/sex/centuries/sort/order in the to prop.

element={
<PeopleProvider>
<PeoplePage />
</PeopleProvider>
}
/>
<Route path="*" element={<NotFoundPage />} />
</Routes>
</div>
</div>
</main>
</div>
);
};
33 changes: 33 additions & 0 deletions src/components/NavBar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { NavLink, useSearchParams } from 'react-router-dom';

const navClass = ({ isActive }: { isActive: boolean }) =>
['navbar-item', isActive && 'has-background-grey-lighter']
.filter(Boolean)
.join(' ');

export const Navbar = () => {
const [searchParams] = useSearchParams();

return (
<nav
data-cy="nav"
className="navbar is-fixed-top has-shadow"
role="navigation"
aria-label="main navigation"
>
<div className="container">
<div className="navbar-brand">
<NavLink className={navClass} to="/">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PersonLink builds a plain path string (to={/people/${person.slug}}), which drops any existing search params for filters and sorting. According to the requirements, navigation within the People page (person links, table row links) must keep current search params; you can fix this by replacing Link with SearchLink and passing a params object that doesn’t change filters, or by deriving current searchParams and including them in the to prop.

Home
</NavLink>
<NavLink
className={navClass}
to={{ pathname: '/people', search: searchParams.toString() }}
>
People
</NavLink>
</div>
Comment on lines +12 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You already have a shared getSearchWith/SearchParams helper in src/utils/searchHelper.ts per the task description. Duplicating a local version here instead of importing and using the common helper can lead to inconsistency and diverges from checklist item #17, which expects reuse of the provided code.

</div>
</nav>
);
};
26 changes: 0 additions & 26 deletions src/components/Navbar.tsx

This file was deleted.

110 changes: 110 additions & 0 deletions src/components/PeopleFilter/PeopleFilters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { useSearchParams } from 'react-router-dom';
import { SearchLink } from '../SearchLink/SearchLink';
import { getSearchWith, SearchParams } from '../../utils/searchHelper';

type Props = {};

export const PeopleFilters: React.FC<Props> = () => {
const [searchParams, setSearchParams] = useSearchParams();
const sex = searchParams.get('sex') || '';
const query = searchParams.get('query') || '';
const centuries = searchParams.getAll('centuries') || [];

function setSearchWith(params: SearchParams) {
const search = getSearchWith(searchParams, params);

setSearchParams(search);
}

const handleQueryChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSearchWith({ query: event.target.value || null });
};

const toggledCenturies = (century: number) => {
return centuries.includes(century.toString())
? centuries.filter(cent => cent !== century.toString())
: [...centuries, century].map(String);
};

return (
<nav className="panel">
<p className="panel-heading">Filters</p>

<p className="panel-tabs" data-cy="SexFilter">
<SearchLink
className={`${sex !== 'm' && sex !== 'f' ? 'is-active' : ''}`}
params={{ sex: null }}
>
All
</SearchLink>
<SearchLink
className={`${sex === 'm' ? 'is-active' : ''}`}
params={{ sex: 'm' }}
>
Male
</SearchLink>
<SearchLink
className={`${sex === 'f' ? 'is-active' : ''}`}
params={{ sex: 'f' }}
>
Female
</SearchLink>
</p>

<div className="panel-block">
<p className="control has-icons-left">
<input
data-cy="NameFilter"
type="search"
className="input"
placeholder="Search"
value={query}
onChange={handleQueryChange}
/>

<span className="icon is-left">
<i className="fas fa-search" aria-hidden="true" />
</span>
</p>
</div>

<div className="panel-block">
<div className="level is-flex-grow-1 is-mobile" data-cy="CenturyFilter">
<div className="level-left">
{[16, 17, 18, 19, 20].map(century => {
return (
<SearchLink
key={century}
data-cy="century"
className={`button mr-1 ${centuries.includes(century.toString()) ? 'is-info' : ''}`}
params={{ centuries: toggledCenturies(century) }}
>
{century}
</SearchLink>
);
})}
</div>

<div className="level-right ml-4">
<SearchLink
data-cy="centuryALL"
className="button is-success is-outlined"
params={{ centuries: null }}
>
All
</SearchLink>
</div>
</div>
</div>

<div className="panel-block">
<SearchLink
className="button is-link is-outlined is-fullwidth"
params={{ sex: null, centuries: null, query: null }}
>
Reset all filters
</SearchLink>
</div>
</nav>
);
};
96 changes: 0 additions & 96 deletions src/components/PeopleFilters.tsx

This file was deleted.

33 changes: 0 additions & 33 deletions src/components/PeoplePage.tsx

This file was deleted.

Loading
Loading