@extends('layouts.dashboard') @section('content') @php /** * Operation Analytics → Kitchen efficiency: how long the kitchen actually takes, * measured from the per-item prep marks the board records rather than from a target * somebody typed into settings once. * * Two readings, because they lead to two different decisions: WHICH DISH is slow is a * recipe or a prep-list problem, WHICH HOUR is slow is a rota problem. * * @var array $kpis @var array $prepChart @var array $prepMeta @var array $hourChart @var array $hourMeta * @var array $slowChart @var array $slowMeta @var array $stationChart @var array $stationMeta * @var array $dishRows @var array $dishPager @var array $stationRows @var bool $hasStations * @var string|null $avgTicket @var int $ticketCount @var int $targetMinutes @var int $measured * @var int $rangeDays @var array $rangeLinks */ $dishRows = $dishRows ?? []; $stationRows = $stationRows ?? []; $hasStations = !empty($hasStations); $measured = (int) ($measured ?? 0); $targetMinutes = (int) ($targetMinutes ?? 30); $ticketCount = (int) ($ticketCount ?? 0); @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

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

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

@foreach ($rangeLinks['options'] as $val => $text) @php $on = ((string) $val === $rangeLinks['selected']); @endphp {{ $text }} @endforeach
@php /* Nothing has been ticked off yet. Every figure below would be an average of no measurements, so the page says so once instead of printing a screen of zeros and an accusation against whichever dish happens to sort first. */ @endphp @if ($measured < 1)

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

{{ t_raw('nav.kitchen_display') }}
@else
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'blue', 'icon' => 'fa-stopwatch', 'label' => t_raw('vendor.analytics.kpi_avg_prep'), 'value' => $kpis['avgPrep']['value'] ?? dash(), 'spark' => $kpis['avgPrep']['spark'], 'meta' => $kpis['avgPrep']['meta']]) @php /* The named dish. This is the whole point of the page — a number nobody can act on becomes a recipe somebody can change. */ @endphp @partial('kpi-card', ['variant' => 'panel', 'accent' => 'rose', 'icon' => 'fa-hourglass-half', 'label' => t_raw('vendor.analytics.kpi_slowest_dish'), 'value' => $kpis['slowestDish']['value'] ?? dash(), 'meta' => $kpis['slowestDish']['meta'], 'bgImage' => $kpis['slowestDish']['image'] ?? '']) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'amber', 'icon' => 'fa-clock', 'label' => t_raw('vendor.analytics.kpi_slowest_hour'), 'value' => $kpis['slowestHour']['value'] ?? dash(), 'meta' => $kpis['slowestHour']['meta']]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'teal', 'icon' => 'fa-utensils', 'label' => t_raw('vendor.analytics.kpi_dishes_prepped'), 'value' => number_format((int) $kpis['dishesPrepped']['value']), 'spark' => $kpis['dishesPrepped']['spark'], 'meta' => $kpis['dishesPrepped']['meta']]) @partial('kpi-card', ['variant' => 'panel', 'accent' => 'violet', 'icon' => 'fa-bullseye', 'label' => t_raw('vendor.analytics.kpi_on_target'), 'value' => $kpis['onTarget']['value'] !== null ? number_format($kpis['onTarget']['value'], 1) . '%' : dash(), 'meta' => $kpis['onTarget']['meta']])

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

@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_prep_speed'), 'sub' => t_raw('vendor.analytics.chart_avg_min_per_day_sub'), 'cfg' => $prepChart, 'meta' => $prepMeta, 'accent' => 'blue', 'icon' => 'fa-stopwatch', 'opts' => ['id' => 'kitchenPrepChart', 'url' => route('vendor.chart-series', ['chart' => 'kitchenPrep']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_prep_by_hour'), 'sub' => t_raw('vendor.analytics.chart_prep_by_hour_sub'), 'cfg' => $hourChart, 'meta' => $hourMeta, 'icon' => 'fa-clock', 'accent' => 'amber', 'opts' => ['id' => 'kitchenHourChart', 'url' => route('vendor.chart-series', ['chart' => 'kitchenHour']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_slowest_dishes'), 'sub' => t_raw('vendor.analytics.chart_slowest_dishes_sub'), 'cfg' => $slowChart, 'meta' => $slowMeta, 'icon' => 'fa-hourglass-half', 'accent' => 'rose', 'opts' => ['id' => 'kitchenSlowChart', 'url' => route('vendor.chart-series', ['chart' => 'kitchenSlow']), 'selected' => $rangeLinks['selected'], 'options' => $rangeLinks['options'], 'control' => 'compact']])
@php /* Only where the kitchen is divided: on one undivided board every line belongs to the same station and the chart would be a single bar. */ @endphp @if ($hasStations)
@partial('chart-card', ['heading' => t_raw('vendor.analytics.chart_prep_by_station'), 'sub' => t_raw('vendor.analytics.chart_prep_by_station_sub'), 'cfg' => $stationChart, 'meta' => $stationMeta, 'icon' => 'fa-fire', 'accent' => 'violet'])
@endif

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

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

{{ t_raw('vendor.analytics.hint_dish_prep_times', [':target' => (string) $targetMinutes]) }}

{{ t_raw('vendor.analytics.link_set_prep_target') }}
@if ($dishRows) @foreach ($dishRows as $d) @endforeach @else @partial('table-empty', ['colspan' => 5, 'icon' => 'fa-utensils', 'msg' => t_raw('vendor.analytics.empty_no_prep_data')]) @endif
{{ t_raw('vendor.analytics.caption_dish_prep_times') }}
{{ t_raw('vendor.analytics.col_dish') }} {{ t_raw('vendor.analytics.col_times_prepped') }} {{ t_raw('vendor.analytics.col_avg_prep') }} {{ t_raw('vendor.analytics.col_slowest_single') }} {{ t_raw('vendor.analytics.col_over_target') }}
@if ($d['menu_item_id'] > 0) {{ $d['name'] }} @else {{ $d['name'] }} @endif {{ number_format($d['times']) }} @php /* Amber past the target, so the row that needs attention is visible without reading five numbers first. */ @endphp {{ (string) round($d['avg_minutes'], 1) }} {{ t_raw('common.min') }} {{ (string) round($d['max_minutes'], 1) }} {{ t_raw('common.min') }} @if ($d['over_target'] > 0) {{ t_raw('vendor.analytics.pill_over_target', [':n' => number_format($d['over_target']), ':pct' => number_format($d['over_rate'] ?? 0, 1)]) }} @else{{ t_raw('vendor.analytics.pill_all_on_target') }}@endif
@partial('table-toolbar', ['pager' => $dishPager, 'base' => '/vendor/analytics/kitchen'])
@if ($hasStations)

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

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

{{ t_raw('vendor.menu.stations_title') }}
@if ($stationRows) @foreach ($stationRows as $s) @endforeach @else @partial('table-empty', ['colspan' => 3, 'icon' => 'fa-fire', 'msg' => t_raw('vendor.analytics.empty_no_prep_data')]) @endif
{{ t_raw('vendor.analytics.caption_station_prep_times') }}
{{ t_raw('vendor.menu.station_label') }} {{ t_raw('vendor.analytics.col_times_prepped') }} {{ t_raw('vendor.analytics.col_avg_prep') }}
{{ $s['name'] }} {{ number_format($s['times']) }} {{ (string) round($s['avg_minutes'], 1) }} {{ t_raw('common.min') }}
@endif @endif
@php /* /.qm-d2 */ @endphp @endsection