From b305474a99915a03bf0140a5abdfd1323505d6f3 Mon Sep 17 00:00:00 2001 From: Sonya-Miss Date: Wed, 25 Dec 2024 14:26:32 +0300 Subject: [PATCH] add task solution --- src/App.tsx | 167 +++++++++++++++++++++------ src/components/TodoInfo/TodoInfo.tsx | 26 ++++- src/components/TodoList/TodoList.tsx | 29 ++++- src/components/UserInfo/UserInfo.tsx | 14 ++- 4 files changed, 196 insertions(+), 40 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a9a9bb4c53..e2b1edf778 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,61 +1,154 @@ +import React, { useState } from 'react'; import './App.scss'; +import usersFromServer from './api/users'; +import todosFromServer from './api/todos'; +import { TodoList } from './components/TodoList/TodoList'; -// import usersFromServer from './api/users'; -// import todosFromServer from './api/todos'; +type User = { + id: number; + name: string; + email: string; +}; + +type Todo = { + id: number; + title: string; + user: User; + completed: boolean; +}; + +export const App: React.FC = () => { + const [todos, setTodos] = useState( + todosFromServer.map(todo => { + const user = usersFromServer.find(u => u.id === todo.userId) || { + id: 0, + name: 'Unknown', + email: '', + }; + + return { + id: todo.id, + title: todo.title, + user, + completed: todo.completed, + }; + }), + ); + + const [errors, setErrors] = useState<{ + title: string | null; + user: string | null; + }>({ + title: null, + user: null, + }); + + const addTodo = (todo: Omit) => { + const maxId = todos.length > 0 ? Math.max(...todos.map(t => t.id)) : 0; + + const newTodo: Todo = { + id: maxId + 1, + ...todo, + }; + + setTodos(prevTodos => [...prevTodos, newTodo]); + }; -export const App = () => { return (

Add todo form

-
+ { + e.preventDefault(); + const form = e.currentTarget; + + const titleElement = form.elements.namedItem('title'); + const userElement = form.elements.namedItem('user'); + + if ( + !(titleElement instanceof HTMLInputElement) || + !(userElement instanceof HTMLSelectElement) + ) { + return; + } + + const title = titleElement.value.trim(); + const userId = parseInt(userElement.value, 10); + const user = usersFromServer.find(u => u.id === userId); + + const newErrors = { + title: title ? null : 'Please enter a title', + user: user ? null : 'Please choose a user', + }; + + setErrors(newErrors); + + if (newErrors.title || newErrors.user) { + return; + } + + addTodo({ + title, + user: user as User, + completed: false, + }); + + setErrors({ title: null, user: null }); + form.reset(); + }} + >
- - Please enter a title + Title: + { + setErrors(prev => ({ ...prev, title: null })); + }} + />
- { + setErrors(prev => ({ ...prev, user: null })); + }} + > + + {usersFromServer.map(user => ( + + ))} - - Please choose a user
+ {errors.title && ( +

+ {errors.title} +

+ )} + {errors.user && ( +

+ {errors.user} +

+ )} +
-
- - - - - -
+
); }; diff --git a/src/components/TodoInfo/TodoInfo.tsx b/src/components/TodoInfo/TodoInfo.tsx index d164511fa8..fa749f883b 100644 --- a/src/components/TodoInfo/TodoInfo.tsx +++ b/src/components/TodoInfo/TodoInfo.tsx @@ -1 +1,25 @@ -export const TodoInfo = () => {}; +import React from 'react'; +import { UserInfo } from '../UserInfo/UserInfo'; + +type Todo = { + id: number; + title: string; + user: { name: string; email: string }; + completed: boolean; +}; + +type Props = { + todo: Todo; +}; + +export const TodoInfo: React.FC = ({ todo }) => { + return ( +
+

{todo.title}

+ +
+ ); +}; diff --git a/src/components/TodoList/TodoList.tsx b/src/components/TodoList/TodoList.tsx index c12fae07c0..1099ab6b73 100644 --- a/src/components/TodoList/TodoList.tsx +++ b/src/components/TodoList/TodoList.tsx @@ -1 +1,28 @@ -export const TodoList = () => {}; +import React from 'react'; +import { TodoInfo } from '../TodoInfo/TodoInfo'; + +export type User = { + name: string; + email: string; +}; + +export type Todo = { + id: number; + title: string; + user: User; + completed: boolean; +}; + +type Props = { + todos: Todo[]; +}; + +export const TodoList: React.FC = ({ todos }) => { + return ( +
+ {todos.map(todo => ( + + ))} +
+ ); +}; diff --git a/src/components/UserInfo/UserInfo.tsx b/src/components/UserInfo/UserInfo.tsx index f7bf0410ec..d3ef3a8bbf 100644 --- a/src/components/UserInfo/UserInfo.tsx +++ b/src/components/UserInfo/UserInfo.tsx @@ -1 +1,13 @@ -export const UserInfo = () => {}; +import React from 'react'; + +type Props = { + user: { name: string; email: string }; +}; + +export const UserInfo: React.FC = ({ user }) => { + return ( + + {user.name} + + ); +};