@extends('front.layout.master') @section('title', $product->product_name . ' | ') @section('meta_tags') @if($product->thumbnail && file_exists(public_path('images/simple_products/' . $product->thumbnail))) @endif @endsection @section('stylesheet') @endsection @section('body') @php $lang = session()->get('changed_language') ?? 'en'; $isAuth = auth()->check(); // Price + discount. // Schema note: admin enters `actual_selling_price` and `actual_offer_price` (pre-tax). // `price` and `offer_price` are the same values WITH tax computed and stored, which is what // the customer should see. Treat the offer as real ONLY when admin actually set a non-zero // `actual_offer_price` AND the resulting `offer_price` is strictly less than `price`. Without // this check the page can show a phantom "offer" because tax is sometimes baked into // `offer_price` even when the admin meant "no offer". $basePrice = (float) ($product->price ?? 0); $proOffer = (float) ($product->offer_price ?? 0); $actualOffer = (float) ($product->actual_offer_price ?? 0); $hasOffer = $actualOffer > 0 && $proOffer > 0 && $proOffer < $basePrice; $variantPrice = $hasOffer ? $proOffer : $basePrice; $variantCompare = $hasOffer ? $basePrice : null; $disPct = ($variantCompare && $variantPrice > 0) ? round((1 - $variantPrice / $variantCompare) * 100) : 0; // Reviews aggregate (uses real review rows like the variant page) $allReviews = $product->reviews()->where('status', '1')->get(); $review_count = $allReviews->count(); $sub_total = 0; $denom = 0; foreach ($allReviews as $r) { $sub_total += ($r->qty * 5) + ($r->price * 5) + ($r->value * 5); } $denom = ($review_count * 3) * 5; $overallrating = $denom > 0 ? round(($sub_total / $denom) * 5, 1) : 0; // Per-product policy facts $hasFreeShip = $product->free_shipping == 1; $hasReturn = $product->return_avbl == 1; $hasCancel = $product->cancel_avbl == 1; $hasCOD = $product->cod_avbl == 1; $returnDays = optional(\App\Genral::first())->return_in_days ?? 30; // Simple products don't carry a warranty column in this schema; surface only when something is set. $warrantyLabel = trim(implode(' ', array_filter([ $product->w_d ?? '', $product->w_my ?? '', $product->w_type ?? '', ]))); $hasWarranty = $warrantyLabel !== ''; $tiles = []; if ($hasFreeShip) { $tiles[] = ['label' => __('Free Delivery'), 'sub' => __('On this product'), 'svg' => '', 'tone' => 'emerald']; } if ($hasReturn) { $tiles[] = ['label' => __('Easy Returns'), 'sub' => $returnDays . ' ' . __('day policy'), 'svg' => '', 'tone' => 'amber']; } if ($hasWarranty) { $tiles[] = ['label' => __('Warranty'), 'sub' => $warrantyLabel, 'svg' => '', 'tone' => 'brand']; } if ($hasCOD) { $tiles[] = ['label' => __('Cash on Delivery'), 'sub' => __('Available'), 'svg' => '', 'tone' => 'sky']; } if ($hasCancel) { $tiles[] = ['label' => __('Cancellable'), 'sub' => __('Order can be cancelled'), 'svg' => '', 'tone' => 'rose']; } $toneMap = [ 'emerald' => ['icon' => 'text-emerald-600', 'bg' => 'bg-emerald-50'], 'amber' => ['icon' => 'text-amber-600', 'bg' => 'bg-amber-50'], 'brand' => ['icon' => 'text-brand-600', 'bg' => 'bg-brand-50'], 'sky' => ['icon' => 'text-sky-600', 'bg' => 'bg-sky-50'], 'rose' => ['icon' => 'text-rose-500', 'bg' => 'bg-rose-50'], ]; // Wishlist + compare state $detailInWish = false; if ($isAuth) { $detailInWish = \App\Wishlist::where('user_id', auth()->id())->where('simple_pro_id', $product->id)->exists(); } $detailInCompare = false; foreach ((array) session('comparison', []) as $cmp) { if (($cmp['proid'] ?? null) == $product->id && (($cmp['type'] ?? 'variant') === 'simple')) { $detailInCompare = true; break; } } // Gallery URLs $imgs = []; if ($product->thumbnail && file_exists(public_path('images/simple_products/' . $product->thumbnail))) { $imgs[] = url('images/simple_products/' . $product->thumbnail); } foreach ($product->productGallery as $g) { if (!empty($g->image) && file_exists(public_path('images/simple_products/gallery/' . $g->image))) { $imgs[] = url('images/simple_products/gallery/' . $g->image); } } $imgs = array_values(array_unique($imgs)); $mainSrc = $imgs[0] ?? url('images/no-image.png'); // Sale tag — guard against admin-entered black-on-black or invalid hexes. $saleTag = is_array($product->sale_tag ?? null) ? ($product->sale_tag[$lang] ?? (array_values($product->sale_tag)[0] ?? null)) : ($product->sale_tag ?? null); $saleTag = is_string($saleTag) ? trim($saleTag) : $saleTag; $saleColor = $product->sale_tag_color ?: '#3b6df0'; $saleTextColor = $product->sale_tag_text_color ?: '#ffffff'; $_rgb = function ($hex) { $hex = ltrim((string) $hex, '#'); if (strlen($hex) === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2]; if (strlen($hex) !== 6) return null; return [hexdec(substr($hex,0,2)), hexdec(substr($hex,2,2)), hexdec(substr($hex,4,2))]; }; $_luma = function ($rgb) { return $rgb ? (0.299*$rgb[0] + 0.587*$rgb[1] + 0.114*$rgb[2]) / 255 : 1; }; $_bg = $_rgb($saleColor); $_tx = $_rgb($saleTextColor); if ($_bg && $_tx && abs($_luma($_bg) - $_luma($_tx)) < 0.35) { $saleTextColor = $_luma($_bg) > 0.6 ? '#0a1430' : '#ffffff'; } // Real rating distribution for the bars $ratingBuckets = [5=>0, 4=>0, 3=>0, 2=>0, 1=>0]; foreach ($allReviews as $rv) { $avg = (int) round((($rv->qty + $rv->price + $rv->value) / 3)); $avg = max(1, min(5, $avg)); $ratingBuckets[$avg]++; } $ratingTotal = array_sum($ratingBuckets); $ratingPct = []; foreach ($ratingBuckets as $k => $v) { $ratingPct[$k] = $ratingTotal > 0 ? round($v / $ratingTotal * 100) : 0; } @endphp {{-- Breadcrumbs --}}
{{-- LEFT: Gallery card --}}
@foreach($imgs as $i => $imgsrc) @endforeach
{{ $product->product_name }} @if($disPct > 0) −{{ $disPct }}% @endif
{{-- Action buttons --}}
@php $cartAction = ($product->type ?? null) == 'ex_product' ? $product->external_product_link : route('add.cart.simple', ['pro_id' => $product->id, 'price' => $product->price, 'offerprice' => $product->offer_price ?? 0]); @endphp @if(($product->type ?? null) == 'ex_product') {{ __('Buy Now') }} @elseif($product->stock > 0)
@csrf
@if($isAuth) @else @endif @else @endif
{{-- Trust badges --}} @if(count($tiles))
@foreach($tiles as $tile)
{!! $tile['svg'] !!}
{{ $tile['label'] }}
{{ $tile['sub'] }}
@endforeach
@endif
{{-- RIGHT: Info column --}}
{{-- Title block --}}
@if($product->store)
{{ __('Sold by') }} {{ $product->store->name }}
@endif

{{ $product->product_name }}

@if($overallrating > 0)
{{ number_format($overallrating, 1) }}
@endif {{ $review_count }} {{ __('Reviews') }} | @if($product->stock > 0) {{ __('In Stock') }} @if($product->stock <= 10){{ __('Only :n left', ['n' => $product->stock]) }}@endif @else {{ __('Out of Stock') }} @endif
@if(!empty($saleTag))
{{ $saleTag }}
@endif
{{-- Price block --}}
@if($disPct > 0)
{{ __('Special price') }} {{ __('Limited time deal') }}
@endif
{!! price_format($variantPrice * $conversion_rate) !!} @if($variantCompare) {!! price_format($variantCompare * $conversion_rate) !!} {{ $disPct }}% {{ __('off') }} @endif

{{ __('Inclusive of all taxes') }}

@if(($product->pre_order ?? 0) == 1)
{{ __('Pre-order') }}
@if(($product->preorder_type ?? '') === 'partial' && !empty($product->partial_payment_per))
{{ __('Pay :n% now to reserve', ['n' => $product->partial_payment_per]) }}@if(!empty($product->product_avbl_date)) · {{ __('Available') }} {{ \Illuminate\Support\Carbon::parse($product->product_avbl_date)->format('d M Y') }} @endif
@elseif(!empty($product->product_avbl_date))
{{ __('Available') }} {{ \Illuminate\Support\Carbon::parse($product->product_avbl_date)->format('d M Y') }}
@endif
@endif
{{-- Quantity --}} @if($product->stock > 0 && ($product->type ?? null) != 'ex_product')
{{ __('Quantity') }}
@if($product->stock < 10 && $product->stock > 0) {{ __('Only') }} {{ $product->stock }} {{ __('left') }} {{ __('in stock') }} @endif
@endif {{-- Delivery / Seller --}}

{{ __('Delivery & Seller') }}

@if(count($tiles))
@foreach($tiles as $tile)
{!! $tile['svg'] !!}
{{ $tile['label'] }}
{{ $tile['sub'] }}
@endforeach
@else

{{ __('Standard shipping rates apply.') }}

@endif @if(isset($product->store) && $product->store) @php $sLogoFile = $product->store->store_logo ?? null; $sLogoUrl = $sLogoFile && file_exists(public_path('images/store/logo/' . $sLogoFile)) ? url('images/store/logo/' . $sLogoFile) : null; @endphp
@if($sLogoUrl) {{ $product->store->name }} @else {{ strtoupper(substr($product->store->name ?? 'S', 0, 2)) }} @endif
{{ $product->store->name ?? __('Authorised Seller') }}
{{ __('Authorised seller') }} · {{ __('Verified') }}
@if(isset($product->store->id)) {{ __('View store') }} @endif
@endif
{{-- HIGHLIGHTS + ABOUT --}}

{{ __('Highlights') }}

@php $highlightItems = []; $tags = trim((string) ($product->product_tags ?? $product->tags ?? '')); if ($tags !== '') { foreach (explode(',', $tags) as $tag) { $tag = trim($tag); if ($tag !== '') $highlightItems[] = $tag; } } if (empty($highlightItems) && !empty($product->key_features)) { $kf = strip_tags(str_replace(['', '

', '
', '
', '
'], "\n", $product->key_features)); foreach (preg_split('/\r?\n+/', $kf) as $line) { $line = trim($line); if ($line !== '') $highlightItems[] = $line; } } @endphp

{{ __('About this item') }}

{!! $product->product_detail !!}
{{-- SPECIFICATIONS --}} @php $specs = []; if (!empty(optional($product->brand)->name)) $specs[__('Brand')] = $product->brand->name; if (!empty($product->model_no)) $specs[__('Model')] = $product->model_no; if (!empty($product->sku)) $specs[__('SKU')] = $product->sku; if (!empty($product->hsin)) $specs[__('HSN Code')] = $product->hsin; // Weight is a free-text field admins sometimes fill with junk; only show numeric values. if (!empty($product->weight) && is_numeric($product->weight) && (float) $product->weight > 0) { $specs[__('Weight')] = (float) $product->weight; } // Tax: `tax` is the percentage admins enter; `tax_name` is the label. tax_rate is the // computed absolute amount per item — not useful in the spec line. if (!empty($product->tax_name) || !empty($product->tax)) { $taxLabel = trim((string) ($product->tax_name ?? '')); if (!empty($product->tax)) { $taxLabel = ($taxLabel !== '' ? $taxLabel . ' ' : '') . '(' . rtrim(rtrim(number_format($product->tax, 2), '0'), '.') . '%)'; } if ($taxLabel !== '') $specs[__('Tax')] = $taxLabel; } if (!empty(optional($product->category)->title)) $specs[__('Category')] = $product->category->title; if (!empty(optional($product->subcategory)->title)) $specs[__('Subcategory')] = $product->subcategory->title; @endphp @if(!empty($specs))

{{ __('Specifications') }}

@foreach($specs as $label => $value)
{{ $label }}
{{ $value }}
@endforeach
@endif {{-- REVIEWS --}}

{{ __('Ratings & Reviews') }}

@auth @else {{ __('Login to rate') }} @endauth
{{ number_format($overallrating, 1) }}
{{ $ratingTotal }} {{ __('reviews') }}
@foreach([5,4,3,2,1] as $stars)
{{ $stars }}
{{ $ratingPct[$stars] }}%
@endforeach
@if($allReviews->count())
@foreach($allReviews->take(6) as $r)
@php $stars = round((($r->qty + $r->price + $r->value) / 3)); @endphp {{ $stars }} ✓ {{ __('Verified') }} · {{ $r->created_at ? $r->created_at->format('M d, Y') : '' }}
@if($r->summary ?? null)

{{ $r->summary }}

@endif

{{ $r->review ?? '' }}

{{ optional($r->users)->name ?? __('Anonymous') }}
@endforeach
@else

{{ __('No reviews yet. Be the first to review!') }}

@endif
@auth {{-- Rate Product modal --}} @endauth @endsection @section('script') @endsection