Skip to content

Visual Journey Mapping

A lightweight visual journey mapping system for Vellocity. This feature helps marketing and alliance managers visualize GTM workflows, partner co-sell journeys, and agent execution paths.

Overview

The visual journey mapping system consists of:

Components

  1. <x-journey-map> - Simple linear journey visualization
  2. <x-journey-map-swimlane> - Advanced swimlane layout with groups
  3. <x-journey-node> - Card-based node for individual steps
  4. <x-journey-connector> - SVG connectors between nodes
  5. <x-journey-visualize-button> - Button/icon to trigger visualization
  6. <x-icons.journey-visualize> - SVG icon variants

PHP Support

  • HasJourneyVisualization - Trait for models to generate journey data
  • JourneyPresets - Pre-built journey configurations

Quick Start

Simple Linear Journey

{{-- Using preset type --}}
<x-journey-map type="gtm-campaign" :current="2" />

{{-- With model data --}}
<x-journey-map :stages="$coSellPlan->getJourneyStages()" />

Enhanced Swimlane Journey

{{-- Using preset --}}
@php
    use App\Support\JourneyPresets;
@endphp

<x-journey-map-swimlane
    :groups="JourneyPresets::gtmCampaign(currentStep: 4)"
    title="Q1 Product Launch"
    :collaborators="[
        ['name' => 'Sarah', 'initials' => 'SK'],
        ['name' => 'Mike', 'initials' => 'MJ'],
    ]"
/>

{{-- With model data --}}
<x-journey-map-swimlane
    :groups="$coSellPlan->getJourneyGroups()"
    :title="$coSellPlan->getJourneyTitle()"
    :collaborators="$coSellPlan->getJourneyCollaborators()"
/>

Visualize Button

{{-- Icon button --}}
<x-journey-visualize-button type="gtm-campaign" />

{{-- Menu item --}}
<x-journey-visualize-button
    type="partner-cosell"
    variant="menu-item"
    label="View Partner Journey"
/>

{{-- Progress badge --}}
<x-journey-visualize-button
    :stages="$execution->getJourneyStages()"
    variant="badge"
/>

Components Reference

<x-journey-map-swimlane>

Advanced journey visualization with stage groups (swim lanes), card nodes, and assignees.

Props

Prop Type Default Description
groups array [] Array of group objects with stages
title string null Journey title
subtitle string null Journey subtitle
size string md Size: sm, md, lg
interactive bool false Enable expandable nodes
showAssignees bool true Show assignee avatars
showDescriptions bool true Show stage descriptions
layout string horizontal horizontal (groups as columns) or vertical (groups as rows)
collaborators array [] Team avatars shown in header

Group Object Structure

[
    'id' => 'strategy',              // Unique group identifier
    'label' => 'Strategy Phase',     // Group header label
    'color' => 'purple',             // Optional: purple, blue, green, amber
    'stages' => [
        [
            'id' => 'define_goals',
            'label' => 'Define Goals',
            'icon' => 'tabler-target',
            'description' => 'Set campaign objectives',
            'status' => 'completed',  // completed, current, pending, failed, skipped
            'assignee' => [
                'name' => 'Sarah Kim',
                'initials' => 'SK',
                'avatar' => '/path/to/avatar.jpg',  // Optional
                'type' => 'user',  // user or ai
            ],
            'cta' => 'Start',  // Call-to-action button text
            'metadata' => [    // Additional info for expanded view
                'Due' => 'Jan 15',
                'Priority' => 'High',
            ],
        ],
        // ... more stages
    ],
]

<x-journey-node>

Individual journey node card with status indicators and assignee.

<x-journey-node
    :stage="[
        'id' => 'review',
        'label' => 'Review Content',
        'icon' => 'tabler-eye',
        'status' => 'current',
        'assignee' => ['name' => 'Sarah', 'initials' => 'SK'],
    ]"
    size="md"
    :show-assignee="true"
    :interactive="true"
/>

<x-journey-connector>

SVG connectors between nodes.

<x-journey-connector type="horizontal" status="completed" />
<x-journey-connector type="vertical" status="current" :animated="true" />
<x-journey-connector type="branch-down" status="pending" :dashed="true" />

Connector Types: - horizontal - Simple horizontal arrow - vertical - Simple vertical arrow - corner-down-right - Corner going down then right - corner-down-left - Corner going down then left - branch-right - Branch splitting right - branch-down - Branch splitting down - merge-right - Merge from below - parallel-down - Two parallel vertical lines - step-down - Short vertical connector

<x-journey-map>

Simple linear journey visualization (original component).

Props

Prop Type Default Description
stages array null Array of stage objects
type string null Preset type: gtm-campaign, partner-cosell, agent-workflow, cosell-wizard
current int\|string null Current stage index (0-based) or stage id
variant string horizontal Layout variant: horizontal or vertical
size string md Size: sm, md, lg
interactive bool false Enable click-to-expand details

Journey Presets

Pre-built journey configurations in App\Support\JourneyPresets.

GTM Campaign

use App\Support\JourneyPresets;

// Basic usage
$groups = JourneyPresets::gtmCampaign(currentStep: 3);

// With custom assignees
$groups = JourneyPresets::gtmCampaign(
    currentStep: 3,
    assignees: [
        'define_goals' => ['name' => 'Sarah', 'initials' => 'SK'],
        'create_messaging' => ['name' => 'Content Team', 'initials' => 'CT'],
    ]
);

Stages: Strategy (3) → Content Creation (3) → Launch (2) → Measurement (3) = 11 total

Partner Co-Sell

$groups = JourneyPresets::partnerCoSell(
    currentStep: 5,
    partners: [
        'partner_a' => ['name' => 'Acme Corp', 'initials' => 'AC'],
        'partner_b' => ['name' => 'TechCo', 'initials' => 'TC'],
    ]
);

Stages: Discovery (3) → Joint Planning (3) → Execution (4) → Results (2) = 12 total

Agent Workflow

// Default workflow
$groups = JourneyPresets::agentWorkflow(currentStep: 2);

// From actual execution plan
$groups = JourneyPresets::agentWorkflow(
    steps: $execution->execution_plan,
    currentStep: $execution->current_step
);

Marketplace Launch

$groups = JourneyPresets::marketplaceLaunch(currentStep: 4);

Stages: Preparation (2) → Asset Creation (2) → Promotion (3) = 7 total


Model Integration

Using the Trait

use App\Traits\HasJourneyVisualization;

class Campaign extends Model
{
    use HasJourneyVisualization;

    // Simple linear journey
    protected function getJourneyDefinition(): array
    {
        return [
            ['id' => 'draft', 'label' => 'Draft', 'icon' => 'tabler-file'],
            ['id' => 'review', 'label' => 'Review', 'icon' => 'tabler-eye'],
            ['id' => 'published', 'label' => 'Published', 'icon' => 'tabler-check'],
        ];
    }

    protected function getJourneyCurrentIndex(): ?int
    {
        return match($this->status) {
            'draft' => 0,
            'review' => 1,
            'published' => 2,
            default => null,
        };
    }

    // Optional: Grouped journey for swimlane
    protected function getJourneyGroupsDefinition(): array
    {
        return [
            [
                'id' => 'creation',
                'label' => 'Content Creation',
                'color' => 'blue',
                'stages' => [
                    [
                        'id' => 'write',
                        'label' => 'Write Content',
                        'assignee' => $this->makeJourneyAssignee($this->author),
                    ],
                    [
                        'id' => 'generate_images',
                        'label' => 'Generate Images',
                        'assignee' => $this->makeAIAssignee(),
                    ],
                ],
            ],
            // ... more groups
        ];
    }

    // Optional: Collaborators for header
    protected function defineJourneyCollaborators(): array
    {
        return $this->team->members->map(fn($m) =>
            $this->makeJourneyAssignee($m->user)
        )->toArray();
    }
}

Available Methods

// Simple journey
$stages = $model->getJourneyStages();          // For <x-journey-map>
$title = $model->getJourneyTitle();
$progress = $model->getJourneyProgressPercent(); // 0-100

// Grouped journey
$groups = $model->getJourneyGroups();           // For <x-journey-map-swimlane>
$collaborators = $model->getJourneyCollaborators();

// Status helpers
$isComplete = $model->isJourneyComplete();
$hasStarted = $model->hasJourneyStarted();
$current = $model->getCurrentJourneyStage();
$next = $model->getNextJourneyStage();
$total = $model->getJourneyTotalStages();
$completed = $model->getJourneyCompletedStages();

// Assignee helpers
$assignee = $model->makeJourneyAssignee($user);
$aiAssignee = $model->makeAIAssignee('Content Agent');

Examples

Dashboard Widget with Swimlane

<div class="bg-white rounded-xl shadow-sm border p-6">
    <x-journey-map-swimlane
        :groups="JourneyPresets::gtmCampaign($campaign->current_step)"
        :title="$campaign->name"
        :collaborators="$campaign->team_members"
        size="sm"
        layout="vertical"
    />
</div>

Co-Sell Plan Page

<div class="space-y-6">
    {{-- Header with visualize button --}}
    <div class="flex items-center justify-between">
        <h1 class="text-2xl font-bold">{{ $coSellPlan->name }}</h1>
        <x-journey-visualize-button
            :stages="$coSellPlan->getJourneyStages()"
            variant="button"
            label="View Full Journey"
        />
    </div>

    {{-- Inline progress --}}
    <x-journey-map
        :stages="$coSellPlan->getJourneyStages()"
        size="sm"
    />
</div>

Agent Execution Monitor

<div class="bg-gray-50 rounded-xl p-6">
    <x-journey-map-swimlane
        :groups="JourneyPresets::agentWorkflow(
            steps: $execution->execution_plan ?? [],
            currentStep: $execution->current_step
        )"
        :title="$execution->agent->name . ' Workflow'"
        :subtitle="'Started ' . $execution->started_at->diffForHumans()"
        interactive
    />
</div>

List Item with Badge

@foreach($campaigns as $campaign)
    <div class="flex items-center justify-between p-4 border-b">
        <div>
            <h4 class="font-medium">{{ $campaign->name }}</h4>
            <p class="text-sm text-gray-500">{{ $campaign->type_label }}</p>
        </div>
        <x-journey-visualize-button
            :stages="$campaign->getJourneyStages()"
            variant="badge"
        />
    </div>
@endforeach

Styling

Brand Colors

The components use Vellocity's purple brand palette: - Primary: #330582 - Accent: #9333ea

Status Colors

Status Color Use
completed Emerald (green) Finished stages
current Purple Active stage
pending Gray Future stages
failed Red Error state
skipped Light gray Bypassed stages

Group Colors

Available colors for swimlane groups: purple, blue, green, amber

Dark Mode

All components support dark mode via Tailwind's dark: variants.


Files Reference

File Purpose
resources/views/components/journey-map.blade.php Simple linear journey
resources/views/components/journey-map-swimlane.blade.php Advanced swimlane layout
resources/views/components/journey-node.blade.php Individual node card
resources/views/components/journey-connector.blade.php SVG connectors
resources/views/components/journey-visualize-button.blade.php Trigger button
resources/views/components/icons/journey-visualize.blade.php Icon variants
app/Traits/HasJourneyVisualization.php Model trait
app/Support/JourneyPresets.php Pre-built journeys