@php /** * The cart page's line list and its order summary — ONE source of markup for both the full page * render and the AJAX repaint. * * Why this partial exists * ----------------------- * Two faults, one cause. `/cart` was rendered entirely server-side with no repaint path, so an * upsell added from the "goes well with your order" band posted successfully and changed nothing on * screen: the diner saw a stale line list and a stale total until they reloaded. And the summary * derived its own figures from `restaurants.delivery_fee` instead of the resolver that had already * decided them, so the free-delivery meter directly above could promise free delivery while the row * beneath still charged — and a QR diner sitting at a table was quoted a delivery fee. * * The fix for both is the same and is the rule the storefront already follows elsewhere: the SERVER * renders, the client swaps the result in. `qm-upsell.js` already works this way and says why — * "the cart drawer already lost its delivery-fee row once to a second copy of markup living in * JavaScript". This partial is what stops a third copy being written. * * Every money figure comes from CartController::totals(), which resolves the delivery zone, honours * Restaurant::deliversNow() and computes tax. Nothing here recomputes any of it. * * @var array $items * @var float $subtotal * @var array|null $restaurant * @var array $totals CartController::totals() */ $deliversNow = $restaurant && \App\Models\Restaurant::deliversNow($restaurant); $feeShown = (float) ($totals['delivery_fee'] ?? 0); $taxShown = (float) ($totals['tax'] ?? 0); $grandTotal = (float) ($totals['total'] ?? $subtotal); @endphp
| {{ t_raw('cart.col_image') }} | {{ t_raw('cart.col_item') }} | {{ t_raw('common.quantity_aria') }} | {{ t_raw('cart.col_line_total') }} | {{ t_raw('common.actions') }} |
|---|---|---|---|---|
|
{{ $line['name'] }}
@if (!empty($line['option'])){{ $line['option'] }} @endif
@if (!empty($line['ingredient_label'])){{ $line['ingredient_label'] }} @endif
@php /* The line note belongs here for the same reason the option and the ingredient label do:
it is part of what the diner asked for, and Cart::add() folds it into the line KEY, so two
otherwise identical dishes with different notes are two separate rows. Left unrendered they
were byte-identical on screen and the diner could not tell which note they were about to
delete. Quoted exactly as OrderService::lineOptionsText() quotes it on the order itself. */
@endphp
@if (trim((string) ($line['notes'] ?? '')) !== '')“{{ trim((string) $line['notes']) }}” @endif
{{ t_raw('cart.unit_each', [':amount' => money($line['unit_price'])]) }}
|
{{ money($line['unit_price'] * $line['qty']) }} |
{!! \App\Services\Tax::isInclusive($restaurant) ? t('cart.tax_note_inclusive', [':label' => \App\Services\Tax::label($restaurant)]) : t('cart.tax_note_exclusive', [':label' => \App\Services\Tax::label($restaurant)]) !!}
@endif{{ t_raw('cart.non_customer_notice') }}
{{ t_raw('cart.checkout') }} @elseif ($belowMin){{ t_raw('cart.min_order_warn', [':min' => money($restaurant['min_order']), ':amount' => money((float) $restaurant['min_order'] - $subtotal)]) }}
{{ t_raw('cart.checkout') }} @else {{ t_raw('cart.checkout') }} @endif