diff --git a/src/App.tsx b/src/App.tsx index d46111e825..1e1b88ae04 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ /* 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'; @@ -7,8 +7,55 @@ 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'; +import { Completed, Filters } from './types/Filters'; export const App: React.FC = () => { + const [todos, setTodos] = useState([]); + const [selectedTodo, setSelectedTodo] = useState(undefined); + const [errorMessage, setErrorMessage] = useState(null); + const [filters, setFilters] = useState({ + completedType: Completed.All, + searchByText: '', + }); + + const selectTodo = (todo: Todo | null) => { + setSelectedTodo(todo); + }; + + const updateFilters = (key: keyof Filters, value: string | Completed) => { + setFilters(prevFilters => ({ + ...prevFilters, + [key]: value, + })); + }; + + const filteredTodos = useMemo(() => { + return todos.filter(item => { + const matchesCompletedType = + filters.completedType === Completed.All || + (filters.completedType === Completed.Completed && item.completed) || + (filters.completedType === Completed.Active && !item.completed); + + const matchesSearchText = item.title + .toLowerCase() + .includes(filters.searchByText.toLowerCase()); + + return matchesCompletedType && matchesSearchText; + }); + }, [todos, filters]); + + useEffect(() => { + getTodos() + .then(todosData => { + setTodos(todosData); + }) + .catch(error => { + setErrorMessage(`Failed to fetch todos: ${error.message}`); + }); + }, []); + return ( <>
@@ -16,19 +63,39 @@ export const App: React.FC = () => {

Todos:

+ {errorMessage && ( +

{errorMessage}

+ )} +
- +
- - + {todos.length === 0 ? ( + + ) : ( + + )}
- + {selectedTodo && ( + selectTodo(null)} + todo={selectedTodo} + resetSelectedTodo={() => selectTodo(null)} + /> + )} ); }; diff --git a/src/components/TodoFilter/TodoFilter.tsx b/src/components/TodoFilter/TodoFilter.tsx index 193f1cd2b2..7b5cf9f1b0 100644 --- a/src/components/TodoFilter/TodoFilter.tsx +++ b/src/components/TodoFilter/TodoFilter.tsx @@ -1,30 +1,67 @@ -export const TodoFilter = () => ( -
-

- - - -

+import { Completed, Filters } from '../../types/Filters'; -

- - - - +interface Props { + filterOptions: Filters; + onFilterChange: (key: keyof Filters, value: string | Completed) => void; +} - - {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} -