From 7a5bb6947938f7286e6b1e22b273b53d2496143a Mon Sep 17 00:00:00 2001 From: Nazar Date: Tue, 24 Oct 2023 01:16:13 +0300 Subject: [PATCH 1/3] first solution --- src/App.tsx | 131 +++++++++++++++++++-------- src/components/TodoInfo/TodoInfo.tsx | 26 +++++- src/components/TodoList/TodoList.tsx | 17 +++- src/components/UserInfo/UserInfo.tsx | 13 ++- src/types/Todo.ts | 9 ++ src/types/User.ts | 6 ++ 6 files changed, 162 insertions(+), 40 deletions(-) create mode 100644 src/types/Todo.ts create mode 100644 src/types/User.ts diff --git a/src/App.tsx b/src/App.tsx index 9646bf5c6f..292ccd0798 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,25 +1,110 @@ +import React, { useState } from 'react'; import './App.scss'; -// import usersFromServer from './api/users'; -// import todosFromServer from './api/todos'; +import usersFromServer from './api/users'; +import todosFromServer from './api/todos'; + +import { Todo } from './types/Todo'; + +import { TodoList } from './components/TodoList'; + +const findUserById = (id: number) => { + return usersFromServer.find(user => user.id === id) || null; +}; + +const todosWithUsers = todosFromServer.map(todo => ({ + ...todo, + user: findUserById(todo.userId), +})); + +export const App: React.FC = () => { + const [title, setTitle] = useState(''); + const [userId, setUserId] = useState(0); + + const [hasTitleError, setHasTitleError] = useState(false); + const [hasUserError, setHasUserError] = useState(false); + + const [newTodos, setNewTodos] = useState(todosWithUsers); + + const handleTitleInput = ((e: React.ChangeEvent) => { + setTitle(e.target.value); + setHasTitleError(false); + }); + + const handleUserSelect = (e: React.ChangeEvent) => { + setUserId(+e.target.value); + setHasUserError(false); + }; + + const handleSubmit = ((e: React.ChangeEvent) => { + e.preventDefault(); + + if (!title && !userId) { + setHasTitleError(!hasTitleError); + setHasUserError(!hasUserError); + + return; + } + + if (!title) { + setHasTitleError(!hasTitleError); + + return; + } + + if (!userId) { + setHasUserError(!hasUserError); + + return; + } + + const newTodo = { + id: Math.max(...newTodos.map(todo => todo.id)) + 1, + title, + userId, + completed: false, + user: findUserById(userId), + }; + + setNewTodos(prevState => [...prevState, newTodo]); + setTitle(''); + setUserId(0); + }); -export const App = () => { return (

Add todo form

-
+
- - Please enter a title + + + {hasTitleError && Please enter a title}
- + {usersFromServer.map(user => ( + + ))} - Please choose a user + {hasUserError && Please choose a user}
-
- - - - - -
+
); }; diff --git a/src/components/TodoInfo/TodoInfo.tsx b/src/components/TodoInfo/TodoInfo.tsx index d164511fa8..9dd7a44dd1 100644 --- a/src/components/TodoInfo/TodoInfo.tsx +++ b/src/components/TodoInfo/TodoInfo.tsx @@ -1 +1,25 @@ -export const TodoInfo = () => {}; +import React from 'react'; +import cn from 'classnames'; + +import { UserInfo } from '../UserInfo'; +import { Todo } from '../../types/Todo'; + +interface Props { + todo: Todo, +} + +export const TodoInfo: React.FC = ({ todo }) => ( +
+ +

+ {todo.title} +

+ + {todo.user && } +
+); diff --git a/src/components/TodoList/TodoList.tsx b/src/components/TodoList/TodoList.tsx index c12fae07c0..558dee522d 100644 --- a/src/components/TodoList/TodoList.tsx +++ b/src/components/TodoList/TodoList.tsx @@ -1 +1,16 @@ -export const TodoList = () => {}; +import React from 'react'; + +import { TodoInfo } from '../TodoInfo/TodoInfo'; +import { Todo } from '../../types/Todo'; + +type Props = { + todos: Todo[]; +}; + +export const TodoList: React.FC = ({ todos }) => ( +
+ {todos.map(todo => ( + + ))} +
+); diff --git a/src/components/UserInfo/UserInfo.tsx b/src/components/UserInfo/UserInfo.tsx index f7bf0410ec..1fbca4e1d8 100644 --- a/src/components/UserInfo/UserInfo.tsx +++ b/src/components/UserInfo/UserInfo.tsx @@ -1 +1,12 @@ -export const UserInfo = () => {}; +import React from 'react'; +import { User } from '../../types/User'; + +type Props = { + user: User; +}; + +export const UserInfo: React.FC = ({ user }) => ( + + {user.name} + +); diff --git a/src/types/Todo.ts b/src/types/Todo.ts new file mode 100644 index 0000000000..99f6f5f38d --- /dev/null +++ b/src/types/Todo.ts @@ -0,0 +1,9 @@ +import { User } from './User'; + +export interface Todo { + id: number, + title: string, + completed: boolean, + userId: number, + user: User | null, +} diff --git a/src/types/User.ts b/src/types/User.ts new file mode 100644 index 0000000000..4d8e55bc27 --- /dev/null +++ b/src/types/User.ts @@ -0,0 +1,6 @@ +export interface User { + id: number, + name: string, + username: string, + email: string, +} From 9e26c71b31b24de0e382263d2a5499cee76c52b6 Mon Sep 17 00:00:00 2001 From: Nazar Date: Tue, 24 Oct 2023 10:38:21 +0300 Subject: [PATCH 2/3] add reset form --- src/App.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 292ccd0798..3bb83a13b5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -36,6 +36,11 @@ export const App: React.FC = () => { setHasUserError(false); }; + const resetForm = () => { + setTitle(''); + setUserId(0); + }; + const handleSubmit = ((e: React.ChangeEvent) => { e.preventDefault(); @@ -67,8 +72,7 @@ export const App: React.FC = () => { }; setNewTodos(prevState => [...prevState, newTodo]); - setTitle(''); - setUserId(0); + resetForm(); }); return ( From 344c97138d7901ee794decc7abf36f4611be9fb9 Mon Sep 17 00:00:00 2001 From: Nazar Date: Thu, 26 Oct 2023 02:00:36 +0300 Subject: [PATCH 3/3] after check without separate file for form --- src/components/TodoInfo/TodoInfo.tsx | 28 +++++++++++++++------------- src/services/findUser.ts | 5 +++++ 2 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 src/services/findUser.ts diff --git a/src/components/TodoInfo/TodoInfo.tsx b/src/components/TodoInfo/TodoInfo.tsx index 9dd7a44dd1..2188dc05f8 100644 --- a/src/components/TodoInfo/TodoInfo.tsx +++ b/src/components/TodoInfo/TodoInfo.tsx @@ -8,18 +8,20 @@ interface Props { todo: Todo, } -export const TodoInfo: React.FC = ({ todo }) => ( -
+export const TodoInfo: React.FC = ({ todo }) => { + const isCompleted = todo.completed && 'TodoInfo--completed'; -

- {todo.title} -

+ return ( +
- {todo.user && } -
-); +

+ {todo.title} +

+ + {todo.user && } +
+ ); +}; diff --git a/src/services/findUser.ts b/src/services/findUser.ts new file mode 100644 index 0000000000..63c98ef69b --- /dev/null +++ b/src/services/findUser.ts @@ -0,0 +1,5 @@ +import usersFromServer from '../api/users'; + +export const findUserById = (id: number) => { + return usersFromServer.find(user => user.id === id) || null; +};