@extends('front/layout.master') @section('title', "$pro->name") @section('meta_tags') @if(isset($pro->subvariants[0]) && isset($pro->subvariants[0]->variantimages)) @endif @endsection @section('stylesheet') @endsection @section('body') @php // Compute compare + wishlist active state for the detail page $detailInCompare = false; foreach ((array) session('comparison', []) as $cmp) { if (($cmp['proid'] ?? null) == $pro->id && (($cmp['type'] ?? 'variant') === 'variant')) { $detailInCompare = true; break; } } $detailInWish = false; if (auth()->check() && isset($pro->subvariants[0])) { $detailInWish = \App\Wishlist::where('user_id', auth()->id()) ->where('pro_id', $pro->subvariants[0]->id) ->exists(); } // Compute review aggregates $review_t = 0; $price_t = 0; $value_t = 0; $sub_total = 0; $ratings_var = 0; $review_count = count($pro->reviews); $count = $review_count; $onlyrev = []; foreach ($pro->reviews as $review) { $review_t = $review->qty * 5; $price_t = $review->price * 5; $value_t = $review->value * 5; $sub_total = $sub_total + $review_t + $price_t + $value_t; } $denom = ($count * 3) * 5; $overallrating = 0; if ($denom > 0) { $rat = $sub_total / $denom; $ratings_var = ($rat * 100) / 5; $overallrating = ($ratings_var / 2) / 10; } $overallRoundedHalf = floor($overallrating * 2) / 2; // Resolve active variant axes ($pro->variants = AddProductVariant rows; one per attribute axis). // Each row has attr_name = ProductAttribute id, attr_value = JSON array of ProductValue ids. $variantAxes = []; // [ [attribute, valueIds[], selectedValueId|null], ... ] $selectedMap = []; // [attribute_id => value_id] picked from query string foreach ($pro->variants ?? [] as $axisRow) { $attr = \App\ProductAttributes::find($axisRow->attr_name); if (!$attr) continue; $rawValues = $axisRow->attr_value; $valueIds = is_array($rawValues) ? $rawValues : (array) (json_decode((string) $rawValues, true) ?: []); $valueIds = array_values(array_filter(array_map('intval', $valueIds))); if (!$valueIds) continue; $param = request()->query($attr->attr_name); $selected = (is_numeric($param) && in_array((int) $param, $valueIds, true)) ? (int) $param : null; if ($selected !== null) $selectedMap[$attr->id] = $selected; $variantAxes[] = ['attr' => $attr, 'values' => $valueIds, 'selected' => $selected]; } // Pick the subvariant matching every selected axis; fall back to first. $activeVariant = null; foreach ($pro->subvariants as $sv) { $svMap = is_array($sv->main_attr_value) ? $sv->main_attr_value : (array) (json_decode((string) $sv->main_attr_value, true) ?: []); $matchAll = true; foreach ($selectedMap as $aid => $vid) { if (!isset($svMap[$aid]) || (int) $svMap[$aid] !== (int) $vid) { $matchAll = false; break; } } if ($matchAll) { $activeVariant = $sv; break; } } $firstVariant = $activeVariant ?? ($pro->subvariants[0] ?? null); // For axes with no explicit selection, default to whatever the active variant carries. if ($firstVariant) { $svMap = is_array($firstVariant->main_attr_value) ? $firstVariant->main_attr_value : (array) (json_decode((string) $firstVariant->main_attr_value, true) ?: []); foreach ($variantAxes as $i => $axis) { if ($axis['selected'] === null && isset($svMap[$axis['attr']->id])) { $variantAxes[$i]['selected'] = (int) $svMap[$axis['attr']->id]; } } } // Build a query-string preserver so clicking a value flips just that axis. $detailSlug = $pro->slug ?: \Illuminate\Support\Str::slug($pro->name) ?: 'product'; $buildAxisUrl = function ($attrName, $valueId) use ($pro, $variantAxes, $detailSlug) { $params = []; foreach ($variantAxes as $a) { $name = $a['attr']->attr_name; $val = ($name === $attrName) ? $valueId : $a['selected']; if ($val !== null) $params[$name] = $val; } return url('details/' . $detailSlug . '/' . $pro->id) . ($params ? ('?' . http_build_query($params)) : ''); }; $variantImages = $firstVariant && $firstVariant->variantimages ? $firstVariant->variantimages : null; // Compute price using the same helper as the product cards so the detail page // and the cards always agree (mainprice = MRP / strike-through; offerprice = sale). $variantPrice = 0; $variantCompare = null; $disPct = 0; if ($firstVariant) { $priceResp = ProductPrice::getprice($pro, $firstVariant)->getData(); $mp = (float) ($priceResp->mainprice ?? 0); $op = (float) ($priceResp->offerprice ?? 0); $variantPrice = ($op > 0 && $op < $mp) ? $op : $mp; $variantCompare = ($op > 0 && $op < $mp) ? $mp : null; $disPct = ($variantCompare && $variantPrice > 0) ? round((1 - $variantPrice / $variantCompare) * 100) : 0; } // Stock status $totalStock = 0; foreach ($pro->subvariants as $sv) { $totalStock += $sv->stock ?? 0; } // Hide prices for guests when "login to view price" is enabled in general settings. $hidePrice = (\App\Genral::first()->login ?? 0) == 1 && !auth()->check(); // Warranty (stored as w_d + w_my unit + w_type label, e.g. "1 year Warranty") $warrantyParts = array_filter([ trim((string) ($pro->w_d ?? '')), trim((string) ($pro->w_my ?? '')), trim((string) ($pro->w_type ?? '')), ], function($v){ return $v !== ''; }); $warrantyLabel = $warrantyParts ? implode(' ', $warrantyParts) : ''; // Real per-product policy facts (drives the trust badges, the Delivery card, and any other // module that wants to surface what this product actually offers). $returnDays = optional(\App\Genral::first())->return_in_days ?? 30; $hasWarranty = $warrantyLabel !== ''; $hasReturn = ($pro->return_avbl == '1'); $hasCancel = ($pro->cancel_avl == 1); $hasFreeShip = ($pro->free_shipping == 1); $hasCOD = ($pro->codcheck == 1); $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'], ]; @endphp {{-- Breadcrumbs --}}
{{-- LEFT: Gallery card --}}
@if($variantImages) @php // Build the list of available product images. Prefer the // thumbnail copy when it exists; if the thumb is missing // (admin uploaded but thumb wasn't generated) fall back // to the original image so it still renders instead of // being silently dropped. $imgs = []; $thumbsDir = public_path('variantimages/thumbnails/'); $originalDir = public_path('variantimages/'); foreach (['main_image','image2','image3','image4','image5'] as $field) { $f = $variantImages->{$field} ?? null; if (!$f) continue; if (is_file($thumbsDir . $f)) { $imgs[] = url('variantimages/thumbnails/' . $f); } elseif (is_file($originalDir . $f)) { $imgs[] = url('variantimages/' . $f); } } @endphp @foreach($imgs as $i => $imgsrc) @endforeach @endif
@php $mainSrc = url('images/no-image.png'); if ($variantImages && $variantImages->main_image) { $mainFile = $variantImages->main_image; if (is_file(public_path('variantimages/thumbnails/' . $mainFile))) { $mainSrc = url('variantimages/thumbnails/' . $mainFile); } elseif (is_file(public_path('variantimages/' . $mainFile))) { $mainSrc = url('variantimages/' . $mainFile); } } @endphp {{ $pro->name }} @if($firstVariant) @endif
{{-- Action buttons --}}
@if($hidePrice) {{ __('Login to purchase') }} @elseif($firstVariant && $totalStock > 0)
@csrf
{{ __('Buy now') }} @else @endif
{{-- Trust badges (real per-product flags) --}} @if(count($tiles))
@foreach($tiles as $tile)
{!! $tile['svg'] !!}
{{ $tile['label'] }}
{{ $tile['sub'] }}
@endforeach
@endif
{{-- RIGHT: Info column --}}
{{-- Title block --}}
@if(isset($pro->store) && $pro->store) {{ $pro->store->name ?? $pro->store }} · @endif {{ $title ?? 'Emart' }} {{ __('Assured') }}

{{ $pro->name }}

@if($overallrating > 0)
{{ number_format($overallrating, 1) }}
@endif {{ $review_count }} {{ __('Reviews') }} | @if($totalStock > 0) {{ __('In Stock') }} @else {{ __('Out of Stock') }} @endif
✓ 100% {{ __('Authentic') }} @if($disPct > 0) ⚡ {{ __('Special Deal') }} @endif {{ __('Free Shipping') }}
{{-- Price block --}}
@if($hidePrice)
{{ __('Login to view price') }}
{{ __('Sign in') }} @else @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') }}

@endif
{{-- Variant picker --}}
@foreach($variantAxes as $axis) @php $attr = $axis['attr']; $isColour = in_array(strtolower($attr->attr_name), ['color', 'colour']); $selectedVal = $axis['selected']; $selectedLabel = ''; if ($selectedVal) { $selObj = \App\ProductValues::find($selectedVal); $selectedLabel = $selObj ? trim($selObj->values . ($selObj->unit_value && strcasecmp($selObj->values, $selObj->unit_value) !== 0 && !$isColour ? ' ' . $selObj->unit_value : '')) : ''; } @endphp
{{ str_replace('_', ' ', $attr->attr_name) }}: @if($selectedLabel !== '') {{ $selectedLabel }} @endif
@foreach($axis['values'] as $valId) @php $val = \App\ProductValues::find($valId); if (!$val) continue; // Find the subvariant whose map[attr_id] = $valId for swatch image / stock. $svMatch = null; foreach ($pro->subvariants as $sv) { $svMap = is_array($sv->main_attr_value) ? $sv->main_attr_value : (array) (json_decode((string) $sv->main_attr_value, true) ?: []); if (isset($svMap[$attr->id]) && (int) $svMap[$attr->id] === (int) $valId) { $svMatch = $sv; break; } } $isActive = ((int) $selectedVal === (int) $valId); $href = $buildAxisUrl($attr->attr_name, $valId); $oos = $svMatch && (int) ($svMatch->stock ?? 0) <= 0; @endphp @if($isColour) @if($svMatch && $svMatch->variantimages && $svMatch->variantimages->image1 && file_exists(public_path('variantimages/' . $svMatch->variantimages->image1))) {{ $val->values }} @else @endif @if($isActive) @endif @else {{ $val->values }}@if($val->unit_value && strcasecmp($val->values, $val->unit_value) !== 0) {{ $val->unit_value }}@endif @endif @endforeach
@endforeach
{{-- Quantity --}} @if($firstVariant)
{{ __('Quantity') }}
@if($totalStock < 10 && $totalStock > 0) {{ __('Only') }} {{ $totalStock }} {{ __('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($pro->store) && $pro->store) @php $storeLogoFile = $pro->store->store_logo ?? null; $storeLogoUrl = $storeLogoFile && file_exists(public_path('images/store/logo/' . $storeLogoFile)) ? url('images/store/logo/' . $storeLogoFile) : null; @endphp
@if($storeLogoUrl) {{ $pro->store->name }} @else {{ strtoupper(substr($pro->store->name ?? 'S', 0, 2)) }} @endif
{{ $pro->store->name ?? __('Authorised Seller') }}
{{ __('Authorised seller') }} · {{ __('Verified') }}
@if(isset($pro->store->id)) {{ __('View store') }} @endif
@endif
{{-- HIGHLIGHTS + ABOUT --}}

{{ __('Highlights') }}

@php $highlightItems = []; // Prefer explicit `tags` (comma-separated), fall back to key_features stripped of HTML. $tags = trim((string) ($pro->tags ?? '')); if ($tags !== '') { foreach (explode(',', $tags) as $tag) { $tag = trim($tag); if ($tag !== '') $highlightItems[] = $tag; } } if (empty($highlightItems) && !empty($pro->key_features)) { $kf = strip_tags(str_replace(['', '

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

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

{!! $pro->des !!}
{{-- SPECIFICATIONS + WARRANTY/POLICIES --}} @php $specs = []; if (!empty($pro->brand) && !empty($pro->brand->name)) $specs[__('Brand')] = $pro->brand->name; if (!empty($pro->model)) $specs[__('Model')] = $pro->model; if (!empty($pro->sku)) $specs[__('SKU')] = $pro->sku; if (!empty($pro->hsn)) $specs[__('HSN Code')]= $pro->hsn; if ($firstVariant && !empty($firstVariant->weight)) { $specs[__('Weight')] = trim($firstVariant->weight . ' ' . ($firstVariant->w_unit ?? '')); } if (!empty($pro->tax_name)) $specs[__('Tax')] = $pro->tax_name . (isset($pro->tax_r) ? ' (' . $pro->tax_r . '%)' : ''); if (!empty($pro->category->title)) $specs[__('Category')] = $pro->category->title; if (!empty($pro->subcategory->title)) $specs[__('Subcategory')] = $pro->subcategory->title; if (!empty($pro->childcat->title)) $specs[__('Section')] = $pro->childcat->title; @endphp @if(!empty($specs))

{{ __('Specifications') }}

@foreach($specs as $label => $value)
{{ $label }}
{{ $value }}
@endforeach
@endif {{-- REVIEWS --}} @php // Real rating distribution (5..1) computed from reviews $ratingBuckets = [5=>0, 4=>0, 3=>0, 2=>0, 1=>0]; foreach (($pro->reviews ?? []) 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

{{ __('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(count($pro->reviews))
@foreach($pro->reviews->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->title ?? null)

{{ $r->title }}

@endif

{{ $r->message ?? $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