Skip to content

Commit

Permalink
solution
Browse files Browse the repository at this point in the history
  • Loading branch information
Dushkaaa-BabyBoss committed Jan 5, 2025
1 parent 8d91581 commit ccbea11
Show file tree
Hide file tree
Showing 7 changed files with 3,314 additions and 2,215 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Implement the ability to add TODOs to the `TodoList` implemented in the **Static
- 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 `<your_account>` with your Github username in the [DEMO LINK](https://<your_account>.github.io/react_add-todo-form/) and add it to the PR description.
- Replace `<your_account>` with your Github username in the [DEMO LINK](https://Dushkaaa-BabyBoss.github.io/react_add-todo-form/) and add it to the PR description.
5,325 changes: 3,149 additions & 2,176 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
114 changes: 80 additions & 34 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,107 @@
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 { useState } from 'react';

interface Todo {
id: number;
title: string;
completed: boolean;
userId: number;
}

interface User {
id: number;
name: string;
username: string;
email: string;
}

export const App = () => {
const [todos, setTodos] = useState<Todo[]>(todosFromServer);
const [users] = useState<User[]>(usersFromServer);
const [title, setTitle] = useState('');
const [userId, setUserId] = useState(0);

const [titleError, setTitleError] = useState(false);
const [useError, setUseError] = useState(false);

const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();

setTitleError(!title);

setUseError(!userId);

if (!title || !userId) {
return;
}

const newTodo: Todo = {
id: Math.max(...todos.map(todo => todo.id + 1)),
title: title.trim(),
completed: false,
userId,
};

setTodos(currentTodo => [...currentTodo, newTodo]);
setTitle('');
setUserId(0);
};

const handleTitleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setTitle(event.target.value);
setTitleError(false);
};

const handleUserIdChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setUserId(+event.target.value);
setUseError(false);
};

return (
<div className="App">
<h1>Add todo form</h1>

<form action="/api/todos" method="POST">
<form action="/api/todos" method="POST" onSubmit={handleSubmit}>
<div className="field">
<input type="text" data-cy="titleInput" />
<span className="error">Please enter a title</span>
<input
type="text"
data-cy="titleInput"
value={title}
onChange={handleTitleChange}
/>
{titleError && <span className="error">Please enter a title</span>}
</div>

<div className="field">
<select data-cy="userSelect">
<select
data-cy="userSelect"
onChange={handleUserIdChange}
value={userId}
>
<option value="0" disabled>
Choose a user
</option>

{usersFromServer.map(user => (
<option value={user.id} key={user.id}>
{user.name}
</option>
))}
</select>

<span className="error">Please choose a user</span>
{useError && <span className="error">Please choose a user</span>}
</div>

<button type="submit" data-cy="submitButton">
Add
</button>
</form>

<section className="TodoList">
<article data-id="1" className="TodoInfo TodoInfo--completed">
<h2 className="TodoInfo__title">delectus aut autem</h2>

<a className="UserInfo" href="mailto:Sincere@april.biz">
Leanne Graham
</a>
</article>

<article data-id="15" className="TodoInfo TodoInfo--completed">
<h2 className="TodoInfo__title">delectus aut autem</h2>

<a className="UserInfo" href="mailto:Sincere@april.biz">
Leanne Graham
</a>
</article>

<article data-id="2" className="TodoInfo">
<h2 className="TodoInfo__title">
quis ut nam facilis et officia qui
</h2>

<a className="UserInfo" href="mailto:Julianne.OConner@kory.org">
Patricia Lebsack
</a>
</article>
</section>
<TodoList todos={todos} users={users} />
</div>
);
};
28 changes: 27 additions & 1 deletion src/components/TodoInfo/TodoInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
export const TodoInfo = () => {};
import { UserInfo } from '../UserInfo';

type TodoInfoProps = {
title: string;
completed: boolean;
user: {
name: string;
email: string;
};
};

export const TodoInfo: React.FC<TodoInfoProps> = ({
title,
completed,
user,
}) => {
return (
<article
data-id="1"
className={`TodoInfo ${completed ? 'TodoInfo--completed' : ''}`}
>
<h2 className="TodoInfo__title">{title}</h2>

<UserInfo name={user.name} email={user.email} />
</article>
);
};
45 changes: 44 additions & 1 deletion src/components/TodoList/TodoList.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
export const TodoList = () => {};
import { TodoInfo } from '../TodoInfo';

type Todo = {
id: number;
title: string;
completed: boolean;
userId: number;
};

type User = {
id: number;
name: string;
email: string;
};

type TodoListProps = {
todos: Todo[];
users: User[];
};

export const TodoList: React.FC<TodoListProps> = ({ todos, users }) => {
const getUserById = (userId: number) =>
users.find(user => user.id === userId);

return (
<section className="TodoList">
{todos.map(todo => {
const user = getUserById(todo.userId);

return (
<TodoInfo
key={todo.id}
title={todo.title}
completed={todo.completed}
user={{
name: user?.name || 'Empty',
email: user?.email || '',
}}
/>
);
})}
</section>
);
};
13 changes: 12 additions & 1 deletion src/components/UserInfo/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
export const UserInfo = () => {};
type TodoUserProps = {
name: string;
email: string;
};

export const UserInfo: React.FC<TodoUserProps> = ({ name, email }) => {
return (
<a className="UserInfo" href={`mailto:${email}`}>
{name}
</a>
);
};

0 comments on commit ccbea11

Please sign in to comment.