Skip to content

Commit d548349

Browse files
authored
Merge pull request #478 from ThulaxanUthayakumar/improve-todo-performance-ui
Refactor Todo App UI and improve performance
2 parents ab0c1ee + 0ff3472 commit d548349

2 files changed

Lines changed: 45 additions & 35 deletions

File tree

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { AnimatePresence, motion } from 'framer-motion';
2-
import React from 'react';
2+
import React, { useMemo, useCallback } from 'react';
33
import { useSelector, useDispatch } from 'react-redux';
4+
45
import styles from '../styles/modules/app.module.scss';
56
import TodoItem from './TodoItem';
6-
import { clearCompletedTodos } from '../slices/todoSlice'; // ✅ import action
7+
import { clearCompletedTodos } from '../slices/todoSlice';
78

89
const container = {
910
hidden: { opacity: 1 },
@@ -15,35 +16,36 @@ const container = {
1516
},
1617
},
1718
};
19+
1820
const child = {
1921
hidden: { y: 20, opacity: 0 },
20-
visible: {
21-
y: 0,
22-
opacity: 1,
23-
},
22+
visible: { y: 0, opacity: 1 },
2423
};
2524

2625
function AppContent() {
2726
const dispatch = useDispatch();
27+
2828
const todoList = useSelector((state) => state.todo.todoList);
2929
const filterStatus = useSelector((state) => state.todo.filterStatus);
3030

31-
const sortedTodoList = [...todoList];
32-
sortedTodoList.sort((a, b) => new Date(b.time) - new Date(a.time));
31+
// ✅ Optimized sorting + filtering
32+
const filteredTodoList = useMemo(() => {
33+
return [...todoList]
34+
.sort((a, b) => new Date(b.time) - new Date(a.time))
35+
.filter((item) =>
36+
filterStatus === 'all' ? true : item.status === filterStatus
37+
);
38+
}, [todoList, filterStatus]);
3339

34-
const filteredTodoList = sortedTodoList.filter((item) => {
35-
if (filterStatus === 'all') {
36-
return true;
37-
}
38-
return item.status === filterStatus;
39-
});
40+
const hasCompleted = useMemo(
41+
() => todoList.some((todo) => todo.status === 'complete'),
42+
[todoList]
43+
);
4044

41-
// ✅ Handler for clearing completed todos
42-
const handleClearCompleted = () => {
45+
// ✅ Stable handler
46+
const handleClearCompleted = useCallback(() => {
4347
dispatch(clearCompletedTodos());
44-
};
45-
46-
const hasCompleted = todoList.some((todo) => todo.status === 'complete');
48+
}, [dispatch]);
4749

4850
return (
4951
<motion.div
@@ -52,31 +54,20 @@ function AppContent() {
5254
initial="hidden"
5355
animate="visible"
5456
>
55-
{/* Clear Completed button */}
57+
{/* Clear Completed Button */}
5658
{hasCompleted && (
57-
<div style={{ textAlign: 'right', marginBottom: '1rem' }}>
59+
<div className={styles.clearWrapper}>
5860
<button
61+
className={styles.clearButton}
5962
onClick={handleClearCompleted}
60-
style={{
61-
backgroundColor: '#ff5c5c',
62-
border: 'none',
63-
color: 'white',
64-
padding: '0.5rem 1rem',
65-
borderRadius: '8px',
66-
cursor: 'pointer',
67-
fontWeight: '500',
68-
transition: 'background 0.2s',
69-
}}
70-
onMouseOver={(e) => (e.target.style.backgroundColor = '#ff3b3b')}
71-
onMouseOut={(e) => (e.target.style.backgroundColor = '#ff5c5c')}
7263
>
7364
Clear Completed
7465
</button>
7566
</div>
7667
)}
7768

7869
<AnimatePresence>
79-
{filteredTodoList && filteredTodoList.length > 0 ? (
70+
{filteredTodoList.length > 0 ? (
8071
filteredTodoList.map((todo) => (
8172
<TodoItem key={todo.id} todo={todo} />
8273
))
@@ -90,4 +81,4 @@ function AppContent() {
9081
);
9182
}
9283

93-
export default AppContent;
84+
export default AppContent;

react-todo-app/src/styles/modules/app.module.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,22 @@
3232
width: max-content;
3333
height: auto;
3434
}
35+
.clearWrapper {
36+
text-align: right;
37+
margin-bottom: 1rem;
38+
}
39+
40+
.clearButton {
41+
background-color: #ff5c5c;
42+
border: none;
43+
color: white;
44+
padding: 0.5rem 1rem;
45+
border-radius: 8px;
46+
cursor: pointer;
47+
font-weight: 500;
48+
transition: 0.2s ease;
49+
50+
&:hover {
51+
background-color: #ff3b3b;
52+
}
53+
}

0 commit comments

Comments
 (0)