@extends('layouts.dashboard') @section('content') @php /** * Platform Analytics → Customers: who is ordering across the platform — * first-timers vs regulars, guest checkouts, how well each intake month is * retained, and the customers who matter most. * * @var array $active @var array $newAccounts @var array $newCustomers @var array $returning * @var array $guestOrders @var array $guestShare @var array $orders * @var array $bandRows @var array $top @var array $topPager * @var array $dayChart @var array $dayMeta @var array $mixChart @var array $mixMeta * @var array $cohortChart @var array $cohortMeta @var array $bandChart @var array $bandMeta * @var array $splitChart @var array $splitMeta @var array $guestChart @var array $guestMeta * @var array $spendChart @var array $spendMeta * @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 . ''; $activeCount = max(1, (int) $active['total']); $totalBandCustomers = 0; foreach ($bandRows as $bandRow) { $totalBandCustomers += (int) $bandRow['customers']; } @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

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

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

@foreach ($rangeLinks['options'] as $val => $text) @php $on = ((string) $val === $rangeLinks['selected']); @endphp {{ $text }} @endforeach
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'blue', 'icon' => 'fa-users', 'label' => t_raw('nav.customers'), 'value' => number_format($active['total']), 'spark' => $active['cur'], 'meta' => $kpiMeta($active, t('admin.analytics.meta_account_holders'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'teal', 'icon' => 'fa-user-plus', 'label' => t_raw('admin.analytics.kpi_new_accounts'), 'value' => number_format($newAccounts['total']), 'href' => route('admin.users'), 'spark' => $newAccounts['cur'], 'meta' => $kpiMeta($newAccounts, t('admin.analytics.meta_registered_in_period'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'green', 'icon' => 'fa-user-check', 'label' => t_raw('admin.analytics.kpi_new_customers'), 'value' => number_format($newCustomers['total']), 'spark' => $newCustomers['cur'], 'meta' => $kpiMeta($newCustomers, t('admin.analytics.meta_first_order_period'))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'amber', 'icon' => 'fa-redo', 'label' => t_raw('common.returning'), 'value' => number_format($returning['total']), 'spark' => $returning['cur'], 'meta' => $kpiMeta($returning, t('admin.analytics.meta_pct_of_customers', [':pct' => number_format($returning['total'] / $activeCount * 100)]))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'orange', 'icon' => 'fa-user-secret', 'label' => t_raw('common.guest_orders'), 'value' => number_format($guestOrders['total']), 'spark' => $guestOrders['cur'], 'meta' => $kpiMeta($guestOrders, t('admin.analytics.meta_pct_of_orders', [':pct' => number_format($guestShare['total'])]))]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'violet', 'icon' => 'fa-shopping-basket', 'label' => t_raw('common.orders'), 'value' => number_format($orders['total']), 'href' => route('admin.orders'), 'spark' => $orders['cur'], 'meta' => $kpiMeta($orders, t('admin.analytics.meta_vs_prior'))])

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

@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_customers_per_day'), 'sub' => t_raw('admin.analytics.chart_customers_per_day_caption'), 'cfg' => $dayChart, 'meta' => $dayMeta, 'accent' => 'blue', 'opts' => ['id' => 'admCustDayChart', 'url' => route('admin.chart-series', ['chart' => 'custDay']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_account_vs_guest'), 'sub' => t_raw('admin.analytics.chart_account_vs_guest_caption'), 'cfg' => $mixChart, 'meta' => $mixMeta, 'icon' => 'fa-user-secret', 'accent' => 'violet', 'opts' => ['id' => 'admCustMixChart', 'url' => route('admin.chart-series', ['chart' => 'custMix']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_cohort_retention'), 'sub' => t_raw('admin.analytics.chart_cohort_retention_caption'), 'cfg' => $cohortChart, 'meta' => $cohortMeta, 'icon' => 'fa-th', 'accent' => 'teal'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_order_frequency'), 'sub' => t_raw('admin.analytics.chart_order_frequency_caption'), 'cfg' => $bandChart, 'meta' => $bandMeta, 'icon' => 'fa-chart-bar', 'accent' => 'green'])

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

@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_new_vs_returning'), 'sub' => t_raw('admin.analytics.chart_new_vs_returning_caption'), 'cfg' => $splitChart, 'meta' => $splitMeta, 'icon' => 'fa-chart-pie', 'accent' => 'green'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_revenue_by_identity'), 'sub' => t_raw('admin.analytics.chart_revenue_by_identity_caption'), 'cfg' => $guestChart, 'meta' => $guestMeta, 'icon' => 'fa-chart-pie', 'accent' => 'violet'])
@partial('chart-card', ['heading' => t_raw('admin.analytics.chart_top_customers_by_spend'), 'sub' => t_raw('admin.analytics.chart_top_customers_caption'), 'cfg' => $spendChart, 'meta' => $spendMeta, 'icon' => 'fa-chart-bar', 'accent' => 'amber', 'opts' => ['id' => 'admCustSpendChart', 'url' => route('admin.chart-series', ['chart' => 'custSpend']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])

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

@if ($totalBandCustomers > 0) @foreach ($bandRows as $row) @php $n = (int) $row['customers']; @endphp @endforeach @else @partial('table-empty', ['colspan' => 6, 'icon' => 'fa-layer-group', 'msg' => t('admin.analytics.empty_no_customer_orders')]) @endif
{{ t_raw('admin.analytics.caption_order_frequency') }}
{{ t_raw('admin.analytics.col_band') }} {{ t_raw('nav.customers') }} {{ t_raw('admin.analytics.col_share') }} {{ t_raw('common.orders') }} {{ t_raw('admin.analytics.col_spend') }} {{ t_raw('common.average_order') }}
{{ $row['label'] }} {{ number_format($n) }} {!! $n > 0 ? number_format($n / $totalBandCustomers * 100, 1) . '%' : dash() !!} {!! (int) $row['orders'] > 0 ? number_format((int) $row['orders']) : dash() !!} {!! (float) $row['spend'] > 0 ? money($row['spend']) : dash() !!} {!! (int) $row['orders'] > 0 ? money((float) $row['spend'] / (int) $row['orders']) : dash() !!}

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

{{ t_raw('nav.users') }}
@if ($top) @foreach ($top as $t) @php $c = (int) $t['orders_c']; @endphp @endforeach @else @partial('table-empty', ['colspan' => 6, 'icon' => 'fa-users', 'msg' => t('admin.analytics.empty_no_customer_orders')]) @endif
{{ t_raw('admin.analytics.caption_best_customers') }}
{{ t_raw('common.customer') }} {{ t_raw('common.orders') }} {{ t_raw('admin.analytics.col_spend') }} {{ t_raw('common.average_order') }} {{ t_raw('nav.restaurants') }} {{ t_raw('admin.analytics.col_last_order') }}
{!! brandmark_html($t['avatar'] ?? null, (string) $t['name'], 'md', 'qm-brandmark--round') !!}
{{ $t['name'] }}{{ $t['email'] }}
{{ number_format($c) }} {{ money($t['spend']) }} {!! $c > 0 ? money((float) $t['spend'] / $c) : dash() !!} {{ number_format((int) $t['restaurants_c']) }} {{ t_raw('admin.analytics.ordered_from_suffix') }} {!! fmt_day($t['last_order']) !!}
@partial('table-toolbar', ['pager' => $topPager, 'base' => '/admin/analytics/customers'])
@php /* /.qm-d2 */ @endphp @endsection