diff --git a/README.md b/README.md index b8897503d..ce25bedcb 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ that will suggest people matching an entered text. - 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). -- Replace `` with your Github username in the [DEMO LINK](https://.github.io/react_autocomplete/) and add it to the PR description. +- Replace `` with your Github username in the [DEMO LINK](https://vl-tsr.github.io/react_autocomplete/) and add it to the PR description. - Don't remove the `data-qa` attributes. It is required for tests. ## Troubleshooting diff --git a/package-lock.json b/package-lock.json index a57a24cb7..4e1d09049 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@fortawesome/fontawesome-free": "^6.5.2", "bulma": "^1.0.1", "classnames": "^2.5.1", + "lodash": "^4.18.1", "lodash.debounce": "^4.0.8", "react": "^18.3.1", "react-dom": "^18.3.1" @@ -20,7 +21,7 @@ "devDependencies": { "@cypress/react18": "^2.0.1", "@faker-js/faker": "^8.4.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/lodash.debounce": "^4.0.9", @@ -1189,10 +1190,11 @@ } }, "node_modules/@mate-academy/scripts": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.5.tgz", - "integrity": "sha512-mHRY2FkuoYCf5U0ahIukkaRo5LSZsxrTSgMJheFoyf3VXsTvfM9OfWcZIDIDB521kdPrScHHnRp+JRNjCfUO5A==", + "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", @@ -6792,10 +6794,10 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", diff --git a/package.json b/package.json index cda47c54b..7e9530636 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "@fortawesome/fontawesome-free": "^6.5.2", "bulma": "^1.0.1", "classnames": "^2.5.1", + "lodash": "^4.18.1", "lodash.debounce": "^4.0.8", "react": "^18.3.1", "react-dom": "^18.3.1" @@ -16,7 +17,7 @@ "devDependencies": { "@cypress/react18": "^2.0.1", "@faker-js/faker": "^8.4.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/lodash.debounce": "^4.0.9", diff --git a/src/App.tsx b/src/App.tsx index a88cd7a6d..e8448fad8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,45 @@ -import React from 'react'; +import React, { useMemo, useState } from 'react'; +import debounce from 'lodash.debounce'; + import './App.scss'; import { peopleFromServer } from './data/people'; +import { Person } from './types/Person'; export const App: React.FC = () => { - const { name, born, died } = peopleFromServer[0]; + const [selectedPerson, setSelectedPerson] = useState(null); + const [isFocused, setIsFocused] = useState(false); + + const [query, setQuery] = useState(''); + const [debouncedQuery, setDebouncedQuery] = useState(''); + + const debouncedSearch = useMemo( + () => + debounce((value: string) => { + setDebouncedQuery(value); + }, 300), + [], + ); + + const preparedQuery = useMemo( + () => debouncedQuery.trim().toLowerCase(), + [debouncedQuery], + ); + + const preparedPerson = useMemo( + () => + peopleFromServer.filter(person => + person.name.toLowerCase().includes(preparedQuery), + ), + [preparedQuery], + ); return (

- {`${name} (${born} - ${died})`} + {selectedPerson + ? `${selectedPerson.name} (${selectedPerson.born} - ${selectedPerson.died})` + : 'No selected person'}

@@ -19,55 +49,62 @@ export const App: React.FC = () => { placeholder="Enter a part of the name" className="input" data-cy="search-input" + value={query} + onChange={e => { + setQuery(e.target.value); + setSelectedPerson(null); + + debouncedSearch(e.target.value); + }} + onFocus={() => { + setIsFocused(true); + }} + onBlur={() => { + setIsFocused(false); + }} />
-
-
-
-

Pieter Haverbeke

-
- -
-

Pieter Bernard Haverbeke

-
- -
-

Pieter Antone Haverbeke

-
- -
-

Elisabeth Haverbeke

-
- -
-

Pieter de Decker

-
- -
-

Petronella de Decker

-
- -
-

Elisabeth Hercke

+ {isFocused && preparedPerson.length > 0 && ( +
+
+ {preparedPerson.map(person => ( +
{ + setSelectedPerson(person); + setQuery(person.name); + }} + > +

{person.name}

+
+ ))}
-
+ )}
-
-

No matching suggestions

-
+ {preparedQuery && preparedPerson.length === 0 && ( +
+

No matching suggestions

+
+ )}
); diff --git a/tsconfig.json b/tsconfig.json index cfb168bb2..b2735d104 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,9 @@ ], "compilerOptions": { "sourceMap": false, - "types": ["node", "cypress"] + "types": [ + "node", + "cypress" + ] } }