-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create todo app #1557
base: master
Are you sure you want to change the base?
Create todo app #1557
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done 👍
But review my comments and fix them(If u agree with them)
}, {} as Loading); | ||
}; | ||
|
||
const todoFilter = todos.filter(todo => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this function to separate component or use useMemo for it
src/App.tsx
Outdated
interface Loading { | ||
[key: number]: number; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move it outside the function
src/App.tsx
Outdated
setTempTodo(null); | ||
}); | ||
}; | ||
|
||
const deleteTodoItem = (todoId: number): void => { | ||
deleteTodo(todoId) | ||
.then(() => { | ||
setTodos(currentTodos => | ||
currentTodos.filter(todo => todo.id !== todoId), | ||
); | ||
}) | ||
.catch(() => { | ||
setErrorType(ErrorType.UnableToDelete); | ||
}) | ||
.finally(() => { | ||
setTempTodo(null); | ||
}); | ||
}; | ||
|
||
const updateTodoItems = ( | ||
updateTodoItem: Todo, | ||
key: keyof Todo, | ||
value: boolean | string, | ||
): Promise<boolean> => { | ||
return updateTodo({ ...updateTodoItem, [key]: value }) | ||
.then(todoUpdated => { | ||
setTodos(currentTodos => | ||
currentTodos.map(todo => | ||
todo.id === updateTodoItem.id ? todoUpdated : todo, | ||
), | ||
); | ||
|
||
return false; | ||
}) | ||
.catch(() => { | ||
setErrorType(ErrorType.UnableToUpdate); | ||
|
||
return true; | ||
}); | ||
}; | ||
|
||
const loadedDeleteTodo = (): void => { | ||
const completedTodos = todos.filter(todo => todo.completed); | ||
|
||
setTodoLoading(loadingTodo(completedTodos)); | ||
|
||
Promise.allSettled( | ||
completedTodos.map(todo => deleteTodo(todo.id).then(() => todo)), | ||
) | ||
.then(values => { | ||
values.forEach(val => { | ||
if (val.status === 'rejected') { | ||
setErrorType(ErrorType.UnableToDelete); | ||
} else { | ||
setTodos(currentTodos => { | ||
const todoId = val.value as Todo; | ||
|
||
return currentTodos.filter(todo => todo.id !== todoId.id); | ||
}); | ||
} | ||
}); | ||
}) | ||
.finally(() => setTodoLoading({})); | ||
}; | ||
|
||
const handleAllCompleted = (): void => { | ||
const completedAllTodos = ( | ||
targetTodos: Todo[], | ||
completed: boolean, | ||
): Promise<void> => { | ||
return Promise.all( | ||
targetTodos.map(todo => updateTodo({ ...todo, completed })), | ||
) | ||
.then(() => { | ||
setTodos(currentTodos => | ||
currentTodos.map(todo => | ||
targetTodos.some(t => t.id === todo.id) | ||
? { ...todo, completed } | ||
: todo, | ||
), | ||
); | ||
}) | ||
.catch(() => { | ||
setErrorType(ErrorType.UnableToUpdate); | ||
}) | ||
.finally(() => { | ||
setTodoLoading({}); | ||
}); | ||
}; | ||
|
||
const activeTodos = todos.filter(todo => !todo.completed); | ||
|
||
if (activeTodos.length) { | ||
setTodoLoading(loadingTodo(activeTodos)); | ||
completedAllTodos(activeTodos, true); | ||
} else { | ||
setTodoLoading(loadingTodo(todos)); | ||
completedAllTodos(todos, false); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- do we need
useCallback
for these function? for which one? - use naming convention for all the functions. For all such cases
src/App.tsx
Outdated
setErrorType={setErrorType} | ||
onChangeTodoTask={setTempTodo} | ||
tempTodo={tempTodo} | ||
addNewTodo={addNewTodo} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addNewTodo={addNewTodo} | |
onAddNewTodo={handleAddNewTodo} |
src/commponents/Footer.tsx
Outdated
import { Status } from '../types/Status'; | ||
import { Todo } from '../types/Todo'; | ||
|
||
interface LoadingTodo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen this type before. Extract it to a separate file and export it.
Import it wherever u need it
src/commponents/Footer.tsx
Outdated
[todos], | ||
); | ||
|
||
const onTodoCompleted = useMemo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on
?why?
i see that this variable contains boolean value and doesn't change anything
() => todos.some(todo => todo.completed), | ||
[todos], | ||
); | ||
let onCompletedDelete = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useState?
src/commponents/Footer.tsx
Outdated
</span> | ||
<nav className="filter" data-cy="Filter"> | ||
{filtersValue.map(filter => ( | ||
<a | ||
key={filter} | ||
href={`#/${filter !== Status.All && filter.toLowerCase()}`} | ||
className={cn('filter__link', { | ||
selected: filter === filterType, | ||
})} | ||
data-cy={`FilterLink${filter}`} | ||
onClick={() => onFiltered(filter)} | ||
> | ||
{filter} | ||
</a> | ||
))} | ||
</nav> | ||
<button | ||
type="button" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't forget about indents(for all cases)
</span> | |
<nav className="filter" data-cy="Filter"> | |
{filtersValue.map(filter => ( | |
<a | |
key={filter} | |
href={`#/${filter !== Status.All && filter.toLowerCase()}`} | |
className={cn('filter__link', { | |
selected: filter === filterType, | |
})} | |
data-cy={`FilterLink${filter}`} | |
onClick={() => onFiltered(filter)} | |
> | |
{filter} | |
</a> | |
))} | |
</nav> | |
<button | |
type="button" | |
</span> | |
<nav className="filter" data-cy="Filter"> | |
{filtersValue.map(filter => ( | |
<a | |
key={filter} | |
href={`#/${filter !== Status.All && filter.toLowerCase()}`} | |
className={cn('filter__link', { | |
selected: filter === filterType, | |
})} | |
data-cy={`FilterLink${filter}`} | |
onClick={() => onFiltered(filter)} | |
> | |
{filter} | |
</a> | |
))} | |
</nav> | |
<button | |
type="button" |
src/commponents/Header.tsx
Outdated
|
||
const todoUseRef = useRef<HTMLInputElement>(null); | ||
|
||
const completedTodos = todos.every(todo => todo.completed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useMemo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks much more better, I'm approving it 🔥
DEMO LINK
Все працює, але падає тест. Було б добре, щоб глянув ментор, в чому може бути причина. Дякую.