is_enabled_pusher_broadcast) wire:poll.15s @endif>

@lang('modules.settings.orderDetails')

@if ($this->shouldShowWaiterButtonMobile && $order->order_type === 'dine_in')
@livewire('forms.callWaiterButton', ['tableNumber' => $table->id ?? null, 'shopBranch' => $shopBranch])
@endif
@if ($order->order_status->value === 'cancelled')

@lang('modules.order.info_cancelled')

@lang('modules.order.orderCancelledMessage')

@else @php $steps = \App\Enums\OrderStatus::progressStepsFor($order->order_type); $currentStepIndex = \App\Enums\OrderStatus::progressIndex($order->order_status->value, $order->order_type); @endphp
@foreach($steps as $index => $status) @php $stepStatus = App\Enums\OrderStatus::from($status); $isCompleted = $index < $currentStepIndex; $isCurrent = $index === $currentStepIndex; $isNext = $index === $currentStepIndex + 1; @endphp
!$loop->first && !$loop->last, 'sm:items-start' => $loop->first, 'sm:items-end' => $loop->last, 'w-full sm:w-auto', ])>
progressStepIconClasses($isCompleted, $isCurrent, $isNext), ]) data-status-step="{{ $status }}"> @if($index <= $currentStepIndex) @else @php $svgBase = 'class="w-4 h-4" fill="none" viewBox="0 0 24 24"'; $pathBase = 'stroke="currentColor" stroke-linecap="round" stroke-width="2"'; @endphp @switch($status) @case('placed') @break @case('confirmed') @break @case('preparing') @break @case('out_for_delivery') @break @case('ready_for_pickup') @break @case('delivered') @break @case('completed') @break @case('served') @break @case('food_ready') @break @case('reached_destination') @break @case('picked_up') @break @default @endswitch @endif
@if(!$loop->last) @endif
!$loop->first && !$loop->last, 'text-left' => $loop->first || true, 'sm:text-right' => $loop->last, 'pt-1 sm:pt-0', ])>

$index == $currentStepIndex, 'text-skin-base dark:text-skin-base/90' => $index <= $currentStepIndex, 'text-gray-500 dark:text-gray-400' => $index > $currentStepIndex, ])> {{ App\Enums\OrderStatus::from($status)->translatedLabel() }}

@endforeach
@endif

{{ $order->show_formatted_order_number }}

@php $svgPath = match($order->order_type) { 'delivery' => 'M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m7-5l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2', 'pickup' => 'M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z', default => 'M15 11v.01M16 20h-8c-2.76 0-5-2.24-5-5s2.24-5 5-5h8c2.76 0 5 2.24 5 5s-2.24 5-5 5zM3 11h18M12 4v3M8.5 7h7' }; @endphp {{ Str::of($order->order_type)->replace('_', ' ')->title() }}
{{ $order->pickup_date ? $order->pickup_date->timezone(timezone())->format($dateFormat . ' ' . $timeFormat) : ($order->date_time->timezone(timezone())->format($dateFormat . ' ' . $timeFormat)) }}
{{ $order->items->count() }} @lang('modules.menu.item')
@if($order->table_id)
@lang('modules.settings.tableNumber') {{ $order->table->table_code ?? '--' }}
@endif
{{ currency_format($this->correctedTotal, $restaurant->currency_id) }}
@lang('modules.order.includeTax')
@if($order->order_type === 'delivery' && $order->delivery_address)

{{ $order->delivery_address }}

@endif
@php $timeValue = null; $timeLabel = null; if ($order->order_type === 'delivery' && !is_null($order->estimated_eta_max)) { $timeValue = $order->estimated_eta_max; $timeLabel = 'modules.order.estimatedDeliveryTime'; } else { $maxPreparationTime = $order->items->max(function($item) { return $item->menuItem->preparation_time; }); if ($maxPreparationTime) { $timeValue = $maxPreparationTime; $timeLabel = 'modules.menu.preparationTime'; } } @endphp @if ($timeValue) @lang($timeLabel): {{ $timeValue }} @lang('modules.menu.minutes') (@lang('app.approx')) @else @lang('modules.delivery.estimatedTimeUnavailable') @endif
@php $orderDetailEuSelectable = $restaurant ? $restaurant->selectableEuAllergenKeys() : []; $orderDetailEuEnabled = count($orderDetailEuSelectable) > 0; @endphp
@foreach ($order->items as $item) @php // Set price context for all modifiers before calculating (calculate once for reuse) if ($order->order_type_id) { foreach ($item->modifierOptions as $modifier) { $modifier->setPriceContext($order->order_type_id, $order?->delivery_app_id); } } $modifierTotal = $item->modifierOptions->sum(function($modifier) { return $modifier->pivot->modifier_option_price ?? $modifier->price; }); // Calculate original amount for free items $isFreeItem = $item->is_free_item_from_stamp ?? false; $originalAmount = $isFreeItem ? (($item->price ?? 0) + $modifierTotal) * $item->quantity : 0; @endphp
@if ($restaurant && !$restaurant->hide_menu_item_image_on_customer_site)
{{ $item->menuItem->item_name }}
@endif
{{ $item->menuItem->item_name }}
@if(isset($item->menuItemVariation)) {{ $item->menuItemVariation->variation }} @endif @if($isFreeItem) @lang('app.freeItem') ({{ currency_format($originalAmount, $restaurant->currency_id) }}) @endif
@if($taxMode === 'item' && $restaurant?->tax_inclusive && $item->tax_amount > 0) {{ currency_format(($item->price + $modifierTotal) - ($item->tax_amount / $item->quantity), $restaurant->currency_id) }} + tax = @endif {{ currency_format($item->price + $modifierTotal, $restaurant->currency_id) }} × {{ $item->quantity }}
@php $status = null; $statusLabel = null; $statusClasses = null; if ($order->order_type === 'delivery') { $status = $order->order_status->value ?? null; $statusLabel = \App\Enums\OrderStatus::tryFrom($status)?->translatedLabel() ?? \Illuminate\Support\Str::of((string)$status)->replace('_', ' ')->title(); $statusClasses = match ($status) { 'delivered' => 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-300', 'cancelled' => 'bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-300', 'out_for_delivery', 'picked_up', 'reached_destination' => 'bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-300', default => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-300', }; } elseif ($order->kot->isNotEmpty()) { $kotItem = $order->kot->flatMap->items->where('menu_item_id', $item->menu_item_id) ->where('menu_item_variation_id', $item->menu_item_variation_id) ->first(); $status = $kotItem ? $kotItem->status : null; $statusLabel = $status ? ucfirst($status) : null; $statusClasses = match ($status) { 'pending' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-300', 'cooking' => 'bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-300', 'ready' => 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-300', default => 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-300', }; } @endphp @if($status) {{ $statusLabel }} @endif
{{ currency_format($item->amount, $restaurant->currency_id) }}
@if($item->modifierOptions->isNotEmpty())
@foreach ($item->modifierOptions as $modifier) {{ $modifier->name ?? $modifier->pivot->modifier_option_name }} (+{{ currency_format($modifier->pivot->modifier_option_price ?? $modifier->price, $restaurant->currency_id) }}) @endforeach
@endif @if ($orderDetailEuEnabled && !empty($item->menuItem->eu_allergen_keys)) @php $orderDetailLineAllergens = array_values(array_unique(array_intersect( \App\Support\EuAnnexIiAllergens::keys(), $orderDetailEuSelectable, array_filter((array) $item->menuItem->eu_allergen_keys, 'is_string') ))); @endphp @if (count($orderDetailLineAllergens) > 0)
@foreach ($orderDetailLineAllergens as $odAllergenKey) @php $odAllergenLabel = __(\App\Support\EuAnnexIiAllergens::langKey($odAllergenKey)); @endphp {{ $odAllergenLabel }} @endforeach
@endif @endif @php $orderDetailLineDietary = \App\Support\DietaryLabels::normalize( is_array($item->menuItem->dietary_labels ?? null) ? $item->menuItem->dietary_labels : [] ); @endphp @if (count($orderDetailLineDietary) > 0)
@foreach ($orderDetailLineDietary as $odDietaryKey) @php $odDietaryLabel = __(\App\Support\DietaryLabels::langKey($odDietaryKey)); @endphp {{ $odDietaryLabel }} @endforeach
@endif @if($item->note)
@lang('modules.order.note'): {{ $item->note }}
@endif
@endforeach
@lang('modules.order.subTotal') @php // Display stamp discount $displayStampDiscountAmount = (float)($order->stamp_discount_amount ?? 0); if ($displayStampDiscountAmount == 0) { $displayStampDiscountAmount = (float)($stampDiscountAmount ?? 0); } // Check if there are free items from stamp redemption $hasFreeStampItems = $order->items()->where('is_free_item_from_stamp', true)->exists(); @endphp @if($displayStampDiscountAmount > 0 || $hasFreeStampItems) @lang('app.stampDiscount') @if($displayStampDiscountAmount > 0) (-{{ currency_format($displayStampDiscountAmount, $restaurant->currency_id) }}) @elseif($hasFreeStampItems) (@lang('app.freeItem')) @endif @endif
@php // Get sub_total directly from order (already refreshed in mount) // Use getOriginal to get database value if order was modified $displaySubTotal = (float)($order->getOriginal('sub_total') ?? $order->sub_total ?? 0); @endphp {{ currency_format($displaySubTotal, $restaurant->currency_id) }}
{{-- @if(function_exists('module_enabled') && module_enabled('Loyalty')) --}} @php // Always prioritize order data from database $displayLoyaltyPointsRedeemed = (float)($order->loyalty_points_redeemed ?? 0); $displayLoyaltyDiscountAmount = (float)($order->loyalty_discount_amount ?? 0); // Fallback to component variables if order values are 0 if ($displayLoyaltyPointsRedeemed == 0) { $displayLoyaltyPointsRedeemed = (float)($loyaltyPointsRedeemed ?? 0); } if ($displayLoyaltyDiscountAmount == 0) { $displayLoyaltyDiscountAmount = (float)($loyaltyDiscountAmount ?? 0); } @endphp @if($displayLoyaltyPointsRedeemed > 0 && $displayLoyaltyDiscountAmount > 0)
@lang('app.loyaltyDiscount') @if($displayLoyaltyPointsRedeemed > 0) ({{ number_format($displayLoyaltyPointsRedeemed, 0) }} @lang('app.points')) @endif
-{{ currency_format($displayLoyaltyDiscountAmount, $restaurant->currency_id) }}
@endif {{-- @endif --}} @php // Use order data if component variables are not set (for discount check) $checkLoyaltyPointsRedeemed = $loyaltyPointsRedeemed ?? $order->loyalty_points_redeemed ?? 0; @endphp @if (!is_null($order->discount_amount) && $checkLoyaltyPointsRedeemed == 0)
@lang('modules.order.discount') @if ($order->discount_type == 'percent') ({{ rtrim(rtrim(number_format($order->discount_value, 2), '0'), '.') }}%) @endif
-{{ currency_format($order->discount_amount, $restaurant->currency_id) }}
@endif @php $orderTypeSlug = optional($order->orderType)->slug ?? ($order->order_type ?? null); // Step 1: Calculate net = subtotal - discount $net = $order->sub_total - ($order->discount_amount ?? 0); // Separate applicable and non-applicable charges $applicableCharges = collect(); $nonApplicableCharges = collect(); foreach ($order->charges as $item) { $charge = $item->charge; if (!$charge) { continue; } $allowedTypes = $charge->order_types ?? []; // Handle string (JSON) format if (is_string($allowedTypes)) { $decoded = json_decode($allowedTypes, true); $allowedTypes = json_last_error() === JSON_ERROR_NONE ? $decoded : []; } // If order_types is empty or not an array, charge doesn't apply if (!is_array($allowedTypes) || empty($allowedTypes)) { $nonApplicableCharges->push($item); continue; } // Check if charge applies to this order type if (in_array($orderTypeSlug, $allowedTypes, true)) { $applicableCharges->push($item); } else { $nonApplicableCharges->push($item); } } // Use saved tax_base from database (calculated during order save) $taxBase = $order->tax_base ?? ($net + $applicableCharges->sum(fn($item) => $item->charge->getAmount($net))); @endphp @foreach ($applicableCharges as $item)
{{ $item->charge->charge_name }} @if ($item->charge->charge_type == 'percent') ({{ $item->charge->charge_value }}%) @endif
@php // Calculate discounted subtotal for charges (after both regular and loyalty discounts) $chargeBase = $order->sub_total - ($order->discount_amount ?? 0) - ($order->loyalty_discount_amount ?? 0); @endphp {{ currency_format($item->charge->getAmount($chargeBase), $restaurant->currency_id) }}
@endforeach @if ($taxMode == 'order') @foreach ($order->taxes as $item)
{{ $item->tax->tax_name }} ({{ $item->tax->tax_percent }}%) @php // Step 1: Calculate discounted subtotal (after both regular and loyalty discounts) // Loyalty points are always removed from subtotal before calculating tax $discountedSubtotal = $order->sub_total - ($order->discount_amount ?? 0) - ($order->loyalty_discount_amount ?? 0); // Step 2: Calculate service charges on discounted subtotal $serviceTotal = 0; if ($order->charges && $order->charges->count() > 0) { foreach ($order->charges as $chargeRelation) { $charge = $chargeRelation->charge; if ($charge) { $chargeAmount = $charge->getAmount((float)$discountedSubtotal); $serviceTotal += (float)$chargeAmount; } } } // Step 3: Calculate tax_base based on Tax Calculation Base setting // Check if service charges should be included in tax base $includeChargesInTaxBase = false; if ($restaurant && isset($restaurant->include_charges_in_tax_base)) { $includeChargesInTaxBase = (bool)$restaurant->include_charges_in_tax_base; } // Tax base = (subtotal - discounts) + service charges (if enabled) $taxBase = $includeChargesInTaxBase ? ($discountedSubtotal + $serviceTotal) : $discountedSubtotal; $taxBase = max(0, (float)$taxBase); // Step 4: Calculate tax on tax_base $taxAmount = ($item->tax->tax_percent / 100) * $taxBase; @endphp {{ currency_format($taxAmount, $restaurant->currency_id) }}
@endforeach @else @if($order->total_tax_amount > 0) @php $taxTotals = []; $totalTax = 0; foreach ($order->items as $item) { $qty = $item->quantity ?? 1; $taxBreakdown = is_array($item->tax_breakup) ? $item->tax_breakup : (json_decode($item->tax_breakup, true) ?? []); foreach ($taxBreakdown as $taxName => $taxInfo) { if (!isset($taxTotals[$taxName])) { $taxTotals[$taxName] = [ 'percent' => $taxInfo['percent'] ?? 0, 'amount' => ($taxInfo['amount'] ?? 0) * $qty ]; } else { $taxTotals[$taxName]['amount'] += ($taxInfo['amount'] ?? 0) * $qty; } } $totalTax += $item->tax_amount ?? 0; } @endphp
@foreach ($taxTotals as $taxName => $taxInfo)
{{ $taxName }} ({{ $taxInfo['percent'] }}%) {{ currency_format($taxInfo['amount'], $restaurant->currency_id) }}
@endforeach
@lang('modules.order.totalTax') @lang($restaurant?->tax_inclusive ? 'modules.settings.taxInclusive' : 'modules.settings.taxExclusive')
{{ currency_format($totalTax, $restaurant->currency_id) }}
@endif @endif @if ($order->order_type === 'delivery' && !is_null($order->delivery_fee))
@lang('modules.delivery.deliveryFee')
@if($order->delivery_fee > 0) {{ currency_format($order->delivery_fee, $restaurant->currency_id) }} @else @lang('modules.delivery.freeDelivery') @endif
@endif @include('livewire.shop.partials.order-loyalty-customer-ui') @if ($canAddTip || $order->tip_amount > 0)
@lang('modules.order.tip') @if($order->tip_amount > 0 && $order->tip_note)

"{{ $order->tip_note }}"

@endif
@if($order->tip_amount > 0 && !$canAddTip) {{ currency_format($order->tip_amount, $restaurant->currency_id) }} @endif @if($canAddTip) @if($order->tip_amount > 0) {{ currency_format($order->tip_amount, $restaurant->currency_id) }} @else @lang('modules.order.addTip') @endif @endif
@endif
@lang('modules.order.total')
@php $correctedTotal = $this->correctedTotal; $originalTotal = $order->total; $hasDifference = abs($correctedTotal - $originalTotal) > 0.01; $hasNonApplicable = isset($nonApplicableCharges) && $nonApplicableCharges->isNotEmpty(); @endphp {{ currency_format($correctedTotal, $restaurant->currency_id) }}

@lang('modules.order.paymentInformation')

@php $isSubdomainEnabled = function_exists('module_enabled') && module_enabled('Subdomain'); if ($order->order_type === 'delivery' || $order->isFullyPaid() || in_array($order->status, ['pending_verification', 'canceled', 'delivered'])) { $newOrderLink = $order->table_id ? route('table_order', [$order->table->hash]) . '?new_order=1' : ($isSubdomainEnabled ? url('/?new_order=1') : route('shop_restaurant', ['hash' => $restaurant->hash, 'new_order' => 1])); } else { $newOrderLink = ($isSubdomainEnabled ? url('/') : route('shop_restaurant', ['hash' => $restaurant->hash])) . '?current_order=' . $order->id; } @endphp @if($order->payments->count())
@foreach($order->payments as $payment)
@switch($payment->payment_method) @case('stripe') @break @case('razorpay') @break @case('paystack') @break @case('paypal') @break @case('payfast') @break @case('flutterwave') @break @case('mollie') @break @case('epay') @break @case('upi') @break @default @endswitch

{{ ucwords(str_replace('_', ' ', $payment->payment_method)) }}

{{ $payment->created_at->timezone(timezone())->format(dateFormat() . ' ' . timeFormat()) }}

@if($payment->transaction_id)

@lang('modules.order.transactionId'): {{ $payment->transaction_id }}

@endif
{{ currency_format($payment->amount, $restaurant->currency_id) }} @if($payment->balance > 0)

@lang('modules.order.balanceReturn'): {{ currency_format($payment->balance, $restaurant->currency_id) }}

@endif
@endforeach
@endif @if($order->isFullyPaid()) @lang('modules.order.paid') @lang('modules.order.newOrder') @else @if ($order->status === 'pending_verification' && !$order->isFullyPaid()) @lang('modules.order.pendingPaymentVerification') @else @lang('modules.order.paymentPending') @endif
@if (!$isRestaurantOpenForOrders)
{{ $restaurantClosedMessage }}
@lang('modules.order.newOrder')
@elseif (is_null($customer) && ($restaurant->customer_login_required || $orderType == 'delivery')) @lang('app.next') @else
@php $showPayNow = $paymentGateway->is_qr_payment_enabled || $paymentGateway->stripe_status || $paymentGateway->razorpay_status || $paymentGateway->flutterwave_status || $paymentGateway->paypal_status || $paymentGateway->payfast_status || $paymentGateway->paystack_status || $paymentGateway->xendit_status || $paymentGateway->epay_status || $paymentGateway->mollie_status || $paymentGateway->tap_status || count($offlinePaymentMethods) > 0; @endphp @if ($showPayNow) @if ($order && $order->order_status->value !== 'cancelled' && $order->status !== 'pending_verification') @lang('modules.order.payNow') @endif @endif @lang('modules.order.newOrder')
@endif
@endif
@lang('modules.order.chooseGateway') @php $offlinePaymentMethodMapForModal = isset($offlinePaymentMethods) ? $offlinePaymentMethods->keyBy('name') : collect(); $activeOfflinePaymentMethodName = $selectedOfflinePaymentMethod ?? 'bank_transfer'; $activeOfflinePaymentMethod = !empty($selectedOfflinePaymentMethod) ? $offlinePaymentMethodMapForModal->get($selectedOfflinePaymentMethod) : null; @endphp
{{ $paymentOrder->show_formatted_order_number }}
{{ currency_format($total, $restaurant->currency_id) }}
@if ($showQrCode || $showPaymentDetail) @lang('modules.billing.showOtherPaymentOption')
@if ($showQrCode) QR Code Preview @elseif ($showPaymentDetail) @if ($activeOfflinePaymentMethod && !empty($activeOfflinePaymentMethod->description))

{{ ucwords(str_replace('_', ' ', $activeOfflinePaymentMethod->name)) }}

{!! nl2br(e($activeOfflinePaymentMethod->description)) !!}

@else

{{ ucwords(str_replace('_', ' ', $activeOfflinePaymentMethodName)) }}

@lang('app.noDescription')

@endif @endif
@else @if(!$isRestaurantOpenForOrders)
{{ $restaurantClosedMessage }}
@else
@if ($paymentGateway->stripe_status) @endif @if ($paymentGateway->razorpay_status) @endif @if ($paymentGateway->flutterwave_status) @endif @if ($paymentGateway->paypal_status) PayPal @endif @if($paymentGateway->payfast_status) @lang('modules.billing.payfast') @endif @if($paymentGateway->paystack_status) @lang('modules.billing.paystack') @endif @if($paymentGateway->xendit_status) Xendit Streamline Icon: https://streamlinehq.com Xendit @lang('modules.billing.xendit') @endif @if($paymentGateway->epay_status) @lang('modules.billing.epay') @endif @if ($paymentGateway->mollie_status) @lang('modules.billing.mollie') @endif @if ($paymentGateway->tap_status) @lang('modules.billing.tap') @endif @if ($paymentGateway->is_qr_payment_enabled && $paymentGateway->qr_code_image_url) @lang('modules.billing.paybyQr') @endif {{-- Dynamic Offline Payment Methods --}} @if (count($offlinePaymentMethods) > 0) @foreach ($offlinePaymentMethods as $offlineMethod) {{ ucwords(str_replace('_', ' ', $offlineMethod->name)) }} @endforeach @endif
@endif @endif
@if (($showQrCode || $showPaymentDetail) && $isRestaurantOpenForOrders) @php $selectedMethodForFooter = $showQrCode ? 'upi' : ($selectedOfflinePaymentMethod ?? 'others'); @endphp @lang('modules.billing.paymentDone') @endif
@if($paymentGateway->stripe_status) @lang('modules.billing.stripe')
@lang('modules.billing.payNow')
@lang('app.cancel') @lang('modules.billing.payNow')
@endif
@lang('modules.order.addTip')
@lang('modules.order.currentTotal') {{ currency_format($order->total - $order->tip_amount, $restaurant->currency_id) }}
@lang('modules.order.tipAmount') + {{ currency_format($tipAmount ?? 0, $restaurant->currency_id) }}
@lang('modules.order.newTotal') {{ currency_format(($order->total - $order->tip_amount + ($tipAmount ?: 0)), $restaurant->currency_id) }}
@foreach ([5, 10, 15, 20] as $percentage) @php $calculatedTip = round($order->sub_total * $percentage / 100, 2); @endphp @endforeach
{{ $restaurant->currency->currency_symbol }}
@lang('app.cancel') @lang('app.save')
@include('livewire.shop.partials.order-loyalty-modals') @script @endscript
@push('scripts') @if(pusherSettings()->is_enabled_pusher_broadcast) @endif @endpush