sky-and-soil/src/components/PropertyDetailClient.tsx

2502 lines
112 KiB
TypeScript

"use client";
import { useState, ChangeEvent, FormEvent, useEffect } from "react";
import Footer from "@/components/Footer";
import PropertyGallery from "@/components/PropertyGallery";
import PropertyNav from "@/components/PropertyNav";
import InnerBanner from "@/components/InnerBanner";
import { Property } from "@/data/properties";
import axios from "axios";
import { useCompare } from "@/context/CompareContext";
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { motion } from "framer-motion";
const AnimateSection = ({ children, className, id, direction = "left" }: { children: React.ReactNode, className?: string, id?: string, direction?: "left" | "right" | "up" | "down" }) => {
const variants = {
hidden: {
opacity: 0,
scale: direction === "left" || direction === "right" ? 0.95 : 1,
y: direction === "up" ? 30 : direction === "down" ? -30 : 0
},
visible: { opacity: 1, scale: 1, y: 0 }
};
return (
<motion.div
id={id}
className={className}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-50px" }}
transition={{ duration: 0.6, ease: "easeOut" }}
variants={variants}
>
{children}
</motion.div>
);
};
const getOverviewIcon = (type: string) => {
switch (type) {
case "land":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
</svg>
);
case "metro":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
);
case "road":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
</svg>
);
case "openArea":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
);
case "density":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v7a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 16a1 1 0 011-1h4a1 1 0 011 1v3a1 1 0 01-1 1H5a1 1 0 01-1-1v-3zM14 16a1 1 0 011-1h4a1 1 0 011 1v3a1 1 0 01-1 1h-4a1 1 0 01-1-1v-3z" />
</svg>
);
case "clubhouse":
return (
<svg className="w-5 h-5 text-gray-700 dark:text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
);
default:
return null;
}
};
const ConnectivityMap = dynamic(() => import('./ConnectivityMap'), {
ssr: false,
loading: () => <div className="h-[450px] w-full bg-gray-100 animate-pulse rounded-xl" />
});
interface FormData {
name: string;
email: string;
phone: string;
message: string;
}
interface FormErrors {
name?: string;
email?: string;
phone?: string;
}
const sections = [
{ id: "overview", label: "Overview" },
{ id: "pricing", label: "Pricing" },
{ id: "connectivity", label: "Connectivity" },
{ id: "master-plan", label: "Master Plan" },
{ id: "floor-plans", label: "Floor Plans" },
{ id: "amenities", label: "Amenities" },
// { id: "challenges", label: "Challenges" },
{ id: "approvals", label: "Approvals" },
{ id: "builder", label: "Builder" },
{ id: "locality", label: "Locality" },
{ id: "faq", label: "FAQ's" },
];
export default function PropertyDetailClient({ property }: { property: Property }) {
const [formData, setFormData] = useState<FormData>({
name: "",
email: "",
phone: "",
message: "",
});
const [formErrors, setFormErrors] = useState<FormErrors>({});
const [alert, setAlert] = useState<{ show: boolean; type: string; message: string }>({
show: false,
type: "",
message: "",
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
const [isConnectivityExpanded, setIsConnectivityExpanded] = useState(false);
const [activeMapTab, setActiveMapTab] = useState("Transit");
const [isMapEnabled, setIsMapEnabled] = useState(false);
const [isLightboxOpen, setIsLightboxOpen] = useState(false);
const [isAmenitiesModalOpen, setIsAmenitiesModalOpen] = useState(false);
const [isAmenitiesLoading, setIsAmenitiesLoading] = useState(false);
const [activeFaqTab, setActiveFaqTab] = useState('Services');
const [expandedFaq, setExpandedFaq] = useState<number | null>(null);
const { addToCompare, removeFromCompare, isInCompare } = useCompare();
const isCompared = isInCompare(property.id);
const [isWishlisted, setIsWishlisted] = useState(false);
const handleShare = async () => {
if (navigator.share) {
try {
await navigator.share({
title: property.title,
text: `Check out this property: ${property.title} in ${property.location}`,
url: window.location.href,
});
} catch (error) {
console.log('Error sharing:', error);
}
} else {
// Fallback to clipboard
navigator.clipboard.writeText(window.location.href);
setAlert({
show: true,
type: 'success',
message: 'Link copied to clipboard!'
});
}
};
const handleWishlist = () => {
setIsWishlisted(!isWishlisted);
setAlert({
show: true,
type: 'success',
message: !isWishlisted ? 'Added to your wishlist!' : 'Removed from your wishlist'
});
};
const handlePrint = () => {
window.print();
};
const handleCompareToggle = () => {
if (isCompared) {
removeFromCompare(property.id);
setAlert({
show: true,
type: 'success',
message: 'Removed from compare list'
});
} else {
addToCompare(property);
setAlert({
show: true,
type: 'success',
message: 'Added to compare list'
});
}
};
// Helper for icons
const getAmenityIcon = (name: string) => {
switch (name) {
case "Gym - Indoor":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3" /></svg>;
case "Gym - Outdoor":
case "Running Track":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>;
case "Kids Play Area":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>;
case "Amphitheatre":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" /></svg>;
case "Cafe/Restaurant":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /></svg>;
case "Badminton":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /></svg>;
case "Basketball":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" /></svg>;
case "Cricket Ground":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>;
case "Cricket Pitch":
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" /></svg>;
default:
return <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" /></svg>;
}
};
const faqData = property.faq || {};
const floorPlans = property.floorPlans || [];
// Initialize activeFloorPlan with the first plan's ID if available
const [activeFloorPlan, setActiveFloorPlan] = useState<string>("");
useEffect(() => {
if (floorPlans.length > 0 && !activeFloorPlan) {
setActiveFloorPlan(floorPlans[0].id);
}
}, [floorPlans, activeFloorPlan]);
const activePlanDetails = floorPlans.find(plan => plan.id === activeFloorPlan) || (floorPlans.length > 0 ? floorPlans[0] : null);
const handleSeeAllAmenities = () => {
setIsAmenitiesLoading(true);
setTimeout(() => {
setIsAmenitiesLoading(false);
setIsAmenitiesModalOpen(true);
}, 500);
};
const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
// Clear error when user types
if (formErrors[name as keyof FormErrors]) {
setFormErrors(prev => ({ ...prev, [name]: undefined }));
}
};
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
const errors: FormErrors = {};
if (!formData.name.trim()) errors.name = "Name is required.";
if (!formData.phone.trim()) errors.phone = "Phone number is required.";
if (!formData.email.trim()) errors.email = "Email is required.";
setFormErrors(errors);
if (Object.keys(errors).length > 0) return;
setIsSubmitting(true);
const emailData = {
name: formData.name,
phone: formData.phone,
email: formData.email,
subject: `Property Inquiry: ${property?.title} from ${formData.name}`,
message: `<strong>Property Inquiry</strong><br /><br />
<strong>Property:</strong> ${property?.title}<br />
<strong>Location:</strong> ${property?.location}<br />
<strong>Price:</strong> ${property?.price}<br /><br />
<strong>Customer Details:</strong><br />
Name: ${formData.name}<br />
Phone: ${formData.phone}<br />
Email: ${formData.email}<br />
Message: ${formData.message || 'N/A'}`,
to: "hello@skyandsoil.com",
senderName: "Sky and Soil Property Inquiry",
};
try {
const res = await axios.post("https://mailserver.metatronnest.com/send", emailData, {
headers: { "Content-Type": "application/json" },
});
setAlert({
show: true,
type: "success",
message: res?.data?.message || "Request sent successfully! We will contact you soon.",
});
setFormData({ name: "", email: "", phone: "", message: "" });
setFormErrors({});
} catch (error) {
setAlert({
show: true,
type: "danger",
message: "Failed to send request. Please try again later.",
});
} finally {
setIsSubmitting(false);
}
};
useEffect(() => {
if (alert.show) {
const timer = setTimeout(() => {
setAlert(prev => ({ ...prev, show: false }));
}, 5000);
return () => clearTimeout(timer);
}
}, [alert.show]);
return (
<div className="min-h-screen bg-gray-50 dark:bg-black">
<InnerBanner
title={property.title}
subtitle={property.location}
breadcrumbs={[
{ label: "Home", href: "/" },
{ label: "Projects", href: "/projects" },
{ label: "Residential Real Estate", href: "/residential-real-estate" },
{ label: property.title }
]}
backgroundImage={property.image}
/>
<div>
{/* Sticky Navigation */}
<PropertyNav sections={sections} />
<div className="max-w-7xl mx-auto px-6 py-8">
{/* Image Gallery */}
<AnimateSection direction="up">
<PropertyGallery images={property.images} title={property.title} />
</AnimateSection>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mt-8">
{/* Main Content */}
<div className="lg:col-span-2 space-y-8">
{/* Property Header */}
<div className="bg-white dark:bg-gray-900 rounded-2xl p-6 md:p-8 shadow-sm border border-gray-200 dark:border-gray-800">
{/* Title and Price Row */}
<div className="flex flex-col space-y-4 mb-6">
{/* Title */}
<h1 className="text-2xl md:text-3xl lg:text-4xl font-bold text-gray-900 dark:text-white">
{property.title}
</h1>
{/* Location and Price */}
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-content-center gap-9">
<div className="flex items-center text-gray-600 dark:text-gray-400">
<svg className="w-5 h-5 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
</svg>
<span className="text-base text-md md:text-lg">{property.location}</span>
</div>
<div className="text-xl md:text-2xl lg:text-3xl font-bold text-gray-900 dark:text-white">
{property.price}
</div>
</div>
</div>
{/* Stats Row with Icons */}
<div className="flex flex-wrap items-center gap-4 md:gap-6 pt-6 border-t border-gray-200 dark:border-gray-800">
{/* Possession */}
<div className="flex items-center gap-2">
<svg className="w-5 h-5 text-gray-500 dark:text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<div className="flex items-baseline gap-1">
<span className="text-sm text-gray-600 dark:text-gray-400">Possession:</span>
<span className="text-sm font-semibold text-gray-900 dark:text-white">{property.overview.possession}</span>
</div>
</div>
{/* Area/Plot */}
<div className="flex items-center gap-2">
<svg className="w-5 h-5 text-gray-500 dark:text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
<div className="flex items-baseline gap-1">
<span className="text-sm text-gray-600 dark:text-gray-400">{property.category === "Plots" ? "Plot" : property.overview.bhk} -</span>
<span className="text-sm font-semibold text-gray-900 dark:text-white">{property.overview.size}</span>
</div>
</div>
{/* Sky&Soil Score */}
<div className="flex items-center gap-2">
<svg className="w-5 h-5 text-gray-500 dark:text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div className="flex items-center gap-2">
<span className="text-sm text-gray-600 dark:text-gray-400">Sky&Soil Score:</span>
<div className="flex items-center gap-1">
{[1, 2, 3, 4, 5].map((star) => {
const score = property.skyAndSoilScore || 4;
const isFilled = star <= Math.floor(score);
const isHalf = !isFilled && star === Math.ceil(score) && score % 1 !== 0;
return (
<svg
key={star}
className={`w-4 h-4 ${isFilled ? 'text-orange-400' : isHalf ? 'text-orange-400' : 'text-gray-300 dark:text-gray-600'
}`}
fill={isFilled || isHalf ? 'currentColor' : 'none'}
stroke="currentColor"
viewBox="0 0 24 24"
>
{isHalf ? (
<>
<defs>
<linearGradient id={`half-${star}`}>
<stop offset="50%" stopColor="currentColor" />
<stop offset="50%" stopColor="transparent" />
</linearGradient>
</defs>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={1.5}
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
fill={`url(#half-${star})`}
/>
</>
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={isFilled ? 0 : 1.5}
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
/>
)}
</svg>
);
})}
</div>
</div>
</div>
</div>
</div>
{/* Overview Section */}
<AnimateSection id="overview" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="left">
{/* Header Row: Title Left, Badges Right, Subtitle Right */}
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4 mb-8">
{/* Left Side: Title and Builder */}
<div>
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-2">Overview</h2>
<p className="text-gray-600 dark:text-gray-400">
{property.title} by <span className="text-primary font-medium">{property.builder?.name || "Builder"}</span>
</p>
</div>
{/* Right Side: Badges and Subtitle */}
<div className="flex flex-col items-start lg:items-end gap-3">
{/* Badges Row */}
<div className="flex items-center gap-2 flex-wrap">
{property.overview.badges?.map((badge, index) => (
<span key={index} className={`px-3 py-1.5 rounded-full text-sm font-medium ${badge === "Better" || badge === "Green Living" || badge === "Lake View" || badge === "Skyline Views"
? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" :
badge === "Average" || badge === "Premium" || badge === "Luxury" || badge === "Elite"
? "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400" :
"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
}`}>
{badge}
</span>
))}
</div>
{/* Subtitle Text */}
<p className="text-gray-500 dark:text-gray-400 text-sm lg:text-right">
Average is based on comparable projects in {property.locality?.name || "this area"}
</p>
</div>
</div>
{/* Info Grid - 2 rows x 3 columns */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{property.overview.stats?.map((stat, index) => {
const getBgColor = (index: number) => {
const colors = [
"bg-green-50 dark:bg-green-900/10 border-green-100 dark:border-green-800/30 text-green-600 dark:text-green-400",
"bg-blue-50 dark:bg-blue-900/10 border-blue-100 dark:border-blue-800/30 text-blue-600 dark:text-blue-400",
"bg-blue-50 dark:bg-blue-900/10 border-blue-100 dark:border-blue-800/30 text-blue-600 dark:text-blue-400",
"bg-red-50 dark:bg-red-900/10 border-red-100 dark:border-red-800/30 text-red-600 dark:text-red-400",
"bg-blue-50 dark:bg-blue-900/10 border-blue-100 dark:border-blue-800/30 text-blue-600 dark:text-blue-400",
"bg-blue-50 dark:bg-blue-900/10 border-blue-100 dark:border-blue-800/30 text-blue-600 dark:text-blue-400"
];
return colors[index % colors.length];
};
const bgColorClass = getBgColor(index).split(' ').slice(0, 2).join(' '); // Extract bg classes
const borderColorClass = getBgColor(index).split(' ').slice(2, 4).join(' '); // Extract border classes
const textColorClass = getBgColor(index).split(' ').slice(4).join(' '); // Extract text classes
// Simplified color logic to avoid complex parsing, just use alternating or specific based on type if needed.
// For now, let's use a simpler approach based on the original code
let bgClass = "bg-blue-50 dark:bg-blue-900/10 border border-blue-100 dark:border-blue-800/30";
let textClass = "text-blue-600 dark:text-blue-400";
if (stat.icon === 'land') {
bgClass = "bg-green-50 dark:bg-green-900/10 border border-green-100 dark:border-green-800/30";
textClass = "text-blue-600 dark:text-blue-400";
} else if (stat.icon === 'openArea') {
bgClass = "bg-red-50 dark:bg-red-900/10 border border-red-100 dark:border-red-800/30";
textClass = "text-red-600 dark:text-red-400";
}
return (
<div key={index} className={`${bgClass} rounded-xl p-6`}>
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-white dark:bg-gray-800 rounded-lg flex items-center justify-center">
{getOverviewIcon(stat.icon)}
</div>
</div>
<div className="text-2xl font-bold text-gray-900 dark:text-white mb-1">{stat.value}</div>
<div className="text-sm font-medium text-gray-900 dark:text-white mb-1">{stat.label}</div>
<div className={`text-xs ${textClass}`}>{stat.subtext}</div>
</div>
);
})}
</div>
</AnimateSection>
<AnimateSection className="space-y-4" direction="left">
<div className={`relative ${!isConnectivityExpanded ? 'max-h-[60px] overflow-hidden' : ''}`}>
<p className="text-gray-700 dark:text-gray-300 leading-relaxed">
<span className="text-blue-500 mr-2"></span>
{property.overview.description || property.connectivity?.description || `${property.title} is located in ${property.location}.`}
</p>
{!isConnectivityExpanded && (
<div className="absolute bottom-0 left-0 right-0 h-10 bg-gradient-to-t from-white dark:from-gray-900 to-transparent"></div>
)}
</div>
<button
onClick={() => setIsConnectivityExpanded(!isConnectivityExpanded)}
className="text-blue-500 font-medium hover:text-blue-600 transition-colors mt-2 text-sm underline"
>
{isConnectivityExpanded ? "Read less" : "Read more"}
</button>
</AnimateSection>
{/* Info Cards Grid */}
<AnimateSection className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-8" direction="right">
{/* RERA Card */}
<div className="bg-cyan-50 dark:bg-cyan-900/20 rounded-2xl p-6 flex flex-col items-center text-center border border-cyan-100 dark:border-cyan-800/30">
<div className="w-12 h-12 mb-4 relative">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-12 h-12 text-blue-600">
<path fillRule="evenodd" d="M12.516 2.17a.75.75 0 00-1.032 0 11.209 11.209 0 01-7.877 3.08.75.75 0 00-.722.515A12.74 12.74 0 002.25 9.75c0 5.942 4.064 10.933 9.563 12.348a.749.749 0 00.374 0c5.499-1.415 9.563-6.406 9.563-12.348 0-1.352-.272-2.636-.759-3.808a.75.75 0 00-.722-.515 11.209 11.209 0 01-7.877-3.08zM12 13.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z" clipRule="evenodd" />
</svg>
<div className="absolute bottom-0 right-0 bg-white rounded-full p-0.5">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-4 h-4 text-green-500">
<path fillRule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" clipRule="evenodd" />
</svg>
</div>
</div>
<h3 className="font-bold text-gray-900 dark:text-white mb-2">{property.title} is {property.reraInfo?.isApproved ? 'approved by RERA' : 'pending RERA approval'}</h3>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6">{property.reraInfo?.isApproved && `It was approved on ${property.reraInfo.approvalDate}`}</p>
<button className="w-full py-2.5 px-4 bg-white dark:bg-transparent border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-semibold text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors mt-auto">
View RERA details
</button>
</div>
{/* Brochure Card */}
<div className="bg-purple-50 dark:bg-purple-900/20 rounded-2xl p-6 flex flex-col items-center text-center border border-purple-100 dark:border-purple-800/30">
<div className="w-12 h-12 mb-4 text-purple-400">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-12 h-12">
<path d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0016.5 9h-1.875a1.875 1.875 0 01-1.875-1.875V5.25A3.75 3.75 0 009 1.5H5.625z" />
<path d="M12.971 1.816A5.23 5.23 0 0114.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 013.434 1.279 9.768 9.768 0 00-6.963-6.963z" />
</svg>
</div>
<h3 className="font-bold text-gray-900 dark:text-white mb-2">{property.brochureCard?.title || `See ${property.title} brochure`}</h3>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6">{property.brochureCard?.description || "Download the detailed brochure"}</p>
<button className="w-full py-2.5 px-4 bg-white dark:bg-transparent border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-semibold text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors mt-auto">
Download Brochure
</button>
</div>
{/* Pros & Cons Card */}
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-2xl p-6 flex flex-col items-center text-center border border-blue-100 dark:border-blue-800/30">
<div className="w-12 h-12 mb-4 text-purple-500 relative">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-12 h-12">
<path d="M11.25 4.533A9.707 9.707 0 006 3.75a9.753 9.753 0 00-3.255.555.75.75 0 00-.575.69v9.12c0 .266.183.505.435.58 1.86.556 3.867.556 5.722 0 .253-.075.436-.314.436-.58v-9.12a.75.75 0 00-.575-.69zM12.75 4.533c.58.194 1.177.34 1.78.435v9.12c0 .266.183.505.435.58 1.86.556 3.867.556 5.722 0 .253-.075.436-.314.436-.58v-9.12a.75.75 0 00-.575-.69 9.753 9.753 0 00-3.255-.555 9.707 9.707 0 00-5.25.784v-9.12c0-.266.183-.505.435-.58a9.709 9.709 0 015.25-.784z" />
</svg>
<div className="absolute -bottom-1 -right-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6 text-gray-700">
<path d="M8.25 10.875a2.625 2.625 0 115.25 0 2.625 2.625 0 01-5.25 0z" />
<path fillRule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zm-1.125 4.5a4.125 4.125 0 102.338 7.524l2.007 2.006a.75.75 0 101.06-1.06l-2.006-2.007a4.125 4.125 0 00-3.399-6.463z" clipRule="evenodd" />
</svg>
</div>
</div>
<h3 className="font-bold text-gray-900 dark:text-white mb-2">{property.prosConsCard?.title || "See the truth beyond the brochures"}</h3>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6">{property.prosConsCard?.description || "See every risk & potential clearly with our experts"}</p>
<button className="w-full py-2.5 px-4 bg-blue-500 hover:bg-blue-600 text-white rounded-lg text-sm font-semibold transition-colors mt-auto shadow-md shadow-blue-500/20">
{property.prosConsCard?.buttonText || "Get Pros & Cons"}
</button>
</div>
</AnimateSection>
{/* Pricing Section - Moved and Redesigned */}
<AnimateSection id="pricing" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="right">
<h2 className="text-3xl font-bold text-foreground mb-2">Pricing</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">Last updated on {property.pricingUpdateDate || "Recently"}</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-4 gap-4 md:gap-8">
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Total Range</div>
<div className="text-2xl font-bold text-foreground whitespace-nowrap">{property.pricingDetails?.totalRange || property.price}</div>
</div>
<div>
<div className="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 mb-1">
Monthly EMI
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4 text-blue-500">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clipRule="evenodd" />
</svg>
</div>
<div className="text-2xl font-bold text-foreground whitespace-nowrap">{property.pricingDetails?.emi || "N/A"}</div>
</div>
<div>
<div className="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 mb-1">
Project's Avg.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4 text-blue-500">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clipRule="evenodd" />
</svg>
</div>
<div className="text-2xl font-bold text-foreground">{property.pricingDetails?.projectAvg || "N/A"}</div>
</div>
<div>
<div className="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 mb-1">
Market Avg.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4 text-blue-500">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clipRule="evenodd" />
</svg>
</div>
<div className="text-2xl font-bold text-foreground">{property.pricingDetails?.marketAvg || "N/A"}</div>
</div>
</div>
</AnimateSection>
{/* Connectivity Section (Formerly Location) */}
<AnimateSection id="connectivity" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="left">
<h2 className="text-3xl font-bold text-foreground mb-2">Connectivity</h2>
<p className="text-gray-500 dark:text-gray-400 mb-6">{property.title}</p>
<div className="mb-8">
<div className={`relative ${!isConnectivityExpanded ? 'max-h-[60px] overflow-hidden' : ''}`}>
<p className="text-gray-700 dark:text-gray-300 leading-relaxed">
<span className="text-blue-500 mr-2">✦</span>
{property.connectivity?.description || `${property.title} is located in ${property.location}.`}
</p>
{!isConnectivityExpanded && (
<div className="absolute bottom-0 left-0 right-0 h-10 bg-gradient-to-t from-white dark:from-gray-900 to-transparent"></div>
)}
</div>
<button
onClick={() => setIsConnectivityExpanded(!isConnectivityExpanded)}
className="text-blue-500 font-medium hover:text-blue-600 transition-colors mt-2 text-sm underline"
>
{isConnectivityExpanded ? "Read less" : "Read more"}
</button>
</div>
{/* Map Interface */}
<ConnectivityMap />
</AnimateSection>
{/* Master Plan Section */}
<AnimateSection id="master-plan" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="right">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
<div>
<h2 className="text-3xl font-bold text-foreground mb-2">Master Plan</h2>
<p className="text-gray-500 dark:text-gray-400">
{property.masterPlan?.description || "Master plan details unavailable."}
</p>
</div>
<button className="bg-orange-500 hover:bg-orange-600 text-white px-4 py-3 rounded-xl font-semibold text-base transition-colors shadow-md whitespace-nowrap md:ml-6">
Compare Sanction Plan
</button>
</div>
{/* Master Plan Image */}
<div
className="relative rounded-xl overflow-hidden border border-gray-100 dark:border-gray-700 cursor-zoom-in group mb-8"
onClick={() => setIsLightboxOpen(true)}
>
<img
src={property.masterPlan?.image || "/assets/images/image.png"}
alt="Master Plan"
className="w-full h-auto object-cover hover:scale-105 transition-transform duration-500"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors flex items-center justify-center opacity-0 group-hover:opacity-100">
<span className="bg-white/90 text-gray-900 px-4 py-2 rounded-full text-sm font-medium shadow-lg backdrop-blur-sm">
Click to zoom
</span>
</div>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 border-t border-gray-100 dark:border-gray-800 pt-8">
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Total Units</div>
<div className="text-lg font-semibold text-foreground">{property.masterPlan?.totalUnits || "N/A"}</div>
</div>
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Water Source</div>
<div className="flex items-center gap-2">
<span className="text-lg font-semibold text-foreground">{property.masterPlan?.waterSource || "N/A"}</span>
<span className="bg-orange-100 text-orange-600 text-xs px-2 py-0.5 rounded-full font-medium">+1</span>
</div>
</div>
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Park Area</div>
<div className="text-lg font-semibold text-foreground">{property.masterPlan?.parkArea || "N/A"}</div>
</div>
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Land type</div>
<div className="text-lg font-semibold text-foreground">{property.masterPlan?.landType || "N/A"}</div>
</div>
</div>
</AnimateSection>
{/* Sky & Soil Clarity Engine Section */}
<AnimateSection className="py-12" direction="up">
<div className="text-center mb-12">
<h2 className="text-3xl md:text-4xl font-bold text-foreground mb-3">The Sky & Soil Clarity Engine</h2>
<p className="text-gray-500 dark:text-gray-400 text-lg flex items-center justify-center gap-2">
300+ families found safer homes with Sky & Soil. You could be next
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{/* Card 1: Compare */}
<div className="bg-orange-50 dark:bg-orange-900/10 rounded-2xl p-6 flex flex-col items-center text-center relative overflow-hidden group hover:shadow-lg transition-shadow duration-300">
{/* Decorative Circle */}
<div className="absolute -top-10 -right-10 w-32 h-32 bg-orange-100 dark:bg-orange-800/20 rounded-full blur-2xl"></div>
<div className="w-24 h-24 mb-6 relative z-10">
{/* House Icon Placeholder - Using SVG for 3D feel */}
<svg viewBox="0 0 200 200" className="w-full h-full drop-shadow-xl">
<path fill="#FDBA74" d="M100 20L20 90h20v90h40v-60h40v60h40V90h20L100 20z" />
<path fill="#FB923C" d="M120 180v-60H80v60H40V90H20L100 20l80 70h-20v90h-40z" opacity="0.5" />
<circle cx="140" cy="140" r="30" fill="#22C55E" />
<path fill="#FFF" d="M130 140l10 10 20-20" stroke="#FFF" strokeWidth="5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2">Like this project?</h3>
<h3 className="text-md font-bold text-gray-900 dark:text-white mb-4">Compare it with the rest</h3>
<p className="text-gray-600 dark:text-gray-400 mb-8 leading-relaxed">
Compare 2 properties side by side on 40+ parameters like connectivity, layout, price, specs and more
</p>
<button className="w-full py-3 px-6 bg-transparent border-2 border-gray-900 dark:border-white rounded-lg text-sm font-bold text-gray-900 dark:text-white hover:bg-gray-900 hover:text-white dark:hover:bg-white dark:hover:text-gray-900 transition-colors mt-auto">
Compare With Peers
</button>
</div>
{/* Card 2: Negotiate (Green) */}
<div className="bg-green-50 dark:bg-green-900/10 rounded-2xl p-6 pt-12 flex flex-col items-center text-center relative overflow-hidden group hover:shadow-lg transition-shadow duration-300 border-green-500">
{/* Trusted Badge */}
<div className="absolute top-0 left-0 right-0 bg-green-500 text-white text-xs font-bold py-1.5 uppercase tracking-wider">
{property.skyandsoilClarity?.familiesHelped}
</div>
{/* Sparkles */}
<div className="absolute top-10 left-4 text-green-300">
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2L14.5 9.5L22 12L14.5 14.5L12 22L9.5 14.5L2 12L9.5 9.5L12 2Z" /></svg>
</div>
<div className="w-24 h-24 mb-6 relative z-10">
{/* Trophy Icon */}
<svg viewBox="0 0 24 24" className="w-full h-full drop-shadow-xl text-green-500" fill="currentColor">
<path d="M20 2H4C2.9 2 2 2.9 2 4V6C2 8.21 3.79 10 6 10H6.17C6.58 11.86 7.84 13.42 9.5 14.24V16H8C6.9 16 6 16.9 6 18V20C6 21.1 6.9 22 8 22H16C17.1 22 18 21.1 18 20V18C18 16.9 17.1 16 16 16H14.5V14.24C16.16 13.42 17.42 11.86 17.83 10H18C20.21 10 22 8.21 22 6V4C22 2.9 21.1 2 20 2ZM6 8C4.9 8 4 7.1 4 6V4H6V8ZM18 8V4H20V6C20 7.1 19.1 8 18 8Z" />
</svg>
</div>
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2">Pay less. Get more.</h3>
<h3 className="text-md font-bold text-gray-900 dark:text-white mb-4">Let us negotiate for you.</h3>
<p className="text-gray-600 dark:text-gray-400 mb-8 leading-relaxed">
Get a free Peace of Mind report, solid negotiations & a loyalty reward up to ₹3.29 Lakhs when you work with us
</p>
<button className="w-full py-3 px-6 bg-green-500 hover:bg-green-600 text-white rounded-lg text-sm font-bold transition-colors mt-auto shadow-lg shadow-green-500/30">
Get Pros & Cons
</button>
</div>
{/* Card 3: Report (Purple) */}
<div className="bg-purple-50 dark:bg-purple-900/10 rounded-2xl p-6 flex flex-col items-center text-center relative overflow-hidden group hover:shadow-lg transition-shadow duration-300">
{/* Decorative Triangle */}
<div className="absolute top-0 right-0 w-24 h-24 bg-purple-200 dark:bg-purple-800/30 transform rotate-45 translate-x-12 -translate-y-12"></div>
<div className="w-24 h-24 mb-6 relative z-10">
{/* Report Icon */}
<svg viewBox="0 0 200 200" className="w-full h-full drop-shadow-xl text-purple-500">
<path fill="#E9D5FF" d="M60 20h80l40 40v120H60V20z" />
<path fill="currentColor" d="M80 60h60v10H80zM80 90h60v10H80zM80 120h40v10H80z" />
<circle cx="140" cy="140" r="30" fill="#A855F7" />
<path fill="none" stroke="#FFF" strokeWidth="4" d="M130 140l5 5 15-15" />
</svg>
</div>
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2">Almost convinced?</h3>
<h3 className="text-md font-bold text-gray-900 dark:text-white mb-4">See what we uncovered</h3>
<p className="text-gray-600 dark:text-gray-400 mb-8 leading-relaxed">
Ideal if you've already visited and close to deciding. Our Peace of Mind report shows you what builders won't.
</p>
<button className="w-full py-3 px-6 bg-transparent border-2 border-gray-900 dark:border-white rounded-lg text-sm font-bold text-gray-900 dark:text-white hover:bg-gray-900 hover:text-white dark:hover:bg-white dark:hover:text-gray-900 transition-colors mt-auto">
See Sample Report
</button>
</div>
</div>
</AnimateSection>
{/* Floor Plans Section */}
<AnimateSection id="floor-plans" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="right">
<h2 className="text-3xl font-bold text-foreground mb-2">Floor Plans</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">
{property.floorPlans && property.floorPlans.length > 0
? `${property.title} has configurations ranging from ${property.floorPlans[0].area} to ${property.floorPlans[property.floorPlans.length - 1].area}.`
: "Floor plans details coming soon."}
</p>
{/* Tabs */}
<div className="flex items-center gap-4 mb-6">
<div className="flex-1 overflow-x-auto flex gap-3 pb-2 scrollbar-hide">
{floorPlans.map((plan) => (
<button
key={plan.id}
onClick={() => setActiveFloorPlan(plan.id)}
className={`px-6 py-2 rounded-full text-sm font-medium whitespace-nowrap transition-all ${activeFloorPlan === plan.id
? "bg-orange-50 text-orange-500 border border-orange-200"
: "bg-white text-gray-600 border border-gray-200 hover:border-gray-300 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-700"
}`}
>
{plan.id}
</button>
))}
</div>
<div className="flex gap-2">
<button
onClick={() => {
const currentIndex = floorPlans.findIndex(p => p.id === activeFloorPlan);
if (currentIndex > 0) {
setActiveFloorPlan(floorPlans[currentIndex - 1].id);
}
}}
disabled={floorPlans.findIndex(p => p.id === activeFloorPlan) === 0}
className="p-2 rounded-full bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-5 h-5 text-gray-600 dark:text-gray-400">
<path fillRule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clipRule="evenodd" />
</svg>
</button>
<button
onClick={() => {
const currentIndex = floorPlans.findIndex(p => p.id === activeFloorPlan);
if (currentIndex < floorPlans.length - 1) {
setActiveFloorPlan(floorPlans[currentIndex + 1].id);
}
}}
disabled={floorPlans.findIndex(p => p.id === activeFloorPlan) === floorPlans.length - 1}
className="p-2 rounded-full bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-5 h-5 text-gray-600 dark:text-gray-400">
<path fillRule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clipRule="evenodd" />
</svg>
</button>
</div>
</div>
{/* Active Plan Details Card */}
{activePlanDetails && (
<div className="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl p-8 flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
<div className="space-y-6 flex-1">
<div className="flex items-baseline gap-4">
<h3 className="text-3xl font-medium text-gray-900 dark:text-white">{activePlanDetails.id}</h3>
<span className="text-2xl font-bold text-gray-900 dark:text-white">{activePlanDetails.price}</span>
</div>
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Saleable Area</div>
<div className="text-lg font-medium text-gray-900 dark:text-white">{activePlanDetails.area}</div>
</div>
<div>
<div className="text-sm text-gray-500 dark:text-gray-400 mb-1">Direction(s)</div>
<div className="text-lg font-medium text-gray-900 dark:text-white">{activePlanDetails.direction}</div>
</div>
</div>
</div>
)}
</AnimateSection>
{/* Amenities Section */}
<AnimateSection id="amenities" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="left">
<h2 className="text-3xl font-bold text-foreground mb-2">Amenities</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">{property.title}</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
{/* Lifestyle */}
<div>
<h3 className="text-xl font-medium text-gray-900 dark:text-white mb-6">Lifestyle Amenities</h3>
<ul className="space-y-4">
{property.detailedAmenities?.Lifestyle?.map((item, idx) => (
<li key={idx} className={`flex items-center gap-3 ${!item.available ? 'opacity-40 grayscale' : ''}`}>
<div className={`w-6 h-6 ${item.available ? 'text-purple-600' : 'text-gray-400'}`}>
{/* Icon rendering logic can be improved here if needed, for now assuming icons are handled or passed */}
{getOverviewIcon(item.name.toLowerCase().replace(" ", "")) || (
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
)}
</div>
<span className={`text-base ${!item.available ? 'text-gray-400 line-through decoration-gray-400' : 'text-purple-600 font-medium'}`}>
{item.name}
</span>
</li>
))}
</ul>
</div>
{/* Sports */}
<div>
<h3 className="text-xl font-medium text-gray-900 dark:text-white mb-6">Sports Amenities</h3>
<ul className="space-y-4">
{property.detailedAmenities?.Sports?.map((item, idx) => (
<li key={idx} className={`flex items-center gap-3 ${!item.available ? 'opacity-40 grayscale' : ''}`}>
<div className={`w-6 h-6 ${item.available ? 'text-purple-600' : 'text-gray-400'}`}>
{/* Icon rendering logic can be improved here if needed, for now assuming icons are handled or passed */}
{getOverviewIcon(item.name.toLowerCase().replace(" ", "")) || (
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
)}
</div>
<span className={`text-base ${!item.available ? 'text-gray-400 line-through decoration-gray-400' : 'text-purple-600 font-medium'}`}>
{item.name}
</span>
</li>
))}
</ul>
</div>
{/* Natural */}
<div>
<h3 className="text-xl font-medium text-gray-900 dark:text-white mb-6">Natural Amenities</h3>
<ul className="space-y-4">
{property.detailedAmenities?.Natural?.map((item, idx) => (
<li key={idx} className={`flex items-center gap-3 ${!item.available ? 'opacity-40 grayscale' : ''}`}>
<div className={`w-6 h-6 ${item.available ? 'text-purple-600' : 'text-gray-400'}`}>
{getOverviewIcon(item.name.toLowerCase().replace(" ", "")) || (
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
)}
</div>
<span className={`text-base ${!item.available ? 'text-gray-400 line-through decoration-gray-400' : 'text-purple-600 font-medium'}`}>
{item.name}
</span>
</li>
))}
</ul>
</div>
</div>
<button
onClick={handleSeeAllAmenities}
disabled={isAmenitiesLoading}
className="mt-10 px-6 py-3 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-bold text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors min-w-[160px] flex items-center justify-center"
>
{isAmenitiesLoading ? (
<span className="flex items-center gap-2">
<svg className="animate-spin h-4 w-4 text-gray-700 dark:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Loading...
</span>
) : (
"See all amenities"
)}
</button>
</AnimateSection>
{/* Approvals Section */}
<AnimateSection id="approvals" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="right">
<h2 className="text-3xl font-bold text-foreground mb-2">Approvals</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">
{property.title} by <span className="text-primary font-medium">Modern Spaaces</span> has received 4 out of 4 important approvals as per RERA
</p>
{/* Approvals List - Two Column Grid */}
<ul className="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-3 mb-12">
{property.approvals?.map((approval, index) => (
<li key={index} className="flex items-start gap-3">
<span className="inline-block w-1.5 h-1.5 rounded-full bg-gray-700 dark:bg-gray-300 mt-2.5 flex-shrink-0"></span>
<span className="text-gray-900 dark:text-white font-medium">{approval.name}</span>
</li>
))}
</ul>
{/* Documents Subsection */}
<h3 className="text-2xl font-bold text-foreground mb-2">Documents</h3>
<p className="text-gray-500 dark:text-gray-400 mb-8">
Curated documents from various sources for {property.title} by {property.builder?.name || "Builder"}
</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{property.documents?.map((doc, index) => (
<a
key={index}
href={doc.pdfUrl || "#"}
target="_blank"
rel="noopener noreferrer"
className="bg-blue-50 dark:bg-blue-900/10 rounded-xl p-6 flex flex-col h-full relative group hover:shadow-md transition-all cursor-pointer"
>
<div className="absolute top-6 right-6 text-gray-400">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-4 h-4">
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
</div>
<div className="w-12 h-12 mb-4 text-gray-700 dark:text-gray-300">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-10 h-10">
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
</svg>
</div>
<h4 className="font-bold text-gray-900 dark:text-white mb-2">{doc.title}</h4>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-8 flex-grow leading-relaxed">
{doc.description}
</p>
<span className="text-sm font-bold text-gray-900 dark:text-white hover:underline text-left inline-block">
See Document
</span>
</a>
))}
</div>
</AnimateSection>
{/* About the Builder Section */}
<AnimateSection id="builder" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="left">
<h2 className="text-3xl font-bold text-foreground mb-2">About the builder</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">{property.builder?.name || "Builder"}</p>
<div className="flex flex-col md:flex-row gap-12">
<div className="flex-1">
<p className="text-gray-600 dark:text-gray-300 leading-relaxed mb-8">
{property.builder?.description}
</p>
<Link href={`/buy/property-for-sale-in-bengaluru?search=${encodeURIComponent(property.builder?.name || "")}`} className="text-blue-600 dark:text-blue-400 font-bold hover:underline">
See all properties by {property.builder?.name || "this builder"}
</Link>
</div>
<div className="w-full md:w-1/3 space-y-8">
<div>
<h4 className="text-sm text-gray-500 dark:text-gray-400 mb-1">Established On</h4>
<p className="text-xl font-bold text-gray-900 dark:text-white">{property.builder?.establishedYear || "N/A"}</p>
</div>
<div>
<h4 className="text-sm text-gray-500 dark:text-gray-400 mb-1">Completed Projects</h4>
<p className="text-xl font-bold text-gray-900 dark:text-white">{property.builder?.completedProjects || "N/A"}</p>
</div>
</div>
</div>
</AnimateSection>
{/* Locality Section */}
<AnimateSection id="locality" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="right">
<h2 className="text-3xl font-bold text-foreground mb-2">Locality</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">{property.locality?.name || "Bangalore"}</p>
{/* Large Image */}
<div className="relative rounded-2xl overflow-hidden mb-8 h-[300px] group">
<img
src={property.locality?.mapImage || "/assets/images/map-placeholder.webp"}
alt={`Map of ${property.locality?.name} Locality`}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent flex flex-col justify-end p-8">
<h3 className="text-3xl font-bold text-white">{property.locality?.name || "Locality"}</h3>
</div>
</div>
<p className="text-gray-600 dark:text-gray-300 leading-relaxed mb-12">
{property.locality?.description}
</p>
{/* Gauges */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-4">
{/* Developing */}
<div className="flex flex-col items-center text-center">
<div className="relative w-48 h-24 mb-4 overflow-hidden">
<div className="absolute top-0 left-0 w-full h-full bg-orange-100 rounded-t-full"></div>
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-r from-orange-200 to-orange-500 rounded-t-full origin-bottom transform rotate-[-45deg]" style={{ clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0 100%)' }}></div>
<div className="absolute bottom-0 left-1/2 w-1 h-12 bg-orange-600 origin-bottom transform -translate-x-1/2 rotate-[-45deg]"></div>
</div>
<h4 className="text-xl font-bold text-gray-900 dark:text-white">Developing</h4>
<p className="text-sm text-gray-500 dark:text-gray-400">Living Experience</p>
</div>
{/* Medium */}
<div className="flex flex-col items-center text-center">
<div className="relative w-48 h-24 mb-4 overflow-hidden">
<div className="absolute top-0 left-0 w-full h-full bg-orange-100 rounded-t-full"></div>
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-r from-orange-200 to-orange-500 rounded-t-full origin-bottom transform rotate-[0deg]" style={{ clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0 100%)' }}></div>
<div className="absolute bottom-0 left-1/2 w-1 h-12 bg-orange-600 origin-bottom transform -translate-x-1/2 rotate-[0deg]"></div>
</div>
<h4 className="text-xl font-bold text-gray-900 dark:text-white">Medium</h4>
<p className="text-sm text-gray-500 dark:text-gray-400">Investment Potential</p>
</div>
{/* Moderate */}
<div className="flex flex-col items-center text-center">
<div className="relative w-48 h-24 mb-4 overflow-hidden">
<div className="absolute top-0 left-0 w-full h-full bg-orange-100 rounded-t-full"></div>
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-r from-orange-200 to-orange-500 rounded-t-full origin-bottom transform rotate-[45deg]" style={{ clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0 100%)' }}></div>
<div className="absolute bottom-0 left-1/2 w-1 h-12 bg-orange-600 origin-bottom transform -translate-x-1/2 rotate-[45deg]"></div>
</div>
<h4 className="text-xl font-bold text-gray-900 dark:text-white">Moderate</h4>
<p className="text-sm text-gray-500 dark:text-gray-400">Price Range</p>
</div>
</div>
{/* Checkout Nearby Properties Section */}
<AnimateSection id="nearby" className="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="left">
<h2 className="text-3xl font-bold text-foreground mb-2">Checkout Nearby Properties</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">
See properties similar to {property.title} by {property.builder?.name || "Builder"} in the same neighbourhood
</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-8">
{/* Property 1 */}
<div className="group cursor-pointer">
<div className="rounded-xl overflow-hidden mb-4 h-48">
<img src="/assets/images/map-placeholder.webp" alt="Nearby property Prestige Raintree Park" className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
</div>
<h4 className="text-lg font-bold text-gray-900 dark:text-white mb-1">Prestige Raintree Park</h4>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-1">3.07 Crores - 5.67 Crores</p>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">Varthur</p>
<button className="text-sm font-medium text-gray-500 dark:text-gray-400 underline hover:text-gray-900 dark:hover:text-white transition-colors">
Compare with this property
</button>
</div>
{/* Property 2 */}
<div className="group cursor-pointer">
<div className="rounded-xl overflow-hidden mb-4 h-48">
<img src="/assets/images/image.png" alt="Nearby property Adarsh Park Heights" className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
</div>
<h4 className="text-lg font-bold text-gray-900 dark:text-white mb-1">Adarsh Park Heights</h4>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-1">1.63 Crores - 2.32 Crores</p>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">Varthur</p>
<button className="text-sm font-medium text-gray-500 dark:text-gray-400 underline hover:text-gray-900 dark:hover:text-white transition-colors">
Compare with this property
</button>
</div>
{/* Property 3 */}
<div className="group cursor-pointer">
<div className="rounded-xl overflow-hidden mb-4 h-48">
<img src="/assets/images/map-placeholder.webp" alt="Nearby property Tru Aquapolis" className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" />
</div>
<h4 className="text-lg font-bold text-gray-900 dark:text-white mb-1">Tru Aquapolis</h4>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-1">2.22 Crores - 3.51 Crores</p>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">Varthur</p>
<button className="text-sm font-medium text-gray-500 dark:text-gray-400 underline hover:text-gray-900 dark:hover:text-white transition-colors">
Compare with this property
</button>
</div>
</div>
<a href="#" className="text-blue-600 dark:text-blue-400 font-bold hover:underline">
See all properties in Varthur
</a>
</AnimateSection>
</AnimateSection>
{/* FAQ Section */}
<AnimateSection id="faq" className="bg-white dark:bg-gray-900 rounded-2xl p-4 md:p-8 shadow-sm border border-gray-200 dark:border-gray-800 scroll-mt-32" direction="up">
<h2 className="text-xl md:text-3xl font-bold text-foreground mb-2">Frequently Asked Questions</h2>
<p className="text-gray-500 dark:text-gray-400 mb-8">
99% of your queries should get answered here, for others, you can always talk to us
</p>
{/* Tabs */}
<div className="bg-gray-100 dark:bg-gray-800 p-1 rounded-lg flex flex-wrap mb-8">
{Object.keys(faqData).map((tab) => (
<button
key={tab}
onClick={() => setActiveFaqTab(tab)}
className={`flex-1 py-3 px-4 text-sm font-medium rounded-md transition-all ${activeFaqTab === tab
? 'bg-white dark:bg-gray-700 text-orange-500 shadow-sm'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
}`}
>
{tab}
</button>
))}
</div>
{/* Accordion List */}
<div className="space-y-4">
{faqData[activeFaqTab]?.map((item, index) => (
<div key={index} className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
<button
onClick={() => setExpandedFaq(expandedFaq === index ? null : index)}
className="w-full flex items-center justify-between p-3 md:p-6 text-left bg-white dark:bg-gray-800
hover:bg-gray-50 dark:hover:bg-gray-750 transition-colors group"
>
<span className="font-medium text-gray-900 dark:text-white pr-8 group-hover:text-blue-600">
{item.question}
</span>
<span className="text-gray-400 group-hover:text-blue-600">
{expandedFaq === index ? (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 12h-15" />
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
)}
</span>
</button>
{expandedFaq === index && (
<div className="p-3 pt-0 md:p-6 md:pt-0 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 leading-relaxed border-t border-gray-100 dark:border-gray-700">
{item.answer}
</div>
)}
</div>
))}
</div>
</AnimateSection>
</div>
{/* Sidebar */}
<div className="lg:col-span-1">
<div className="sticky top-32 space-y-6">
{/* Contact Form */}
<AnimateSection direction="up" className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-2xl p-6 shadow-lg">
<h3 className="text-xl font-bold text-foreground mb-4">Get in Touch</h3>
{alert.show && (
<div className={`mb-4 p-3 rounded-lg text-sm font-medium ${alert.type === 'success' ? 'bg-green-50 text-green-700 border border-green-200' : 'bg-red-50 text-red-700 border border-red-200'}`}>
{alert.message}
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Your Name"
className={`w-full px-4 py-3 border ${formErrors.name ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'} rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent bg-white dark:bg-gray-800 text-foreground transition-all`}
/>
{formErrors.name && <small className="text-red-500 text-xs ml-1">{formErrors.name}</small>}
</div>
<div>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email Address"
className={`w-full px-4 py-3 border ${formErrors.email ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'} rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent bg-white dark:bg-gray-800 text-foreground transition-all`}
/>
{formErrors.email && <small className="text-red-500 text-xs ml-1">{formErrors.email}</small>}
</div>
<div>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
placeholder="Phone Number"
className={`w-full px-4 py-3 border ${formErrors.phone ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'} rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent bg-white dark:bg-gray-800 text-foreground transition-all`}
/>
{formErrors.phone && <small className="text-red-500 text-xs ml-1">{formErrors.phone}</small>}
</div>
<textarea
rows={4}
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Message (Optional)"
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent bg-white dark:bg-gray-800 text-foreground transition-all"
/>
<button
type="submit"
disabled={isSubmitting}
className={`w-full bg-gradient-to-r from-primary to-blue-600 text-white py-3 rounded-lg font-semibold hover:shadow-lg transition-all transform hover:scale-105 ${isSubmitting ? 'opacity-70 cursor-not-allowed' : ''}`}
>
{isSubmitting ? 'Sending...' : 'Request Callback'}
</button>
</form>
</AnimateSection>
{/* Quick Actions */}
<div className="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 rounded-2xl p-6 border border-gray-200 dark:border-gray-700">
<h3 className="text-lg font-bold text-foreground mb-4">Quick Actions</h3>
<div className="space-y-3">
<button
onClick={handleShare}
className="w-full flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg hover:shadow-md transition-all text-foreground"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
</svg>
Share Property
</button>
<button
onClick={handleWishlist}
className={`w-full flex items-center justify-center gap-2 px-4 py-3 border rounded-lg hover:shadow-md transition-all ${isWishlisted
? 'bg-red-50 border-red-200 text-red-600'
: 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-foreground'
}`}
>
<svg
className={`w-5 h-5 ${isWishlisted ? 'fill-current' : 'fill-none'}`}
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
{isWishlisted ? 'Saved to Wishlist' : 'Save to Wishlist'}
</button>
<button
onClick={handlePrint}
className="w-full flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg hover:shadow-md transition-all text-foreground"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z" />
</svg>
Print Details
</button>
<button
onClick={handleCompareToggle}
className={`w-full flex items-center justify-center gap-2 px-4 py-3 border rounded-lg hover:shadow-md transition-all ${isCompared
? 'bg-blue-50 border-blue-200 text-blue-600'
: 'bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-700 text-foreground'
}`}
>
<svg
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>
{isCompared ? 'Added to Compare' : 'Add to Compare'}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div >
<Footer />
{/* Lightbox */}
{
isLightboxOpen && (
<div
className="fixed inset-0 z-[100] bg-black/90 backdrop-blur-sm flex items-center justify-center p-4 animate-in fade-in duration-200"
onClick={() => setIsLightboxOpen(false)}
>
<button
className="absolute top-4 right-4 text-white/70 hover:text-white p-2 rounded-full hover:bg-white/10 transition-colors"
onClick={() => setIsLightboxOpen(false)}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-8 h-8">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<img
src="/assets/images/image.png"
alt="Master Plan Full View"
className="max-w-full max-h-[90vh] object-contain rounded-lg shadow-2xl scale-in-95 duration-200"
onClick={(e) => e.stopPropagation()}
/>
</div>
)
}
{/* Amenities Modal */}
{
isAmenitiesModalOpen && (
<div
className="fixed inset-0 z-[100] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 animate-in fade-in duration-200"
onClick={() => setIsAmenitiesModalOpen(false)}
>
<div
className="bg-white dark:bg-gray-900 w-full max-w-4xl max-h-[90vh] rounded-2xl shadow-2xl overflow-hidden flex flex-col scale-in-95 duration-200"
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div className="p-6 border-b border-gray-100 dark:border-gray-800 flex justify-between items-center">
<div>
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">Amenities</h2>
<p className="text-sm text-gray-500 dark:text-gray-400">Lifestyle</p>
</div>
<button
onClick={() => setIsAmenitiesModalOpen(false)}
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* Content */}
<div className="p-8 overflow-y-auto">
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
{property.detailedAmenities && Object.entries(property.detailedAmenities).flatMap(([category, items]) =>
items.map((item, idx) => (
<div key={`${category}-${idx}`} className="flex flex-col items-center text-center gap-3">
<div className="relative">
<div className={`w-12 h-12 ${item.available ? 'text-purple-600' : 'text-gray-300'} mb-1`}>
{getOverviewIcon(item.name.toLowerCase().replace(" ", "")) || (
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
)}
</div>
{(item as any).rare && (
<span className="absolute -top-2 -right-4 bg-purple-100 text-purple-600 text-[10px] font-bold px-1.5 py-0.5 rounded uppercase tracking-wider">
Rare
</span>
)}
</div>
<span className={`text-sm ${item.available ? 'text-gray-700 dark:text-gray-300' : 'text-gray-400 line-through'}`}>
{item.name}
</span>
</div>
))
)}
</div>
</div>
</div>
</div>
)
}
</div >
);
}