import React, { useState, useEffect, useRef } from 'react'; import { Card, CardContent, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { useNavigate } from 'react-router-dom'; import { Search, ChevronDown, ArrowUpDown, Edit, Lightbulb, PencilLine, ShoppingCart, ShoppingBag, PartyPopper, Mail, ChevronRight, ChevronLeft } from 'lucide-react'; interface Workflow { id: number; name: string; lastRanAt: string; openRate: string; clickRate: string; status: 'Active' | 'Not Active' | 'Draft'; isActive: boolean; } const WorkflowList: React.FC = () => { const navigate = useNavigate(); const [searchTerm, setSearchTerm] = useState(''); const [selectedList, setSelectedList] = useState('All'); const [selectedStatus, setSelectedStatus] = useState('All'); const [currentPage, setCurrentPage] = useState(1); // Start with page 1 as default const [sortBy, setSortBy] = useState<'lastRanAt' | null>(null); const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc'); const [showListDropdown, setShowListDropdown] = useState(false); const [showStatusDropdown, setShowStatusDropdown] = useState(false); const [selectedWorkflowIds, setSelectedWorkflowIds] = useState>(new Set()); const [isAllSelected, setIsAllSelected] = useState(false); const listDropdownRef = useRef(null); const statusDropdownRef = useRef(null); const [allWorkflows, setAllWorkflows] = useState([ // Page 1 workflows { id: 1, name: 'Subscriber: Confirmation email', lastRanAt: '5 min ago', openRate: '24%', clickRate: '12.5%', status: 'Not Active', isActive: false }, { id: 2, name: 'Cart: Abandoned cart email with coupon', lastRanAt: '10 hrs ago', openRate: '40.8%', clickRate: '10.3%', status: 'Active', isActive: true }, { id: 3, name: 'Send welcome email when someone subscribes', lastRanAt: '1 day ago', openRate: '0.0', clickRate: '0.0', status: 'Draft', isActive: false }, { id: 4, name: 'Send confirmation email', lastRanAt: '3 days ago', openRate: '50.2%', clickRate: '15.8%', status: 'Not Active', isActive: false }, { id: 5, name: 'Notify admin when someone subscribes', lastRanAt: '7 days ago', openRate: '38.7%', clickRate: '9.4%', status: 'Draft', isActive: false }, // Page 2 workflows { id: 6, name: 'Welcome series for new customers', lastRanAt: '2 hours ago', openRate: '35.2%', clickRate: '18.7%', status: 'Active', isActive: true }, { id: 7, name: 'Product recommendation email', lastRanAt: '5 hours ago', openRate: '28.5%', clickRate: '14.2%', status: 'Not Active', isActive: false }, { id: 8, name: 'Birthday discount workflow', lastRanAt: '12 hours ago', openRate: '45.3%', clickRate: '22.1%', status: 'Active', isActive: true }, { id: 9, name: 'Post-purchase follow-up', lastRanAt: '2 days ago', openRate: '32.8%', clickRate: '16.4%', status: 'Draft', isActive: false }, { id: 10, name: 'Newsletter subscription confirmation', lastRanAt: '4 days ago', openRate: '41.7%', clickRate: '19.3%', status: 'Active', isActive: true }, // Page 3 workflows { id: 11, name: 'Seasonal promotion campaign', lastRanAt: '1 hour ago', openRate: '52.1%', clickRate: '26.8%', status: 'Active', isActive: true }, { id: 12, name: 'Feedback request workflow', lastRanAt: '6 hours ago', openRate: '29.4%', clickRate: '12.7%', status: 'Draft', isActive: false }, { id: 13, name: 'Win-back campaign for inactive users', lastRanAt: '8 hours ago', openRate: '18.9%', clickRate: '8.5%', status: 'Not Active', isActive: false }, { id: 14, name: 'VIP customer exclusive offers', lastRanAt: '1 day ago', openRate: '67.3%', clickRate: '34.2%', status: 'Active', isActive: true }, { id: 15, name: 'Account verification reminder', lastRanAt: '3 days ago', openRate: '43.6%', clickRate: '21.8%', status: 'Draft', isActive: false } ]); // Close dropdowns when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (listDropdownRef.current && !listDropdownRef.current.contains(event.target as Node)) { setShowListDropdown(false); } if (statusDropdownRef.current && !statusDropdownRef.current.contains(event.target as Node)) { setShowStatusDropdown(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); // Filter and search workflows const filteredWorkflows = allWorkflows.filter(workflow => { // Search filter const matchesSearch = workflow.name.toLowerCase().includes(searchTerm.toLowerCase()); // Status filter const matchesStatus = selectedStatus === 'All' || workflow.status === selectedStatus; // List filter (for now, we'll keep it simple - could be extended) const matchesList = selectedList === 'All' || true; // You can extend this logic return matchesSearch && matchesStatus && matchesList; }); // Apply sorting const sortedWorkflows = [...filteredWorkflows]; if (sortBy === 'lastRanAt') { sortedWorkflows.sort((a, b) => { // Convert time strings to comparable values for sorting const timeToMinutes = (timeStr: string) => { if (timeStr.includes('min ago')) { return parseInt(timeStr); } else if (timeStr.includes('hrs ago')) { return parseInt(timeStr) * 60; } else if (timeStr.includes('hour ago')) { return parseInt(timeStr) * 60; } else if (timeStr.includes('day ago') || timeStr.includes('days ago')) { return parseInt(timeStr) * 24 * 60; } return 0; }; const aTime = timeToMinutes(a.lastRanAt); const bTime = timeToMinutes(b.lastRanAt); return sortOrder === 'asc' ? aTime - bTime : bTime - aTime; }); } // Pagination const itemsPerPage = 5; const totalPages = Math.ceil(sortedWorkflows.length / itemsPerPage); const startIndex = (currentPage - 1) * itemsPerPage; const endIndex = startIndex + itemsPerPage; const paginatedWorkflows = sortedWorkflows.slice(startIndex, endIndex); // Interactive handlers const handleToggleWorkflow = (id: number) => { // Update the allWorkflows state by toggling the isActive property setAllWorkflows(prevWorkflows => prevWorkflows.map(workflow => workflow.id === id ? { ...workflow, isActive: !workflow.isActive, status: !workflow.isActive ? 'Active' : 'Not Active' as 'Active' | 'Not Active' | 'Draft' } : workflow ) ); }; const handleSort = (field: 'lastRanAt') => { if (sortBy === field) { setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc'); } else { setSortBy(field); setSortOrder('desc'); } }; const handlePageChange = (page: number) => { if (page >= 1 && page <= totalPages) { setCurrentPage(page); } }; const handlePreviousPage = () => { if (currentPage > 1) { setCurrentPage(currentPage - 1); } }; const handleNextPage = () => { if (currentPage < totalPages) { setCurrentPage(currentPage + 1); } }; // Checkbox handlers const handleSelectAll = (checked: boolean) => { if (checked) { const allIds = new Set(paginatedWorkflows.map(workflow => workflow.id)); setSelectedWorkflowIds(allIds); setIsAllSelected(true); } else { setSelectedWorkflowIds(new Set()); setIsAllSelected(false); } }; const handleSelectWorkflow = (id: number) => { const newSelected = new Set(selectedWorkflowIds); if (newSelected.has(id)) { newSelected.delete(id); } else { newSelected.add(id); } setSelectedWorkflowIds(newSelected); setIsAllSelected(newSelected.size === paginatedWorkflows.length && paginatedWorkflows.length > 0); }; // Update isAllSelected when paginatedWorkflows changes useEffect(() => { const allCurrentIds = paginatedWorkflows.map(workflow => workflow.id); const allSelected = allCurrentIds.length > 0 && allCurrentIds.every(id => selectedWorkflowIds.has(id)); setIsAllSelected(allSelected); }, [paginatedWorkflows, selectedWorkflowIds]); const listOptions = ['All', 'Active', 'Inactive']; const statusOptions = ['All', 'Active', 'Not Active', 'Draft']; const prebuiltWorkflows = [ { title: 'Build Workflow From Scratch', icon: PencilLine, color: '#5e19cf', isPro: false }, { title: 'Abandoned Cart', icon: ShoppingCart, color: '#0a0a0a', isPro: true }, { title: 'Product Purchase', icon: ShoppingBag, color: '#0a0a0a', isPro: false }, { title: 'Welcome Series', icon: PartyPopper, color: '#0a0a0a', isPro: false, emailCount: 3 } ]; const getStatusColor = (status: string) => { switch (status) { case 'Active': return 'text-green-600'; case 'Not Active': return 'text-red-600'; case 'Draft': return 'text-blue-600'; default: return 'text-gray-500'; } }; const getStatusIcon = (status: string) => { if (status === 'Active') { return (
); } else if (status === 'Not Active') { return (
); } else { return (
); } }; return (
{/* Header */}

Workflows

Automate tasks at any stage. Set it up once, and let it run—simple, smart, and scalable.

{/* Preview Section */}

Preview a popular pre-built workflow

{/* Divider */}
{/* Info Banner */}
You're on the Free Plan. Enjoy a preview of pre-built customer workflows— upgrade to launch them.
{/* Workflow Templates */}
{prebuiltWorkflows.map((workflow, index) => { const IconComponent = workflow.icon; return (
{workflow.title}
{/* Pro Badge */} {workflow.isPro && (
Pro
)} {/* Email Count Badge */} {workflow.emailCount && (
{workflow.emailCount}
)} ); })}
{/* Browse Templates Button */}
{/* Recent Workflows Section */}

Recent Workflows

Page {currentPage}
{/* Search and Filter Controls */}
setSearchTerm(e.target.value)} className="w-full h-9 pl-10 pr-3 bg-white border border-neutral-200 rounded-lg text-sm text-neutral-950 placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-[#5e19cf] focus:border-transparent shadow-sm" />
{/* Lists Dropdown */}
{showListDropdown && (
{listOptions.map((option) => ( ))}
)}
{/* Status Dropdown */}
{showStatusDropdown && (
{statusOptions.map((option) => ( ))}
)}
{/* Data Table */}
{/* Desktop Table Header - Hidden on mobile */}
Flow
Open Rate
Click Rate
Status
Action
{/* Mobile Header - Visible only on mobile */}
Select All
{/* Table Rows */} {paginatedWorkflows.map((workflow: Workflow) => (
{/* Desktop Row Layout */}
handleSelectWorkflow(workflow.id)} className="border-neutral-400 data-[state=checked]:bg-primary data-[state=checked]:border-primary" />
{workflow.name}
{workflow.lastRanAt}
{workflow.openRate}
{workflow.clickRate}
{getStatusIcon(workflow.status)} {workflow.status}
{workflow.status === 'Draft' ? ( ) : (
)}
{/* Mobile Row Layout */}
handleSelectWorkflow(workflow.id)} className="border-neutral-400 data-[state=checked]:bg-primary data-[state=checked]:border-primary mt-0.5" />

{workflow.name}

{getStatusIcon(workflow.status)} {workflow.status}
{workflow.status === 'Draft' ? ( ) : ( )}
Last ran:

{workflow.lastRanAt}

Open Rate:

{workflow.openRate}

Click Rate:

{workflow.clickRate}

))}
{/* Pagination - Position inside Recent workflows section */}
Showing {(currentPage - 1) * itemsPerPage + 1} to {Math.min(currentPage * itemsPerPage, sortedWorkflows.length)} of {sortedWorkflows.length} results
); }; export default WorkflowList;