@extends('layouts.dashboard') @section('content') @php use App\Models\Order; /** * @var array $orders page of cross-restaurant orders * @var array $pager pagination metadata * @var array $filters active filter values * @var array $restaurants id + name for the restaurant picker * @var array $totals count / gross / refunds / net for the WHOLE filtered set * @var array $refundable payment methods the admin can refund from here */ $filters = $filters ?? []; $restaurants = $restaurants ?? []; $totals = $totals ?? ['count' => 0, 'gross' => 0.0, 'refunds' => 0.0, 'net' => 0.0]; $refundable = $refundable ?? []; $f = static fn (string $k): string => (string) ($filters[$k] ?? ''); $hasFilters = trim(implode('', array_map($f, ['date_from', 'date_to', 'status', 'payment_status', 'q']))) !== '' || (int) ($filters['restaurant_id'] ?? 0) > 0; $statusOpts = ['pending', 'confirmed', 'preparing', 'out_for_delivery', 'delivered', 'cancelled']; $payPill = ['paid' => 'qm-pill-green', 'unpaid' => 'qm-pill-amber', 'refunded' => 'qm-pill-red']; // The filter query the row actions return to, so a refund or cancel fired from // page 3 of a filtered view lands back on page 3 of that same view. $backQuery = http_build_query(array_filter(request()->query(), static fn ($v) => is_scalar($v) && (string) $v !== '')); // Current filters, so the Export link carries the same view the admin is looking at. $qs = http_build_query(array_filter([ 'date_from' => $f('date_from'), 'date_to' => $f('date_to'), 'restaurant_id' => (int) ($filters['restaurant_id'] ?? 0) ?: '', 'status' => $f('status'), 'payment_status' => $f('payment_status'), 'q' => $f('q'), ], static fn ($v) => (string) $v !== '')); @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

{{ t_raw('admin.orders.title') }}

@if (!empty($pager['total'])){{ t_raw('common.count_total', [':count' => (int) $pager['total']]) }}@endif
{{ t_raw('common.export_csv') }}
@php /* Cross-restaurant order filter bar — mirrors the vendor Orders bar. */ @endphp
@partial('filter-collapse')
@php /* What the current filter adds up to across every page, not just the visible one. */ @endphp
{{ t_raw('admin.orders.total_orders') }}{{ number_format((int) $totals['count']) }} {{ t_raw('admin.orders.total_gross') }}{{ money($totals['gross']) }} {{ t_raw('common.refunded') }}{{ (float) $totals['refunds'] > 0 ? '−' . money($totals['refunds']) : money(0) }} {{ t_raw('admin.orders.total_net') }}{{ money($totals['net']) }}
@php /* NOT data-sortable, for the same reason Placed/Completed carry no data-sort: the control must not be offered where it would sort wrongly. qm-sortable-table.js reorders only the rows already in the ("not a substitute for server-side pagination", its own header comment), and this table renders $pager['perPage'] of $pager['total'] — 10 of 3,056. Clicking Total therefore put $44.28 on top and announced aria-sort="descending" while MAX(total) was $389.88, on another page. The controller reads no sort key, so there is nothing to escalate the click to. */ @endphp @if (count($orders)) @foreach ($orders as $o) @php $payStatus = (string) $o['payment_status']; $method = (string) $o['payment_method']; $canRefund = in_array($method, $refundable, true) && $payStatus === 'paid'; $canCancel = in_array('cancelled', Order::transitions()[(string) $o['status']] ?? [], true); @endphp @php /* Payment state is the operator's question ("has this been settled?"); the tender it was taken on rides underneath rather than as a column. */ @endphp @php // Blank until the order actually completes - an order still in the kitchen has no completion time to show. @endphp @endforeach @else @partial('table-empty', ['colspan' => 9, 'icon' => 'fa-receipt', 'msg' => $hasFilters ? t('admin.orders.empty_filtered') : t('admin.orders.empty_none')]) @endif
{{ t_raw('admin.orders.col_order') }}{{ t_raw('nav.restaurants') }}{{ t_raw('common.customer') }}{{ t_raw('admin.orders.col_total') }}{{ t_raw('admin.orders.col_payment') }}{{ t_raw('common.status') }}{{ t_raw('admin.orders.col_placed') }}{{ t_raw('admin.orders.col_completed') }}{{ t_raw('common.actions') }}
{{ $o['order_number'] }} @if (!empty($o['first_item_name'])){{ $o['first_item_name'] }}@if ((int) ($o['item_count'] ?? 0) > 1) {{ t_raw('admin.orders.more_items_suffix', [':count' => (int) $o['item_count'] - 1]) }}@endif@endif
{!! restaurant_brandmark(['logo' => $o['restaurant_logo'] ?? '', 'name' => $o['restaurant_name'] ?? '', 'cuisine_slug' => $o['cuisine_slug'] ?? ''], 'md') !!}
{{ $o['restaurant_name'] }}
{!! brandmark_html($o['customer_avatar'] ?? null, (string) $o['customer_name'], 'md', 'qm-brandmark--round') !!}
{{ $o['customer_name'] }}
{{ money($o['total']) }}
{{ t_raw('status.payment.' . $payStatus) }} @php $pmIco = payment_method_icon($method); echo $pmIco !== '' ? $pmIco : '' . t('status.payment_method.' . $method) . ''; @endphp
{{ Order::statusLabel($o['status'], $o['service_mode'] ?? 'delivery') }} {!! fmt_datetime($o['placed_at']) !!}{!! fmt_datetime($o['completed_at'] ?? null) !!} @partial('row-actions', ['actions' => [ ['label' => t_raw('admin.orders.aria_view_order', [':number' => $o['order_number']]), 'icon' => 'fa-eye', 'href' => '/admin/orders/' . (int) $o['id'], 'primary' => true], !empty($o['track_token']) ? ['label' => t_raw('admin.orders.aria_track', [':number' => $o['order_number']]), 'icon' => 'fa-external-link-alt', 'href' => '/order/' . rawurlencode((string) $o['track_token']) . '/track'] : null, $canRefund ? [ 'label' => t_raw('admin.orders.action_refund'), 'icon' => 'fa-undo', 'form' => [ 'action' => '/admin/orders/refund', 'fields' => ['id' => (int) $o['id'], 'back' => $backQuery], 'confirm' => t_raw('admin.orders.confirm_refund', [':amount' => money($o['total']), ':number' => $o['order_number']]), ], ] : null, $canCancel ? [ 'label' => t_raw('admin.orders.action_cancel'), 'icon' => 'fa-ban', 'danger' => true, 'form' => [ 'action' => '/admin/orders/cancel', 'fields' => ['id' => (int) $o['id'], 'back' => $backQuery], 'confirm' => t_raw('admin.orders.confirm_cancel', [':number' => $o['order_number']]), ], ] : null, ]])
@partial('table-toolbar', ['pager' => $pager, 'base' => '/admin/orders'])
@php /* /.qm-d2 */ @endphp @endsection