@extends('layouts.dashboard') @section('content') @php /** * Operation Analytics → Operations: how smoothly the restaurant runs — fulfilment * speed, cancellations, the channels orders arrive through, the staffing clock, * waste and drawer accuracy. * * @var array $kpis @var array $fulChart @var array $fulMeta @var array $cxChart @var array $cxMeta * @var array $dowChart @var array $dowMeta @var array $chanChart @var array $chanMeta * @var array $modeChart @var array $modeMeta @var array $heatChart @var array $heatMeta * @var array $chanRows @var array $chanPager @var array $waste @var array $wastePager * @var array $shifts @var array $shiftPager * @var int $rangeDays @var array $rangeLinks @var bool $showMoney */ @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

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

{{ t_raw('vendor.analytics.subtitle_operations') }}

@foreach ($rangeLinks['options'] as $val => $text) @php $on = ((string) $val === $rangeLinks['selected']); @endphp {{ $text }} @endforeach
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'blue', 'icon' => 'fa-stopwatch', 'label' => t_raw('vendor.analytics.kpi_avg_fulfilment'), 'value' => $kpis['fulfilment']['value'] ?? '—', 'spark' => $kpis['fulfilment']['spark'], 'meta' => $kpis['fulfilment']['meta']]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'rose', 'icon' => 'fa-ban', 'label' => t_raw('vendor.analytics.kpi_cancellations'), 'value' => number_format($kpis['cancels']['value']), 'spark' => $kpis['cancels']['spark'], 'meta' => $kpis['cancels']['meta']]) @php /* A no-show COUNT says nothing without the bookings behind it, so the headline is the rate and the caption carries the raw figures. */ @endphp @partial('kpi-card', ['variant' => 'panel', 'accent' => 'amber', 'icon' => 'fa-user-slash', 'label' => t_raw('vendor.analytics.kpi_no_show_rate'), 'value' => $kpis['noShow']['value'] !== null ? number_format($kpis['noShow']['value'], 1) . '%' : '—', 'spark' => $kpis['noShow']['spark'], 'meta' => $kpis['noShow']['meta']]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'violet', 'icon' => 'fa-tablet-alt', 'label' => t_raw('vendor.analytics.kpi_self_service'), 'value' => $kpis['selfServe']['value'] !== null ? number_format($kpis['selfServe']['value'], 1) . '%' : '—', 'spark' => $kpis['selfServe']['spark'], 'meta' => $kpis['selfServe']['meta']]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'teal', 'icon' => 'fa-user-friends', 'label' => t_raw('vendor.analytics.kpi_covers'), 'value' => $kpis['covers']['value'] > 0 ? number_format($kpis['covers']['value']) : '—', 'spark' => $kpis['covers']['spark'], 'meta' => $kpis['covers']['meta']]) @if ($showMoney) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'slate', 'icon' => 'fa-wallet', 'label' => t_raw('vendor.analytics.kpi_drawer_variance'), 'value' => ($kpis['drawer']['value'] == 0.0 ? t_raw('vendor.analytics.balanced_label') : ($kpis['drawer']['value'] > 0 ? '+' : '−') . money(abs($kpis['drawer']['value']))), 'meta' => $kpis['drawer']['meta']]) @endif

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

@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_fulfilment_speed'), 'sub' => t_raw('vendor.analytics.chart_avg_min_per_day_sub'), 'cfg' => $fulChart, 'meta' => $fulMeta, 'accent' => 'blue', 'opts' => ['id' => 'opsFulChart', 'url' => route('vendor.chart-series', ['chart' => 'opsFulfil']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_cancellations_per_day'), 'sub' => t_raw('vendor.analytics.chart_cancellations_caption'), 'cfg' => $cxChart, 'meta' => $cxMeta, 'icon' => 'fa-chart-bar', 'accent' => 'rose', 'opts' => ['id' => 'opsCxChart', 'url' => route('vendor.chart-series', ['chart' => 'opsCancels']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_busiest_weekdays'), 'sub' => t_raw('vendor.analytics.chart_orders_by_day_sub'), 'cfg' => $dowChart, 'meta' => $dowMeta, 'icon' => 'fa-chart-bar', 'accent' => 'violet'])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_order_channels'), 'sub' => t_raw('vendor.analytics.chart_order_channels_sub'), 'cfg' => $chanChart, 'meta' => $chanMeta, 'icon' => 'fa-chart-pie', 'accent' => 'blue'])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.heading_service_modes'), 'sub' => t_raw('vendor.analytics.chart_service_modes_sub'), 'cfg' => $modeChart, 'meta' => $modeMeta, 'icon' => 'fa-chart-pie', 'accent' => 'teal'])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_staffing_clock'), 'sub' => t_raw('vendor.analytics.chart_staffing_clock_sub'), 'cfg' => $heatChart, 'meta' => $heatMeta, 'icon' => 'fa-th', 'accent' => 'blue'])

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

{{ t_raw('vendor.analytics.heading_channel_performance') }}

{{ t_raw('vendor.analytics.hint_channel_performance') }}

@if ($chanRows) @foreach ($chanRows as $c) @php /* Terminals counts the distinct kiosks that produced these orders; at-table counts the orders raised against a seated table. */ @endphp @endforeach @else @partial('table-empty', ['colspan' => 7, 'icon' => 'fa-random', 'msg' => t_raw('vendor.analytics.empty_no_orders_period')]) @endif
{{ t_raw('vendor.analytics.caption_channel_performance') }}
{{ t_raw('vendor.analytics.col_channel') }} {{ t_raw('common.orders') }} {{ t_raw('vendor.analytics.col_avg_minutes') }} {{ t_raw('vendor.analytics.kpi_cancellations') }} {{ t_raw('vendor.analytics.kpi_covers') }} {{ t_raw('vendor.analytics.col_terminals') }} {{ t_raw('vendor.analytics.col_at_table') }}
{{ $c['label'] }} {{ number_format($c['orders']) }} {!! $c['avg_minutes'] !== null ? number_format($c['avg_minutes']) . ' ' . t('common.min') : dash() !!} @if ($c['cancelled'] > 0) {{ t_raw('vendor.analytics.pill_cancelled_rate', [':n' => number_format($c['cancelled']), ':pct' => number_format($c['cancel_rate'] ?? 0, 1)]) }} @else{{ t_raw('vendor.analytics.pill_none_cancelled') }}@endif {!! $c['covers'] > 0 ? number_format($c['covers']) : dash() !!}{!! $c['terminals'] > 0 ? number_format($c['terminals']) : dash() !!} {!! $c['at_table'] > 0 ? number_format($c['at_table']) : dash() !!}
@partial('table-toolbar', ['pager' => $chanPager, 'base' => '/vendor/analytics/operations'])

{{ t_raw('vendor.analytics.heading_kitchen_waste') }}

{{ t_raw('nav.inventory') }}
@if ($waste) @foreach ($waste as $w) @endforeach @else @partial('table-empty', ['colspan' => 3, 'icon' => 'fa-boxes', 'msg' => t_raw('vendor.analytics.empty_no_waste')]) @endif
{{ t_raw('vendor.analytics.caption_waste') }}
{{ t_raw('vendor.analytics.col_stock_item') }}{{ t_raw('vendor.analytics.col_wasted') }}{{ t_raw('vendor.analytics.col_entries') }}
{{ $w['name'] }} {{ rtrim(rtrim(number_format((float) $w['qty'], 2, '.', ''), '0'), '.') }} {{ $w['unit'] }} {{ (int) $w['times'] }}
@partial('table-toolbar', ['pager' => $wastePager, 'base' => '/vendor/analytics/operations', 'showPager' => false])

{{ t_raw('vendor.analytics.heading_drawer_sessions') }}

{{ t_raw('vendor.dashboard.cash_drawer_label') }}
@if ($showMoney)@endif @if ($shifts) @foreach ($shifts as $s) @php $v = (float) ($s['variance'] ?? 0); @endphp @if ($showMoney) @endif @endforeach @else @partial('table-empty', ['colspan' => $showMoney ? 5 : 3, 'icon' => 'fa-wallet', 'msg' => t_raw('vendor.analytics.empty_no_drawer_sessions')]) @endif
{{ t_raw('vendor.analytics.caption_drawer_sessions') }}
{{ t_raw('vendor.analytics.col_closed') }}{{ t_raw('vendor.analytics.col_expected') }}{{ t_raw('vendor.analytics.col_counted') }}{{ t_raw('vendor.analytics.col_variance') }}{{ t_raw('common.actions') }}
{!! fmt_datetime($s['closed_at']) !!}{!! $s['expected_cash'] !== null ? money($s['expected_cash']) : dash() !!} {!! $s['counted_cash'] !== null ? money($s['counted_cash']) : dash() !!} @php /* Managers see the balanced/over/short signal but not the cash amount (the till figures are owner-only). */ @endphp @if ($v == 0.0){{ t_raw('vendor.analytics.balanced_label') }} @elseif ($v > 0){!! $showMoney ? t('vendor.analytics.pill_over_amount', [':amount' => money($v)]) : t('vendor.analytics.pill_over_plain') !!} @else{!! $showMoney ? t('vendor.analytics.pill_short_amount', [':amount' => money(abs($v))]) : t('vendor.analytics.pill_short_plain') !!}@endif {{ t_raw('vendor.analytics.link_z_report') }}
@partial('table-toolbar', ['pager' => $shiftPager, 'base' => '/vendor/analytics/operations', 'showPager' => false])
@php /* /.qm-d2 */ @endphp @endsection