@@ -7,6 +7,7 @@ import type { Script } from "~/types/script";
77import { DiffViewer } from "./DiffViewer" ;
88import { TextViewer } from "./TextViewer" ;
99import { ExecutionModeModal } from "./ExecutionModeModal" ;
10+ import { ConfirmationModal } from "./ConfirmationModal" ;
1011import { TypeBadge , UpdateableBadge , PrivilegedBadge , NoteBadge } from "./Badge" ;
1112import { Button } from "./ui/button" ;
1213import { useRegisterModal } from './modal/ModalStackProvider' ;
@@ -37,6 +38,8 @@ export function ScriptDetailModal({
3738 const [ selectedDiffFile , setSelectedDiffFile ] = useState < string | null > ( null ) ;
3839 const [ textViewerOpen , setTextViewerOpen ] = useState ( false ) ;
3940 const [ executionModeOpen , setExecutionModeOpen ] = useState ( false ) ;
41+ const [ isDeleting , setIsDeleting ] = useState ( false ) ;
42+ const [ deleteConfirmOpen , setDeleteConfirmOpen ] = useState ( false ) ;
4043
4144 // Check if script files exist locally
4245 const {
@@ -83,6 +86,31 @@ export function ScriptDetailModal({
8386 } ,
8487 } ) ;
8588
89+ // Delete script mutation
90+ const deleteScriptMutation = api . scripts . deleteScript . useMutation ( {
91+ onSuccess : ( data ) => {
92+ setIsDeleting ( false ) ;
93+ if ( data . success ) {
94+ const message =
95+ "message" in data ? data . message : "Script deleted successfully" ;
96+ setLoadMessage ( `[SUCCESS] ${ message } ` ) ;
97+ // Refetch script files status and comparison data to update the UI
98+ void refetchScriptFiles ( ) ;
99+ void refetchComparison ( ) ;
100+ } else {
101+ const error = "error" in data ? data . error : "Failed to delete script" ;
102+ setLoadMessage ( `[ERROR] ${ error } ` ) ;
103+ }
104+ // Clear message after 5 seconds
105+ setTimeout ( ( ) => setLoadMessage ( null ) , 5000 ) ;
106+ } ,
107+ onError : ( error ) => {
108+ setIsDeleting ( false ) ;
109+ setLoadMessage ( `[ERROR] ${ error . message } ` ) ;
110+ setTimeout ( ( ) => setLoadMessage ( null ) , 5000 ) ;
111+ } ,
112+ } ) ;
113+
86114 if ( ! isOpen || ! script ) return null ;
87115
88116 const handleImageError = ( ) => {
@@ -130,6 +158,19 @@ export function ScriptDetailModal({
130158 setTextViewerOpen ( true ) ;
131159 } ;
132160
161+ const handleDeleteScript = ( ) => {
162+ if ( ! script ) return ;
163+ setDeleteConfirmOpen ( true ) ;
164+ } ;
165+
166+ const handleConfirmDelete = ( ) => {
167+ if ( ! script ) return ;
168+ setDeleteConfirmOpen ( false ) ;
169+ setIsDeleting ( true ) ;
170+ setLoadMessage ( null ) ;
171+ deleteScriptMutation . mutate ( { slug : script . slug } ) ;
172+ } ;
173+
133174 return (
134175 < div
135176 className = "fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-sm bg-black/50"
@@ -373,6 +414,42 @@ export function ScriptDetailModal({
373414 ) ;
374415 }
375416 } ) ( ) }
417+
418+ { /* Delete Button - only show if script files exist */ }
419+ { scriptFilesData ?. success &&
420+ ( scriptFilesData . ctExists || scriptFilesData . installExists ) && (
421+ < Button
422+ onClick = { handleDeleteScript }
423+ disabled = { isDeleting }
424+ variant = "destructive"
425+ size = "default"
426+ className = "w-full sm:w-auto flex items-center justify-center space-x-2"
427+ >
428+ { isDeleting ? (
429+ < >
430+ < div className = "h-4 w-4 animate-spin rounded-full border-b-2 border-white" > </ div >
431+ < span > Deleting...</ span >
432+ </ >
433+ ) : (
434+ < >
435+ < svg
436+ className = "h-4 w-4"
437+ fill = "none"
438+ stroke = "currentColor"
439+ viewBox = "0 0 24 24"
440+ >
441+ < path
442+ strokeLinecap = "round"
443+ strokeLinejoin = "round"
444+ strokeWidth = { 2 }
445+ d = "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
446+ />
447+ </ svg >
448+ < span > Delete Script</ span >
449+ </ >
450+ ) }
451+ </ Button >
452+ ) }
376453 </ div >
377454
378455 { /* Content */ }
@@ -736,6 +813,20 @@ export function ScriptDetailModal({
736813 onExecute = { handleExecuteScript }
737814 />
738815 ) }
816+
817+ { /* Delete Confirmation Modal */ }
818+ { script && (
819+ < ConfirmationModal
820+ isOpen = { deleteConfirmOpen }
821+ onClose = { ( ) => setDeleteConfirmOpen ( false ) }
822+ onConfirm = { handleConfirmDelete }
823+ title = "Delete Script"
824+ message = { `Are you sure you want to delete all downloaded files for "${ script . name } "? This action cannot be undone.` }
825+ variant = "simple"
826+ confirmButtonText = "Delete"
827+ cancelButtonText = "Cancel"
828+ />
829+ ) }
739830 </ div >
740831 ) ;
741832}
0 commit comments