import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Plus, Pencil, Trash2, Search, FileText, AlertTriangle } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { getTemplates, deleteTemplate, WorkflowTemplate, getCachedTemplates } from '@/services/workflowTemplateApi'; import { toast } from 'sonner'; export function AdminTemplatesList() { const navigate = useNavigate(); const [templates, setTemplates] = useState(() => getCachedTemplates() || []); // Only show full loading skeleton if we don't have any data yet const [loading, setLoading] = useState(() => !getCachedTemplates()); const [searchQuery, setSearchQuery] = useState(''); const [deleteId, setDeleteId] = useState(null); const [deleting, setDeleting] = useState(false); const fetchTemplates = async () => { try { // If we didn't have cache, we are already loading. // If we HAD cache, we don't want to set loading=true (flashing skeletons), // we just want to update the data in background. if (templates.length === 0) setLoading(true); const data = await getTemplates(); setTemplates(data || []); } catch (error) { console.error('Failed to fetch templates:', error); toast.error('Failed to load templates'); } finally { setLoading(false); } }; useEffect(() => { fetchTemplates(); }, []); const handleDelete = async () => { if (!deleteId) return; try { setDeleting(true); await deleteTemplate(deleteId); toast.success('Template deleted successfully'); setTemplates(prev => prev.filter(t => t.id !== deleteId)); } catch (error) { console.error('Failed to delete template:', error); toast.error('Failed to delete template'); } finally { setDeleting(false); setDeleteId(null); } }; const filteredTemplates = templates.filter(template => template.name.toLowerCase().includes(searchQuery.toLowerCase()) || template.category.toLowerCase().includes(searchQuery.toLowerCase()) ); const getPriorityColor = (priority: string) => { switch (priority.toLowerCase()) { case 'high': return 'bg-red-100 text-red-700 border-red-200'; case 'medium': return 'bg-orange-100 text-orange-700 border-orange-200'; case 'low': return 'bg-green-100 text-green-700 border-green-200'; default: return 'bg-gray-100 text-gray-700 border-gray-200'; } }; return (

Admin Templates

Manage workflow templates for your organization

setSearchQuery(e.target.value)} />
{loading ? (
{[1, 2, 3].map(i => ( ))}
) : filteredTemplates.length === 0 ? (

No templates found

{searchQuery ? 'Try adjusting your search terms' : 'Get started by creating your first workflow template'}

{!searchQuery && ( )}
) : (
{filteredTemplates.map((template) => (
{template.priority}
{template.name} {template.description}
Category: {template.category}
SLA: {template.suggestedSLA} hours
Approvers: {template.approvers?.length || 0} levels
))}
)} !open && setDeleteId(null)}> Delete Template Are you sure you want to delete this template? This action cannot be undone. Active requests using this template will not be affected. Cancel { e.preventDefault(); handleDelete(); }} className="bg-red-600 hover:bg-red-700" disabled={deleting} > {deleting ? 'Deleting...' : 'Delete'}
); }