From afd8b819b0635fdfbeec41afea042f123c35db8b Mon Sep 17 00:00:00 2001 From: Ivadriil Date: Fri, 19 Jun 2026 22:16:05 +0300 Subject: [PATCH 1/4] solution --- src/App.tsx | 7 +- src/Root.tsx | 23 + src/components/Navbar.tsx | 28 +- src/components/Pages/HomePage.tsx | 5 + src/components/Pages/PageNotFound.tsx | 5 + src/components/PeopleFilters.tsx | 150 +++++- src/components/PeoplePage.tsx | 62 ++- src/components/PeopleTable.tsx | 731 +++++--------------------- src/components/PersonLink.tsx | 18 + src/components/SearchLink.tsx | 16 +- src/constants/Error.ts | 7 + src/index.tsx | 9 +- 12 files changed, 420 insertions(+), 641 deletions(-) create mode 100644 src/Root.tsx create mode 100644 src/components/Pages/HomePage.tsx create mode 100644 src/components/Pages/PageNotFound.tsx create mode 100644 src/components/PersonLink.tsx create mode 100644 src/constants/Error.ts diff --git a/src/App.tsx b/src/App.tsx index adcb8594e..f1f6a3baf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,8 @@ -import { PeoplePage } from './components/PeoplePage'; +// import { PeoplePage } from './components/PeoplePage'; import { Navbar } from './components/Navbar'; import './App.scss'; +import { Outlet } from 'react-router-dom'; export const App = () => { return ( @@ -10,9 +11,7 @@ export const App = () => {
-

Home Page

-

Page not found

- +
diff --git a/src/Root.tsx b/src/Root.tsx new file mode 100644 index 000000000..a63e3c2f1 --- /dev/null +++ b/src/Root.tsx @@ -0,0 +1,23 @@ +import { + Navigate, + Route, + HashRouter as Router, + Routes, +} from 'react-router-dom'; +import { App } from './App'; +import { PageNotFound } from './components/Pages/PageNotFound'; +import { HomePage } from './components/Pages/HomePage'; +import { PeoplePage } from './components/PeoplePage'; + +export const Root = () => ( + + + }> + } /> + } /> + } /> + } /> + + + +); diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 3f63898b2..a9b9f5114 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,3 +1,7 @@ +import '../App.scss'; +import { NavLink } from 'react-router-dom'; +import classNames from 'classnames'; + export const Navbar = () => { return ( diff --git a/src/components/Pages/HomePage.tsx b/src/components/Pages/HomePage.tsx new file mode 100644 index 000000000..551de3626 --- /dev/null +++ b/src/components/Pages/HomePage.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export const HomePage: React.FC = () => { + return

Home Page

; +}; diff --git a/src/components/Pages/PageNotFound.tsx b/src/components/Pages/PageNotFound.tsx new file mode 100644 index 000000000..d6837dce6 --- /dev/null +++ b/src/components/Pages/PageNotFound.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export const PageNotFound: React.FC = () => { + return

Page not found

; +}; diff --git a/src/components/PeopleFilters.tsx b/src/components/PeopleFilters.tsx index c9c819cd3..3bb94a1c3 100644 --- a/src/components/PeopleFilters.tsx +++ b/src/components/PeopleFilters.tsx @@ -1,16 +1,106 @@ -export const PeopleFilters = () => { +import React, { useEffect } from 'react'; +import { Person } from '../types'; +import { useSearchParams } from 'react-router-dom'; +import cn from 'classnames'; + +type Props = { + peoples: Person[]; + onFilter: (persons: Person[]) => void; +}; + +export const PeopleFilters: React.FC = ({ peoples, onFilter }) => { + const [serchParams, setSerchParams] = useSearchParams(); + const query = serchParams.get('query') || ''; + const centuries = serchParams.getAll('centuries') || []; + const sex = serchParams.get('sex') || ''; + + function hangeChangeQuery(event: React.ChangeEvent) { + const params = new URLSearchParams(serchParams); + + params.set('query', event.target.value); + setSerchParams(params); + } + + function hangeChangeSex(sexe: string) { + const params = new URLSearchParams(serchParams); + + params.set('sex', sexe); + setSerchParams(params); + } + + function hangeChangeAges(n: string) { + const params = new URLSearchParams(serchParams); + + 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 => { + 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]); + return (