'use client'
import React, { useState, useEffect, useCallback } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { ArrowLeft, Play, Plus, Edit, Trash2, Search, FileText } from 'lucide-react'
import { workflowService, Workflow } from '../../services/workflowService'
export default function WorkflowsPage() {
const [workflows, setWorkflows] = useState<Workflow[]>([])
const [loading, setLoading] = useState(true)
const [searchQuery, setSearchQuery] = useState('')
const [categoryFilter, setCategoryFilter] = useState<string>('all')
const navigate = useNavigate()
const loadWorkflows = useCallback(async () => {
setLoading(true)
try {
const category = categoryFilter === 'all' ? undefined : categoryFilter
const workflowsData = await workflowService.listWorkflows(category, undefined, searchQuery || undefined)
setWorkflows(workflowsData)
} catch (error) {
console.error('Failed to load workflows:', error)
} finally {
setLoading(false)
}
}, [categoryFilter, searchQuery])
useEffect(() => {
loadWorkflows()
}, [loadWorkflows])
const handleDelete = async (workflowId: string) => {
if (!confirm('Are you sure you want to delete this workflow?')) return
try {
await workflowService.deleteWorkflow(workflowId)
await loadWorkflows()
} catch (error) {
alert(`Failed to delete workflow: ${error}`)
}
}
const handleExecute = (workflowId: string) => {
navigate(`/workflows/${workflowId}/execute`)
}
const getCategoryColor = (category: string) => {
switch (category) {
case 'avatar': return '#8b5cf6'
case 'vbot': return '#06b6d4'
case 'sync': return '#10b981'
default: return '#6b7280'
}
}
return (
<div style={{ minHeight: '100vh', padding: '24px', backgroundColor: '#f8fafc' }}>
<div style={{ maxWidth: '1400px', margin: '0 auto' }}>
{/* Header */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '32px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
<Link
to="/"
style={{
display: 'flex',
alignItems: 'center',
padding: '8px',
borderRadius: '8px',
backgroundColor: 'white',
border: '1px solid #e5e7eb',
textDecoration: 'none',
color: '#374151'
}}
>
<ArrowLeft style={{ width: '20px', height: '20px' }} />
</Link>
<div>
<h1 style={{ fontSize: '32px', fontWeight: '700', margin: '0 0 4px 0', color: '#111827' }}>
Workflows
</h1>
<p style={{ fontSize: '16px', color: '#6b7280', margin: 0 }}>
Preprogrammed flows for robotics automation
</p>
</div>
</div>
<button
onClick={() => navigate('/workflows/new')}
style={{
display: 'flex',
alignItems: 'center',
gap: '8px',
padding: '12px 24px',
backgroundColor: '#3b82f6',
color: 'white',
border: 'none',
borderRadius: '8px',
fontSize: '16px',
fontWeight: '500',
cursor: 'pointer'
}}
>
<Plus style={{ width: '20px', height: '20px' }} />
New Workflow
</button>
</div>
{/* Filters */}
<div style={{
display: 'flex',
gap: '16px',
marginBottom: '24px',
padding: '16px',
backgroundColor: 'white',
borderRadius: '12px',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
}}>
<div style={{ flex: 1, position: 'relative' }}>
<Search style={{
position: 'absolute',
left: '12px',
top: '50%',
transform: 'translateY(-50%)',
width: '20px',
height: '20px',
color: '#9ca3af'
}} />
<input
type="text"
placeholder="Search workflows..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
style={{
width: '100%',
padding: '10px 12px 10px 40px',
border: '1px solid #e5e7eb',
borderRadius: '8px',
fontSize: '14px'
}}
/>
</div>
<select
value={categoryFilter}
onChange={(e) => setCategoryFilter(e.target.value)}
style={{
padding: '10px 16px',
border: '1px solid #e5e7eb',
borderRadius: '8px',
fontSize: '14px',
backgroundColor: 'white'
}}
>
<option value="all">All Categories</option>
<option value="avatar">Avatar</option>
<option value="vbot">VBot</option>
<option value="sync">Sync</option>
<option value="custom">Custom</option>
</select>
</div>
{/* Workflows List */}
{loading ? (
<div style={{ display: 'flex', justifyContent: 'center', padding: '64px' }}>
<div style={{
width: '32px',
height: '32px',
border: '3px solid #e5e7eb',
borderTop: '3px solid #3b82f6',
borderRadius: '50%',
animation: 'spin 1s linear infinite'
}} />
<style>{`
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`}</style>
</div>
) : workflows.length === 0 ? (
<div style={{
textAlign: 'center',
padding: '64px',
backgroundColor: 'white',
borderRadius: '12px',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
}}>
<FileText style={{ width: '48px', height: '48px', color: '#9ca3af', margin: '0 auto 16px' }} />
<h3 style={{ fontSize: '18px', fontWeight: '600', margin: '0 0 8px 0', color: '#374151' }}>
No workflows found
</h3>
<p style={{ fontSize: '14px', color: '#6b7280', margin: '0 0 24px 0' }}>
{searchQuery || categoryFilter !== 'all'
? 'Try adjusting your filters'
: 'Create your first workflow to get started'}
</p>
{!searchQuery && categoryFilter === 'all' && (
<button
onClick={() => navigate('/workflows/new')}
style={{
padding: '12px 24px',
backgroundColor: '#3b82f6',
color: 'white',
border: 'none',
borderRadius: '8px',
fontSize: '14px',
fontWeight: '500',
cursor: 'pointer'
}}
>
Create Workflow
</button>
)}
</div>
) : (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(400px, 1fr))', gap: '20px' }}>
{workflows.map((workflow) => (
<div
key={workflow.id}
style={{
backgroundColor: 'white',
borderRadius: '12px',
padding: '20px',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
border: '1px solid #e5e7eb',
transition: 'transform 0.2s, box-shadow 0.2s'
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-2px)'
e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)'
e.currentTarget.style.boxShadow = '0 1px 3px rgba(0,0,0,0.1)'
}}
>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: '12px' }}>
<div style={{ flex: 1 }}>
<h3 style={{ fontSize: '18px', fontWeight: '600', margin: '0 0 4px 0', color: '#111827' }}>
{workflow.name}
</h3>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' }}>
<span
style={{
padding: '4px 8px',
borderRadius: '4px',
fontSize: '12px',
fontWeight: '500',
backgroundColor: `${getCategoryColor(workflow.category)}20`,
color: getCategoryColor(workflow.category)
}}
>
{workflow.category}
</span>
{workflow.tags && workflow.tags.length > 0 && (
<span style={{ fontSize: '12px', color: '#6b7280' }}>
{workflow.tags.length} tag{workflow.tags.length !== 1 ? 's' : ''}
</span>
)}
</div>
</div>
</div>
<p style={{ fontSize: '14px', color: '#6b7280', margin: '0 0 16px 0', lineHeight: '1.5' }}>
{workflow.description || 'No description'}
</p>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '16px' }}>
<span style={{ fontSize: '12px', color: '#9ca3af' }}>
{workflow.steps?.length || 0} step{workflow.steps?.length !== 1 ? 's' : ''}
</span>
{workflow.variables && workflow.variables.length > 0 && (
<>
<span style={{ color: '#e5e7eb' }}>•</span>
<span style={{ fontSize: '12px', color: '#9ca3af' }}>
{workflow.variables.length} variable{workflow.variables.length !== 1 ? 's' : ''}
</span>
</>
)}
</div>
<div style={{ display: 'flex', gap: '8px' }}>
<button
onClick={() => handleExecute(workflow.id)}
style={{
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '6px',
padding: '8px 16px',
backgroundColor: '#10b981',
color: 'white',
border: 'none',
borderRadius: '6px',
fontSize: '14px',
fontWeight: '500',
cursor: 'pointer'
}}
>
<Play style={{ width: '16px', height: '16px' }} />
Execute
</button>
<button
onClick={() => navigate(`/workflows/edit/${workflow.id}`)}
style={{
padding: '8px',
backgroundColor: '#f3f4f6',
border: 'none',
borderRadius: '6px',
cursor: 'pointer'
}}
>
<Edit style={{ width: '16px', height: '16px', color: '#374151' }} />
</button>
<button
onClick={() => handleDelete(workflow.id)}
style={{
padding: '8px',
backgroundColor: '#f3f4f6',
border: 'none',
borderRadius: '6px',
cursor: 'pointer'
}}
>
<Trash2 style={{ width: '16px', height: '16px', color: '#ef4444' }} />
</button>
</div>
</div>
))}
</div>
)}
</div>
</div>
)
}