ci-electrical/web/components/InteractiveMap.tsx

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>
);
}