165 lines
6.9 KiB
TypeScript
165 lines
6.9 KiB
TypeScript
'use client';
|
|
import { useState } from 'react';
|
|
|
|
interface Location {
|
|
name: string;
|
|
coordinates: [number, number];
|
|
description: string;
|
|
services: string[];
|
|
responseTime: string;
|
|
}
|
|
|
|
const locations: Location[] = [
|
|
{
|
|
name: 'Corpus Christi',
|
|
coordinates: [27.8006, -97.3964],
|
|
description: 'Main service area - 24/7 emergency response',
|
|
services: ['Emergency Repair', 'Panel Upgrades', 'EV Chargers', 'Commercial'],
|
|
responseTime: '< 30 minutes'
|
|
},
|
|
{
|
|
name: 'Flour Bluff',
|
|
coordinates: [27.6831, -97.2201],
|
|
description: 'Residential and commercial electrical services',
|
|
services: ['Emergency Repair', 'Panel Upgrades', 'Lighting'],
|
|
responseTime: '< 45 minutes'
|
|
},
|
|
{
|
|
name: 'Portland',
|
|
coordinates: [27.8772, -97.3239],
|
|
description: 'Full electrical contractor services',
|
|
services: ['Emergency Repair', 'Panel Upgrades', 'Commercial'],
|
|
responseTime: '< 60 minutes'
|
|
},
|
|
{
|
|
name: 'Aransas Pass',
|
|
coordinates: [27.9095, -97.1499],
|
|
description: 'Coastal electrical services',
|
|
services: ['Emergency Repair', 'Panel Upgrades', 'Marine Electrical'],
|
|
responseTime: '< 60 minutes'
|
|
},
|
|
{
|
|
name: 'Rockport',
|
|
coordinates: [28.0206, -97.0544],
|
|
description: 'Coastal and residential electrical',
|
|
services: ['Emergency Repair', 'Panel Upgrades', 'Outdoor Lighting'],
|
|
responseTime: '< 75 minutes'
|
|
}
|
|
];
|
|
|
|
export default function InteractiveMap() {
|
|
const [selectedLocation, setSelectedLocation] = useState<Location | null>(null);
|
|
const [hoveredLocation, setHoveredLocation] = useState<string | null>(null);
|
|
|
|
return (
|
|
<div className="relative">
|
|
{/* Map Container */}
|
|
<div className="bg-gradient-to-br from-blue-50 to-blue-100 rounded-3xl h-96 relative overflow-hidden shadow-xl">
|
|
{/* Background Pattern */}
|
|
<div className="absolute inset-0 bg-[url('data:image/svg+xml,%3Csvg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="none" fill-rule="evenodd"%3E%3Cg fill="%23000000" fill-opacity="0.03"%3E%3Ccircle cx="30" cy="30" r="2"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')]"></div>
|
|
|
|
{/* Service Area Circle */}
|
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64 bg-gradient-to-br from-brand-green/20 to-green-600/20 rounded-full border-2 border-brand-green/30 animate-pulse-slow"></div>
|
|
|
|
{/* Location Markers */}
|
|
{locations.map((location, index) => (
|
|
<div
|
|
key={location.name}
|
|
className={`absolute transform -translate-x-1/2 -translate-y-1/2 cursor-pointer transition-all duration-300 ${
|
|
hoveredLocation === location.name ? 'scale-125' : 'scale-100'
|
|
}`}
|
|
style={{
|
|
left: `${20 + (index * 15)}%`,
|
|
top: `${30 + (index * 10)}%`
|
|
}}
|
|
onMouseEnter={() => setHoveredLocation(location.name)}
|
|
onMouseLeave={() => setHoveredLocation(null)}
|
|
onClick={() => setSelectedLocation(location)}
|
|
>
|
|
{/* Marker */}
|
|
<div className={`w-4 h-4 bg-gradient-to-r from-brand-green to-green-600 rounded-full border-2 border-white shadow-lg ${
|
|
selectedLocation?.name === location.name ? 'ring-4 ring-brand-green/50' : ''
|
|
}`}></div>
|
|
|
|
{/* Location Name */}
|
|
<div className={`absolute top-6 left-1/2 transform -translate-x-1/2 whitespace-nowrap bg-white px-3 py-1 rounded-full text-xs font-semibold shadow-md transition-all duration-300 ${
|
|
hoveredLocation === location.name ? 'opacity-100 scale-100' : 'opacity-0 scale-95'
|
|
}`}>
|
|
{location.name}
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
{/* Center Point */}
|
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-6 h-6 bg-gradient-to-r from-brand-green to-green-600 rounded-full border-4 border-white shadow-xl animate-bounce-gentle"></div>
|
|
|
|
{/* Map Title */}
|
|
<div className="absolute top-6 left-6 bg-white/90 backdrop-blur-sm px-4 py-2 rounded-full shadow-md">
|
|
<h3 className="font-semibold text-gray-800">Service Coverage Area</h3>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Location Info Panel */}
|
|
{selectedLocation && (
|
|
<div className="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-full max-w-md animate-slide-up">
|
|
<div className="bg-white rounded-2xl shadow-2xl p-6 border border-gray-100">
|
|
<div className="flex items-start justify-between mb-4">
|
|
<h3 className="font-heading font-bold text-xl text-gradient">
|
|
{selectedLocation.name}
|
|
</h3>
|
|
<button
|
|
onClick={() => setSelectedLocation(null)}
|
|
className="text-gray-400 hover:text-gray-600 transition-colors"
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<p className="text-gray-600 mb-4">{selectedLocation.description}</p>
|
|
|
|
<div className="mb-4">
|
|
<h4 className="font-semibold text-gray-800 mb-2">Services Available:</h4>
|
|
<div className="flex flex-wrap gap-2">
|
|
{selectedLocation.services.map((service) => (
|
|
<span key={service} className="bg-brand-green/10 text-brand-green px-2 py-1 rounded-full text-xs font-medium">
|
|
{service}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<span className="text-sm text-gray-500">Response Time:</span>
|
|
<p className="font-semibold text-brand-green">{selectedLocation.responseTime}</p>
|
|
</div>
|
|
<a
|
|
href="tel:+13618850315"
|
|
className="btn-primary btn-sm"
|
|
>
|
|
Call Now
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Legend */}
|
|
<div className="absolute bottom-4 right-4 bg-white/90 backdrop-blur-sm px-4 py-3 rounded-xl shadow-md">
|
|
<div className="flex items-center gap-3 text-sm">
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-3 h-3 bg-gradient-to-r from-brand-green to-green-600 rounded-full"></div>
|
|
<span className="text-gray-700">Service Area</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-3 h-3 bg-gradient-to-r from-brand-green to-green-600 rounded-full border-2 border-white"></div>
|
|
<span className="text-gray-700">Locations</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|