diff --git a/README.md b/README.md index 064a39440..c2f248f5d 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,22 @@ implement the ability to filter and sort people in the table. 1. Keep search params when navigating within the `People` page (when selecting a person or clicking the `People` link). 1. The sidebar with the filters should appear only when people are loaded. 1. `NameFilter` should update the `query` search param with the text from the input. - - show only people with the `name`, `motherName` or `fatherName` that match the query case insensitive; - - if the input is empty there should not be `query` in the search params. + - show only people with the `name`, `motherName` or `fatherName` that match the query case insensitive; + - if the input is empty there should not be `query` in the search params. 1. `CenturyFilter` should allow to choose several centuries or all of them. - - add `centuries` search params using `append` method `getAll` method; + - add `centuries` search params using `append` method `getAll` method; 1. Implement sorting by `name`, `sex`, `born` and `died` by clicking on arrows in a `th`; - - the first click on a column sorts people by the selected field ascending (`a -> z` or `0 -> 9`); - - the second click (when people are already sorted ascending by this field) reverses the order of sorting; - - the third click (when people are already sorted in reversed order by this field) disables sorting; - - use `sort` search param to save sort field; - - add `order=desc` (short for `descending`) if sorted in reversed order; - - if sorting is disabled there should not be `sort` and `order` search params; + - the first click on a column sorts people by the selected field ascending (`a -> z` or `0 -> 9`); + - the second click (when people are already sorted ascending by this field) reverses the order of sorting; + - the third click (when people are already sorted in reversed order by this field) disables sorting; + - use `sort` search param to save sort field; + - add `order=desc` (short for `descending`) if sorted in reversed order; + - if sorting is disabled there should not be `sort` and `order` search params; ## Instructions + - Install Prettier Extention and use this [VSCode settings](https://mate-academy.github.io/fe-program/tools/vscode/settings.json) to enable format on save. - 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://valerij0412.github.io/react_people-table-advanced/) and add it to the PR description. diff --git a/package-lock.json b/package-lock.json index df276ce8a..a2d822adb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.9.12", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", @@ -1184,10 +1184,11 @@ } }, "node_modules/@mate-academy/scripts": { - "version": "1.9.12", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", - "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.3.tgz", + "integrity": "sha512-a07wHTj/1QUK2Aac5zHad+sGw4rIvcNl5lJmJpAD7OxeSbnCdyI6RXUHwXhjF5MaVo9YHrJ0xVahyERS2IIyBQ==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index 919fbd42b..77fc93ccf 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.9.12", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", diff --git a/src/App.tsx b/src/App.tsx index adcb8594e..3bb22d5c0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,13 @@ +import { Routes, Route, Navigate } from 'react-router-dom'; import { PeoplePage } from './components/PeoplePage'; import { Navbar } from './components/Navbar'; import './App.scss'; +// Створюємо прості компоненти для сторінок прямо тут +const HomePage = () =>

Home Page

; +const NotFoundPage = () =>

Page not found

; + export const App = () => { return (
@@ -10,9 +15,17 @@ export const App = () => {
-

Home Page

-

Page not found

- + + } /> + } /> + + + } /> + } /> + + + } /> +
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 3f63898b2..6419803e8 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,4 +1,9 @@ +import { NavLink, useLocation } from 'react-router-dom'; + export const Navbar = () => { + // Дістаємо поточний рядок з параметрами (наприклад: "?sex=m¢uries=18") + const { search } = useLocation(); + return ( diff --git a/src/components/PeopleFilters.tsx b/src/components/PeopleFilters.tsx index c9c819cd3..1699cfe43 100644 --- a/src/components/PeopleFilters.tsx +++ b/src/components/PeopleFilters.tsx @@ -1,18 +1,65 @@ +import { Link, useSearchParams } from 'react-router-dom'; +import { getSearchWith } from '../utils/searchHelper'; + export const PeopleFilters = () => { + const [searchParams, setSearchParams] = useSearchParams(); + + // Витягуємо поточні значення з URL для підсвічування активних кнопок/табів + const query = searchParams.get('query') || ''; + const sex = searchParams.get('sex'); + const centuries = searchParams.getAll('centuries'); + + // Обробник для текстового поля пошуку + // Як має бути: + // Як має бути: + const handleQueryChange = (e: React.ChangeEvent) => { + const value = e.target.value; + + setSearchParams( + new URLSearchParams( + getSearchWith(searchParams, { query: value || null }), + ), + ); + }; + + // Логіка для додавання/видалення століть + const getCenturySearch = (century: string) => { + let newCenturies = [...centuries]; + + if (newCenturies.includes(century)) { + newCenturies = newCenturies.filter(c => c !== century); + } else { + newCenturies.push(century); + } + + return getSearchWith(searchParams, { + centuries: newCenturies.length > 0 ? newCenturies : null, + }); + }; + return (