Skip to content

Commit

Permalink
addtask solution
Browse files Browse the repository at this point in the history
  • Loading branch information
dsfreedom committed Oct 24, 2023
1 parent d3a183a commit 6d84542
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 40 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://dsfreedom.github.io/react_add-todo-form/) and add it to the PR description.
142 changes: 106 additions & 36 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,131 @@
import './App.scss';
import { useState } from 'react';

// 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 { Todo } from './Types/Todo';

function getUserById(userId: number) {
return usersFromServer.find(user => user.id === userId) || null;
}

const preparedTodos: Todo[] = todosFromServer.map(todo => ({
...todo,
user: getUserById(todo.userId),
}));

function getMaxId(recievedTodos: Todo[]) {
const maxId = Math.max(
...recievedTodos.map(todo => todo.id),
);

return maxId + 1;
}

export const App = () => {
const [title, setTitle] = useState('');
const [userId, setUserId] = useState(0);
const [todos, setTodos] = useState(preparedTodos);

const [hasTitleError, setHasTitleError] = useState(false);
const [selectedIdUserError, setSelectedIdUserError] = useState(false);

function handleSubmit(event: React.ChangeEvent<HTMLFormElement>) {
event.preventDefault();

let hasErrors = false;

if (!title) {
setHasTitleError(true);
hasErrors = true;
} else {
setHasTitleError(false);
}

if (!userId) {
setSelectedIdUserError(true);
hasErrors = true;
} else {
setSelectedIdUserError(false);
}

if (hasErrors) {
return;
}

const newPost: Todo = {
id: getMaxId(todos),
title,
completed: false,
userId,
user: getUserById(userId),
};

setTodos(currentTodos => [...currentTodos, newPost]);
setTitle('');
setUserId(0);
}

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>
<label htmlFor="titleInput">Title: </label>
<input
type="text"
data-cy="titleInput"
placeholder="Enter a title"
value={title}
onChange={(event) => {
setTitle(event.target.value);
setHasTitleError(false);
}}
/>

{hasTitleError && (
<span className="error">Please enter a title</span>
)}
</div>

<div className="field">
<select data-cy="userSelect">
<label htmlFor="userSelect">User: </label>
<select
data-cy="userSelect"
value={userId}
onChange={(event) => {
setUserId(+event.target.value);
setSelectedIdUserError(false);
}}
>
<option value="0" disabled>Choose a user</option>
{usersFromServer.map(user => (
<option
key={user.id}
value={user.id}
>
{user.name}
</option>
))}
</select>

<span className="error">Please choose a user</span>
{selectedIdUserError && (
<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} />
</div>
);
};
9 changes: 9 additions & 0 deletions src/Types/Todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { User } from './User';

export interface Todo {
id: number,
title: string,
completed: boolean,
userId: number,
user: User | null,
}
6 changes: 6 additions & 0 deletions src/Types/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface User {
id: number,
name: string,
username: string,
email: string,
}
27 changes: 26 additions & 1 deletion src/components/TodoInfo/TodoInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
export const TodoInfo = () => {};
import classNames from 'classnames';
import { Todo } from '../../Types/Todo';
import { UserInfo } from '../UserInfo';

type Props = {
todo: Todo,
};

export const TodoInfo: React.FC<Props> = ({ todo }) => {
return (
<>
<article
className={classNames('TodoInfo', {
'TodoInfo--completed': todo.completed,
})}
data-id={todo.id}
>
<h2 className="TodoInfo__title">
{todo.title}
</h2>

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

type Props = {
todos: Todo[];
};

export const TodoList: React.FC<Props> = ({ todos }) => {
return (
<section className="TodoList">
{todos.map(todo => (
<TodoInfo todo={todo} key={todo.id} />
))}
</section>
);
};
14 changes: 13 additions & 1 deletion src/components/UserInfo/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
export const UserInfo = () => {};
import { User } from '../../Types/User';

type Props = {
user: User | null,
};

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

0 comments on commit 6d84542

Please sign in to comment.