diff --git a/src/App.scss b/src/App.scss index 9b9ddc979c..803ddbb506 100644 --- a/src/App.scss +++ b/src/App.scss @@ -12,6 +12,8 @@ button { } .error { + margin: 0; + padding: 0; color: red; } @@ -37,3 +39,10 @@ button { .UserInfo { font-style: italic; } +.field { + padding-bottom: 10px; + + &__title { + margin-right: 4px; + } +} diff --git a/src/App.tsx b/src/App.tsx index a9a9bb4c53..e8166cfaca 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,114 @@ +import { 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 { TodoList } from './components/TodoList'; +import { getHigherId } from './serveses/todos'; +import { getUserById } from './serveses/user'; + +import { User } from './serveses/types'; + +const completedTodos = todosFromServer.map(todo => { + const user = getUserById(usersFromServer, todo.userId); + + return { + ...todo, + user, + }; +}); export const App = () => { + const [title, setTitle] = useState(''); + const [hasTitleError, setHasTitleError] = useState(false); + + const [selectedUserId, setSelectedUserId] = useState(0); + const [hasUserError, setHasUserError] = useState(false); + + const [todos, setTodos] = useState(completedTodos); + + const handleTitle = (event: React.ChangeEvent) => { + setTitle(event.target.value); + setHasTitleError(false); + }; + + const handleUser = (event: React.ChangeEvent) => { + setSelectedUserId(+event.target.value); + setHasUserError(false); + }; + + const addTodo = (event: React.FormEvent) => { + event.preventDefault(); + + if (!title) { + setHasTitleError(true); + } + + if (!selectedUserId) { + setHasUserError(true); + } + + if (!title || !selectedUserId) { + return; + } + + setTodos(currentTodos => { + const user = getUserById(usersFromServer, selectedUserId); + + const todo = { + id: getHigherId(todos), + title, + completed: false, + userId: +selectedUserId, + user, + }; + + return [...currentTodos, todo]; + }); + + setTitle(''); + setSelectedUserId(0); + }; + return (

Add todo form

- -
+
- - Please enter a title + + + {hasTitleError && Please enter a title}
- + {usersFromServer.map((user: User) => { + return ( + + ); + })} - 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..a764fca3fc 100644 --- a/src/components/TodoInfo/TodoInfo.tsx +++ b/src/components/TodoInfo/TodoInfo.tsx @@ -1 +1,22 @@ -export const TodoInfo = () => {}; +import classNames from 'classnames'; +import React from 'react'; +import { UserInfo } from '../UserInfo'; +import { Todo } from '../../serveses/types'; + +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..49bc4ef8cd 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'; +import { Todo } from '../../serveses/types'; + +type Props = { + todos: Todo[]; +}; +export const TodoList: React.FC = ({ todos }) => { + return ( +
+ {todos.map(todo => { + return ; + })} +
+ ); +}; diff --git a/src/components/UserInfo/UserInfo.tsx b/src/components/UserInfo/UserInfo.tsx index f7bf0410ec..f1c82ba5f8 100644 --- a/src/components/UserInfo/UserInfo.tsx +++ b/src/components/UserInfo/UserInfo.tsx @@ -1 +1,14 @@ -export const UserInfo = () => {}; +import React from 'react'; +import { User } from '../../serveses/types'; + +type Props = { + user: User; +}; + +export const UserInfo: React.FC = ({ user }) => { + return ( + + {user.name} + + ); +}; diff --git a/src/serveses/todos.ts b/src/serveses/todos.ts new file mode 100644 index 0000000000..5ee462eac5 --- /dev/null +++ b/src/serveses/todos.ts @@ -0,0 +1,10 @@ +type Todo = { + id: number; + title: string; + completed: boolean; + userId: number; +}; + +export const getHigherId = (todos: Todo[]) => { + return Math.max(...todos.map(todo => todo.id)) + 1; +}; diff --git a/src/serveses/types.ts b/src/serveses/types.ts new file mode 100644 index 0000000000..6b110ad41a --- /dev/null +++ b/src/serveses/types.ts @@ -0,0 +1,14 @@ +export type User = { + id: number; + name: string; + username: string; + email: string; +}; + +export type Todo = { + id: number; + title: string; + completed: boolean; + userId: number; + user: User | null; +}; diff --git a/src/serveses/user.ts b/src/serveses/user.ts new file mode 100644 index 0000000000..21bc7d440f --- /dev/null +++ b/src/serveses/user.ts @@ -0,0 +1,10 @@ +type User = { + id: number; + name: string; + username: string; + email: string; +}; + +export const getUserById = (users: User[], id: number) => { + return users.find(user => user.id === id) || null; +};