Skip to content

Commit

Permalink
add task solution
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew17752985 committed Nov 2, 2023
1 parent 1f2dad9 commit 0472175
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 42 deletions.
127 changes: 89 additions & 38 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,112 @@
import { ChangeEventHandler, FormEventHandler, 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 { Todo } from './types';

export const App = () => {
const [selectedUserId, setSelectedUserId] = useState(0);
const [typedTitle, setTypedTitle] = useState('');
const [todosList, setTodosList] = useState(todosFromServer);
const [hasTitleError, setHasTitleError] = useState(false);
const [hasNameError, setHasNameError] = useState(false);

const handleSubmit: FormEventHandler<HTMLButtonElement> = (event) => {
event.preventDefault();

if (!typedTitle) {
setHasTitleError(true);
}

if (selectedUserId === 0) {
setHasNameError(true);
}

const maxId = Math.max(...todosList.map(todo => todo.id));

if (typedTitle !== '' && selectedUserId) {
const newTodo: Todo = {
id: maxId + 1,
title: typedTitle,
userId: +selectedUserId,
completed: false,
};

setTodosList((prevTodos) => [...prevTodos, newTodo]);
setTypedTitle('');
setSelectedUserId(0);
}
};

const handleChangeTitle: ChangeEventHandler<HTMLInputElement> = (event) => {
setTypedTitle(event.target.value);
setHasTitleError(false);
};

const handleUserChange: ChangeEventHandler<HTMLSelectElement> = (event) => {
setSelectedUserId(+event.target.value);
setHasNameError(false);
};

const todos = () => todosList.map(todo => ({
...todo,
user: usersFromServer.find(u => u.id === todo.userId),
}));

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

<form action="/api/todos" method="POST">
<div className="field">
<input type="text" data-cy="titleInput" />
<span className="error">Please enter a title</span>
<label htmlFor="text" title="title">Title: </label>
<input
value={typedTitle}
onChange={handleChangeTitle}
type="text"
data-cy="titleInput"
title="title"
placeholder="Enter a title"
/>
{hasTitleError && <span className="error">Please enter a title</span>}
</div>

<div className="field">
<select data-cy="userSelect">
<option value="0" disabled>Choose a user</option>
</select>
<label htmlFor="text" title="User">User: </label>
<select
value={selectedUserId}
onChange={handleUserChange}
data-cy="userSelect"
title="User"
defaultValue={0}
>

<span className="error">Please choose a user</span>
<option disabled value={0}>
Choose a user
</option>
{usersFromServer.map(user => {
return (
<option
key={user.id}
value={user.id}
>
{user.name}
</option>
);
})}
</select>
{hasNameError
&& <span className="error">Please choose a user</span>}
</div>

<button type="submit" data-cy="submitButton">
<button type="submit" data-cy="submitButton" onClick={handleSubmit}>
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>
);
};
2 changes: 1 addition & 1 deletion src/api/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ export default [
username: 'Moriah.Stanton',
email: 'Rey.Padberg@karina.biz',
},
];
];
26 changes: 25 additions & 1 deletion src/components/TodoInfo/TodoInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,25 @@
export const TodoInfo = () => {};
import cn from 'classnames';
import { UserInfo } from '../UserInfo';
import { Todo } from '../../types';

interface TodoInfoProps {
todo: Todo;
// user?: User;
}

export const TodoInfo = ({ todo }: TodoInfoProps) => {
return (
<article
data-id={todo.id}
className={cn('TodoInfo', {
'TodoInfo--completed': todo.completed,
})}
>
<h2 className="TodoInfo__title">
{todo.title}
</h2>
{todo.user
&& <UserInfo user={todo.user} />}
</article>
);
};
18 changes: 17 additions & 1 deletion src/components/TodoList/TodoList.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
export const TodoList = () => {};
import { TodoInfo } from '../TodoInfo';
import { Todo } from '../../types';

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

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

type UserInfoProps = {
user?: User,
};

export const UserInfo = ({ user }: UserInfoProps) => {
if (!user) {
return null;
}

return (
<a className="UserInfo" href={`mailto:${user.email}`}>
{user.name}
</a>
);
};
14 changes: 14 additions & 0 deletions src/types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface Todo {
id: number;
title: string;
userId: number;
completed: boolean;
user?: User | null;
}

export interface User {
id: number,
name: string,
username: string,
email: string,
}

0 comments on commit 0472175

Please sign in to comment.