@extends('layouts.app') @section('head') {{-- Kitchen wall-tablet board: kept live by a JS auto-refresh (the orderFeed Alpine component at the bottom of the feed) instead of , so the reload PAUSES while an order card is expanded. location.reload() is still a full page load, so the new-order overlay keeps working against localStorage. --}} @endsection @section('styles') @endsection @section('content') @php $latestPlatform = $latest ? config('delivery.platforms.' . ($latest->integration?->tool ?? ''), []) : []; $latestDisplay = $latest ? (data_get($latest->payload, 'display_id') ?: ('#' . substr($latest->order_id, 0, 8))) : ''; $branchNote = session('selected_pos_note') ?: (session('selected_pos_service_id') ? __('Selected business') : __('No business selected')); // Compact money formatter (mirrors orders/show) for the expanded card content. $money = fn($m) => is_array($m) ? ($m['formatted_amount'] ?? (isset($m['amount']) ? number_format(((int) $m['amount']) / 100, 2) . ' ' . ($m['currency_code'] ?? '') : '-')) : '-'; @endphp
{{-- HEADER --}}

{{ __('Live Order Feed') }}

{{ $isHistory ? $orders->total() : $orders->count() }}
{{ __('Orders') }}

{{ $branchNote }} · {{ __('All integrations') }} · {{ $isHistory ? __('Older than 60 minutes') : __('Last 60 minutes') }} @if ($isHistory) · {{ __($activeStatus) }} @endif

{{-- LIVE ORDER FEED (single column, large type, click-to-expand accordion) --}}
@forelse ($orders as $order) @php $platform = config('delivery.platforms.' . ($order->integration?->tool ?? ''), []); $status = (string) ($order->status ?? ''); $stateUpper = strtoupper($status); $badge = match (true) { in_array($stateUpper, ['READY_FOR_PICKUP', 'FINISHED', 'COMPLETED', 'DELIVERED'], true) => 'bg-green-100 text-green-700 ring-green-300', in_array($stateUpper, ['ACCEPTED'], true) => 'bg-green-100 text-green-700 ring-green-300', in_array($stateUpper, ['PREPARING', 'IN_PROGRESS'], true) => 'bg-blue-100 text-blue-700 ring-blue-300', in_array($stateUpper, ['DENIED', 'CANCELED', 'CANCELLED'], true) => 'bg-red-100 text-red-700 ring-red-300', in_array($stateUpper, ['CREATED', 'PLACED'], true) => 'bg-amber-100 text-amber-700 ring-amber-300', str_contains(strtolower($status), 'cancel') => 'bg-red-100 text-red-700 ring-red-300', $status === '' => 'bg-amber-100 text-amber-700 ring-amber-300', default => 'bg-blue-100 text-blue-700 ring-blue-300', }; // Left stripe now reflects the ORDER STATUS colour family (not the // platform colour) at full strength. Derived from $badge so the two // never drift apart; inline hex keeps it working in the compiled build. $stripeFamily = preg_match('/bg-([a-z]+)-100/', $badge, $m) ? $m[1] : 'stone'; $stripeColor = match ($stripeFamily) { 'green' => '#22c55e', 'red' => '#ef4444', 'amber' => '#f59e0b', 'blue' => '#3b82f6', default => '#a8a29e', }; $display = data_get($order->payload, 'display_id') ?: ('#' . substr($order->order_id, 0, 8)); $store = $order->integration?->posAccess?->note ?? ($order->pos_service_id ? __('Business #:id', ['id' => $order->pos_service_id]) : ($order->store_id ? substr($order->store_id, 0, 8) . '…' : '-')); // Kitchen lifecycle: a new order is accepted/denied, an accepted // (PREPARING) order is marked ready for pickup or cancelled. $isNew = in_array($stateUpper, ['CREATED', 'PLACED', ''], true); $isPreparing = in_array($stateUpper, ['PREPARING', 'ACCEPTED'], true); $items = data_get($order->payload, 'cart.items') ?? []; $charges = data_get($order->payload, 'payment.charges') ?? []; $eater = data_get($order->payload, 'eater') ?? []; $acceptConfirm = __('This order will be ACCEPTED on Uber Eats. Are you sure?'); $denyConfirm = __('This order will be DENIED on Uber Eats. Are you sure?'); $readyConfirm = __('This order will be marked READY for pickup. Are you sure?'); $cancelConfirm = __('This order will be CANCELLED. Are you sure?'); @endphp
{{-- Clickable header row: toggles the accordion --}} {{-- Expandable order content --}}
{{-- Cart --}}

restaurant {{ __('Cart (:count items)', ['count' => count($items)]) }}

@if (count($items) > 0)
    @foreach ($items as $item)
  • {{ data_get($item, 'title') ?? data_get($item, 'id') ?? '-' }}
    @if (data_get($item, 'special_instructions'))

    “{{ data_get($item, 'special_instructions') }}”

    @endif @foreach (data_get($item, 'selected_modifier_groups') ?? [] as $group) @php $selected = data_get($group, 'selected_items') ?? []; @endphp @if (count($selected) > 0)

    {{ data_get($group, 'title') }}: {{ collect($selected)->map(fn($s) => trim((data_get($s, 'title') ?? '') . (data_get($s, 'quantity', 1) > 1 ? ' ×' . data_get($s, 'quantity') : '')))->filter()->implode(', ') }}

    @endif @endforeach
    × {{ data_get($item, 'quantity', 1) }}
    {{ $money(data_get($item, 'price.total_price')) }}
  • @endforeach
@else

{{ __('No cart detail — the order may not be enriched (raw webhook payload).') }}

@endif
{{-- Summary + quick actions --}}
{{ __('Customer') }}
{{ data_get($eater, 'first_name') ?: '-' }}
@if (data_get($eater, 'phone'))
{{ data_get($eater, 'phone') }}
@endif
{{ __('Total') }} {{ $money(data_get($charges, 'total')) }}
@if ($isNew) {{-- New order: accept or deny --}}
@csrf
@csrf
@elseif ($isPreparing) {{-- Preparing: mark ready for pickup or cancel --}}
@csrf
@csrf
@else

{!! __('This order is in :status state — accept/deny cannot be applied.', ['status' => '' . e(__($stateUpper)) . '']) !!}

@endif open_in_new {{ __('View details') }} print {{ __('Print') }}
@empty
local_shipping

{{ __('No orders match this filter.') }}

{{ !session('selected_pos_service_id') ? __('Select a business first.') : ($isHistory ? __('Older than 60 minutes') : __('New orders will appear here live.')) }}

@endforelse @if ($isHistory)
{{ $orders->links() }}
@endif {{-- Centered confirm modal — replaces the native confirm() for accept/deny/ready/cancel. Driven by the feed Alpine root; the triggering form is submitted only after the big confirm button is pressed (form.submit() bypasses @submit.prevent, so no re-entry). --}}
help_outline

{{-- FULL-SCREEN NEW-ORDER ALERT (revealed by JS when a newer order landed) --}} @if ($latest) @endif @endsection @section('scripts') @endsection