Skip to content

Commit

Permalink
add TODO Form
Browse files Browse the repository at this point in the history
  • Loading branch information
Anna committed Jan 6, 2025
1 parent 8d91581 commit 5a3690a
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 38 deletions.
141 changes: 106 additions & 35 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,132 @@
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 React, { useState } from 'react';
import { Todo, User } from './components/utils/types';

export const App = () => {
const getUserById = (userId: number): User | null =>
usersFromServer.find(user => user.id === userId) || null;

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

const [userList] = useState(usersFromServer);
const [todosList, setTodosList] = useState(initialTodos);

const [titleInput, setTitleInput] = useState('');
const [userSelected, setUserSelected] = useState('');

const [titleInputError, setTitleInputError] = useState(false);
const [userSelectError, setUserSelectError] = useState(false);

const receiveTheMaxId = () => {
const todoIds = todosList.map(todo => todo.id);

return Math.max(...todoIds) + 1;
};

const createNewTodo = (): Todo => ({
id: receiveTheMaxId(),
title: titleInput.trim(),
completed: false,
userId: +userSelected,
user: getUserById(+userSelected),
});

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

let isValid = true;

if (titleInput === '') {
setTitleInputError(true);
isValid = false;
} else {
setTitleInputError(false);
}

if (userSelected === '') {
setUserSelectError(true);
isValid = false;
} else {
setUserSelectError(false);
}

if (isValid) {
setTodosList(prevTodos => [...prevTodos, createNewTodo()]);
setTitleInput('');
setUserSelected('');
}
};

const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setUserSelected(event.target.value);

if (event.target.value !== '') {
setUserSelectError(false);
}
};

const validateTitleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const checkValues = event.target.value.replace(/[^a-zA-Zа-яА-Я0-9 ]/g, '');

setTitleInput(checkValues);

if (checkValues !== '') {
setTitleInputError(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={titleInput}
placeholder="Enter a title"
onChange={validateTitleChange}
/>
{titleInputError && (
<span className="error">Please enter a title</span>
)}
</div>

<div className="field">
<select data-cy="userSelect">
<option value="0" disabled>
<select
data-cy="userSelect"
value={userSelected}
onChange={handleSelectChange}
>
<option value="" disabled={userSelected !== ''}>
Choose a user
</option>
{userList.map(user => (
<option value={user.id} key={user.id}>
{user.name}
</option>
))}
</select>

<span className="error">Please choose a user</span>
{userSelectError && (
<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={todosList} />
</div>
);
};
23 changes: 22 additions & 1 deletion src/components/TodoInfo/TodoInfo.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
export const TodoInfo = () => {};
import classNames from 'classnames';
import { Todo } from '../utils/types';
import { UserInfo } from '../UserInfo';

type Props = {
todo: Todo;
};

export const TodoInfo: React.FC<Props> = ({ todo }) => {
return (
<article
data-id={todo.id}
className={classNames('TodoInfo', {
'TodoInfo--completed': todo.completed,
})}
>
<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 { TodoInfo } from '../TodoInfo';
import { Todo } from '../utils/types';

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>
);
};
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 '../utils/types';

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

export const UserInfo: React.FC<Props> = ({ user }) => {
if (!user) {
return null;
}

return (
<a className="UserInfo" href={`mailto:${user.email}`}>
{user.name}
</a>
);
};
19 changes: 19 additions & 0 deletions src/components/utils/types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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;
};

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

0 comments on commit 5a3690a

Please sign in to comment.