Map integration updated

This commit is contained in:
akash 2025-12-05 23:20:44 +05:30
parent 1b4729145a
commit 2a9404d1e5
6 changed files with 1767 additions and 106 deletions

View File

@ -21,7 +21,7 @@ export default function CompareBar() {
<span className="font-semibold text-foreground">Compare Properties ({compareList.length}/4)</span> <span className="font-semibold text-foreground">Compare Properties ({compareList.length}/4)</span>
</div> </div>
<div className="flex gap-3"> <div className="flex gap-3 pt-3 pr-3">
{compareList.map((property) => ( {compareList.map((property) => (
<div key={property.id} className="relative group flex-shrink-0"> <div key={property.id} className="relative group flex-shrink-0">
<div className="w-20 h-20 rounded-lg overflow-hidden border-2 border-gray-200 dark:border-gray-700"> <div className="w-20 h-20 rounded-lg overflow-hidden border-2 border-gray-200 dark:border-gray-700">

View File

@ -21,7 +21,7 @@ export default function Header() {
return ( return (
<> <>
<header <header
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${isScrolled className={`fixed top-0 left-0 right-0 z-[6000] transition-all duration-300 ${isScrolled
? "bg-white/5 dark:bg-black/5 backdrop-blur-md shadow-sm py-4" ? "bg-white/5 dark:bg-black/5 backdrop-blur-md shadow-sm py-4"
: "bg-transparent py-6" : "bg-transparent py-6"
}`} }`}

View File

@ -84,10 +84,10 @@ export default function PropertyCard({ property }: PropertyCardProps) {
{/* Status Badge */} {/* Status Badge */}
{property.status && ( {property.status && (
<div className={`absolute top-4 left-4 px-3 py-1 rounded-full text-xs font-semibold ${property.status === "Sold Out" <div className={`absolute top-4 left-4 px-3 py-1 rounded-full text-xs font-semibold ${property.status === "Sold Out"
? "bg-red-500 text-white" ? "bg-red-500 text-white"
: property.status === "New Launch" : property.status === "New Launch"
? "bg-green-500 text-white" ? "bg-green-500 text-white"
: "bg-white/90 text-gray-900" : "bg-white/90 text-gray-900"
}`}> }`}>
{property.status} {property.status}
</div> </div>
@ -98,14 +98,26 @@ export default function PropertyCard({ property }: PropertyCardProps) {
<button <button
onClick={handleCompareClick} onClick={handleCompareClick}
className={`p-2 rounded-full shadow-lg transition-all ${inCompare className={`p-2 rounded-full shadow-lg transition-all ${inCompare
? "bg-primary text-white scale-110" ? "bg-primary text-white scale-110"
: "bg-white hover:bg-gray-100 text-gray-700" : "bg-white hover:bg-gray-100 text-gray-700"
}`} }`}
aria-label={inCompare ? "Remove from compare" : "Add to compare"} aria-label={inCompare ? "Remove from compare" : "Add to compare"}
> >
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /> xmlns="http://www.w3.org/2000/svg"
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8 7h8v10H8zM4 11h8v10H4z"
/>
</svg> </svg>
</button> </button>
<button <button
onClick={handleShareClick} onClick={handleShareClick}
@ -119,8 +131,8 @@ export default function PropertyCard({ property }: PropertyCardProps) {
<button <button
onClick={handleWishlistClick} onClick={handleWishlistClick}
className={`p-2 rounded-full shadow-lg transition-all ${isWishlisted className={`p-2 rounded-full shadow-lg transition-all ${isWishlisted
? "bg-red-500 text-white scale-110" ? "bg-red-500 text-white scale-110"
: "bg-white hover:bg-gray-100 text-gray-700" : "bg-white hover:bg-gray-100 text-gray-700"
}`} }`}
aria-label={isWishlisted ? "Remove from wishlist" : "Add to wishlist"} aria-label={isWishlisted ? "Remove from wishlist" : "Add to wishlist"}
> >

File diff suppressed because it is too large Load Diff

View File

@ -1,151 +1,313 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import Image from "next/image"; import Image from "next/image";
interface PropertyGalleryProps { interface PropertyGalleryProps {
images: string[]; images: string[];
title: string; title: string;
} }
export default function PropertyGallery({ images, title }: PropertyGalleryProps) { export default function PropertyGallery({ images, title }: PropertyGalleryProps) {
const [activeImage, setActiveImage] = useState(0); const [activeImage, setActiveImage] = useState(0);
const [showLightbox, setShowLightbox] = useState(false); const [showLightbox, setShowLightbox] = useState(false);
const [lightboxIndex, setLightboxIndex] = useState(0); const [lightboxIndex, setLightboxIndex] = useState(0);
const openLightbox = (index: number) => { const openLightbox = (index: number) => {
setLightboxIndex(index); setLightboxIndex(index);
setShowLightbox(true); setShowLightbox(true);
document.body.style.overflow = 'hidden'; document.body.style.overflow = 'hidden';
}; };
const closeLightbox = () => { const closeLightbox = () => {
setShowLightbox(false); setShowLightbox(false);
document.body.style.overflow = 'unset'; document.body.style.overflow = 'unset';
}; };
// Ensure we have at least 5 images for the gallery (1 big + 4 small)
const displayImages = [...images];
while (displayImages.length < 5) {
displayImages.push("/assets/images/image.png");
}
const nextImage = () => { const nextImage = () => {
setLightboxIndex((prev) => (prev + 1) % images.length);
setLightboxIndex((prev) => (prev + 1) % displayImages.length);
}; };
const prevImage = () => { const prevImage = () => {
setLightboxIndex((prev) => (prev - 1 + images.length) % images.length);
setLightboxIndex((prev) => (prev - 1 + displayImages.length) % displayImages.length);
}; };
return ( return (
<> <>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<div className="md:col-span-2 relative h-[500px] rounded-2xl overflow-hidden group cursor-pointer" onClick={() => openLightbox(activeImage)}> <div className="md:col-span-2 relative h-[500px] rounded-2xl overflow-hidden group cursor-pointer" onClick={() => openLightbox(activeImage)}>
<Image <Image
src={images[activeImage]}
src={displayImages[activeImage]}
alt={title} alt={title}
fill fill
className="object-cover transition-transform duration-300 group-hover:scale-105" className="object-cover transition-transform duration-300 group-hover:scale-105"
/> />
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors duration-300" /> <div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors duration-300" />
<div className="absolute bottom-4 right-4 bg-black/70 text-white px-3 py-1.5 rounded-lg text-sm opacity-0 group-hover:opacity-100 transition-opacity"> <div className="absolute bottom-4 right-4 bg-black/70 text-white px-3 py-1.5 rounded-lg text-sm opacity-0 group-hover:opacity-100 transition-opacity">
Click to enlarge Click to enlarge
</div> </div>
</div> </div>
<div className="grid grid-cols-2 md:grid-cols-1 gap-4">
{images.slice(0, 2).map((img, idx) => ( <div className="grid grid-cols-2 grid-rows-2 gap-4 h-[500px]">
{displayImages.slice(0, 3).map((img, idx) => (
<div <div
key={idx} key={idx}
onClick={() => setActiveImage(idx)} onClick={() => setActiveImage(idx)}
className={`relative h-[160px] rounded-xl overflow-hidden cursor-pointer transition-all duration-300 ${activeImage === idx ? 'ring-4 ring-primary scale-105' : 'hover:scale-105'
className={`relative w-full h-full rounded-xl overflow-hidden cursor-pointer transition-all duration-300 ${activeImage === idx ? 'ring-4 ring-primary scale-95' : 'hover:scale-95'
}`} }`}
> >
<Image src={img} alt={`View ${idx + 1}`} fill className="object-cover" /> <Image src={img} alt={`View ${idx + 1}`} fill className="object-cover" />
</div> </div>
))} ))}
{/* View All Photos Button */}
{/* View All Photos Button (4th slot) */}
<div <div
onClick={() => openLightbox(0)} onClick={() => openLightbox(0)}
className="relative h-[160px] rounded-xl overflow-hidden cursor-pointer group"
className="relative w-full h-full rounded-xl overflow-hidden cursor-pointer group"
> >
<Image <Image
src={images[2] || images[0]}
src={displayImages[3]}
alt="View all photos" alt="View all photos"
fill fill
className="object-cover" className="object-cover"
/> />
<div className="absolute inset-0 bg-black/60 group-hover:bg-black/70 transition-colors flex flex-col items-center justify-center text-white"> <div className="absolute inset-0 bg-black/60 group-hover:bg-black/70 transition-colors flex flex-col items-center justify-center text-white">
<svg className="w-10 h-10 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-10 h-10 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg> </svg>
<span className="font-semibold text-lg">View All Photos</span> <span className="font-semibold text-lg">View All Photos</span>
<span className="text-sm opacity-90">({images.length} images)</span>
<span className="text-sm opacity-90">({displayImages.length} images)</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Lightbox Modal */} {/* Lightbox Modal */}
{showLightbox && ( {showLightbox && (
<div className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center"> <div className="fixed inset-0 z-50 bg-black/95 flex items-center justify-center">
{/* Close Button */} {/* Close Button */}
<button <button
onClick={closeLightbox} onClick={closeLightbox}
className="absolute top-4 right-4 text-white hover:text-gray-300 transition-colors z-10" className="absolute top-4 right-4 text-white hover:text-gray-300 transition-colors z-10"
aria-label="Close gallery" aria-label="Close gallery"
> >
<svg className="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg> </svg>
</button> </button>
{/* Image Counter */} {/* Image Counter */}
<div className="absolute top-4 left-1/2 -translate-x-1/2 text-white text-lg font-medium bg-black/50 px-4 py-2 rounded-full"> <div className="absolute top-4 left-1/2 -translate-x-1/2 text-white text-lg font-medium bg-black/50 px-4 py-2 rounded-full">
{lightboxIndex + 1} / {images.length}
{lightboxIndex + 1} / {displayImages.length}
</div> </div>
{/* Previous Button */} {/* Previous Button */}
<button <button
onClick={prevImage} onClick={prevImage}
className="absolute left-4 text-white hover:text-gray-300 transition-colors p-2 bg-black/50 rounded-full hover:bg-black/70" className="absolute left-4 text-white hover:text-gray-300 transition-colors p-2 bg-black/50 rounded-full hover:bg-black/70"
aria-label="Previous image" aria-label="Previous image"
> >
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg> </svg>
</button> </button>
{/* Main Image */} {/* Main Image */}
<div className="relative w-full h-full max-w-6xl max-h-[90vh] mx-4"> <div className="relative w-full h-full max-w-6xl max-h-[90vh] mx-4">
<Image <Image
src={images[lightboxIndex]}
src={displayImages[lightboxIndex]}
alt={`${title} - Image ${lightboxIndex + 1}`} alt={`${title} - Image ${lightboxIndex + 1}`}
fill fill
className="object-contain" className="object-contain"
/> />
</div> </div>
{/* Next Button */} {/* Next Button */}
<button <button
onClick={nextImage} onClick={nextImage}
className="absolute right-4 text-white hover:text-gray-300 transition-colors p-2 bg-black/50 rounded-full hover:bg-black/70" className="absolute right-4 text-white hover:text-gray-300 transition-colors p-2 bg-black/50 rounded-full hover:bg-black/70"
aria-label="Next image" aria-label="Next image"
> >
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg> </svg>
</button> </button>
{/* Thumbnail Strip */} {/* Thumbnail Strip */}
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 overflow-x-auto max-w-[90vw] px-4 py-2 bg-black/50 rounded-lg hide-scrollbar"> <div className="absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 overflow-x-auto max-w-[90vw] px-4 py-2 bg-black/50 rounded-lg hide-scrollbar">
{images.map((img, idx) => (
{displayImages.map((img, idx) => (
<div <div
key={idx} key={idx}
onClick={() => setLightboxIndex(idx)} onClick={() => setLightboxIndex(idx)}
className={`relative w-20 h-20 flex-shrink-0 rounded-lg overflow-hidden cursor-pointer transition-all ${lightboxIndex === idx ? 'ring-4 ring-white scale-110' : 'opacity-60 hover:opacity-100' className={`relative w-20 h-20 flex-shrink-0 rounded-lg overflow-hidden cursor-pointer transition-all ${lightboxIndex === idx ? 'ring-4 ring-white scale-110' : 'opacity-60 hover:opacity-100'
}`} }`}
> >
<Image src={img} alt={`Thumbnail ${idx + 1}`} fill className="object-cover" /> <Image src={img} alt={`Thumbnail ${idx + 1}`} fill className="object-cover" />
</div> </div>
))} ))}
</div> </div>
</div> </div>
)} )}
</> </>
); );
}
}

View File

@ -44,7 +44,7 @@ export default function PropertyNav({ sections }: PropertyNavProps) {
}; };
return ( return (
<div className="sticky top-28 z-[1000] bg-white/95 dark:bg-gray-900/95 backdrop-blur-md border-b border-gray-200 dark:border-gray-800 shadow-sm"> <div className="sticky top-28 z-[5000] bg-white/95 dark:bg-gray-900/95 backdrop-blur-md border-b border-gray-200 dark:border-gray-800 shadow-sm">
<div className="max-w-7xl mx-auto px-6"> <div className="max-w-7xl mx-auto px-6">
<nav className="flex gap-1 overflow-x-auto hide-scrollbar py-3"> <nav className="flex gap-1 overflow-x-auto hide-scrollbar py-3">
{sections.map((section) => ( {sections.map((section) => (