Skip to content

Commit

Permalink
add task solution
Browse files Browse the repository at this point in the history
  • Loading branch information
Marina Rohozhynska committed Nov 13, 2023
1 parent 3c2abd6 commit 1085a28
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 87 deletions.
92 changes: 5 additions & 87 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,93 +1,11 @@
/* eslint-disable jsx-a11y/control-has-associated-label */
import React from 'react';
import { TodosProvider } from './Utils/TodosContext';
import { TodoApp } from './Components/TodoApp/TodoApp';

export const App: React.FC = () => {
return (
<div className="todoapp">
<header className="header">
<h1>todos</h1>

<form>
<input
type="text"
data-cy="createTodo"
className="new-todo"
placeholder="What needs to be done?"
/>
</form>
</header>

<section className="main">
<input
type="checkbox"
id="toggle-all"
className="toggle-all"
data-cy="toggleAll"
/>
<label htmlFor="toggle-all">Mark all as complete</label>

<ul className="todo-list" data-cy="todoList">
<li>
<div className="view">
<input type="checkbox" className="toggle" id="toggle-view" />
<label htmlFor="toggle-view">asdfghj</label>
<button type="button" className="destroy" data-cy="deleteTodo" />
</div>
<input type="text" className="edit" />
</li>

<li className="completed">
<div className="view">
<input type="checkbox" className="toggle" id="toggle-completed" />
<label htmlFor="toggle-completed">qwertyuio</label>
<button type="button" className="destroy" data-cy="deleteTodo" />
</div>
<input type="text" className="edit" />
</li>

<li className="editing">
<div className="view">
<input type="checkbox" className="toggle" id="toggle-editing" />
<label htmlFor="toggle-editing">zxcvbnm</label>
<button type="button" className="destroy" data-cy="deleteTodo" />
</div>
<input type="text" className="edit" />
</li>

<li>
<div className="view">
<input type="checkbox" className="toggle" id="toggle-view2" />
<label htmlFor="toggle-view2">1234567890</label>
<button type="button" className="destroy" data-cy="deleteTodo" />
</div>
<input type="text" className="edit" />
</li>
</ul>
</section>

<footer className="footer">
<span className="todo-count" data-cy="todosCounter">
3 items left
</span>

<ul className="filters">
<li>
<a href="#/" className="selected">All</a>
</li>

<li>
<a href="#/active">Active</a>
</li>

<li>
<a href="#/completed">Completed</a>
</li>
</ul>

<button type="button" className="clear-completed">
Clear completed
</button>
</footer>
</div>
<TodosProvider>
<TodoApp />
</TodosProvider>
);
};
142 changes: 142 additions & 0 deletions src/Components/TodoApp/TodoApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { useContext, useState } from 'react';

import { TodosContext } from '../../Utils/TodosContext';
import { TodoList } from '../TodoList/TodoList';
import { TodosFilter } from '../TodoFilter/TodoFilter';
import { Filter } from '../../Utils/Types/Filter';

type Props = {
};

export const TodoApp: React.FC<Props> = () => {
const { todos, setTodos } = useContext(TodosContext);
const [title, setTitle] = useState('');
const [filter, setFilter] = useState(Filter.ALL);

const handlerFilterChange = (newFilter: string) => {
setFilter(newFilter);
};

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

const handlerAddTodo = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (title.trim() !== '') {
const newTask = {
id: +new Date(),
title,
completed: false,
};

setTodos((prevTodos) => [...prevTodos, newTask]);
setTitle('');
}
};

const handlerCompleteAll = () => {
if (todos.some(todo => todo.completed === false)) {
const updatedTodos = todos.map((todo) => ({
...todo,
completed: true,
}));

setTodos(updatedTodos);
} else {
const updatedTodos = todos.map((todo) => ({
...todo,
completed: false,
}));

setTodos(updatedTodos);
}
};

const handlerClearCompletes = () => {
setTodos(currentTodos => currentTodos
.filter(elem => !elem.completed));
};

const filteredTodos = todos.filter((todo) => {
if (filter === Filter.ALL) {
return true;
}

if (filter === Filter.ACTIVE) {
return !todo.completed;
}

return todo.completed;
});

const noCompleteTodos = todos.filter(elem => !elem.completed);
const isSomeComplete = todos.some(todo => todo.completed === true);
const allCompleted = todos.every(todo => todo.completed === true);

return (
<div className="todoapp">
<header className="header">
<h1>todos</h1>

<form
onSubmit={handlerAddTodo}
onBlur={handlerAddTodo}
>
<input
type="text"
data-cy="createTodo"
className="new-todo"
placeholder="What needs to be done?"
value={title}
onChange={handlerChangeTitle}
/>
</form>
</header>

{todos.length !== 0 && (
<section className="main">

<input
checked={allCompleted}
type="checkbox"
id="toggle-all"
className="toggle-all"
data-cy="toggleAll"
onChange={handlerCompleteAll}
/>
{todos.length !== 0 && (
<label htmlFor="toggle-all">Mark all as complete</label>
)}

<TodoList todos={filteredTodos} />

</section>
)}

{todos.length !== 0 && (
<footer className="footer">
<span className="todo-count" data-cy="todosCounter">
{`${noCompleteTodos.length} items left`}
</span>

<TodosFilter
currentFilter={filter}
onFilterChange={handlerFilterChange}
/>

{isSomeComplete && (
<button
type="button"
className="clear-completed"
onClick={handlerClearCompletes}
>
Clear completed
</button>
)}

</footer>
)}
</div>
);
};
58 changes: 58 additions & 0 deletions src/Components/TodoFilter/TodoFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import classNames from 'classnames';
import { Filter } from '../../Utils/Types/Filter';

type Props = {
currentFilter: string,
onFilterChange?: (filter: string) => void
};

export const TodosFilter: React.FC<Props> = ({
currentFilter,
onFilterChange = () => { },
}) => {
return (
<ul className="filters" data-cy="todosFilter">
<li>
<a
href="#/"
className={classNames({
selected: currentFilter === Filter.ALL,
})}
onClick={() => {
onFilterChange(Filter.ALL);
}}
>
All
</a>
</li>

<li>
<a
href="#/active"
className={classNames({
selected: currentFilter === Filter.ACTIVE,
})}
onClick={() => {
onFilterChange(Filter.ACTIVE);
}}
>
Active
</a>
</li>

<li>
<a
href="#/completed"
className={classNames({
selected: currentFilter === Filter.COMPLETED,
})}
onClick={() => {
onFilterChange(Filter.COMPLETED);
}}
>
Completed
</a>
</li>
</ul>
);
};
Loading

0 comments on commit 1085a28

Please sign in to comment.