Skip to content

Commit 6717d27

Browse files
committed
feat: filter todos by status
1 parent 0f69ace commit 6717d27

File tree

5 files changed

+80
-22
lines changed

5 files changed

+80
-22
lines changed

app/page.tsx

+21-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import DarkModeToggler from "@/components/DarkModeToggler"
33
import Form from "@/components/Form"
44
import TodosContents from "@/components/TodosContents"
55
import AnimationProvider from "@/provider/AnimationProvider"
6+
import FilterProvider from "@/provider/FilterProvider"
67
import ThemeProvider from "@/provider/ThemeProvider"
78
import TodoProvider from "@/provider/TodoProvider"
89

@@ -11,34 +12,36 @@ const Home = () => {
1112
return (
1213
<ThemeProvider>
1314
<TodoProvider>
14-
<AnimationProvider>
15-
<main className="bg-bg h-screen">
15+
<FilterProvider>
16+
<AnimationProvider>
17+
<main className="bg-bg h-screen">
1618

17-
<BackgroundImage />
19+
<BackgroundImage />
1820

19-
<section className="container relative max-w-2xl mx-auto p-5">
21+
<section className="container relative max-w-2xl mx-auto p-5">
2022

21-
<div className="flex items-center justify-between sm:pt-16 pt-8">
22-
<h1 className="uppercase tracking-widest md:text-4xl text-2xl font-bold text-white">
23-
Todo
24-
</h1>
23+
<div className="flex items-center justify-between sm:pt-16 pt-8">
24+
<h1 className="uppercase tracking-widest md:text-4xl text-2xl font-bold text-white">
25+
Todo
26+
</h1>
2527

26-
<DarkModeToggler />
28+
<DarkModeToggler />
2729

28-
</div>
30+
</div>
2931

30-
<div className="bg-card-bg rounded-md shadow-lg px-5 py-2 mt-8">
31-
<Form />
32-
</div>
32+
<div className="bg-card-bg rounded-md shadow-lg px-5 py-2 mt-8">
33+
<Form />
34+
</div>
3335

34-
<TodosContents />
36+
<TodosContents />
3537

36-
</section>
38+
</section>
3739

38-
<p className="text-grayish-text text-center md:mt-0 pb-10 mt-20">Drag and drop yo reorder list</p>
40+
<p className="text-grayish-text text-center md:mt-0 pb-10 mt-20">Drag and drop yo reorder list</p>
3941

40-
</main>
41-
</AnimationProvider>
42+
</main>
43+
</AnimationProvider>
44+
</FilterProvider>
4245
</TodoProvider>
4346
</ThemeProvider>
4447
)

components/ListControls.tsx

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import React from 'react'
22
import ClearAllCompletedBtn from './ClearAllCompletedBtn'
3+
import { FilterContext } from '@/context/FilterContext'
34

45
const ListControls = ({ len, todos }: ListControlProps) => {
56

7+
const { filter, setFilter } = React.useContext(FilterContext)
8+
69
return (
710
<div className='flex px-5 py-2 justify-between items-center text-sm text-grayish-text'>
811

@@ -11,9 +14,26 @@ const ListControls = ({ len, todos }: ListControlProps) => {
1114
</div>
1215

1316
<div className='flex md:w-fit gap-3 font-bold md:mt-0 md:static absolute mt-36 md:shadow-none shadow-md w-[calc(100%-40px)] left-5 right-5 rounded-md bg-card-bg md:py-0 py-4 px-5 justify-center'>
14-
<button className='text-bright-blue hover:text-text-hovered'>All</button>
15-
<button className='hover:text-text-hovered'>Active</button>
16-
<button className='hover:text-text-hovered'>Completed</button>
17+
<button
18+
onClick={() => setFilter('all')}
19+
className={`${filter === 'all' ? 'text-bright-blue' : ''} sm:hover:text-text-hovered`}
20+
>
21+
All
22+
</button>
23+
24+
<button
25+
onClick={() => setFilter('active')}
26+
className={`${filter === 'active' ? 'text-bright-blue' : ''} sm:hover:text-text-hovered`}
27+
>
28+
Active
29+
</button>
30+
31+
<button
32+
onClick={() => setFilter('completed')}
33+
className={`${filter === 'completed' ? 'text-bright-blue' : ''} sm:hover:text-text-hovered`}
34+
>
35+
Completed
36+
</button>
1737
</div>
1838

1939
<ClearAllCompletedBtn todos={todos} />

components/TodosContents.tsx

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,40 @@ import React from 'react'
33
import ListItem from './ListItem'
44
import ListControls from './ListControls'
55
import { TodoContext } from '@/context/TodoContext'
6+
import { FilterContext } from '@/context/FilterContext'
67

78
const TodosContainer = () => {
89

910
const [todos, setTodos] = React.useState<TodoType[]>([])
1011
const [loading, setLoading] = React.useState(true)
12+
const [filteredTodos, setFilteredTodos] = React.useState<TodoType[]>([])
1113

1214
const { isManipulated, setIsManipulated } = React.useContext(TodoContext)
15+
const { filter, setFilter } = React.useContext(FilterContext)
1316

1417
React.useEffect(() => {
18+
setFilter('all')
1519
setIsManipulated(false)
1620
const todos = JSON.parse(localStorage.getItem('todos') || '[]')
1721
setTodos(todos)
1822
setLoading(false)
1923
}, [isManipulated])
2024

25+
React.useEffect(() => {
26+
if (filter === 'active') setFilteredTodos(todos.filter(todo => !todo.completed))
27+
else if (filter === 'completed') setFilteredTodos(todos.filter(todo => todo.completed))
28+
else setFilteredTodos(todos)
29+
}, [filter, todos])
30+
2131
const renderTodos = () => {
2232

2333
if (todos.length <= 0) {
2434
return <p className="text-center text-grayish-text my-10">Nothing to do for now.</p>
2535
}
2636

27-
return todos.map(todo => {
37+
let todosWithContent = filteredTodos.length > 0 ? filteredTodos : todos as TodoType[]
38+
39+
return todosWithContent.map(todo => {
2840
return (
2941
<ListItem
3042
key={todo.id}

context/FilterContext.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use client'
2+
import React from 'react'
3+
4+
export const FilterContext = React.createContext({
5+
filter: 'all',
6+
setFilter: (filter: string) => {},
7+
})

provider/FilterProvider.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use client'
2+
import React from 'react'
3+
import { FilterContext } from '@/context/FilterContext'
4+
5+
const FilterProvider = ({ children }: ChildrenProps) => {
6+
7+
const [filter, setFilter] = React.useState('all')
8+
9+
return (
10+
<FilterContext.Provider value={{ filter, setFilter }}>
11+
{children}
12+
</FilterContext.Provider>
13+
)
14+
}
15+
16+
export default FilterProvider

0 commit comments

Comments
 (0)