@php $stageTone = [ 'prospect' => ['bar' => 'border-t-sky-400', 'badge' => 'sky'], 'contacted' => ['bar' => 'border-t-cyan-400', 'badge' => 'cyan'], 'meeting' => ['bar' => 'border-t-indigo-400', 'badge' => 'indigo'], 'requirement' => ['bar' => 'border-t-violet-400', 'badge' => 'violet'], 'qualified' => ['bar' => 'border-t-fuchsia-400', 'badge' => 'fuchsia'], 'proposal' => ['bar' => 'border-t-amber-400', 'badge' => 'amber'], 'negotiation' => ['bar' => 'border-t-orange-400', 'badge' => 'orange'], 'won' => ['bar' => 'border-t-emerald-400', 'badge' => 'emerald'], 'lost' => ['bar' => 'border-t-rose-400', 'badge' => 'rose'], 'deferred' => ['bar' => 'border-t-slate-400', 'badge' => 'slate'], ]; $viewMeta = [ 'board' => ['label' => __('Board'), 'icon' => 'squares-2x2'], 'list' => ['label' => __('List'), 'icon' => 'queue-list'], ]; $money = fn (array $totals): string => $totals['by_currency'] === [] && $totals['not_estimated'] > 0 ? __('Not estimated') : $baseCode.' '.number_format($totals['base'], 2); $select = 'block w-full rounded-xl border-slate-300 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500'; @endphp
@foreach ($viewMeta as $key => $meta) @endforeach
@if ($canCreate) {{ __('New opportunity') }} @endif
{{-- KPI cards: each opens the matching list. --}}
@foreach ($cards as $key => $m) @endforeach
@include('livewire.crm.opportunities.partials.filters') @if ($view === 'board') {{-- Board --}}
@foreach ($columns as $key => $column)
{{ $column['label'] }} {{ $column['count'] }}

{{ $money($column['totals']) }}

@if (count($column['totals']['by_currency']) > 1)

{{ collect($column['totals']['by_currency'])->map(fn ($v, $c) => $c.' '.number_format($v, 2))->implode(' · ') }}

@endif @if ($column['totals']['not_estimated'] > 0 && $column['totals']['by_currency'] !== [])

{{ trans_choice(':n not estimated|:n not estimated', $column['totals']['not_estimated'], ['n' => $column['totals']['not_estimated']]) }}

@endif
@forelse ($column['items'] as $opp) @php $editable = $canEdit($opp); $overdue = $opp->next_action_due && $opp->next_action_due->lt($today) && $opp->isOpen(); @endphp
{{ $opp->title }}

{{ $opp->customer?->name ?? __('No organisation') }} @if ($opp->customer?->lifecycle === 'prospect') · {{ __('Prospect') }} @endif

@if ($opp->isOpen() && $opp->accepted_at !== null)

{{ __('Accepted, awaiting confirmation') }}

@endif
@if ($opp->estimated_value === null) {{ __('Not estimated') }} @else {{ $opp->currency_code }} {{ number_format((float) $opp->estimated_value, 2) }} @endif {{ $opp->owner?->name ?? __('No owner') }}
@if ($opp->isOpen())

{{ $opp->next_action ?: __('No next action') }} @if ($opp->next_action_due) · {{ $opp->next_action_due->format('j M') }} @endif

@elseif ($opp->reason)

{{ \Illuminate\Support\Str::limit($opp->reason_note ?: str_replace('_', ' ', $opp->reason), 60) }}

@endif @if ($editable) {{-- Keyed on the stage and the dialog, so a cancelled move redraws the old stage. --}} @endif
@empty
{{ __('Nothing at this stage') }}
@endforelse @if ($column['count'] > $column['items']->count()) {{ __('And :n more in the list', ['n' => $column['count'] - $column['items']->count()]) }} @endif
@endforeach
@else {{-- List --}}
@php $lastGroup = null; @endphp @forelse ($rows as $opp) @php $groupKey = match ($group) { 'stage' => \App\Models\Opportunity::STAGES[$opp->stage] ?? $opp->stage, 'owner' => $opp->owner?->name ?? __('No owner'), 'organisation' => $opp->customer?->name ?? __('No organisation'), default => null, }; $editable = $canEdit($opp); $overdue = $opp->next_action_due && $opp->next_action_due->lt($today) && $opp->isOpen(); @endphp @if ($groupKey !== null && $groupKey !== $lastGroup) @php $lastGroup = $groupKey; @endphp @endif @empty @endforelse
{{ __('Opportunity') }} {{ __('Stage') }} {{ __('Owner') }} {{ __('Estimated value') }} {{ __('Next action') }} {{ __('Actions') }}
{{ $groupKey }}
{{ $opp->title }}

{{ $opp->customer?->name ?? __('No organisation') }} · {{ $types[$opp->type] ?? $opp->type }}

@if ($opp->isOpen() && $opp->accepted_at !== null)

{{ __('Accepted, awaiting confirmation') }}

@endif {{-- Wave 4 lead score: nothing shows until scored. --}} @if ($opp->lead_score !== null)

@endif
{{ \App\Models\Opportunity::STAGES[$opp->stage] ?? $opp->stage }} @if ($opp->stage_entered_at)

{{ __(':n days in stage', ['n' => (int) $opp->stage_entered_at->diffInDays(now())]) }}

@endif
{{ $opp->owner?->name ?? __('No owner') }} @if ($opp->originator && $opp->originator_id !== $opp->owner_id)

{{ __('Brought in by :name', ['name' => $opp->originator->name]) }}

@endif
@if ($opp->estimated_value === null) {{ __('Not estimated') }} @else {{ $opp->currency_code }} {{ number_format((float) $opp->estimated_value, 2) }} @endif @if ($opp->isOpen()) {{ $opp->next_action ?: __('No next action') }} @if ($opp->next_action_due) · {{ $opp->next_action_due->format('j M Y') }} @endif @elseif ($opp->stage === 'deferred' && $opp->review_on) {{ __('Review on :date', ['date' => $opp->review_on->format('j M Y')]) }} @else {{ $opp->outcome_at?->format('j M Y') ?? __('Not available') }} @endif
@if ($editable) @endif {{ __('Open') }}
@if ($filtersOn) @else @endif
@if ($rows->hasPages())
{{ $rows->links() }}
@endif
@endif
@include('livewire.crm.opportunities.partials.stage-dialog')