diff --git a/README.md b/README.md index 5ec1e6f104..30d38be734 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://Dorosh90.github.io/react_dynamic-list-of-todos/) and add it to the PR description. diff --git a/src/App.tsx b/src/App.tsx index d46111e825..d12f2a6d53 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,14 +1,59 @@ /* eslint-disable max-len */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import 'bulma/css/bulma.css'; import '@fortawesome/fontawesome-free/css/all.css'; import { TodoList } from './components/TodoList'; import { TodoFilter } from './components/TodoFilter'; -import { TodoModal } from './components/TodoModal'; import { Loader } from './components/Loader'; +import { Todo } from './types/Todo'; +import { getTodos } from './api'; export const App: React.FC = () => { + const [loader, setLoader] = useState(true); + const [allTodos, setAllTodos] = useState([]); + const [filteredTodos, setFilteredTodos] = useState([]); + const [filter, setFilter] = useState(''); + const [searchQuery, setSearchQuery] = useState(''); + + useEffect(() => { + getTodos() + .then(todos => { + setAllTodos(todos); + setFilteredTodos(todos); + }) + .finally(() => setLoader(false)); + }, []); + + useEffect(() => { + const filterTodosList = () => { + let result = allTodos; + + switch (filter) { + case 'active': + result = allTodos.filter(todo => !todo.completed); + break; + + case 'completed': + result = allTodos.filter(todo => todo.completed); + break; + + default: + break; + } + + if (searchQuery) { + result = result.filter(todo => + todo.title.toLowerCase().includes(searchQuery.toLowerCase()), + ); + } + + return result; + }; + + setFilteredTodos(filterTodosList()); + }, [filter, allTodos, searchQuery]); + return ( <>
@@ -17,18 +62,18 @@ export const App: React.FC = () => {

Todos:

- +
-
- - -
+ {loader ? : }
- - ); }; diff --git a/src/components/TodoFilter/TodoFilter.tsx b/src/components/TodoFilter/TodoFilter.tsx index 193f1cd2b2..f915a2f99e 100644 --- a/src/components/TodoFilter/TodoFilter.tsx +++ b/src/components/TodoFilter/TodoFilter.tsx @@ -1,30 +1,57 @@ -export const TodoFilter = () => ( -
-

- - - -

+interface Props { + currentFilter: string; + setFilter: (filter: string) => void; + query: string; + setQuery: (q: string) => void; +} -

- - - - +export const TodoFilter: React.FC = ({ + currentFilter, + setFilter, + query, + setQuery, +}) => { + return ( + +

+ + + +

- - {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} - + + + ); + })} + + + {isTodoModal && ( + + )} + + ); +}; diff --git a/src/components/TodoModal/TodoModal.tsx b/src/components/TodoModal/TodoModal.tsx index 0fbe6dae99..d397849026 100644 --- a/src/components/TodoModal/TodoModal.tsx +++ b/src/components/TodoModal/TodoModal.tsx @@ -1,12 +1,44 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Loader } from '../Loader'; +import { getUser } from '../../api'; +import { User } from '../../types/User'; +import { Todo } from '../../types/Todo'; +import classNames from 'classnames'; + +interface Props { + todoId: number; + todos: Todo[]; + onClose: () => void; +} + +export const TodoModal: React.FC = ({ todoId, todos, onClose }) => { + const [loader, setLoader] = useState(true); + const [user, setUser] = useState(); + + useEffect(() => { + const todo = todos.find(t => t.id === todoId); + + if (todo) { + setUser(undefined); + + getUser(todo?.userId) + .then(us => setUser(us)) + .finally(() => setLoader(false)); + } + }, [todos, todoId]); + + const preperedTodos = todos.find(todo => todo.id === todoId); -export const TodoModal: React.FC = () => { return ( -
+
- {true ? ( + {loader ? ( ) : (
@@ -15,25 +47,37 @@ export const TodoModal: React.FC = () => { className="modal-card-title has-text-weight-medium" data-cy="modal-header" > - Todo #2 + Todo #{preperedTodos?.id}
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} -