From 2b3c7bdf46576e66db2c2e796be05d4cde5f1d6e Mon Sep 17 00:00:00 2001 From: Artem Puzenko Date: Sat, 4 Jan 2025 17:04:18 +0200 Subject: [PATCH] add solution --- package-lock.json | 9 +- package.json | 2 +- src/App.tsx | 123 +++++++++++++++++++-------- src/components/TodoInfo/TodoInfo.tsx | 33 ++++++- src/components/TodoList/TodoList.tsx | 41 ++++++++- src/components/UserInfo/UserInfo.tsx | 23 ++++- tsconfig.json | 1 + 7 files changed, 188 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8c9a76d958..abe980f895 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", @@ -1170,10 +1170,11 @@ } }, "node_modules/@mate-academy/scripts": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.5.tgz", - "integrity": "sha512-mHRY2FkuoYCf5U0ahIukkaRo5LSZsxrTSgMJheFoyf3VXsTvfM9OfWcZIDIDB521kdPrScHHnRp+JRNjCfUO5A==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", + "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index 3cf9851f4f..eac8bda41c 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", diff --git a/src/App.tsx b/src/App.tsx index a9a9bb4c53..723a362faf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,104 @@ +import React, { useState } from 'react'; import './App.scss'; +import { UserInfo } from './components/UserInfo'; +import usersFromServer from './api/users'; +import todosFromServer from './api/todos'; +import { TodoList } from './components/TodoList'; -// import usersFromServer from './api/users'; -// import todosFromServer from './api/todos'; +type TodoProps = { + id: number; + title: string; + userId: number; + completed: boolean; + name: string; +}; + +export const App: React.FC = () => { + const [errorTitle, setErrorTitle] = useState(false); + const [errorSelect, setErrorSelect] = useState(false); + const [title, setTitle] = useState(''); + const [selectUser, setSelectUser] = useState(0); + const [todos, setTodos] = useState(todosFromServer); + + function cleanForm() { + setTitle(''); + setSelectUser(0); + setErrorTitle(false); + setErrorSelect(false); + } + + function handleTitleChange(event: React.ChangeEvent) { + setTitle(event.target.value); + setErrorTitle(false); + } + + function handleSelectChange(event: React.ChangeEvent) { + setSelectUser(+event.target.value); + setErrorSelect(false); + } + + function handleSubmit(event: React.FormEvent) { + event.preventDefault(); + + setErrorTitle(!title); + setErrorSelect(selectUser === 0); + + if (!title || selectUser === 0) { + return; + } + + const selectedUser = usersFromServer.find(user => user.id === selectUser); + const userName = selectedUser ? selectedUser.name : 'Unknown'; + + const newTodo: TodoProps = { + id: Math.max(...todos.map(todo => todo.id)) + 1, + title, + userId: selectUser, + completed: false, + name: userName, + }; + + setTodos([...todos, newTodo]); + cleanForm(); + } -export const App = () => { return (

Add todo form

-
+
- - Please enter a title + + + {errorTitle && Please enter a title}
- + - - Please choose a user + {errorSelect && Please choose a user}
-
- - - - - -
+
); }; diff --git a/src/components/TodoInfo/TodoInfo.tsx b/src/components/TodoInfo/TodoInfo.tsx index d164511fa8..dec55d907f 100644 --- a/src/components/TodoInfo/TodoInfo.tsx +++ b/src/components/TodoInfo/TodoInfo.tsx @@ -1 +1,32 @@ -export const TodoInfo = () => {}; +import React from 'react'; +import classNames from 'classnames'; + +type TodoProps = { + todo: { + id: number; + title: string; + completed: boolean; + }; + user: { + id: number; + name: string; + email: string; + }; +}; + +export const TodoInfo: React.FC = ({ todo, user }) => { + return ( + + ); +}; diff --git a/src/components/TodoList/TodoList.tsx b/src/components/TodoList/TodoList.tsx index c12fae07c0..ef290c5062 100644 --- a/src/components/TodoList/TodoList.tsx +++ b/src/components/TodoList/TodoList.tsx @@ -1 +1,40 @@ -export const TodoList = () => {}; +import React from 'react'; +import { TodoInfo } from '../TodoInfo'; + +type User = { + id: number; + name: string; + username: string; + email: string; +}; + +type Todo = { + id: number; + title: string; + completed: boolean; + userId: number; +}; + +type Props = { + users: User[]; + todos: Todo[]; +}; + +export const TodoList: React.FC = ({ users, todos }) => { + return ( +
+ {todos.map(todo => { + // eslint-disable-next-line @typescript-eslint/no-shadow + const user = users.find(user => user.id === todo.userId); + + return ( + + ); + })} +
+ ); +}; diff --git a/src/components/UserInfo/UserInfo.tsx b/src/components/UserInfo/UserInfo.tsx index f7bf0410ec..62bd187038 100644 --- a/src/components/UserInfo/UserInfo.tsx +++ b/src/components/UserInfo/UserInfo.tsx @@ -1 +1,22 @@ -export const UserInfo = () => {}; +import React from 'react'; + +type User = { + id: number; + name: string; +}; + +type Props = { + users: User[]; +}; + +export const UserInfo: React.FC = ({ users }) => { + return ( + <> + {users.map(user => ( + + ))} + + ); +}; diff --git a/tsconfig.json b/tsconfig.json index cfb168bb26..778406f15e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "src" ], "compilerOptions": { + "jsx": "react", "sourceMap": false, "types": ["node", "cypress"] }