@php /* The give-back policy is a money setting, so Settings strips the Loyalty
section from a manager's own page — this link would land on nothing. */
@endphp
@if ($showMoney)
{{ t_raw('vendor.loyalty.settings_link') }}
@endif
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'rose', 'icon' => 'fa-gift', 'label' => t_raw('vendor.loyalty.kpi_points_issued'), 'value' => number_format((int) $kpis['issued']), 'href' => route('vendor.orders'), 'spark' => $kpiSparks['issued'] ?? [],
'meta' => '' . t('vendor.loyalty.kpi_points_issued_meta') . ''])
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'amber', 'icon' => 'fa-paper-plane', 'label' => t_raw('vendor.loyalty.kpi_points_redeemed'), 'value' => number_format((int) $kpis['redeemed']), 'href' => route('vendor.orders'), 'spark' => $kpiSparks['redeemed'] ?? [],
'meta' => '' . t('vendor.loyalty.kpi_points_redeemed_meta') . ''])
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'green', 'icon' => 'fa-coins', 'label' => t_raw('vendor.loyalty.kpi_outstanding_balance'), 'value' => number_format((int) $kpis['outstanding']), 'spark' => $kpiSparks['outstanding'] ?? [],
'meta' => '' . t('vendor.loyalty.kpi_outstanding_meta') . ''])
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'teal', 'icon' => 'fa-users', 'label' => t_raw('admin.loyalty.col_members'), 'value' => number_format((int) $kpis['members']), 'spark' => $kpiSparks['members'] ?? [],
'meta' => '' . t('vendor.loyalty.kpi_members_meta') . ''])
@php /* What the programme actually owes. A point balance is not a number an owner can
reconcile against anything; priced through the reward catalogue it becomes the real
cost of every reward still waiting to be claimed. With no active rewards nothing can
be redeemed, so the figure is genuinely undefined rather than zero. Owner-only: it
is a money figure, so it follows the same boundary as the rest of the takings. */
@endphp
@if ($showMoney)
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'orange', 'icon' => 'fa-file-invoice-dollar', 'label' => t_raw('vendor.loyalty.kpi_liability'),
'value' => $liability !== null ? money($liability) : "—", 'spark' => $liability !== null ? ($kpiSparks['liability'] ?? []) : [],
'meta' => '' . ($pointValue !== null
? t('vendor.loyalty.kpi_liability_meta', [':rate' => money($pointValue)])
: t('vendor.loyalty.kpi_liability_meta_none')) . ''])
@endif
@partial('kpi-card', ['variant' => 'panel', 'accent' => 'blue', 'icon' => 'fa-percentage', 'label' => t_raw('vendor.loyalty.kpi_redemption_rate'),
'value' => $redemptionRate !== null ? number_format($redemptionRate, 1) . '%' : "—",
'meta' => '' . t('vendor.loyalty.kpi_redemption_rate_meta') . ''])
@php /* FIND A MEMBER. Points are keyed to the customer's phone number, so the phone is how an
operator reaches a balance: the number goes in on the left and the members it matches list
right under it as it is typed (name, phone, email, points); the one clicked opens on the
right — who they are, their standing, and the owner's adjust fields, which update the balance
in place. It sits under the KPIs because it is the one thing a vendor comes here to DO;
everything below it is reading. loyalty-members.js drives it; without JS the adjust form
still posts and comes back with a flash. */
@endphp
@php /* The heading lives in the left column so the row starts at the top of the card and the
workspace on the right runs level with it - no band of white above the panel. */
@endphp
{{ t_raw('vendor.loyalty.find_heading') }}
{{ t_raw('vendor.loyalty.find_sub') }}
{{ t_raw('vendor.loyalty.find_hint') }}
{{ t_raw('vendor.loyalty.find_matches') }}
@php /* Nothing picked yet: say what the panel is for. */
@endphp
{{ t_raw('vendor.loyalty.find_pick') }}
@php /* The member picked from the matches: who they are, by phone; their standing; and, for
the owner, the adjust fields. Issuing points spends the give-back budget, so a
manager sees the member but not the form. */
@endphp
{{ t_raw('vendor.loyalty.col_lifetime') }}
{{ t_raw('common.joined') }}
@if ($showMoney)
@endif
@php /* Trends: how points flow in and out day by day, and where every point ever issued
now stands. Each card's caption and its accessible summary are the same sentence. */
@endphp
@php /* No rows-per-page control here: this table is the active slice of the very
catalogue the manager below pages over, so a second pager on the same data would
fight the first. The give-back column is drawn as a percentage plus a bar, so it
carries its numeric value in data-sort-value. */
@endphp
@php /* Reward CRUD prices the give-back, so LoyaltyController keeps saveReward,
deleteReward and adjust to the owner. A manager reads the catalogue instead of
editing it — the same boundary the liability KPI above already draws. */
@endphp
@if ($showMoney)
@endif
@php /* A deliberately bounded "latest ten" strip rather than a paged list — the page
already carries one pager, on the reward catalogue, and both would read the same
?page= parameter. When renders via fmt_datetime, so that cell carries its raw
timestamp in data-sort-value. */
@endphp