|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import React, { useState, useRef } from 'react';
|
|
|
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
|
|
|
import { MapPin, Factory, Zap, CheckCircle2, ArrowUpRight } from 'lucide-react';
|
|
|
|
|
import Image from 'next/image';
|
|
|
|
|
@@ -38,10 +38,13 @@ export function InteractiveGermanyMap({
|
|
|
|
|
hideStandorte = false
|
|
|
|
|
}: InteractiveGermanyMapProps) {
|
|
|
|
|
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
|
|
|
|
const [hoverTimeout, setHoverTimeout] = useState<NodeJS.Timeout | null>(null);
|
|
|
|
|
const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
|
|
|
|
|
|
|
const handleMouseEnter = (loc: Location) => {
|
|
|
|
|
if (hoverTimeout) clearTimeout(hoverTimeout);
|
|
|
|
|
if (hoverTimeoutRef.current) {
|
|
|
|
|
clearTimeout(hoverTimeoutRef.current);
|
|
|
|
|
hoverTimeoutRef.current = null;
|
|
|
|
|
}
|
|
|
|
|
setActiveLocation(loc);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -49,7 +52,7 @@ export function InteractiveGermanyMap({
|
|
|
|
|
const timeout = setTimeout(() => {
|
|
|
|
|
setActiveLocation(null);
|
|
|
|
|
}, 200);
|
|
|
|
|
setHoverTimeout(timeout);
|
|
|
|
|
hoverTimeoutRef.current = timeout;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
@@ -162,10 +165,12 @@ export function InteractiveGermanyMap({
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Minor Location Markers (The 100+ generic projects) */}
|
|
|
|
|
{finalLocations.filter(l => l.type === 'minor_node').map((loc, idx) => (
|
|
|
|
|
{finalLocations.filter(l => l.type === 'minor_node').map((loc, idx) => {
|
|
|
|
|
const isActive = activeLocation === loc;
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
key={`minor-${idx}`}
|
|
|
|
|
className="absolute z-10 group/minor cursor-pointer w-10 h-10 flex items-center justify-center"
|
|
|
|
|
className={`absolute group/minor cursor-pointer w-8 h-8 md:w-5 md:h-5 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-10 hover:z-30'}`}
|
|
|
|
|
style={{
|
|
|
|
|
left: `${loc.x}%`,
|
|
|
|
|
top: `${loc.y}%`,
|
|
|
|
|
@@ -173,12 +178,13 @@ export function InteractiveGermanyMap({
|
|
|
|
|
}}
|
|
|
|
|
onMouseEnter={() => handleMouseEnter(loc)}
|
|
|
|
|
onMouseLeave={handleMouseLeave}
|
|
|
|
|
onTouchStart={() => handleMouseEnter(loc)}
|
|
|
|
|
onClick={() => handleMouseEnter(loc)}
|
|
|
|
|
>
|
|
|
|
|
<div className="w-1.5 h-1.5 bg-primary/80 rounded-full group-hover/minor:bg-white group-hover/minor:scale-150 transition-all duration-300" />
|
|
|
|
|
<div className={`w-1.5 h-1.5 rounded-full transition-all duration-300 ${isActive ? 'bg-white scale-150 shadow-[0_0_10px_rgba(130,237,32,1)]' : 'bg-primary/80 group-hover/minor:bg-white group-hover/minor:scale-150'}`} />
|
|
|
|
|
<div className="absolute inset-0 m-auto w-2 h-2 bg-primary rounded-full opacity-0 group-hover/minor:animate-ping" />
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
)})}
|
|
|
|
|
|
|
|
|
|
{/* Major Location Markers (HQ, Branch, Project) */}
|
|
|
|
|
{finalLocations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
|
|
|
|
|
@@ -189,10 +195,11 @@ export function InteractiveGermanyMap({
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
key={loc.id}
|
|
|
|
|
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group/pin cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20'}`}
|
|
|
|
|
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group/pin cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20 hover:z-40'}`}
|
|
|
|
|
style={{ left: `${loc.x}%`, top: `${loc.y}%` }}
|
|
|
|
|
onMouseEnter={() => handleMouseEnter(loc)}
|
|
|
|
|
onMouseLeave={handleMouseLeave}
|
|
|
|
|
onTouchStart={() => handleMouseEnter(loc)}
|
|
|
|
|
onClick={() => handleMouseEnter(loc)}
|
|
|
|
|
>
|
|
|
|
|
{/* Ping Animation for HQ / Branch */}
|
|
|
|
|
|