@extends('layouts.admin')
@section('title', 'Edit Campaign — ' . $campaign->name)
@push('styles')
@vite(['resources/css/email-editor.css'])
{{-- Flatpickr (date/time picker) --}}
@endpush
@section('admin')
@include('admin._nav')
@include('admin._partials.breadcrumbs', ['crumbs' => [
['label' => 'Campaigns', 'url' => route('admin.campaigns.index')],
['label' => $campaign->name, 'url' => route('admin.campaigns.show', $campaign)],
['label' => 'Edit'],
]])
{{ $campaign->name }}
Status: {{ $campaign->status }}
@if($campaign->approval_status && $campaign->approval_status !== 'none')
@php $ac = ['pending' => 'amber', 'approved' => 'emerald', 'rejected' => 'red'][$campaign->approval_status] ?? 'gray'; @endphp
· Approval: {{ $campaign->approval_status }}
@endif
@if($campaign->is_quick_send) quick send @endif
{{-- Cross-cutting modal: preview the campaign rendered with a real subscriber's tokens. --}}
@php
$previewSubs = \App\Models\Subscriber::where('status', \App\Models\Subscriber::STATUS_ACTIVE)
->orderByDesc('id')->limit(20)->get(['id','email','first_name']);
@endphp
@include('admin._partials.preview_subscriber_modal', [
'previewUrl' => route('admin.campaigns.preview', $campaign),
'subscribers' => $previewSubs,
])
{{-- ---- Preflight + approval + winner panels (v2) ---- --}}
@php
$preflightSvc = app(\App\Services\EmailPreflightService::class);
$preflightIssues = $preflightSvc->check($campaign);
$preflight = $preflightSvc->summarize($preflightIssues);
$pfErrors = array_values(array_filter($preflightIssues, fn ($i) => $i['level'] === 'error'));
$pfWarnings = array_values(array_filter($preflightIssues, fn ($i) => $i['level'] === 'warning'));
$pfInfos = array_values(array_filter($preflightIssues, fn ($i) => $i['level'] === 'info'));
@endphp
Preflight
{{ $preflight['score'] }}/100
@foreach($pfErrors as $e) {{ $e['message'] }} @endforeach
@foreach($pfWarnings as $w) {{ $w['message'] }} @endforeach
@foreach($pfInfos as $i) {{ $i['message'] }} @endforeach
@if(empty($pfErrors) && empty($pfWarnings))
All checks passed.
@endif
Approval workflow
@if($campaign->approval_status === 'approved')
Approved by user #{{ $campaign->approved_by }} {{ $campaign->approved_at?->diffForHumans() }}.
@elseif($campaign->approval_status === 'pending')
Awaiting approval. Review and decide on the campaign page →
@elseif($campaign->approval_status === 'rejected')
Rejected. {{ $campaign->approval_notes }}
@else
@endif
A/B winner
@if(! $campaign->subject_b)
No B variant configured.
@elseif($campaign->winner_variant)
Variant {{ $campaign->winner_variant }} selected
@if($campaign->winner_metric)({{ $campaign->winner_metric }})@endif.
@else
@endif
@if(session('success'))
{{ session('success') }}
@endif
@if(session('error'))
{{ session('error') }}
@endif
@php $approvalLocked = $campaign->approval_status === 'pending'; @endphp
@if($approvalLocked)
This campaign is locked for review.
A reviewer must approve or reject this draft before further edits or scheduling. Saves are blocked while pending.
@endif
@if($campaign->approval_status === 'rejected' && $campaign->approval_notes)
Reviewer rejected this draft.
"{{ $campaign->approval_notes }}"
Make changes and submit again from the campaign page .
@endif
{{-- AI generate-whole-email modal --}}
✨ Generate email with AI
✕
Describe the email you want. Claude will draft a complete, on-brand design (hero, scripture, body, CTA) and load it into the canvas. Replaces the current canvas — your existing design will be lost.
Brief / prompt
Replace current canvas (uncheck to append)
Also generate subject + preheader
Hero image
Smart — match a Library image; generate one if none fits
Use Media Library only
Generate a fresh image (Nano Banana)
No hero image
Generated images are auto-saved to the Media Library tagged ai-generated.
🎨 Style options
⏳ Drafting your email — this can take 20–90 seconds (longer when generating a hero image)…
Cancel
Generate
{{-- Replace-with-template modal --}}
{{-- Block library drawer --}}
🧱 Block Library
Click a block to insert it at the bottom of the canvas.
✕
@endsection
@push('scripts')
@vite(['resources/js/unlayer-editor.js'])
@php
$brandKitJson = \App\Models\BrandKit::current()->only(['primary_color','secondary_color','accent_color','text_color','background_color','body_font','heading_font','logo_url','company_name']);
$unlayerProjectId = config('services.unlayer.project_id');
@endphp
{{-- Flatpickr + timezone helper for the schedule row --}}
@endpush