@php $purposeIsRent = $property->listing_purpose === 'for_rent'; $purposeLabel = $purposeIsRent ? 'For Rent' : 'For Sale'; $typeLabel = $propertyTypes[$property->type] ?? ucfirst(str_replace('-', ' ', $property->type)); $bhk = \App\Models\Property::bhkDisplayNumber($property->type_details['bhk'] ?? null); // Never `location` (the free-text "Full Address" field) — exact // address must never reach a public page (PUB-12); it's excluded at // the query level too (see PublicPropertySearchService::DETAIL_COLUMNS). $localityCity = (string) $property->city; $trimNumber = fn ($n) => rtrim(rtrim(number_format((float) $n, 2, '.', ''), '0'), '.'); $areaLabel = $trimNumber($property->area) . ' ' . $property->area_unit; // The "second spec box" (alongside Area) is genuinely different data per // property type, not a copy of Area — flat/bungalow have a real bhk // count; plot has real width x depth dimensions (see // PropertyFieldTemplateSeeder's 'width_ft'/'depth_ft'); every other type // (agricultural_land, commercial, ...) has no such distinct field today, // so only Area renders for those rather than showing the same value // twice under two different labels. $plotWidth = $property->type === 'plot' ? ($property->type_details['width_ft'] ?? null) : null; $plotDepth = $property->type === 'plot' ? ($property->type_details['depth_ft'] ?? null) : null; $plotSizeLabel = (filled($plotWidth) && filled($plotDepth)) ? $trimNumber($plotWidth) . ' x ' . $trimNumber($plotDepth) . ' ft' : null; $specs = [['k' => 'Type', 'v' => $typeLabel]]; if ($bhk) { $specs[] = ['k' => 'Configuration', 'v' => $bhk . ' BHK']; } elseif ($plotSizeLabel) { $specs[] = ['k' => 'Plot Size', 'v' => $plotSizeLabel]; } $specs[] = ['k' => 'Area', 'v' => $areaLabel]; $specs[] = ['k' => 'Purpose', 'v' => $purposeLabel]; $images = $property->images; $canonicalUrl = route('public.properties.show', ['slug' => $property->public_slug, 'id' => $property->id]); $imageUrls = $images->map(fn ($image) => route('public.properties.photo', $image))->values(); $metaDescription = Str::limit(strip_tags((string) $property->description), 155) ?: ($typeLabel . ' ' . $purposeLabel . ' in ' . $localityCity); // RealEstateListing JSON-LD — built from exactly the same public fields // shown on this page (PUB-11). No owner/coordinates/notes/price-history, // no field not already rendered above (PUB-12). $jsonLd = [ '@context' => 'https://schema.org', '@type' => 'RealEstateListing', 'name' => $property->title, 'description' => $metaDescription, 'url' => $canonicalUrl, 'datePosted' => optional($property->created_at)->toAtomString(), ]; if ($imageUrls->isNotEmpty()) { $jsonLd['image'] = $imageUrls->all(); } if ($localityCity) { $jsonLd['address'] = [ '@type' => 'PostalAddress', 'addressLocality' => $property->city, 'addressCountry' => 'IN', ]; } $offer = [ '@type' => 'Offer', 'priceCurrency' => 'INR', 'availability' => 'https://schema.org/InStock', 'businessFunction' => $purposeIsRent ? 'http://purl.org/goodrelations/v1#LeaseOut' : 'http://purl.org/goodrelations/v1#Sell', ]; if (! $property->price_on_request && $property->price) { $offer['price'] = (string) $property->price; } $jsonLd['offers'] = $offer; if ($bhk) { $jsonLd['numberOfRooms'] = (int) $bhk; } if ($property->area) { $jsonLd['floorSize'] = [ '@type' => 'QuantitativeValue', 'value' => (float) $property->area, 'unitText' => $property->area_unit, ]; } @endphp @extends('layouts.public') @section('title', $property->title . ' | Agrawal Properties') @section('meta_description', $metaDescription) @push('head') @if ($imageUrls->isNotEmpty()) @endif @endpush @section('content')
@include('partials.site._breadcrumbs', ['crumbs' => [ ['label' => 'Home', 'url' => route('public.home')], ['label' => $breadcrumbParentLabel, 'url' => $breadcrumbParentUrl], ['label' => $property->title], ]])
@if ($images->isNotEmpty()) @if ($images->count() > 1) {{-- The cover image is included here too (as the first thumbnail, marked active by default) so it stays selectable after viewing another photo — without it, there'd be no way back to the cover once you'd clicked away from it. Clicking any thumbnail only ever updates #galleryMainImg's own src/alt (see the script below) — the thumbnail row itself is never reordered or mutated, so the row's order stays fixed regardless of which thumbnail is currently active. Scroll arrows only render once there are more thumbs than fit in one row (4) — with 4 or fewer there's nothing to scroll to, so the buttons would be dead weight. --}}
@if ($images->count() > 4) @endif @if ($images->count() > 4) @endif
@endif @else @endif
{{ $typeLabel }} · {{ $purposeLabel }}

{{ $property->title }}

@if ($localityCity)
{{ $localityCity }}
@endif
{{ $property->formattedPrice() }}
@foreach ($specs as $spec)
{{ $spec['k'] }}
{{ $spec['v'] }}
@endforeach

About this property

{{ $property->description ?: 'No description provided yet.' }}

@if ($property->tags->isNotEmpty())

Amenities & features

@foreach ($property->tags as $tag)
{{ $tag->name }}
@endforeach
@endif
@if ($images->isNotEmpty()) {{-- Enlarge lightbox — opened by clicking the main gallery image, shows ONLY whatever photo is currently the main image, large, over a dark overlay. No Prev/Next here — navigating between photos still happens via the thumbnail row behind the modal (or the thumb-scroll arrows), not inside the lightbox itself. --}} @endif @include('partials.site._related-properties') @push('scripts') @endpush @endsection