22
33import { cn } from '@/lib/utils' ;
44import { Button } from '@trycompai/ui/button' ;
5- import { ChevronDown , Loader2 , MonitorPlay , Settings } from 'lucide-react' ;
5+ import {
6+ ChevronDown ,
7+ Loader2 ,
8+ MonitorPlay ,
9+ Pencil ,
10+ Power ,
11+ PowerOff ,
12+ Trash2 ,
13+ } from 'lucide-react' ;
614import { formatDistanceToNow } from 'date-fns' ;
15+ import { useState } from 'react' ;
716import type { BrowserAutomation , BrowserAutomationRun } from '../../hooks/types' ;
817import { RunHistory } from './RunHistory' ;
918
@@ -15,6 +24,8 @@ interface AutomationItemProps {
1524 onToggleExpand : ( ) => void ;
1625 onRun : ( ) => void ;
1726 onEdit : ( ) => void ;
27+ onDelete : ( ) => void ;
28+ onToggleEnabled : ( enabled : boolean ) => void ;
1829}
1930
2031export function AutomationItem ( {
@@ -25,23 +36,30 @@ export function AutomationItem({
2536 onToggleExpand,
2637 onRun,
2738 onEdit,
39+ onDelete,
40+ onToggleEnabled,
2841} : AutomationItemProps ) {
42+ const [ confirmDelete , setConfirmDelete ] = useState ( false ) ;
2943 const runs : BrowserAutomationRun [ ] = automation . runs || [ ] ;
3044 const latestRun = runs [ 0 ] ;
3145
3246 // status dot
3347 const hasFailed = latestRun ?. status === 'failed' ;
3448 const isCompleted = latestRun ?. status === 'completed' ;
35- const dotColor = hasFailed
36- ? 'bg-destructive shadow-[0_0_8px_rgba(255,0,0,0.3)]'
37- : isCompleted
38- ? 'bg-primary shadow-[0_0_8px_rgba(0,77,64,0.4)]'
39- : 'bg-muted-foreground' ;
49+ const isDisabled = ! automation . isEnabled ;
50+ const dotColor = isDisabled
51+ ? 'bg-muted-foreground/40'
52+ : hasFailed
53+ ? 'bg-destructive shadow-[0_0_8px_rgba(255,0,0,0.3)]'
54+ : isCompleted
55+ ? 'bg-primary shadow-[0_0_8px_rgba(0,77,64,0.4)]'
56+ : 'bg-muted-foreground' ;
4057
4158 return (
4259 < div
4360 className = { cn (
4461 'rounded-lg border transition-all duration-300' ,
62+ isDisabled && 'opacity-60' ,
4563 isExpanded
4664 ? 'border-primary/30 shadow-sm bg-primary/2'
4765 : 'border-border/50 hover:border-border hover:shadow-sm' ,
@@ -51,9 +69,16 @@ export function AutomationItem({
5169 < div className = { cn ( 'h-2.5 w-2.5 rounded-full shrink-0' , dotColor ) } />
5270
5371 < div className = "flex-1 min-w-0" >
54- < p className = "font-semibold text-foreground text-sm tracking-tight" >
55- { automation . name }
56- </ p >
72+ < div className = "flex items-center gap-2" >
73+ < p className = "font-semibold text-foreground text-sm tracking-tight" >
74+ { automation . name }
75+ </ p >
76+ { isDisabled && (
77+ < span className = "text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded" >
78+ Paused
79+ </ span >
80+ ) }
81+ </ div >
5782 { latestRun ? (
5883 < p className = "text-xs text-muted-foreground mt-0.5" >
5984 Last ran { formatDistanceToNow ( new Date ( latestRun . createdAt ) , { addSuffix : true } ) }
@@ -63,15 +88,75 @@ export function AutomationItem({
6388 ) }
6489 </ div >
6590
66- < div className = "flex items-center gap-2 " >
91+ < div className = "flex items-center gap-1.5 " >
6792 { ! readOnly && (
68- < Button variant = "ghost" size = "icon" onClick = { onEdit } aria-label = "Edit automation" >
69- < Settings className = "h-4 w-4" />
93+ < Button
94+ variant = "ghost"
95+ size = "icon"
96+ className = "h-8 w-8"
97+ onClick = { ( ) => onToggleEnabled ( ! automation . isEnabled ) }
98+ aria-label = { automation . isEnabled ? 'Pause automation' : 'Enable automation' }
99+ >
100+ { automation . isEnabled ? (
101+ < Power className = "h-3.5 w-3.5 text-primary" />
102+ ) : (
103+ < PowerOff className = "h-3.5 w-3.5 text-muted-foreground" />
104+ ) }
70105 </ Button >
71106 ) }
72107
73108 { ! readOnly && (
74- < Button variant = "outline" size = "sm" onClick = { onRun } disabled = { isRunning } >
109+ < Button
110+ variant = "ghost"
111+ size = "icon"
112+ className = "h-8 w-8"
113+ onClick = { onEdit }
114+ aria-label = "Edit automation"
115+ >
116+ < Pencil className = "h-3.5 w-3.5" />
117+ </ Button >
118+ ) }
119+
120+ { ! readOnly && (
121+ confirmDelete ? (
122+ < div className = "flex items-center gap-1" >
123+ < Button
124+ variant = "destructive"
125+ size = "sm"
126+ className = "h-7 text-xs"
127+ onClick = { ( ) => { onDelete ( ) ; setConfirmDelete ( false ) ; } }
128+ >
129+ Confirm
130+ </ Button >
131+ < Button
132+ variant = "ghost"
133+ size = "sm"
134+ className = "h-7 text-xs"
135+ onClick = { ( ) => setConfirmDelete ( false ) }
136+ >
137+ Cancel
138+ </ Button >
139+ </ div >
140+ ) : (
141+ < Button
142+ variant = "ghost"
143+ size = "icon"
144+ className = "h-8 w-8"
145+ onClick = { ( ) => setConfirmDelete ( true ) }
146+ aria-label = "Delete automation"
147+ >
148+ < Trash2 className = "h-3.5 w-3.5 text-muted-foreground hover:text-destructive" />
149+ </ Button >
150+ )
151+ ) }
152+
153+ { ! readOnly && (
154+ < Button
155+ variant = "outline"
156+ size = "sm"
157+ onClick = { onRun }
158+ disabled = { isRunning || isDisabled }
159+ >
75160 { isRunning ? (
76161 < >
77162 < Loader2 className = "mr-1.5 h-3 w-3 animate-spin" />
0 commit comments