// app/admin/upload/_components/map/GeoPreview.tsx "use client"; import React, { useEffect, useRef } from "react"; import Map from "ol/Map"; import View from "ol/View"; import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; import { OSM } from "ol/source"; import VectorSource from "ol/source/Vector"; import WKT from "ol/format/WKT"; import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style"; import { fromLonLat } from "ol/proj"; const GeoPreview = ({ features }: { features: any[] }) => { const mapRef = useRef(null); const mapObj = useRef(null); useEffect(() => { if (!features || features.length === 0 || !mapRef.current) return; // Bersihkan map lama jika ada re-render strict mode if (mapObj.current) { mapObj.current.setTarget(undefined); } const wktFormat = new WKT(); const vectorSource = new VectorSource(); features.forEach((item) => { try { const feature = wktFormat.readFeature(item.geometry, { dataProjection: `EPSG:4326`, featureProjection: "EPSG:3857", }); vectorSource.addFeature(feature); } catch (err) { console.error("WKT parse error:", err); } }); const vectorLayer = new VectorLayer({ source: vectorSource, style: (feature) => { const type = feature.getGeometry()?.getType(); if (type === "Polygon" || type === "MultiPolygon") { return new Style({ fill: new Fill({ color: "rgba(0, 153, 255, 0.4)" }), stroke: new Stroke({ color: "#0099ff", width: 2 }), }); } if (type === "LineString" || type === "MultiLineString") { return new Style({ stroke: new Stroke({ color: "#0099ff", width: 3 }), }); } if (type === "Point" || type === "MultiPoint") { return new Style({ image: new CircleStyle({ radius: 6, fill: new Fill({ color: "#0099ff" }), stroke: new Stroke({ color: "#ffffff", width: 2 }), }), }); } }, }); mapObj.current = new Map({ target: mapRef.current, layers: [ new TileLayer({ source: new OSM() }), vectorLayer, ], view: new View({ center: fromLonLat([110, -6]), zoom: 5, }), }); const extent = vectorSource.getExtent(); if (extent && extent[0] !== Infinity) { mapObj.current.getView().fit(extent, { padding: [20, 20, 20, 20], }); } return () => { if (mapObj.current) mapObj.current.setTarget(undefined); }; }, [features]); return (
); }; export default GeoPreview;