Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 2 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PeoplePage } from './components/PeoplePage';
import { Outlet } from 'react-router-dom';
import { Navbar } from './components/Navbar';

import './App.scss';

export const App = () => {
Expand All @@ -10,9 +9,7 @@ export const App = () => {

<div className="section">
<div className="container">
<h1 className="title">Home Page</h1>
<h1 className="title">Page not found</h1>
<PeoplePage />
<Outlet />
</div>
</div>
</div>
Expand Down
23 changes: 23 additions & 0 deletions src/Root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { HashRouter, Navigate, Route, Routes } from 'react-router-dom';
import { App } from './App';
import { HomePage } from './components/HomePage';
import { PeoplePage } from './components/PeoplePage';
import { NotFoundPage } from './components/NotFoundPage';

export const Root = () => {
return (
<HashRouter>
<Routes>
<Route path="/" element={<App />}>
<Route index element={<HomePage />} />

<Route path="people" element={<PeoplePage />} />
<Route path="people/:slug" element={<PeoplePage />} />

<Route path="home" element={<Navigate to="/" replace />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
</HashRouter>
);
};
5 changes: 5 additions & 0 deletions src/components/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

export const HomePage: React.FC = () => {
return <h1 className="title">Home Page</h1>;
};
22 changes: 16 additions & 6 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Link, useLocation } from 'react-router-dom';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing implementation: The PeoplePage component with filtering/sorting logic is not included. Per task requirements, this must include URL search params for query, centuries, sort, and order parameters.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing implementation: The PeopleFilters component with NameFilter (query param) and CenturyFilter (centuries params using append/getAll) is not included.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing implementation: The PeopleTable component with 3-click sorting logic (ascending → descending → disabled) and sort/order URL params is not included.


export const Navbar = () => {
const location = useLocation();

const isHomeActive = location.pathname === '/';
const isPeopleActive = location.pathname.startsWith('/people');

return (
<nav
data-cy="nav"
Expand All @@ -8,17 +15,20 @@ export const Navbar = () => {
>
<div className="container">
<div className="navbar-brand">
<a className="navbar-item" href="#/">
<Link
className={`navbar-item ${isHomeActive ? 'has-background-grey-lighter is-active' : ''}`}
to="/"
>
Home
</a>
</Link>

<a
<Link
aria-current="page"
className="navbar-item has-background-grey-lighter"
href="#/people"
className={`navbar-item ${isPeopleActive ? 'has-background-grey-lighter is-active' : ''}`}
to="/people"
>
People
</a>
</Link>
</div>
</div>
</nav>
Expand Down
5 changes: 5 additions & 0 deletions src/components/NotFoundPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

export const NotFoundPage: React.FC = () => {
return <h1 className="title">Page not found</h1>;
};
162 changes: 101 additions & 61 deletions src/components/PeopleFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,77 @@
import React from 'react';
import { useSearchParams } from 'react-router-dom';
import { SearchLink } from './SearchLink';

export const PeopleFilters = () => {
const [searchParams, setSearchParams] = useSearchParams();
const currentSex = searchParams.get('sex');
const query = searchParams.get('query') || '';

const selectedCenturies = searchParams.getAll('centuries');

const centuriesList = ['16', '17', '18', '19', '20'];

//Інпут для пошуку по імені//

const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const text = event.target.value;
const newParams = new URLSearchParams(searchParams);

if (text.trim()) {
newParams.set('query', text);
} else {
newParams.delete('query');
}

setSearchParams(newParams);
};

// Фільтр за статтю //

const getUpdatedCenturies = (targetCentury: string) => {
const currentParams = new URLSearchParams(searchParams);
const activeCenturies = currentParams.getAll('centuries');

const nextCenturies = activeCenturies.includes(targetCentury)
? activeCenturies.filter(century => century !== targetCentury)
: [...activeCenturies, targetCentury];

currentParams.delete('centuries');

nextCenturies.forEach(century => {
currentParams.append('centuries', century);
});

return currentParams.getAll('centuries').length > 0
? currentParams.getAll('centuries')
: null;
};

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

<p className="panel-tabs" data-cy="SexFilter">
<a className="is-active" href="#/people">
<SearchLink
className={currentSex === null ? 'is-active' : ''}
params={{ sex: null }}
>
All
</a>
<a className="" href="#/people?sex=m">
</SearchLink>

<SearchLink
className={currentSex === 'm' ? 'is-active' : ''}
params={{ sex: 'm' }}
>
Male
</a>
<a className="" href="#/people?sex=f">
</SearchLink>

<SearchLink
className={currentSex === 'f' ? 'is-active' : ''}
params={{ sex: 'f' }}
>
Female
</a>
</SearchLink>
</p>

<div className="panel-block">
Expand All @@ -22,74 +81,55 @@ export const PeopleFilters = () => {
type="search"
className="input"
placeholder="Search"
value={query}
onChange={handleSearchChange}
/>

<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">
<a
data-cy="century"
className="button mr-1"
href="#/people?centuries=16"
>
16
</a>

<a
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=17"
>
17
</a>

<a
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=18"
>
18
</a>

<a
data-cy="century"
className="button mr-1 is-info"
href="#/people?centuries=19"
>
19
</a>

<a
data-cy="century"
className="button mr-1"
href="#/people?centuries=20"
>
20
</a>
</div>

<div className="level-right ml-4">
<a
data-cy="centuryALL"
className="button is-success is-outlined"
href="#/people"
>
All
</a>
</div>
<div className="buttons" data-cy="CenturyFilter">
{centuriesList.map(century => {
const centuryStr = century.toString();
const isSelected = selectedCenturies.includes(centuryStr);

return (
<SearchLink
key={centuryStr}
className={`button ${isSelected ? 'is-info' : ''}`}
params={{ centuries: getUpdatedCenturies(centuryStr) }}
>
{centuryStr}
</SearchLink>
);
})}

Comment on lines +108 to +109

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Task requirement violation: The <PeopleFilters /> component at line 109 is always rendered, but requirement #3 states 'The sidebar with the filters should appear only when people are loaded.' Consider wrapping it with a condition like {!isLoading && !error && people.length > 0 && <PeopleFilters />} to ensure filters only appear after successful data load.

<SearchLink
className="button is-success"
params={{ centuries: null }}
>
All
</SearchLink>
</div>
</div>

{/* Кнопка скидання всіх фільтрів (Reset all filters) */}
<div className="panel-block">
<a className="button is-link is-outlined is-fullwidth" href="#/people">
<SearchLink
className="button is-link is-light is-fullwidth"
params={{
sex: null,
query: null,
centuries: null,
sort: null,
order: null,
}}
>
Reset all filters
</a>
</SearchLink>
</div>
</nav>
);
Expand Down
Loading
Loading