import React, { useState, useEffect } from "react"; const sldHeader = ` `; const sldFooter = ``; const singleColorSLD = (color, geometryType) => ` ${sldHeader} layer ${symbolizer(geometryType, color)} ${sldFooter} `; const uniqueValueSLD = (column, rules, geometryType) => ` ${sldHeader} layer ${rules.map(r => ` ${column} ${r.value} ${symbolizer(geometryType, r.color)} `).join("")} ${sldFooter} `; const globalIconSLD = (iconCode) => ` ${sldHeader} layer image/png 10 ${sldFooter} `; const symbolizer = (geometryType, color) => { if (geometryType.toUpperCase() === "POINT" || geometryType.toUpperCase() === "MULTIPOINT") { return ` circle ${color} #000000 2 10 `; } if (geometryType === "line") { return ` ${color} 2 `; } return ` ${color} 0.5 #232323 `; }; // const randomColor = () => // "#" + Math.floor(Math.random() * 16777215).toString(16); const randomColor = () => { let color = "#000000" while (color === "#000000") { color = "#" + Math.floor(Math.random() * 16777215) .toString(16) .padStart(6, "0") } return color } const CustomLayerStyle = ({ data = [], geometryType, onSubmit, onChange }) => { const [columns, setColumns] = useState([]); const [selectedStyle, setSelectedStyle] = useState("single"); // STYLE STATE const [singleColor, setSingleColor] = useState("#3388ff"); const [uniqueColumn, setUniqueColumn] = useState(""); const [uniqueRules, setUniqueRules] = useState([]); const [randomRules, setRandomRules] = useState([]); const [propColumn, setPropColumn] = useState(""); const [propMin, setPropMin] = useState(3); const [propMax, setPropMax] = useState(12); const [iconMode, setIconMode] = useState("global"); // global | per-feature const [iconGlobal, setIconGlobal] = useState(""); const [iconRules, setIconRules] = useState([]); // Extract columns useEffect(() => { if (data.length > 0) { const keys = Object.keys(data[0]).filter((k) => k !== "geometry"); setColumns(keys); } }, [data]); useEffect(() => { onChange({ type: selectedStyle, color: singleColor, unique: uniqueRules, random: randomRules, proportional: { propColumn, propMin, propMax } }); }, [selectedStyle, singleColor, uniqueRules, randomRules, propColumn, propMin, propMax]); // Handle unique value column selection const generateUniqueRules = (column) => { const values = [...new Set(data.map((d) => d[column]))]; const rules = values.map((v) => ({ value: v, color: randomColor(), })); setUniqueRules(rules); }; // Handle random per row const generateRandomRules = () => { const rules = data.map((row) => ({ id: row.id, color: randomColor(), })); setRandomRules(rules); }; // Handle icon rules const generateIconRules = () => { const rules = data.map((row) => ({ id: row.id, iconUrl: "", })); setIconRules(rules); }; async function generateBase64(iconUrl) { const response = await fetch(iconUrl, { mode: "cors", }); const blob = await response.blob(); return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(blob); }); } // Final Submit const submit = async () => { let xml = ""; if (selectedStyle === "single") { xml = singleColorSLD(singleColor, geometryType); } if (selectedStyle === "unique_value") { xml = uniqueValueSLD(uniqueColumn, uniqueRules, geometryType); } if (selectedStyle === "icon") { // const iconCode = await generateBase64('https://cdn-icons-png.flaticon.com/512/0/614.png') const iconCode = 'https://cdn-icons-png.flaticon.com/512/0/614.png' xml = globalIconSLD(iconCode); } // xml = `` onSubmit({ styleType: "sld", sldContent: xml }); }; return (
🎨 Pengaturan Styling Data Spasial
{/* PILIH STYLE */}
{/* ---------------- SINGLE COLOR ---------------- */} {selectedStyle === "single" && (
setSingleColor(e.target.value)} />
)} {/* ---------------- UNIQUE VALUE ---------------- */} {selectedStyle === "unique_value" && (
{/* RULE LIST */}
{uniqueRules.map((r, i) => (
{r.value}
{ const copy = [...uniqueRules]; copy[i].color = e.target.value; setUniqueRules(copy); }} />
))}
)} {/* ---------------- RANDOM COLOR ---------------- */} {selectedStyle === "random" && (
{randomRules.map((r, i) => (
ID {r.id} { const copy = [...randomRules]; copy[i].color = e.target.value; setRandomRules(copy); }} />
))}
)} {/* ---------------- PROPORTIONAL ---------------- */} {selectedStyle === "proportional" && (
setPropMin(Number(e.target.value))} />
setPropMax(Number(e.target.value))} />
)} {/* ---------------- ICON PER FEATURE ---------------- */} {selectedStyle === "icon" && geometryType === "Point" && (
setIconGlobal(e.target.value)} />
)}
); }; export default CustomLayerStyle;