@@ -30,6 +30,14 @@ import {
3030 DropdownMenuItem ,
3131 DropdownMenuTrigger ,
3232} from "@/components/ui/dropdown-menu" ;
33+ import {
34+ Dialog ,
35+ DialogContent ,
36+ DialogDescription ,
37+ DialogFooter ,
38+ DialogHeader ,
39+ DialogTitle ,
40+ } from "@/components/ui/dialog" ;
3341import { api , type Agent , type AgentRunWithMetrics } from "@/lib/api" ;
3442import { save , open } from "@tauri-apps/plugin-dialog" ;
3543import { invoke } from "@tauri-apps/api/core" ;
@@ -87,6 +95,9 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
8795 const [ selectedAgent , setSelectedAgent ] = useState < Agent | null > ( null ) ;
8896 const [ selectedRunId , setSelectedRunId ] = useState < number | null > ( null ) ;
8997 const [ showGitHubBrowser , setShowGitHubBrowser ] = useState ( false ) ;
98+ const [ showDeleteDialog , setShowDeleteDialog ] = useState ( false ) ;
99+ const [ agentToDelete , setAgentToDelete ] = useState < Agent | null > ( null ) ;
100+ const [ isDeleting , setIsDeleting ] = useState ( false ) ;
90101
91102 const AGENTS_PER_PAGE = 9 ; // 3x3 grid
92103
@@ -122,20 +133,46 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
122133 }
123134 } ;
124135
125- const handleDeleteAgent = async ( id : number ) => {
126- if ( ! confirm ( "Are you sure you want to delete this agent?" ) ) return ;
136+ /**
137+ * Initiates the delete agent process by showing the confirmation dialog
138+ * @param agent - The agent to be deleted
139+ */
140+ const handleDeleteAgent = ( agent : Agent ) => {
141+ setAgentToDelete ( agent ) ;
142+ setShowDeleteDialog ( true ) ;
143+ } ;
144+
145+ /**
146+ * Confirms and executes the agent deletion
147+ * Only called when user explicitly confirms the deletion
148+ */
149+ const confirmDeleteAgent = async ( ) => {
150+ if ( ! agentToDelete ?. id ) return ;
127151
128152 try {
129- await api . deleteAgent ( id ) ;
153+ setIsDeleting ( true ) ;
154+ await api . deleteAgent ( agentToDelete . id ) ;
130155 setToast ( { message : "Agent deleted successfully" , type : "success" } ) ;
131156 await loadAgents ( ) ;
132157 await loadRuns ( ) ; // Reload runs as they might be affected
133158 } catch ( err ) {
134159 console . error ( "Failed to delete agent:" , err ) ;
135160 setToast ( { message : "Failed to delete agent" , type : "error" } ) ;
161+ } finally {
162+ setIsDeleting ( false ) ;
163+ setShowDeleteDialog ( false ) ;
164+ setAgentToDelete ( null ) ;
136165 }
137166 } ;
138167
168+ /**
169+ * Cancels the delete operation and closes the dialog
170+ */
171+ const cancelDeleteAgent = ( ) => {
172+ setShowDeleteDialog ( false ) ;
173+ setAgentToDelete ( null ) ;
174+ } ;
175+
139176 const handleEditAgent = ( agent : Agent ) => {
140177 setSelectedAgent ( agent ) ;
141178 setView ( "edit" ) ;
@@ -473,7 +510,7 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
473510 < Button
474511 size = "sm"
475512 variant = "ghost"
476- onClick = { ( ) => handleDeleteAgent ( agent . id ! ) }
513+ onClick = { ( ) => handleDeleteAgent ( agent ) }
477514 className = "flex items-center gap-1 text-destructive hover:text-destructive"
478515 title = "Delete agent"
479516 >
@@ -571,6 +608,50 @@ export const CCAgents: React.FC<CCAgentsProps> = ({ onBack, className }) => {
571608 setToast ( { message : "Agent imported successfully from GitHub" , type : "success" } ) ;
572609 } }
573610 />
611+
612+ { /* Delete Confirmation Dialog */ }
613+ < Dialog open = { showDeleteDialog } onOpenChange = { setShowDeleteDialog } >
614+ < DialogContent className = "sm:max-w-md" >
615+ < DialogHeader >
616+ < DialogTitle className = "flex items-center gap-2" >
617+ < Trash2 className = "h-5 w-5 text-destructive" />
618+ Delete Agent
619+ </ DialogTitle >
620+ < DialogDescription >
621+ Are you sure you want to delete the agent "{ agentToDelete ?. name } "?
622+ This action cannot be undone and will permanently remove the agent and all its associated data.
623+ </ DialogDescription >
624+ </ DialogHeader >
625+ < DialogFooter className = "flex flex-col-reverse sm:flex-row sm:justify-end gap-2" >
626+ < Button
627+ variant = "outline"
628+ onClick = { cancelDeleteAgent }
629+ disabled = { isDeleting }
630+ className = "w-full sm:w-auto"
631+ >
632+ Cancel
633+ </ Button >
634+ < Button
635+ variant = "destructive"
636+ onClick = { confirmDeleteAgent }
637+ disabled = { isDeleting }
638+ className = "w-full sm:w-auto"
639+ >
640+ { isDeleting ? (
641+ < >
642+ < div className = "animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" />
643+ Deleting...
644+ </ >
645+ ) : (
646+ < >
647+ < Trash2 className = "h-4 w-4 mr-2" />
648+ Delete Agent
649+ </ >
650+ ) }
651+ </ Button >
652+ </ DialogFooter >
653+ </ DialogContent >
654+ </ Dialog >
574655 </ div >
575656 ) ;
576657} ;
0 commit comments