11import { useState , useEffect } from 'react'
22import { Dialog , DialogContent , DialogHeader , DialogTitle , DialogFooter } from '@/components/ui/dialog'
3+ import {
4+ AlertDialog ,
5+ AlertDialogAction ,
6+ AlertDialogCancel ,
7+ AlertDialogContent ,
8+ AlertDialogDescription ,
9+ AlertDialogFooter ,
10+ AlertDialogHeader ,
11+ AlertDialogTitle ,
12+ AlertDialogTrigger ,
13+ } from '@/components/ui/alert-dialog'
314import { Field , FieldGroup , FieldLabel } from '@/components/ui/field'
415import { Input } from '@/components/ui/input'
516import { DescriptionTextarea } from '@/components/ui/description-textarea'
17+ import { Checkbox } from '@/components/ui/checkbox'
618import { Button } from '@/components/ui/button'
7- import { useUpdateTask } from '@/hooks/use-tasks'
19+ import { useUpdateTask , useDeleteTask } from '@/hooks/use-tasks'
820import type { Task } from '@/types'
921
1022interface TaskConfigModalProps {
@@ -20,8 +32,10 @@ function parseLinearUrl(url: string): string | null {
2032
2133export function TaskConfigModal ( { task, open, onOpenChange } : TaskConfigModalProps ) {
2234 const updateTask = useUpdateTask ( )
35+ const deleteTask = useDeleteTask ( )
2336
2437 const [ title , setTitle ] = useState ( task . title )
38+ const [ deleteLinkedWorktree , setDeleteLinkedWorktree ] = useState ( true )
2539 const [ description , setDescription ] = useState ( task . description || '' )
2640 const [ prUrl , setPrUrl ] = useState ( task . prUrl || '' )
2741 const [ linearUrl , setLinearUrl ] = useState ( task . linearTicketUrl || '' )
@@ -33,6 +47,7 @@ export function TaskConfigModal({ task, open, onOpenChange }: TaskConfigModalPro
3347 setDescription ( task . description || '' )
3448 setPrUrl ( task . prUrl || '' )
3549 setLinearUrl ( task . linearTicketUrl || '' )
50+ setDeleteLinkedWorktree ( true )
3651 }
3752 } , [ open , task ] )
3853
@@ -76,6 +91,17 @@ export function TaskConfigModal({ task, open, onOpenChange }: TaskConfigModalPro
7691 }
7792 }
7893
94+ const handleDelete = ( ) => {
95+ deleteTask . mutate (
96+ { taskId : task . id , deleteLinkedWorktree } ,
97+ {
98+ onSuccess : ( ) => {
99+ onOpenChange ( false )
100+ } ,
101+ }
102+ )
103+ }
104+
79105 return (
80106 < Dialog open = { open } onOpenChange = { onOpenChange } >
81107 < DialogContent className = "sm:max-w-md" onKeyDown = { handleKeyDown } >
@@ -120,13 +146,50 @@ export function TaskConfigModal({ task, open, onOpenChange }: TaskConfigModalPro
120146 />
121147 </ Field >
122148 </ FieldGroup >
123- < DialogFooter className = "mt-4" >
124- < Button variant = "outline" onClick = { ( ) => onOpenChange ( false ) } >
125- Cancel
126- </ Button >
127- < Button onClick = { handleSave } disabled = { ! title . trim ( ) } >
128- Save
129- </ Button >
149+ < DialogFooter className = "mt-4 flex-row justify-between sm:justify-between" >
150+ < AlertDialog >
151+ < AlertDialogTrigger
152+ render = { < Button variant = "ghost" className = "text-destructive hover:text-destructive hover:bg-destructive/10" disabled = { deleteTask . isPending } /> }
153+ >
154+ { deleteTask . isPending ? 'Deleting...' : 'Delete Task' }
155+ </ AlertDialogTrigger >
156+ < AlertDialogContent >
157+ < AlertDialogHeader >
158+ < AlertDialogTitle > Delete Task</ AlertDialogTitle >
159+ < AlertDialogDescription >
160+ This will permanently delete this task. This action cannot be undone.
161+ </ AlertDialogDescription >
162+ </ AlertDialogHeader >
163+ < div className = "flex items-center gap-2 py-2" >
164+ < Checkbox
165+ id = "delete-worktree"
166+ checked = { deleteLinkedWorktree }
167+ onCheckedChange = { ( checked ) => setDeleteLinkedWorktree ( checked === true ) }
168+ />
169+ < label htmlFor = "delete-worktree" className = "text-sm cursor-pointer" >
170+ Also delete linked worktree
171+ </ label >
172+ </ div >
173+ < AlertDialogFooter >
174+ < AlertDialogCancel > Cancel</ AlertDialogCancel >
175+ < AlertDialogAction
176+ onClick = { handleDelete }
177+ variant = "destructive"
178+ disabled = { deleteTask . isPending }
179+ >
180+ { deleteTask . isPending ? 'Deleting...' : 'Delete' }
181+ </ AlertDialogAction >
182+ </ AlertDialogFooter >
183+ </ AlertDialogContent >
184+ </ AlertDialog >
185+ < div className = "flex gap-2" >
186+ < Button variant = "outline" onClick = { ( ) => onOpenChange ( false ) } >
187+ Cancel
188+ </ Button >
189+ < Button onClick = { handleSave } disabled = { ! title . trim ( ) } >
190+ Save
191+ </ Button >
192+ </ div >
130193 </ DialogFooter >
131194 </ DialogContent >
132195 </ Dialog >
0 commit comments