@extends('layouts.dashboard') @section('content') @php /** * Platform Analytics → Sales: marketplace money across every restaurant — * collected revenue over time, by tender, sales channel, service mode and hour, * with the seats each dine-in ticket filled. * * @var array $revenue @var array $paidOrders @var array $placed @var array $discounts * @var array $tips @var array $refunds @var array $aov @var array $perHead * @var int $coversTotal @var array $seated @var array $seatWait * @var array $byMode @var array $channelRows * @var array $operators @var array $operatorsPager @var array $topRest @var array $restPager * @var array $revChart @var array $revMeta @var array $channelChart @var array $channelMeta * @var array $hourChart @var array $hourMeta @var array $lossChart @var array $lossMeta * @var array $tenderChart @var array $tenderMeta @var array $sourceChart @var array $sourceMeta * @var array $perHeadChart @var array $perHeadMeta * @var int $rangeDays @var string $rangeMode @var array $rangeLinks */ $kpiMeta = static fn (array $m, string $caption): string => kpi_trend((int) $m['pct'], (string) $m['dir']) . '' . $caption . ''; @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

{{ t_raw('dashboard.sec.snapshot') }}

{{ t_raw('admin.analytics.sales_sub') }}

@foreach ($rangeLinks['options'] as $val => $text) @php $on = ((string) $val === $rangeLinks['selected']); @endphp {{ $text }} @endforeach
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'green', 'icon' => 'fa-coins', 'label' => t_raw('common.revenue'), 'value' => money($revenue['total']), 'spark' => $revenue['cur'], 'meta' => $kpiMeta($revenue, t('admin.analytics.meta_vs_prior'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'blue', 'icon' => 'fa-receipt', 'label' => t_raw('common.paid_orders'), 'value' => number_format($paidOrders['total']), 'href' => route('admin.orders'), 'spark' => $paidOrders['cur'], 'meta' => $kpiMeta($paidOrders, t('admin.analytics.meta_of_n_placed', [':n' => number_format($placed['total'])]))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'violet', 'icon' => 'fa-chart-line', 'label' => t_raw('common.average_order'), 'value' => money($aov['total']), 'spark' => $aov['cur'], 'meta' => $kpiMeta($aov, t('admin.analytics.meta_per_paid_order'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'teal', 'icon' => 'fa-user-friends', 'label' => t_raw('admin.analytics.kpi_spend_per_head'), 'value' => $perHead['total'] > 0 ? money($perHead['total']) : "\u{2014}", 'spark' => $perHead['cur'], 'meta' => $perHead['total'] > 0 ? $kpiMeta($perHead, t('admin.analytics.meta_across_n_covers', [':n' => number_format($coversTotal)])) : '' . t('admin.analytics.meta_no_covers_recorded') . '']) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'amber', 'icon' => 'fa-tags', 'label' => t_raw('admin.analytics.kpi_discounts_given'), 'value' => money($discounts['total']), 'href' => route('admin.analytics.promotions'), 'spark' => $discounts['cur'], 'meta' => $kpiMeta($discounts, t('admin.analytics.meta_coupons_rewards'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'orange', 'icon' => 'fa-hand-holding-usd', 'label' => t_raw('admin.analytics.kpi_tips'), 'value' => money($tips['total']), 'spark' => $tips['cur'], 'meta' => $kpiMeta($tips, t('admin.analytics.meta_on_paid_orders'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'slate', 'icon' => 'fa-undo', 'label' => t_raw('common.refunded'), 'value' => money($refunds['total']), 'spark' => $refunds['cur'], 'meta' => $kpiMeta($refunds, t('admin.analytics.meta_returned_to_customers'))])

{{ t_raw('dashboard.sec.trends') }}

@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_revenue_over_time'), 'sub' => t_raw('admin.analytics.chart_revenue_over_time_caption'), 'cfg' => $revChart, 'meta' => $revMeta, 'accent' => 'green', 'opts' => ['id' => 'admSalesRevChart', 'url' => route('admin.chart-series', ['chart' => 'salesRev']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_channel_mix'), 'sub' => t_raw('admin.analytics.chart_channel_mix_caption'), 'cfg' => $channelChart, 'meta' => $channelMeta, 'icon' => 'fa-stream', 'accent' => 'blue', 'opts' => ['id' => 'admSalesChannelChart', 'url' => route('admin.chart-series', ['chart' => 'salesChannel']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_revenue_by_hour'), 'sub' => t_raw('admin.analytics.chart_when_money_made'), 'cfg' => $hourChart, 'meta' => $hourMeta, 'icon' => 'fa-th', 'accent' => 'rose'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_leakage'), 'sub' => t_raw('admin.analytics.chart_leakage_caption'), 'cfg' => $lossChart, 'meta' => $lossMeta, 'icon' => 'fa-undo', 'accent' => 'amber', 'opts' => ['id' => 'admSalesLossChart', 'url' => route('admin.chart-series', ['chart' => 'salesLoss']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])

{{ t_raw('dashboard.sec.breakdown') }}

@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_takings_by_tender'), 'sub' => t_raw('admin.analytics.chart_net_of_refunds'), 'cfg' => $tenderChart, 'meta' => $tenderMeta, 'icon' => 'fa-chart-pie', 'accent' => 'blue'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_revenue_by_channel'), 'sub' => t_raw('admin.analytics.chart_revenue_by_channel_caption'), 'cfg' => $sourceChart, 'meta' => $sourceMeta, 'icon' => 'fa-chart-pie', 'accent' => 'violet'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_spend_per_head_by_mode'), 'sub' => t_raw('admin.analytics.chart_spend_per_head_caption'), 'cfg' => $perHeadChart, 'meta' => $perHeadMeta, 'icon' => 'fa-user-friends', 'accent' => 'teal'])

{{ t_raw('admin.analytics.h_channel_performance') }}

@if ($channelRows) @foreach ($channelRows as $row) @php $paid = (int) $row['paid_orders']; @endphp @endforeach @else @partial('table-empty', ['colspan' => 6, 'icon' => 'fa-stream', 'msg' => t('admin.analytics.empty_no_orders_period')]) @endif
{{ t_raw('admin.analytics.caption_channels') }}
{{ t_raw('admin.analytics.col_channel') }} {{ t_raw('common.orders') }} {{ t_raw('admin.analytics.col_collected') }} {{ t_raw('common.average_order') }} {{ t_raw('common.covers') }} {{ t_raw('admin.analytics.col_last_order') }}
{{ status_label('order_source', $row['source']) }} {{ number_format((int) $row['orders_c']) }} {{ money($row['revenue']) }} {!! $paid > 0 ? money((float) $row['revenue'] / $paid) : dash() !!} {!! (int) $row['covers'] > 0 ? number_format((int) $row['covers']) : dash() !!} {!! fmt_day($row['last_order']) !!}
@php /* The tip rides inside the heading: a .d-flex wrapper around an h2 is tightened to 8px by the density standard (app.css §35), which left this table 8px closer to its title than Channel performance's beside it. A bare h2 wears the same 16px as its neighbour, so the two cards share one rhythm with no extra rules. */ @endphp

{{ t_raw('admin.analytics.h_service_modes') }}

@if ($byMode) @foreach ($byMode as $m) @endforeach @else @partial('table-empty', ['colspan' => 4, 'icon' => 'fa-chart-bar', 'msg' => t('admin.analytics.empty_no_orders_period')]) @endif
{{ t_raw('admin.analytics.caption_modes') }}
{{ t_raw('admin.analytics.col_mode') }} {{ t_raw('common.orders') }} {{ t_raw('admin.analytics.col_collected') }} {{ t_raw('admin.analytics.kpi_spend_per_head') }}
{{ $m['label'] }} {{ number_format((int) $m['orders']) }} {{ money($m['revenue']) }} {!! (int) $m['covers'] > 0 ? money($m['revenue'] / (int) $m['covers']) : dash() !!}

{{ t_raw('admin.dashboard.chart_top_restaurants_title') }}

{{ t_raw('nav.restaurants') }}
@if ($topRest) @foreach ($topRest as $t) @php $c = (int) $t['orders_c']; @endphp @endforeach @else @partial('table-empty', ['colspan' => 7, 'icon' => 'fa-store', 'msg' => t('admin.analytics.empty_no_orders_period')]) @endif
{{ t_raw('admin.analytics.caption_top_rest_by_revenue') }}
{{ t_raw('common.restaurant') }} {{ t_raw('common.orders') }} {{ t_raw('admin.analytics.col_collected') }} {{ t_raw('common.average_order') }} {{ t_raw('common.covers') }} {{ t_raw('common.commission') }} {{ t_raw('admin.analytics.col_last_order') }}
{!! restaurant_logo_html($t, 'md') !!}
{{ $t['name'] }}@if (!empty($t['city'])){{ $t['city'] }}@endif
{{ number_format($c) }} {{ money($t['collected']) }} {!! $c > 0 ? money((float) $t['collected'] / $c) : dash() !!} {!! (int) $t['covers'] > 0 ? number_format((int) $t['covers']) : dash() !!} {!! (float) $t['commission'] > 0 ? money($t['commission']) : dash() !!} {!! fmt_day($t['last_order']) !!}
@partial('table-toolbar', ['pager' => $restPager, 'base' => '/admin/analytics/sales'])

{{ t_raw('admin.analytics.h_cash_handling') }}

{{ t_raw('nav.users') }}
@if ($operators) @foreach ($operators as $op) @endforeach @else @partial('table-empty', ['colspan' => 6, 'icon' => 'fa-cash-register', 'msg' => t('admin.analytics.empty_no_operators')]) @endif
{{ t_raw('admin.analytics.caption_cash_handling') }}
{{ t_raw('admin.analytics.col_taken_by') }} {{ t_raw('admin.analytics.col_captures') }} {{ t_raw('admin.analytics.col_taken') }} {{ t_raw('common.refunded') }} {{ t_raw('nav.restaurants') }} {{ t_raw('common.when') }}
{!! brandmark_html($op['avatar'] ?? null, (string) $op['name'], 'md', 'qm-brandmark--round') !!}
{{ $op['name'] }}{{ role_label((string) $op['role']) }}
{{ number_format((int) $op['captures']) }} {{ money($op['taken']) }} {!! (float) $op['refunded'] > 0 ? money($op['refunded']) : dash() !!} {{ number_format((int) $op['restaurants_c']) }} {!! fmt_datetime($op['last_seen']) !!}
@partial('table-toolbar', ['pager' => $operatorsPager, 'base' => '/admin/analytics/sales'])
@php /* /.qm-d2 */ @endphp @endsection