From 64f62cdf09a14cb0df17b64d44dc956742d1e77d Mon Sep 17 00:00:00 2001 From: Denys Kovalchuk Date: Sat, 11 Jan 2025 21:07:22 +0200 Subject: [PATCH 1/7] add task solution --- src/App.tsx | 75 ++++++++++++- src/components/TodoFilter/TodoFilter.tsx | 31 +++++- src/components/TodoList/TodoList.tsx | 130 +++++++++-------------- src/components/TodoModal/TodoModal.tsx | 44 ++++++-- 4 files changed, 183 insertions(+), 97 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d46111e825..bbd6a9cfc0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ /* 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'; @@ -7,8 +7,59 @@ 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'; export const App: React.FC = () => { + const [todos, setTodos] = useState([]); + const [loading, setLoading] = useState(false); + const [selectedTodo, setSelectedTodo] = useState(null); + const [selecteValue, setSelecteValue] = useState('all'); + const [inputValue, setInputValue] = useState(''); + + useEffect(() => { + setLoading(true); + setTimeout(() => { + setLoading(false); + }, 1000); + }, []); + + useEffect(() => { + fetch(` + https://mate-academy.github.io/react_dynamic-list-of-todos/api/todos.json`) + .then(response => response.json()) + .then((todosFromServer: Todo[]) => { + switch (selecteValue) { + case 'all': + setTodos( + todosFromServer.filter(todo => + todo.title.toLowerCase().includes(inputValue.toLowerCase()), + ), + ); + break; + case 'active': + setTodos( + todosFromServer.filter( + todo => + !todo.completed && + todo.title.toLowerCase().includes(inputValue.toLowerCase()), + ), + ); + break; + case 'completed': + setTodos( + todosFromServer.filter( + todo => + todo.completed && + todo.title.toLowerCase().includes(inputValue.toLowerCase()), + ), + ); + break; + default: + return; + } + }); + }, [selecteValue, inputValue]); + return ( <>
@@ -17,18 +68,32 @@ export const App: React.FC = () => {

Todos:

- +
- - + {loading && } +
- + {selectedTodo && ( + setSelectedTodo(null)} + /> + )} ); }; diff --git a/src/components/TodoFilter/TodoFilter.tsx b/src/components/TodoFilter/TodoFilter.tsx index 193f1cd2b2..5a6e3fdb7e 100644 --- a/src/components/TodoFilter/TodoFilter.tsx +++ b/src/components/TodoFilter/TodoFilter.tsx @@ -1,8 +1,24 @@ -export const TodoFilter = () => ( +type Props = { + selecteValue: string; + setSelecteValue: (selecteValue: string) => void; + inputValue: string; + setInputValue: (selecteValue: string) => void; +}; + +export const TodoFilter: React.FC = ({ + selecteValue, + setSelecteValue, + inputValue, + setInputValue, +}) => (

- setSelecteValue(event.target.value)} + > @@ -16,6 +32,8 @@ export const TodoFilter = () => ( type="text" className="input" placeholder="Search..." + value={inputValue} + onChange={event => setInputValue(event.target.value)} /> @@ -23,7 +41,14 @@ export const TodoFilter = () => ( {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} -