@extends('layouts.admin') @section('title','Abandoned checkouts') @section('content') @php $columns = [ 'customer' => 'Customer', 'cart' => 'Cart', 'value' => 'Value', 'step' => 'Drop-off', 'stage' => 'Sequence', 'channel' => 'Channel', 'status' => 'Status', 'activity' => 'Activity', 'actions' => 'Actions', ]; $label = fn (string $v) => ucwords(str_replace('_', ' ', $v)); $statusTone = fn (string $s) => match ($s) { 'open' => 'warning', 'emailed' => 'info', 'recovered' => 'success', 'suppressed', 'expired' => 'muted', default => 'muted', }; $stepLabel = fn (?string $s) => match ($s) { 'contact' => 'Contact', 'shipping' => 'Shipping', 'payment' => 'Payment', default => 'Unknown', }; $activeChips = collect([ 'status' => request('status'), 'last_step' => request('last_step'), 'country' => request('country'), 'recovery_stage' => request('recovery_stage'), 'from' => request('from'), 'to' => request('to'), 'sort' => request('sort') && request('sort') !== 'newest' ? request('sort') : null, ])->filter(); @endphp Due now ({{ number_format($stats['due_now']) }})
@csrf
Export CSV Settings & emails
@if(session('status'))
{{ session('status') }}
@endif @unless($autoEnabled)
Automatic recovery emails are turned off. Checkouts are still captured, and you can email customers manually. Turn on
@endunless
Active pipeline {{ number_format($stats['open']) }} Open + emailed
Recoverable value AUD {{ number_format($stats['recoverable_value_cents'] / 100, 0) }} Still in sequence
Recovered {{ number_format($stats['recovered']) }} AUD {{ number_format($stats['recovered_value_cents'] / 100, 0) }} won back
Recovery rate {{ number_format($stats['recovery_rate'], 1) }}% {{ number_format($stats['emails_sent']) }} emails sent
Due now {{ number_format($stats['due_now']) }} Ready for next touch Clicked email {{ number_format($stats['clicked']) }} {{ number_format($stats['discount_recoveries']) }} recovered with a discount
@foreach([ ['label' => 'All', 'params' => []], ['label' => 'Active', 'params' => ['status' => 'active']], ['label' => 'Due now', 'params' => ['status' => 'due']], ['label' => 'Payment drop-off', 'params' => ['last_step' => 'payment', 'status' => 'active']], ['label' => 'Clicked email', 'params' => ['status' => 'clicked']], ['label' => 'Recovered', 'params' => ['status' => 'recovered']], ['label' => 'Suppressed', 'params' => ['status' => 'suppressed']], ] as $chip) @php $isActive = collect($chip['params'])->every(fn ($v, $k) => request($k) === $v) && (empty($chip['params']) ? ! request()->hasAny(['status', 'last_step', 'country', 'recovery_stage']) : true); @endphp {{ $chip['label'] }} @endforeach
@if($activeChips->isNotEmpty())
Active @foreach($activeChips as $key => $value) {{ $label($key) }}: {{ $label((string) $value) }} @endforeach Clear all
@endif
Select checkouts, then send each one the next email in its sequence. Customer Cart Value Drop-off Sequence Channel Status Activity @forelse($abandoned as $row) @if($row->isRecoverable()) @endif {{ $row->customer_name ?: ($row->email ?: 'Guest (no email)') }} @if($row->customer_name && $row->email)
{{ $row->email }}
@endif
{{ collect([$row->phone, $row->country])->filter()->implode(' · ') ?: '—' }} @if($row->customer_id) · Customer #{{ $row->customer_id }} @endif
@php $preview = collect($row->line_preview ?? []); @endphp
{{ $preview->first()['title'] ?? ($row->checkout?->lines[0]['title'] ?? 'Empty cart') }}
{{ $row->line_count }} {{ $row->line_count === 1 ? 'item' : 'items' }} · Checkout #{{ $row->checkout_id }}
{{ $row->labeledTotal() }} {{ $stepLabel($row->last_step) }}
@foreach(array_keys($steps) as $stepNumber) {{ $stepNumber }} @endforeach
@if(! $row->isActive()) {{ $row->recovery_emails_sent }} {{ \Illuminate\Support\Str::plural('email', $row->recovery_emails_sent) }} sent @elseif($row->next_email_at) Next {{ $row->next_email_at->isPast() ? 'due now' : $row->next_email_at->diffForHumans() }} @else Sequence complete @endif
@if($row->discount_code)
{{ $row->discount_code }}
@endif @if($row->click_count)
Clicked {{ $row->click_count }}×
@endif
{{ $row->utm_source ?: ($row->source ?: 'direct') }}
@if($row->utm_campaign)
{{ $row->utm_campaign }}
@endif {{ $label($row->status) }}
Abandoned {{ ($row->abandoned_at ?? $row->created_at)?->diffForHumans() }}
@if($row->last_emailed_at)
Emailed {{ $row->last_emailed_at->diffForHumans() }}
@endif
Open @if($row->isRecoverable())
@csrf
@endif
@empty No abandoned checkouts match these filters. @endforelse
{{ $abandoned->links() }}
@endsection