Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 32 additions & 28 deletions db.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
{
"tasks":
[
{
"id": 1,
"title": "Buy groceries",
"completed": false
},
{
"id": 2,
"title": "Finish React project",
"completed": false
},
{
"id": 3,
"title": "Call the bank",
"completed": true
},
{
"id": 4,
"title": "Walk the dog",
"completed": false
},
{
"id": 5,
"title": "Read a book",
"completed": true
}
]
"tasks": [
{
"id": "1",
"title": "Buy groceries",
"completed": false
},
{
"id": "2",
"title": "Finish React project",
"completed": false
},
{
"id": "3",
"title": "Call the bank",
"completed": false
},
{
"id": "4",
"title": "Walk the dog",
"completed": false
},
{
"id": "5",
"title": "Read a book",
"completed": false
},
{
"id": "0526",
"title": "Exercise",
"completed": false
}
]
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import TaskForm from "./TaskForm";
import SearchBar from "./SearchBar";

function App() {
const [tasks, setTasks] = useState([]);
const { tasks, setTasks } = useContext(TaskContext);

useEffect(() => {
fetch('http://localhost:6001/tasks')
.then(r=>r.json())
.then(data=>setTasks(data))
}, []);
.then(r => r.json())
.then(data => setTasks(data))

}, [setTasks]);

return (
<div>
Expand Down
10 changes: 7 additions & 3 deletions src/components/SearchBar.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import React, { useRef, useState, useContext } from "react";
import React, { useRef, useState, useContext, useEffect } from "react";
import TaskList from "./TaskList";
import { TaskContext } from "../context/TaskContext";

function SearchBar() {
const [query, setQuery] = useState("");

const searchRef = useRef(null);
function handleSearch(e) {
setQuery(e.target.value);
}

useEffect(() => {
searchRef.current.focus();
}, []);

return (
<div>
<input
ref={searchRef}
type="text"
placeholder="Search tasks..."
value={query}
onChange={handleSearch}
/>
<TaskList query={query}/>
<TaskList query={query} />
</div>
);
}
Expand Down
6 changes: 5 additions & 1 deletion src/components/TaskForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import { TaskContext } from "../context/TaskContext";

function TaskForm() {
const [taskName, setTaskName] = useState("");
const inputId = useId();
const { addTask } = useContext(TaskContext);

function handleSubmit(e) {
e.preventDefault();
if (taskName.trim() === "") return;
addTask(taskName);
setTaskName("");
}

return (
<form onSubmit={handleSubmit}>
<label>New Task:</label>
<label htmlFor={inputId} >New Task:</label>
<input
id={inputId}
type="text"
value={taskName}
onChange={(e) => setTaskName(e.target.value)}
Expand Down
11 changes: 6 additions & 5 deletions src/components/TaskList.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useContext,useState } from "react";
import React, { useContext, useState } from "react";
import { TaskContext } from "../context/TaskContext";

function TaskList({query}) {
const [tasks, setTasks] = useState([]);
const filteredTasks = tasks.filter(task =>
function TaskList({ query }) {
const { tasks, toggleComplete } = useContext(TaskContext);

const filteredTasks = tasks.filter(task =>
task.title.toLowerCase().includes(query.toLowerCase())
);

Expand All @@ -14,7 +15,7 @@ function TaskList({query}) {
<span style={{ textDecoration: task.completed ? "line-through" : "none" }}>
{task.title}
</span>
<button data-testid={task.id}>
<button onClick={() => toggleComplete(task.id, task.completed)} data-testid={task.id}>
{task.completed ? "Undo" : "Complete"}
</button>
</li>
Expand Down
34 changes: 34 additions & 0 deletions src/context/TaskContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,38 @@ import React, { createContext, useState } from "react";
export const TaskContext = createContext();

export function TaskProvider({ children }) {
const [tasks, setTasks] = useState([]);

function toggleComplete(id, currentStatus) {
fetch(`http://localhost:6001/tasks/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ completed: !currentStatus })
})
.then(r => r.json())
.then(updatedTask => {
setTasks(prev => prev.map(task => (task.id === id ? updatedTask : task)))
});
}

function addTask(taskTitle) {
fetch("http://localhost:6001/tasks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: taskTitle,
completed: false
})
})
.then(r => r.json())
.then(savedTask => {
setTasks(prevTasks => [...prevTasks, savedTask])
})
}

return (
< TaskContext.Provider value={{ tasks, setTasks, toggleComplete, addTask }} >
{children}
</TaskContext.Provider>
)
}
6 changes: 3 additions & 3 deletions src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import './index.css'
import App from './components/App.jsx'
import { TaskProvider } from './context/TaskContext.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
<TaskProvider>
<App />
</TaskProvider>,
)