Skip to content

Commit 96a0db6

Browse files
committed
added editing functionality for TASK NAME ONLY
1 parent 428f0cc commit 96a0db6

4 files changed

Lines changed: 105 additions & 11 deletions

File tree

client/src/components/task_item.tsx

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useState } from "react";
2+
13
interface Time {
24
id: number;
35
day: number;
@@ -24,9 +26,52 @@ interface Item {
2426
type ItemProps = {
2527
item: Item;
2628
onToggle?: (id: number) => void;
29+
onUpdate: (item: Item) => void;
2730
};
2831

29-
export function TaskItem({ item, onToggle }: ItemProps) {
32+
export function TaskItem({ item, onToggle, onUpdate }: ItemProps) {
33+
const [isEditing, setIsEditing] = useState(false);
34+
const [draftName, setDraftName] = useState(item.name);
35+
const [saving, setSaving] = useState(false);
36+
37+
function startEdit() {
38+
setDraftName(item.name);
39+
setIsEditing(true);
40+
}
41+
42+
function cancelEdit() {
43+
setIsEditing(false);
44+
setDraftName(item.name);
45+
}
46+
47+
async function saveEdit() {
48+
setSaving(true);
49+
try {
50+
const response = await fetch(
51+
`http://localhost:8000/api/planner/tasks/${item.id}/`,
52+
{
53+
method: "PUT",
54+
headers: { "Content-Type": "application/json" },
55+
body: JSON.stringify({
56+
name: draftName,
57+
description: item.description,
58+
completed: item.completed,
59+
}),
60+
},
61+
);
62+
if (!response.ok) {
63+
throw new Error("Failed to update task");
64+
}
65+
const updatedItem = await response.json();
66+
onUpdate(updatedItem);
67+
setIsEditing(false);
68+
} catch (error) {
69+
console.error("Error saving task:", error);
70+
} finally {
71+
setSaving(false);
72+
}
73+
}
74+
3075
return (
3176
<label className="m-1 flex w-96 flex-col rounded-md border-2 border-zinc-200 bg-zinc-700 p-2">
3277
<div className="flex items-center justify-between">
@@ -37,13 +82,21 @@ export function TaskItem({ item, onToggle }: ItemProps) {
3782
onChange={() => onToggle?.(item.id)}
3883
className="w-xl h-xl accent-zinc-600"
3984
/>
40-
<span
41-
className={
42-
item.completed ? "text-zinc-400 line-through" : "text-zinc-300"
43-
}
44-
>
45-
{item.name}
46-
</span>
85+
{isEditing ? (
86+
<input
87+
value={draftName}
88+
onChange={(e) => setDraftName(e.target.value)}
89+
className="rounded border-2 bg-zinc-600 p-1 text-zinc-200"
90+
/>
91+
) : (
92+
<span
93+
className={
94+
item.completed ? "text-zinc-400 line-through" : "text-zinc-300"
95+
}
96+
>
97+
{item.name}
98+
</span>
99+
)}
47100
</div>
48101
<div className="flex flex-col items-end text-sm text-zinc-300">
49102
{item.times?.length > 0
@@ -75,6 +128,27 @@ export function TaskItem({ item, onToggle }: ItemProps) {
75128
))
76129
: "No topics"}
77130
</div>
131+
<div>
132+
{item.description ? (
133+
<span className="mt-2 block text-zinc-300">{item.description}</span>
134+
) : (
135+
<span className="mt-2 block italic text-zinc-500">
136+
No description.
137+
</span>
138+
)}
139+
</div>
140+
<div className="mt-2 flex gap-2">
141+
{isEditing ? (
142+
<>
143+
<button onClick={saveEdit} disabled={saving}>
144+
Save
145+
</button>
146+
<button onClick={cancelEdit}>Cancel</button>
147+
</>
148+
) : (
149+
<button onClick={startEdit}>Edit</button>
150+
)}
151+
</div>
78152
</label>
79153
);
80154
}

client/src/components/task_list.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ interface Item {
2626
type ListProps = {
2727
items: Item[];
2828
onToggleTask?: (id: number) => void;
29+
onUpdate: (item: Item) => void;
2930
};
3031

31-
export function TaskList({ items, onToggleTask }: ListProps) {
32+
export function TaskList({ items, onToggleTask, onUpdate }: ListProps) {
3233
if (items.length === 0) {
3334
return (
3435
<div>
@@ -41,7 +42,7 @@ export function TaskList({ items, onToggleTask }: ListProps) {
4142
<ul className="space-y-2">
4243
{items.map((item) => (
4344
<li key={item.id}>
44-
<TaskItem item={item} onToggle={onToggleTask} />
45+
<TaskItem item={item} onToggle={onToggleTask} onUpdate={onUpdate} />
4546
</li>
4647
))}
4748
</ul>

client/src/pages/[id]/tasks.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,19 @@ export default function TasksPage() {
9191
}
9292
}
9393

94+
function handleTaskUpdated(updated: Item) {
95+
setItems((prev) => prev.map((t) => (t.id === updated.id ? updated : t)));
96+
}
97+
9498
return (
9599
<div className="container mx-auto flex flex-row items-center justify-center p-4">
96100
<div className="m-4 h-fit w-fit rounded-xl bg-zinc-700 p-4 text-center">
97101
<h1 className="mb-4 text-3xl font-bold text-zinc-300">Task List</h1>
98-
<TaskList items={items} onToggleTask={handleToggleTask} />
102+
<TaskList
103+
items={items}
104+
onToggleTask={handleToggleTask}
105+
onUpdate={handleTaskUpdated}
106+
/>
99107
</div>
100108
<div className="m-4 h-fit w-fit rounded-xl bg-zinc-700 p-4 text-center">
101109
<h1 className="mb-4 text-3xl font-bold text-zinc-300">Add Task</h1>

server/task_planner/views.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,16 @@ def toggle_complete(self, request, pk=None):
7979
serializer = TaskCompleteSerializer(task, data=request.data, partial=True)
8080
serializer.is_valid(raise_exception=True)
8181
serializer.save()
82+
read_serializer = TaskReadSerializer(task)
83+
return Response(read_serializer.data)
84+
85+
def update(self, request, *args, **kwargs):
86+
partial = kwargs.pop('partial', False)
87+
instance = self.get_object()
88+
89+
write_serializer = TaskWriteSerializer(instance, data=request.data, partial=partial)
90+
write_serializer.is_valid(raise_exception=True)
91+
task = write_serializer.save()
92+
8293
read_serializer = TaskReadSerializer(task)
8394
return Response(read_serializer.data)

0 commit comments

Comments
 (0)