From 22596d3fd49a33d07c0392ea2afe45cc26e1c6e9 Mon Sep 17 00:00:00 2001 From: Mykhailo Oliinyk Date: Wed, 1 Jul 2026 17:26:19 +0300 Subject: [PATCH 1/3] Solution --- README.md | 2 +- src/App.tsx | 28 +- src/components/NavBar/Navbar.tsx | 28 + src/components/Navbar.tsx | 26 - src/components/PeopleFilter/PeopleFilters.tsx | 142 ++++ src/components/PeopleFilters.tsx | 96 --- src/components/PeoplePage.tsx | 33 - src/components/PeopleTable.tsx | 645 ------------------ src/components/PeopleTable/PeopleTable.tsx | 150 ++++ src/components/PersonLink/PersonLink.tsx | 17 + .../{ => SearchLink}/SearchLink.tsx | 2 +- src/index.tsx | 6 +- src/pages/HomePage/HomePage.tsx | 1 + src/pages/NotFoundPage/NotFoundPage.tsx | 3 + src/pages/PeoplePage/PeoplePage.tsx | 91 +++ src/store/PeopleContext.tsx | 46 ++ 16 files changed, 504 insertions(+), 812 deletions(-) create mode 100644 src/components/NavBar/Navbar.tsx delete mode 100644 src/components/Navbar.tsx create mode 100644 src/components/PeopleFilter/PeopleFilters.tsx delete mode 100644 src/components/PeopleFilters.tsx delete mode 100644 src/components/PeoplePage.tsx delete mode 100644 src/components/PeopleTable.tsx create mode 100644 src/components/PeopleTable/PeopleTable.tsx create mode 100644 src/components/PersonLink/PersonLink.tsx rename src/components/{ => SearchLink}/SearchLink.tsx (94%) create mode 100644 src/pages/HomePage/HomePage.tsx create mode 100644 src/pages/NotFoundPage/NotFoundPage.tsx create mode 100644 src/pages/PeoplePage/PeoplePage.tsx create mode 100644 src/store/PeopleContext.tsx diff --git a/README.md b/README.md index 064a39440..184a265db 100644 --- a/README.md +++ b/README.md @@ -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 `` with your Github username in the [DEMO LINK](https://.github.io/react_people-table-advanced/) and add it to the PR description. +- Replace `` with your Github username in the [DEMO LINK](https://azesmmisha.github.io/react_people-table-advanced/) and add it to the PR description. diff --git a/src/App.tsx b/src/App.tsx index adcb8594e..efb74eaac 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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 (
-
+
-

Home Page

-

Page not found

- + + } /> + } /> + + + + } + /> + } /> +
-
+
); }; diff --git a/src/components/NavBar/Navbar.tsx b/src/components/NavBar/Navbar.tsx new file mode 100644 index 000000000..a8f155932 --- /dev/null +++ b/src/components/NavBar/Navbar.tsx @@ -0,0 +1,28 @@ +import { NavLink } from 'react-router-dom'; + +const navClass = ({ isActive }: { isActive: boolean }) => + ['navbar-item', isActive && 'has-background-grey-lighter'] + .filter(Boolean) + .join(' '); + +export const Navbar = () => { + return ( + + ); +}; diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx deleted file mode 100644 index 3f63898b2..000000000 --- a/src/components/Navbar.tsx +++ /dev/null @@ -1,26 +0,0 @@ -export const Navbar = () => { - return ( - - ); -}; diff --git a/src/components/PeopleFilter/PeopleFilters.tsx b/src/components/PeopleFilter/PeopleFilters.tsx new file mode 100644 index 000000000..6f0064bbf --- /dev/null +++ b/src/components/PeopleFilter/PeopleFilters.tsx @@ -0,0 +1,142 @@ +import { Link, useSearchParams } from 'react-router-dom'; + +type Props = {}; + +type Param = string | number; +type Params = { + [key: string]: Param[] | Param | null; +}; + +function getSearchWith(params: Params, search?: string | URLSearchParams) { + const newParams = new URLSearchParams(search); + + for (const [key, value] of Object.entries(params)) { + if (value === null) { + newParams.delete(key); + } else if (Array.isArray(value)) { + newParams.delete(key); + value.forEach(item => newParams.append(key, item.toString())); + } else { + newParams.set(key, value.toString()); + } + } + + return newParams.toString(); +} + +export const PeopleFilters: React.FC = () => { + const [searchParams, setSearchParams] = useSearchParams(); + const sex = searchParams.get('sex') || ''; + const query = searchParams.get('query') || ''; + const centuries = searchParams.getAll('century') || []; + + function setSearchWith(params: Params) { + const search = getSearchWith(params, searchParams); + + setSearchParams(search); + } + + const handleQueryChange = (event: React.ChangeEvent) => { + setSearchWith({ query: event.target.value || null }); + }; + + const toggledCenturies = (century: number) => { + return centuries.includes(century.toString()) + ? centuries.filter(cent => cent !== century.toString()) + : [...centuries, century]; + }; + + return ( +