{{-- Visual Flow Builder -- Single-page three-panel layout Left: Config/Details panel (w-80) Center: Visual flow canvas (flex-1) Right: Add Node panel (w-64) All wire:click / wire:model bindings target existing WorkflowBuilder.php methods & properties. --}} @php // ── Icon SVG path data (reused across canvas nodes AND the left panel) ── $triggerIconPaths = [ 'email_received' => '', 'contact_created' => '', 'contact_updated' => '', 'deal_stage_changed'=> '', 'tag_added' => '', 'tag_removed' => '', 'form_submitted' => '', 'webhook_received' => '', 'scheduled' => '', 'campaign_opened' => '', 'campaign_clicked' => '', ]; $subtypeIcons = [ 'send_email' => '', 'send_notification' => '', 'add_tag' => '', 'remove_tag' => '', 'update_contact' => '', 'assign_agent' => '', 'create_deal' => '', 'move_deal' => '', 'wait_delay' => '', 'webhook_call' => '', 'ai_reply' => '', 'if_else' => '', 'has_tag' => '', 'contact_field' => '', 'email_opened' => '', 'email_clicked' => '', 'add_to_group' => '', 'remove_from_group' => '', 'in_group' => '', ]; // Short descriptions for the right-panel add-node cards $actionDescriptions = [ 'send_email' => __('Compose and send an email'), 'send_notification' => __('Alert via email, Slack, or in-app'), 'add_tag' => __('Attach a tag to the contact'), 'remove_tag' => __('Detach a tag from the contact'), 'update_contact' => __('Change a contact field value'), 'assign_agent' => __('Route to a team member'), 'create_deal' => __('Open a new deal in pipeline'), 'move_deal' => __('Advance a deal to next stage'), 'wait_delay' => __('Pause before the next step'), 'webhook_call' => __('Send data to an external app via Webhook'), 'ai_reply' => __('Generate a reply with AI'), 'add_to_group' => __('Add contact to a group'), 'remove_from_group' => __('Remove contact from a group'), ]; $conditionDescriptions = [ 'if_else' => __('Branch on a field value'), 'has_tag' => __('Check if contact has a tag'), 'contact_field' => __('Evaluate a contact property'), 'email_opened' => __('Was the email opened?'), 'email_clicked' => __('Was a link clicked?'), 'in_group' => __('Check if contact is in a group'), ]; $currentTriggerIcon = $triggerIconPaths[$triggerType] ?? ''; @endphp
{{-- ================================================================== --}} {{-- TOP BAR --}} {{-- ================================================================== --}}
{{-- Left: back + inline name --}}
{{-- Center: node count badge --}} {{-- Right: actions --}}
{{-- Undo / Redo --}}
{{-- Toggle right panel --}}
{{-- Validation errors banner --}} @if($errors->any())
{{ $errors->first() }} @if($errors->count() > 1) (+{{ $errors->count() - 1 }} more) @endif
@endif {{-- ================================================================== --}} {{-- THREE-PANEL BODY --}} {{-- ================================================================== --}}
{{-- ============================================================== --}} {{-- LEFT SIDEBAR: Config / Details Panel --}} {{-- ============================================================== --}} {{-- ============================================================== --}} {{-- CENTER: Visual Flow Canvas --}} {{-- ============================================================== --}}
{{-- ================================================== --}} {{-- TRIGGER NODE --}} {{-- ================================================== --}}
@if($triggerType)
Trigger
{!! $currentTriggerIcon !!}

When

{{ $triggerTypes[$triggerType] ?? $triggerType }}

@else {{-- No trigger selected --}}

{{ __('Start with a trigger') }}

Choose what starts this workflow using the Trigger dropdown in the left panel

{{ __('Left panel') }}
@endif
{{-- Connector from trigger --}}
{{-- ================================================== --}} {{-- EMPTY STATE (no nodes yet) --}} {{-- ================================================== --}} @if(count($nodes) === 0)

{{ __('What should happen next?') }}

Click any action from the right panel to add your first step, like sending an email or tagging a contact.

{{ __('Pick from the panel on the right') }} or
{{-- Connector to end --}}
@endif {{-- ================================================== --}} {{-- NODE LIST --}} {{-- ================================================== --}} @foreach($nodes as $index => $node) @php $isDelay = str_contains($node['subtype'] ?? '', 'wait') || str_contains($node['subtype'] ?? '', 'delay'); $isCondition = $node['type'] === 'condition'; $isEditing = $editingNodeIndex === $index; if ($isCondition) { $nc = [ 'border' => 'border-l-yellow-400', 'ring' => 'ring-yellow-400', 'iconBg' => 'bg-warning/10', 'iconTx' => 'text-yellow-600', 'badge' => 'bg-warning/15 text-warning', 'label' => __('Condition'), ]; } elseif ($isDelay) { $nc = [ 'border' => 'border-l-purple-400', 'ring' => 'ring-purple-400', 'iconBg' => 'bg-brand/10', 'iconTx' => 'text-purple-600', 'badge' => 'bg-brand/15 text-brand', 'label' => __('Delay'), ]; } else { $nc = [ 'border' => 'border-l-green-400', 'ring' => 'ring-green-400', 'iconBg' => 'bg-success/10', 'iconTx' => 'text-success', 'badge' => 'bg-success/15 text-success', 'label' => __('Action'), ]; } $iconSvg = $subtypeIcons[$node['subtype']] ?? ''; $nodeName = $node['type'] === 'action' ? ($actionSubtypes[$node['subtype']] ?? $node['subtype']) : ($conditionSubtypes[$node['subtype']] ?? $node['subtype']); // Build human-readable config summary $configSummary = ''; $cfg = $node['config'] ?? []; switch ($node['subtype']) { case 'send_email': if (!empty($cfg['subject'])) $configSummary = 'Subject: ' . Str::limit($cfg['subject'], 30); break; case 'send_notification': $ch = !empty($cfg['channel']) ? ucfirst($cfg['channel']) : ''; $msg = !empty($cfg['message']) ? Str::limit($cfg['message'], 25) : ''; $configSummary = implode(' - ', array_filter([$ch, $msg])); break; case 'add_tag': case 'remove_tag': case 'has_tag': if (!empty($cfg['tag_name'])) $configSummary = 'Tag: ' . $cfg['tag_name']; break; case 'add_to_group': case 'remove_from_group': case 'in_group': if (!empty($cfg['group_id'])) { $grp = $contactGroups->firstWhere('id', $cfg['group_id']); $configSummary = 'Group: ' . ($grp ? $grp->name : '#' . $cfg['group_id']); } break; case 'wait_delay': if (!empty($cfg['duration'])) $configSummary = $cfg['duration'] . ' ' . ($cfg['unit'] ?? 'hours'); break; case 'if_else': case 'contact_field': $parts = array_filter([ !empty($cfg['field']) ? $cfg['field'] : null, !empty($cfg['operator']) ? str_replace('_', ' ', $cfg['operator']) : null, !empty($cfg['value']) ? '"' . Str::limit($cfg['value'], 15) . '"' : null, ]); $configSummary = implode(' ', $parts); break; case 'update_contact': if (!empty($cfg['field'])) $configSummary = ucfirst(str_replace('_', ' ', $cfg['field'])) . (!empty($cfg['value']) ? ' = ' . Str::limit($cfg['value'], 15) : ''); break; case 'webhook_call': if (!empty($cfg['url'])) $configSummary = ($cfg['method'] ?? 'POST') . ' ' . Str::limit($cfg['url'], 25); break; case 'ai_reply': if (!empty($cfg['instructions'])) $configSummary = Str::limit($cfg['instructions'], 35); break; case 'email_opened': case 'email_clicked': if (!empty($cfg['within_hours'])) $configSummary = 'Within ' . $cfg['within_hours'] . 'h'; break; case 'assign_agent': $configSummary = !empty($cfg['round_robin']) && $cfg['round_robin'] ? 'Round robin' : (!empty($cfg['agent_id']) ? $cfg['agent_id'] : ''); break; default: $parts = []; foreach ($cfg as $cv) { if (!empty($cv) && is_string($cv)) $parts[] = Str::limit($cv, 28); } $configSummary = implode(' / ', array_slice($parts, 0, 2)); } @endphp {{-- Node Card --}}
{{-- Icon --}}
@safeSvg($iconSvg)
{{-- Name + summary --}}
{{ $nc['label'] }} #{{ $index + 1 }}

{{ $nodeName }}

@if($isEditing)

{{ __('Editing in left panel') }}

@elseif($configSummary)

{{ $configSummary }}

@else

{{ __('Click to configure') }}

@endif
{{-- Hover action buttons --}}
@if($index > 0) @endif @if($index < count($nodes) - 1) @endif
{{-- Connector + "+" add button between nodes --}}
{{-- Plus button (grows on hover for better click target) --}}
{{-- Inline add-node dropdown --}}
@endforeach {{-- ================================================== --}} {{-- END NODE --}} {{-- ================================================== --}}
{{ __('End') }}
{{-- ============================================================== --}} {{-- RIGHT SIDEBAR: Add Node Panel --}} {{-- ============================================================== --}}
{{-- end .flex.flex-1 --}} {{-- Undo / Redo toast notification --}} {{-- ================================================================== --}} {{-- GUIDED MODE OVERLAY --}} {{-- ================================================================== --}} @if($showGuidedMode)
{{-- Backdrop --}}
{{-- Modal panel --}}
{{-- Header --}}

{{ $guidedStep === 1 ? __('Choose a Template') : __('Customise Template') }}

{{ $guidedStep === 1 ? __('Pick a pre-built workflow to get started quickly') : __('Adjust the details before creating your workflow') }}

{{-- Step indicator --}}
1 {{ __('Select') }}
2 {{ __('Customise') }}
{{-- Body --}}
{{-- ============================== --}} {{-- STEP 1: Template Grid --}} {{-- ============================== --}} @if($guidedStep === 1)
@foreach($templates as $tpl) @php $isSelected = $selectedTemplate === $tpl['id']; $categoryColors = [ 'email' => 'bg-info/15 text-info', 'crm' => 'bg-success/15 text-success', 'contacts' => 'bg-brand/15 text-brand', ]; $catClass = $categoryColors[$tpl['category']] ?? 'bg-surface text-muted'; @endphp @endforeach
{{-- ============================== --}} {{-- STEP 2: Customise --}} {{-- ============================== --}} @elseif($guidedStep === 2 && $selectedTemplate) @php $tpl = collect($templates)->firstWhere('id', $selectedTemplate); @endphp @if($tpl)
{{-- Template summary --}}

{{ $tpl['name'] }}

{{ $tpl['description'] }}

{{-- Flow preview --}}
@foreach($tpl['nodes'] as $nodeIndex => $tplNode) @php $nodeTypeColors = match($tplNode['type']) { 'trigger' => ['bg' => 'bg-brand/10', 'text' => 'text-brand', 'border' => 'border-brand/20', 'badge' => 'bg-brand/15 text-brand'], 'condition' => ['bg' => 'bg-warning/10', 'text' => 'text-warning', 'border' => 'border-warning/20', 'badge' => 'bg-warning/15 text-warning'], default => ['bg' => 'bg-success/10', 'text' => 'text-success', 'border' => 'border-success/20', 'badge' => 'bg-success/15 text-success'], }; @endphp
{{ $nodeIndex + 1 }}
@if($nodeIndex < count($tpl['nodes']) - 1)
@endif
{{ ucfirst($tplNode['type']) }}

{{ $tplNode['config']['label'] ?? ucfirst(str_replace('_', ' ', $tplNode['subtype'])) }}

@endforeach
{{-- Editable name and description --}}
@endif @endif
{{-- Footer --}}
@if($guidedStep === 2) @endif
@endif
{{-- end root --}}