MIF_E31221222/sigap-website/app/_components/map/layers/timezone.tsx

147 lines
4.9 KiB
TypeScript

"use client"
import React, { useEffect, useRef } from 'react';
import mapboxgl from 'mapbox-gl';
import { createRoot } from 'react-dom/client';
import { Badge } from "@/app/_components/ui/badge";
interface TimezoneLayerProps {
map: mapboxgl.Map | null;
}
// Component to display time in a specific timezone
function Jam({ timeZone }: { timeZone: string }) {
const [time, setTime] = React.useState<string>("");
useEffect(() => {
function updateTime() {
const now = new Date();
const options: Intl.DateTimeFormatOptions = {
hour: '2-digit',
minute: '2-digit',
hour12: false,
timeZone
};
setTime(now.toLocaleTimeString('id-ID', options));
}
updateTime();
const interval = setInterval(updateTime, 1000);
return () => clearInterval(interval);
}, [timeZone]);
return <>{time}</>;
}
export default function TimezoneLayer({ map }: TimezoneLayerProps) {
const hoverTimezone = useRef<any>(null);
const markersRef = useRef<mapboxgl.Marker[]>([]);
useEffect(() => {
if (!map) return;
// Function to add timezone data and markers
function addTimezoneLayers() {
// Add timezone data source
const url = "/geojson/timezones_wVVG8.geojson"; // Changed path to public folder
if (map && !map.getSource('timezone')) {
map.addSource('timezone', {
'type': 'geojson',
'generateId': true,
'data': url
});
// Add timezone boundaries
map.addLayer({
'id': 'timezone-line',
'type': 'line',
'source': 'timezone',
'layout': {},
'paint': {
'line-color': 'orange',
'line-width': 1,
'line-opacity': 0.5
}
});
// Create markers for Indonesian time zones
const createTimeMarker = (lngLat: [number, number], timeZone: string, label: string) => {
const markerElement = document.createElement('div');
const root = createRoot(markerElement);
root.render(
<div className='bordered p-1 text-time show-pop-up text-center'>
<p className="uppercase text-xl" style={{
lineHeight: "1rem"
}}>
<Jam timeZone={timeZone} />
</p>
<Badge variant="outline" className="text-xs mt-1">{label}</Badge>
</div>
);
const marker = new mapboxgl.Marker(markerElement)
.setLngLat(lngLat)
.addTo(map);
markersRef.current.push(marker);
return marker;
};
// WIB (GMT+7)
createTimeMarker([107.4999769225339, 3.4359354227361933], "Asia/Jakarta", "WIB / GMT+7");
// WITA (GMT+8)
createTimeMarker([119.1174733337183, 3.4359354227361933], "Asia/Makassar", "WITA / GMT+8");
// WIT (GMT+9)
createTimeMarker([131.58387377752751, 3.4359354227361933], "Asia/Jayapura", "WIT / GMT+9");
}
}
// Check if style is loaded, otherwise wait for it
if (map.isStyleLoaded()) {
addTimezoneLayers();
} else {
// Use both 'load' and 'style.load' events to ensure we catch the style loading
map.on('load', addTimezoneLayers);
map.on('style.load', addTimezoneLayers);
// Fallback: If style hasn't loaded within 2 seconds, try again
const timeoutId = setTimeout(() => {
if (map.isStyleLoaded()) {
addTimezoneLayers();
}
}, 2000);
// Clean up the timeout if component unmounts
return () => {
clearTimeout(timeoutId);
map.off('load', addTimezoneLayers);
map.off('style.load', addTimezoneLayers);
cleanupLayers();
};
}
function cleanupLayers() {
if (map && map.getLayer('timezone-line')) {
map.removeLayer('timezone-line');
}
if (map && map.getSource('timezone')) {
map.removeSource('timezone');
}
// Remove all markers
markersRef.current.forEach(marker => marker.remove());
markersRef.current = [];
}
// Clean up function
return () => {
cleanupLayers();
};
}, [map]);
return null;
}