From 3da44ab18e2974895b191d533f481356348c52f3 Mon Sep 17 00:00:00 2001 From: Maria Date: Thu, 12 Dec 2024 21:00:31 +0200 Subject: [PATCH 1/4] add task solution --- README.md | 2 +- src/App.tsx | 101 ++++++++++++++- src/components/TodoFilter/TodoFilter.tsx | 80 ++++++++---- src/components/TodoList/TodoList.tsx | 158 +++++++++-------------- src/components/TodoModal/TodoModal.tsx | 35 +++-- 5 files changed, 239 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 5ec1e6f104..fcfbfd429e 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://Mariagosp.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..1c7d4aaaf4 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,80 @@ 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, getUser } from './api'; +import { User } from './types/User'; export const App: React.FC = () => { + const [todos, setTodos] = useState([]); + const [filteredTodos, setFilteredTodos] = useState(todos); + const [query, setQuery] = useState(''); + const [status, setStatus] = useState('all'); // all, active, completed + const [selectedTodo, setSelectedTodo] = useState(null); + const [user, setUser] = useState(null); + + const [loadingTodos, setLoadingTodos] = useState(false); + + const filterTodos = () => { + setFilteredTodos( + todos + .filter(todo => { + if (status === 'active') { + return !todo.completed; + } + + if (status === 'completed') { + return todo.completed; + } + + return true; + }) + .filter(todo => todo.title.toLowerCase().includes(query.toLowerCase())), + ); + }; + + const onQueryChange = (event: React.ChangeEvent) => { + setQuery(event.target.value); + }; + + const onReset = () => { + setQuery(''); + setFilteredTodos(todos); + }; + + const onStatusChange = (newStatus: string) => { + setStatus(newStatus); + }; + + const onOpenModal = (todo: Todo) => { + setSelectedTodo(todo); + setLoadingTodos(true); + + getUser(todo.userId) + .then(setUser) + .finally(() => setLoadingTodos(false)); + }; + + const onCloseModal = () => { + setSelectedTodo(null); + setUser(null); + }; + + useEffect(() => { + filterTodos(); + }, [todos, query, status]); + + useEffect(() => { + setLoadingTodos(true); + + getTodos() + .then(data => { + setTodos(data); + setFilteredTodos(data); + }) + .finally(() => setLoadingTodos(false)); + }, []); + return ( <>
@@ -17,18 +89,35 @@ export const App: React.FC = () => {

Todos:

- +
- - + {loadingTodos && todos.length === 0 && } + {!loadingTodos && ( + + )}
- - + {selectedTodo && user && ( + + )} ); }; diff --git a/src/components/TodoFilter/TodoFilter.tsx b/src/components/TodoFilter/TodoFilter.tsx index 193f1cd2b2..b2989433f7 100644 --- a/src/components/TodoFilter/TodoFilter.tsx +++ b/src/components/TodoFilter/TodoFilter.tsx @@ -1,30 +1,54 @@ -export const TodoFilter = () => ( -
-

- - - -

+type Props = { + query: string; + onQueryChange: (e: React.ChangeEvent) => void; + onReset: () => void; + onStatusChange: (newStatus: string) => void; +}; -

- - - - +export const TodoFilter: React.FC = props => { + const { query, onQueryChange, onReset, onStatusChange } = props; - - {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} -