diff --git a/README.md b/README.md index 5ec1e6f104..3da7d5c158 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,4 @@ loaded and show them using `TodoList` (check the code in the `api.ts`); - 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_dynamic-list-of-todos/) and add it to the PR description. +- Replace `` with your Github username in the [DEMO LINK](https://Vasyl-Zhyliakov.github.io/react_dynamic-list-of-todos/) and add it to the PR description. diff --git a/package-lock.json b/package-lock.json index 76d22cf660..68abdc80c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", @@ -1170,10 +1170,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": "1.9.12", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", + "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", "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 e1661aa8bd..df73292335 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@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 d46111e825..6e3f3e5a98 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,14 +1,57 @@ /* eslint-disable max-len */ -import React from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import 'bulma/css/bulma.css'; import '@fortawesome/fontawesome-free/css/all.css'; +import { Todo } from './types/Todo'; +import { Filter } from './types/Filter'; + import { TodoList } from './components/TodoList'; import { TodoFilter } from './components/TodoFilter'; import { TodoModal } from './components/TodoModal'; import { Loader } from './components/Loader'; +import { getTodos } from './api'; export const App: React.FC = () => { + const [todos, setTodos] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [filter, setFilter] = useState(Filter.All); + const [searchValue, setSearchValue] = useState(''); + const [activeTodo, setActiveTodo] = useState(null); + + const handleEyeChange = (id: number) => { + setActiveTodo(todos.find(todo => todo.id === id) || null); + }; + + const filteredTodos = useMemo(() => { + return todos.filter(todo => + todo.title.toLowerCase().includes(searchValue.toLowerCase()), + ); + }, [todos, searchValue]); + + const getVisibleTodos = () => { + switch (filter) { + case Filter.All: + return filteredTodos; + case Filter.Active: + return filteredTodos.filter(todo => !todo.completed); + case Filter.Completed: + return filteredTodos.filter(todo => todo.completed); + + default: + return filteredTodos; + } + }; + + useEffect(() => { + setIsLoading(true); + + getTodos() + .then(setTodos) + .catch(() => {}) + .finally(() => setIsLoading(false)); + }, []); + return ( <>
@@ -17,18 +60,31 @@ export const App: React.FC = () => {

Todos:

- +
- - + {isLoading && } + + {!isLoading && ( + + )}
- + {activeTodo && ( + + )} ); }; diff --git a/src/api.ts b/src/api.ts index 4bf9d3eccb..5189e5b987 100644 --- a/src/api.ts +++ b/src/api.ts @@ -25,4 +25,4 @@ function get(url: string): Promise { export const getTodos = () => get('/todos'); -export const getUser = (userId: number) => get(`/users/${userId}`); +export const getUser = (userId: number | null) => get(`/users/${userId}`); diff --git a/src/components/TodoFilter/TodoFilter.tsx b/src/components/TodoFilter/TodoFilter.tsx index 193f1cd2b2..6eb79d7349 100644 --- a/src/components/TodoFilter/TodoFilter.tsx +++ b/src/components/TodoFilter/TodoFilter.tsx @@ -1,30 +1,61 @@ -export const TodoFilter = () => ( -
-

- - - -

+import { Filter } from '../../types/Filter'; -

- - - - +type Props = { + setFilter: (filter: Filter) => void; + setSearchValue: React.Dispatch>; + searchValue: string; +}; - - {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} -