1+ import { useState } from "react" ;
2+
13interface Time {
24 id : number ;
35 day : number ;
@@ -24,9 +26,52 @@ interface Item {
2426type 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}
0 commit comments