new strucure are updated

This commit is contained in:
akash 2025-12-05 21:43:53 +05:30
parent debfdc8e2b
commit 1b4729145a
5 changed files with 328 additions and 123 deletions

49
package-lock.json generated
View File

@ -8,14 +8,17 @@
"name": "antigravity_dev",
"version": "0.1.0",
"dependencies": {
"@types/leaflet": "^1.9.21",
"@types/react-google-recaptcha": "^2.1.9",
"axios": "^1.13.2",
"leaflet": "^1.9.4",
"lucide-react": "^0.554.0",
"next": "16.0.3",
"next-themes": "^0.4.6",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-google-recaptcha": "^3.1.0",
"react-leaflet": "^5.0.0",
"selenium-webdriver": "^4.38.0",
"sitemap": "^9.0.0",
"tailwindcss-animate": "^1.0.7",
@ -1241,6 +1244,17 @@
"node": ">=12.4.0"
}
},
"node_modules/@react-leaflet/core": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz",
"integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==",
"license": "Hippocratic-2.1",
"peerDependencies": {
"leaflet": "^1.9.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
},
"node_modules/@rtsao/scc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
@ -1546,6 +1560,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/geojson": {
"version": "7946.0.16",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"license": "MIT"
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@ -1560,6 +1580,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/leaflet": {
"version": "1.9.21",
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz",
"integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==",
"license": "MIT",
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/node": {
"version": "20.19.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz",
@ -4687,6 +4716,12 @@
"node": ">=0.10"
}
},
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
"license": "BSD-2-Clause"
},
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@ -5668,6 +5703,20 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/react-leaflet": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz",
"integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==",
"license": "Hippocratic-2.1",
"dependencies": {
"@react-leaflet/core": "^3.0.0"
},
"peerDependencies": {
"leaflet": "^1.9.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",

View File

@ -9,14 +9,17 @@
"lint": "eslint"
},
"dependencies": {
"@types/leaflet": "^1.9.21",
"@types/react-google-recaptcha": "^2.1.9",
"axios": "^1.13.2",
"leaflet": "^1.9.4",
"lucide-react": "^0.554.0",
"next": "16.0.3",
"next-themes": "^0.4.6",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-google-recaptcha": "^3.1.0",
"react-leaflet": "^5.0.0",
"selenium-webdriver": "^4.38.0",
"sitemap": "^9.0.0",
"tailwindcss-animate": "^1.0.7",

View File

@ -0,0 +1,268 @@
"use client";
import { useState, useEffect, useMemo } from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
// Fix for default markers in Next.js
const DefaultIcon = L.icon({
iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',
shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41]
});
L.Marker.prototype.options.icon = DefaultIcon;
// Custom Icons
const createCustomIcon = (color: string, number?: string) => {
return L.divIcon({
className: 'custom-icon',
html: `<div style="
background-color: ${color};
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid white;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
color: white;
font-weight: bold;
font-size: 14px;
">${number || ''}</div>`,
iconSize: [36, 36],
iconAnchor: [18, 18],
});
};
const homeIcon = L.divIcon({
className: 'home-icon',
html: `<div style="
background-color: #7C3AED;
width: 48px;
height: 48px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 4px solid white;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
color: white;
">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" style="width: 28px; height: 28px;">
<path d="M11.47 3.84a.75.75 0 011.06 0l8.69 8.69a.75.75 0 101.06-1.06l-8.689-8.69a2.25 2.25 0 00-3.182 0l-8.69 8.69a.75.75 0 001.061 1.06l8.69-8.69z" />
<path d="M12 5.432l8.159 8.159c.03.03.06.058.091.086v6.198c0 1.035-.84 1.875-1.875 1.875H15a.75.75 0 01-.75-.75v-4.5a.75.75 0 00-.75-.75h-3a.75.75 0 00-.75.75V21a.75.75 0 01-.75.75H5.625a1.875 1.875 0 01-1.875-1.875v-6.198a2.29 2.29 0 00.091-.086L12 5.43z" />
</svg>
</div>`,
iconSize: [48, 48],
iconAnchor: [24, 24],
});
// Mock Data
type LocationData = {
category: string;
items: {
id: number;
name: string;
dist: string;
time: string;
lat: number;
lng: number;
count: number;
}[];
};
const PROPERTY_LOCATION: [number, number] = [12.9385, 77.7297]; // Approximate Varthur
const MOCK_DATA: Record<string, LocationData['items']> = {
'Commute': [
{ id: 1, name: "Dommasandra Circle Metro Station", dist: "3.62 Km", time: "7 mins", lat: 12.9250, lng: 77.7450, count: 6 },
{ id: 2, name: "Sompura Metro Station", dist: "7.05 Km", time: "15 mins", lat: 12.9100, lng: 77.7600, count: 4 },
{ id: 3, name: "Sarjapur Metro Station", dist: "8.28 Km", time: "18 mins", lat: 12.8900, lng: 77.7800, count: 3 },
{ id: 4, name: "Ambedkar nagar Metro Station", dist: "8.89 Km", time: "18 mins", lat: 12.9550, lng: 77.7100, count: 5 },
],
'Education': [
{ id: 5, name: "Whitefield Global School", dist: "2.5 Km", time: "6 mins", lat: 12.9550, lng: 77.7350, count: 8 },
{ id: 6, name: "Greenwood High", dist: "4.1 Km", time: "10 mins", lat: 12.9150, lng: 77.7550, count: 5 },
],
'Hospitals': [
{ id: 7, name: "Manipal Hospital Varthur", dist: "1.2 Km", time: "4 mins", lat: 12.9420, lng: 77.7320, count: 2 },
],
'Work': [
{ id: 8, name: "RGA Tech Park", dist: "5.5 Km", time: "12 mins", lat: 12.9050, lng: 77.7150, count: 12 },
],
'Entertainment': [
{ id: 9, name: "Nexus Whitefield", dist: "3.2 Km", time: "9 mins", lat: 12.9600, lng: 77.7400, count: 7 },
],
};
function MapController({ center }: { center: [number, number] }) {
const map = useMap();
useEffect(() => {
map.setView(center, 13);
}, [center, map]);
return null;
}
function ZoomHandler({ zoomIn, zoomOut }: { zoomIn: () => void, zoomOut: () => void }) {
return (
<div className="absolute top-4 left-4 flex flex-col gap-2 z-[400]">
<button
onClick={zoomIn}
className="w-8 h-8 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
<span className="text-gray-700 dark:text-gray-300 font-bold text-lg">+</span>
</button>
<button
onClick={zoomOut}
className="w-8 h-8 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
style={{ lineHeight: '0' }}
>
<span className="text-gray-700 dark:text-gray-300 font-bold text-lg"></span>
</button>
</div>
);
}
export default function ConnectivityMap() {
const [activeTab, setActiveTab] = useState("Commute");
const [searchQuery, setSearchQuery] = useState("");
const [mapZoom, setMapZoom] = useState(13);
const [mapRef, setMapRef] = useState<L.Map | null>(null);
const activeData = useMemo(() => {
let data = activeTab === "Search"
? Object.values(MOCK_DATA).flat()
: MOCK_DATA[activeTab] || [];
if (searchQuery) {
data = data.filter(item =>
item.name.toLowerCase().includes(searchQuery.toLowerCase())
);
}
return data;
}, [activeTab, searchQuery]);
const handleZoomIn = () => {
if (mapRef) mapRef.zoomIn();
};
const handleZoomOut = () => {
if (mapRef) mapRef.zoomOut();
};
return (
<div className="bg-white dark:bg-gray-900 rounded-xl overflow-hidden border border-gray-200 dark:border-gray-700">
{/* Tabs */}
<div className="flex overflow-x-auto border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 scrollbar-hide">
{["Commute", "Education", "Hospitals", "Work", "Entertainment", "Search"].map((tab) => (
<button
key={tab}
onClick={() => {
setActiveTab(tab);
setSearchQuery(""); // Clear search when switching tabs
}}
className={`px-6 py-3 text-sm font-medium whitespace-nowrap flex items-center gap-2 transition-colors border-b-2 ${activeTab === tab
? "text-orange-500 border-orange-500 bg-orange-50/30 dark:bg-orange-900/10"
: "text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 border-transparent"
}`}
>
{/* Icons */}
{tab === "Commute" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path d="M6.5 3c-1.051 0-2.093.04-3.125.117A1.49 1.49 0 002 4.607V10.5h9V4.606c0-.771-.59-1.43-1.375-1.489A41.568 41.568 0 006.5 3zM2 12v2.5A1.5 1.5 0 003.5 16h.041a3 3 0 015.918 0h.791a.75.75 0 00.75-.75V12H2z" /><path d="M6.5 18a1.5 1.5 0 100-3 1.5 1.5 0 000 3zM13.25 5a.75.75 0 00-.75.75v8.514a3.001 3.001 0 014.893 1.44c.37-.275.61-.719.595-1.227a24.905 24.905 0 00-1.784-8.549A1.486 1.486 0 0014.823 5H13.25zM14.5 18a1.5 1.5 0 100-3 1.5 1.5 0 000 3z" /></svg>}
{tab === "Education" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path d="M10.75 16.82A7.462 7.462 0 0115 15.5c.71 0 1.396.098 2.046.282A.75.75 0 0018 15.06v-11a.75.75 0 00-.546-.721A9.006 9.006 0 0015 3a8.963 8.963 0 00-4.25 1.065V16.82zM9.25 4.065A8.963 8.963 0 005 3c-.85 0-1.673.118-2.454.339A.75.75 0 002 4.06v11a.75.75 0 00.954.721A7.506 7.506 0 015 15.5c1.579 0 3.042.487 4.25 1.32V4.065z" /></svg>}
{tab === "Hospitals" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path fillRule="evenodd" d="M10 2a6 6 0 00-6 6c0 1.887-.454 3.665-1.257 5.234a.75.75 0 00.515 1.076 32.91 32.91 0 003.256.508 3.5 3.5 0 006.972 0 32.903 32.903 0 003.256-.508.75.75 0 00.515-1.076A11.448 11.448 0 0116 8a6 6 0 00-6-6zM8.05 14.943a33.54 33.54 0 003.9 0 2 2 0 01-3.9 0z" clipRule="evenodd" /></svg>}
{tab === "Work" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path fillRule="evenodd" d="M4 16.5v-13h-.25a.75.75 0 010-1.5h12.5a.75.75 0 010 1.5H16v13h.25a.75.75 0 010 1.5h-3.5a.75.75 0 01-.75-.75v-2.5a.75.75 0 00-.75-.75h-2.5a.75.75 0 00-.75.75v2.5a.75.75 0 01-.75.75h-3.5a.75.75 0 010-1.5H4zm3-11a.5.5 0 01.5-.5h1a.5.5 0 01.5.5v1a.5.5 0 01-.5.5h-1a.5.5 0 01-.5-.5v-1zM7.5 9a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5v-1a.5.5 0 00-.5-.5h-1zM11 5.5a.5.5 0 01.5-.5h1a.5.5 0 01.5.5v1a.5.5 0 01-.5.5h-1a.5.5 0 01-.5-.5v-1zm.5 3.5a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5v-1a.5.5 0 00-.5-.5h-1z" clipRule="evenodd" /></svg>}
{tab === "Entertainment" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path fillRule="evenodd" d="M6 5v1H4.667a1.75 1.75 0 00-1.743 1.598l-.826 9.5A1.75 1.75 0 003.84 19H16.16a1.75 1.75 0 001.743-1.902l-.826-9.5A1.75 1.75 0 0015.333 6H14V5a4 4 0 00-8 0zm4-2.5A2.5 2.5 0 007.5 5v1h5V5A2.5 2.5 0 0010 2.5zM7.5 10a2.5 2.5 0 005 0V8.75a.75.75 0 011.5 0V10a4 4 0 01-8 0V8.75a.75.75 0 011.5 0V10z" clipRule="evenodd" /></svg>}
{tab === "Search" && <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4"><path fillRule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clipRule="evenodd" /></svg>}
{tab}
</button>
))}
</div>
<div className="flex flex-col lg:flex-row h-[450px] relative">
{/* Map Area */}
<div className="flex-1 h-full relative">
<MapContainer
center={PROPERTY_LOCATION}
zoom={13}
style={{ height: '100%', width: '100%' }}
zoomControl={false}
ref={setMapRef}
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<MapController center={PROPERTY_LOCATION} />
<ZoomHandler zoomIn={handleZoomIn} zoomOut={handleZoomOut} />
{/* Property Marker */}
<Marker position={PROPERTY_LOCATION} icon={homeIcon} />
{/* POI Markers */}
{activeData.map((item) => (
<Marker
key={item.id}
position={[item.lat, item.lng]}
icon={createCustomIcon('#F97316', item.count.toString())}
>
<Popup>{item.name}</Popup>
</Marker>
))}
</MapContainer>
{/* Layer Toggle Button (Bottom Left) */}
<div className="absolute bottom-4 left-4 z-[400]">
<button className="w-10 h-10 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
<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="M3.25 3A2.25 2.25 0 001 5.25v9.5A2.25 2.25 0 003.25 17h9.5A2.25 2.25 0 0015 14.75v-9.5A2.25 2.25 0 0012.75 3h-9.5zm9.5 1.5a.75.75 0 00-.75.75V8a.75.75 0 001.5 0V5.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 00-.75.75v2.75a.75.75 0 001.5 0v-2.75a.75.75 0 00-.75-.75zM10 7a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 7zm-3.25.75a.75.75 0 00-1.5 0v4.5a.75.75 0 001.5 0v-4.5z" clipRule="evenodd" />
</svg>
</button>
</div>
</div>
{/* Floating List Card (Right Side) */}
<div className="absolute top-4 right-4 bottom-4 w-full max-w-sm z-[400] flex flex-col pointer-events-none">
<div className="rounded-lg shadow-xl overflow-hidden flex flex-col h-full pointer-events-auto border border-gray-100 dark:border-gray-800">
{/* Search Input for Search Tab */}
{activeTab === "Search" && (
<div className="p-3 border-b border-gray-100 dark:border-gray-800">
<input
type="text"
placeholder="Search location..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full px-4 py-2 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-orange-500"
/>
</div>
)}
<div className="flex-1 overflow-y-auto custom-scrollbar p-2">
{activeData.length > 0 ? (
activeData.map((item) => (
<div key={item.id} className="p-4 mb-2 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-750 rounded-lg cursor-pointer transition-all border border-gray-100 dark:border-gray-800 shadow-sm hover:shadow-md">
<h4 className="font-semibold text-gray-900 dark:text-white text-base mb-2">{item.name}</h4>
<div className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
<span className="font-medium">{item.dist}</span>
<span className="text-orange-300">|</span>
<span className="text-gray-500 font-medium">{item.time}</span>
</div>
</div>
))
) : (
<div className="p-8 text-center text-gray-400">
No results found
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
}

View File

@ -9,6 +9,12 @@ import InnerBanner from "@/components/InnerBanner";
import { Property } from "@/data/properties";
import axios from "axios";
import { useCompare } from "@/context/CompareContext";
import dynamic from 'next/dynamic';
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;
@ -595,128 +601,7 @@ export default function PropertyDetailClient({ property }: { property: Property
</div>
{/* Map Interface */}
<div className="bg-white dark:bg-gray-900 rounded-xl overflow-hidden border border-gray-200 dark:border-gray-700">
{/* Tabs */}
<div className="flex overflow-x-auto border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 scrollbar-hide">
{["Commute", "Education", "Hospitals", "Work", "Entertainment ", "Search"].map((tab) => (
<button
key={tab}
onClick={() => setActiveMapTab(tab)}
className={`px-6 py-3 text-sm font-medium whitespace-nowrap flex items-center gap-2 transition-colors border-b-2 ${activeMapTab === tab
? "text-orange-500 border-orange-500 bg-orange-50/30 dark:bg-orange-900/10"
: "text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 border-transparent"
}`}
>
{/* Icons based on tab */}
{tab === "Commute" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path d="M6.5 3c-1.051 0-2.093.04-3.125.117A1.49 1.49 0 002 4.607V10.5h9V4.606c0-.771-.59-1.43-1.375-1.489A41.568 41.568 0 006.5 3zM2 12v2.5A1.5 1.5 0 003.5 16h.041a3 3 0 015.918 0h.791a.75.75 0 00.75-.75V12H2z" />
<path d="M6.5 18a1.5 1.5 0 100-3 1.5 1.5 0 000 3zM13.25 5a.75.75 0 00-.75.75v8.514a3.001 3.001 0 014.893 1.44c.37-.275.61-.719.595-1.227a24.905 24.905 0 00-1.784-8.549A1.486 1.486 0 0014.823 5H13.25zM14.5 18a1.5 1.5 0 100-3 1.5 1.5 0 000 3z" />
</svg>
)}
{tab === "Education" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path d="M10.75 16.82A7.462 7.462 0 0115 15.5c.71 0 1.396.098 2.046.282A.75.75 0 0018 15.06v-11a.75.75 0 00-.546-.721A9.006 9.006 0 0015 3a8.963 8.963 0 00-4.25 1.065V16.82zM9.25 4.065A8.963 8.963 0 005 3c-.85 0-1.673.118-2.454.339A.75.75 0 002 4.06v11a.75.75 0 00.954.721A7.506 7.506 0 015 15.5c1.579 0 3.042.487 4.25 1.32V4.065z" />
</svg>
)}
{tab === "Hospitals" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path fillRule="evenodd" d="M10 2a6 6 0 00-6 6c0 1.887-.454 3.665-1.257 5.234a.75.75 0 00.515 1.076 32.91 32.91 0 003.256.508 3.5 3.5 0 006.972 0 32.903 32.903 0 003.256-.508.75.75 0 00.515-1.076A11.448 11.448 0 0116 8a6 6 0 00-6-6zM8.05 14.943a33.54 33.54 0 003.9 0 2 2 0 01-3.9 0z" clipRule="evenodd" />
</svg>
)}
{tab === "Work" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path fillRule="evenodd" d="M4 16.5v-13h-.25a.75.75 0 010-1.5h12.5a.75.75 0 010 1.5H16v13h.25a.75.75 0 010 1.5h-3.5a.75.75 0 01-.75-.75v-2.5a.75.75 0 00-.75-.75h-2.5a.75.75 0 00-.75.75v2.5a.75.75 0 01-.75.75h-3.5a.75.75 0 010-1.5H4zm3-11a.5.5 0 01.5-.5h1a.5.5 0 01.5.5v1a.5.5 0 01-.5.5h-1a.5.5 0 01-.5-.5v-1zM7.5 9a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5v-1a.5.5 0 00-.5-.5h-1zM11 5.5a.5.5 0 01.5-.5h1a.5.5 0 01.5.5v1a.5.5 0 01-.5.5h-1a.5.5 0 01-.5-.5v-1zm.5 3.5a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5v-1a.5.5 0 00-.5-.5h-1z" clipRule="evenodd" />
</svg>
)}
{tab === "Entertainment" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path fillRule="evenodd" d="M6 5v1H4.667a1.75 1.75 0 00-1.743 1.598l-.826 9.5A1.75 1.75 0 003.84 19H16.16a1.75 1.75 0 001.743-1.902l-.826-9.5A1.75 1.75 0 0015.333 6H14V5a4 4 0 00-8 0zm4-2.5A2.5 2.5 0 007.5 5v1h5V5A2.5 2.5 0 0010 2.5zM7.5 10a2.5 2.5 0 005 0V8.75a.75.75 0 011.5 0V10a4 4 0 01-8 0V8.75a.75.75 0 011.5 0V10z" clipRule="evenodd" />
</svg>
)}
{tab === "Search" && (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-4 h-4">
<path fillRule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clipRule="evenodd" />
</svg>
)}
{tab}
</button>
))}
</div>
<div className="flex flex-col lg:flex-row h-[450px]">
{/* Map Area */}
<div className="relative flex-1 bg-gray-100 dark:bg-gray-800 h-full">
{/* Map Image Placeholder */}
<div className="absolute inset-0">
<img
src="/assets/images/map-placeholder.png"
alt="Map View"
className="w-full h-full object-cover"
/>
</div>
{/* Map Controls */}
<div className="absolute top-4 left-4 flex flex-col gap-2 z-10">
<button className="w-8 h-8 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
<span className="text-gray-700 dark:text-gray-300 font-bold text-lg">+</span>
</button>
<button className="w-8 h-8 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
<span className="text-gray-700 dark:text-gray-300 font-bold text-lg"></span>
</button>
</div>
{/* Layer Toggle */}
<div className="absolute bottom-4 left-4 z-10">
<button className="w-10 h-10 bg-white dark:bg-gray-800 rounded shadow-md flex items-center justify-center hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
<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="M3.25 3A2.25 2.25 0 001 5.25v9.5A2.25 2.25 0 003.25 17h9.5A2.25 2.25 0 0015 14.75v-9.5A2.25 2.25 0 0012.75 3h-9.5zm9.5 1.5a.75.75 0 00-.75.75V8a.75.75 0 001.5 0V5.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 00-.75.75v2.75a.75.75 0 001.5 0v-2.75a.75.75 0 00-.75-.75zM10 7a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 7zm-3.25.75a.75.75 0 00-1.5 0v4.5a.75.75 0 001.5 0v-4.5z" clipRule="evenodd" />
</svg>
</button>
</div>
{/* Pins (Static for demo) */}
<div className="absolute top-[30%] left-[25%] transform -translate-x-1/2 -translate-y-1/2">
<div className="w-9 h-9 bg-orange-500 rounded-full flex items-center justify-center text-white font-bold shadow-lg border-2 border-white text-sm">6</div>
</div>
<div className="absolute top-[35%] left-[45%] transform -translate-x-1/2 -translate-y-1/2">
<div className="w-9 h-9 bg-orange-500 rounded-full flex items-center justify-center text-white font-bold shadow-lg border-2 border-white text-sm">6</div>
</div>
<div className="absolute top-[50%] left-[35%] transform -translate-x-1/2 -translate-y-1/2">
<div className="w-9 h-9 bg-orange-500 rounded-full flex items-center justify-center text-white font-bold shadow-lg border-2 border-white text-sm">7</div>
</div>
<div className="absolute top-[48%] left-[50%] transform -translate-x-1/2 -translate-y-1/2">
<div className="w-12 h-12 bg-purple-600 rounded-full flex items-center justify-center text-white shadow-lg border-3 border-white">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-7 h-7">
<path d="M11.47 3.84a.75.75 0 011.06 0l8.69 8.69a.75.75 0 101.06-1.06l-8.689-8.69a2.25 2.25 0 00-3.182 0l-8.69 8.69a.75.75 0 001.061 1.06l8.69-8.69z" />
<path d="M12 5.432l8.159 8.159c.03.03.06.058.091.086v6.198c0 1.035-.84 1.875-1.875 1.875H15a.75.75 0 01-.75-.75v-4.5a.75.75 0 00-.75-.75h-3a.75.75 0 00-.75.75V21a.75.75 0 01-.75.75H5.625a1.875 1.875 0 01-1.875-1.875v-6.198a2.29 2.29 0 00.091-.086L12 5.43z" />
</svg>
</div>
</div>
</div>
{/* List Area */}
<div className="w-full lg:w-96 bg-white dark:bg-gray-900 border-l border-gray-200 dark:border-gray-700 overflow-y-auto">
<div className="p-4 space-y-3">
{[
{ name: "Dommasandra Circle Metro Station", dist: "3.62 Km", time: "7 mins" },
{ name: "Sompura Metro Station", dist: "7.05 Km", time: "15 mins" },
{ name: "Sarjapur Metro Station", dist: "8.28 Km", time: "18 mins" },
{ name: "Ambedkar nagar Metro Station", dist: "8.89 Km", time: "18 mins" },
].map((item, idx) => (
<div key={idx} className="p-4 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-lg cursor-pointer transition-colors border border-gray-100 dark:border-gray-800">
<h4 className="font-semibold text-gray-900 dark:text-white text-sm mb-2">{item.name}</h4>
<div className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
<span className="font-medium">{item.dist}</span>
<span className="text-orange-500">|</span>
<span className="text-orange-500 font-medium">{item.time}</span>
</div>
</div>
))}
</div>
</div>
</div>
</div>
<ConnectivityMap />
</div>
{/* Master Plan Section */}

View File

@ -44,7 +44,7 @@ export default function PropertyNav({ sections }: PropertyNavProps) {
};
return (
<div className="sticky top-28 z-30 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-[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="max-w-7xl mx-auto px-6">
<nav className="flex gap-1 overflow-x-auto hide-scrollbar py-3">
{sections.map((section) => (