// app/admin/upload/_components/map/CustomLayerStyle.tsx "use client"; import React, { useState, useEffect } from "react"; import { Button } from "@/shared/components/ui/button"; import { toast } from "sonner"; // --- HELPER FUNCTION SLD GENERATOR --- const sldHeader = ` `; const sldFooter = ``; // Helper symbolizer generator const symbolizer = (geometryType: string, color: string) => { const geomUpper = geometryType?.toUpperCase(); if (geomUpper === "POINT" || geomUpper === "MULTIPOINT") { return ` circle ${color} #000000 1 10 `; } if (geomUpper === "LINE" || geomUpper === "LINESTRING" || geomUpper === "MULTILINESTRING") { return ` ${color} 2 `; } // Polygon default return ` ${color} 0.5 #232323 1 `; }; const singleColorSLD = (color: string, geometryType: string) => `${sldHeader} layer ${symbolizer(geometryType, color)} ${sldFooter} `; const uniqueValueSLD = (column: string, rules: any[], geometryType: string) => `${sldHeader} layer ${rules.map(r => ` ${column} ${r.value} ${symbolizer(geometryType, r.color)} `).join("")} ${sldFooter} `; const globalIconSLD = (iconCode:string) => `${sldHeader} layer image/png 10 ${sldFooter} `; // Helper Random Color const randomColor = () => { let color = "#000000" while (color === "#000000") { color = "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0"); } return color; } interface CustomLayerStyleProps { data: any[]; geometryType: string; onSubmit: (val: any) => void; onChange?: (val: any) => void; } const CustomLayerStyle = ({ data = [], geometryType, onSubmit }: CustomLayerStyleProps) => { const [columns, setColumns] = useState([]); const [selectedStyle, setSelectedStyle] = useState("single"); const [singleColor, setSingleColor] = useState("#3388ff"); const [uniqueColumn, setUniqueColumn] = useState(""); const [uniqueRules, setUniqueRules] = useState<{value: any, color: string}[]>([]); const [iconGlobal, setIconGlobal] = useState(""); const [validIcon, setValidIcon] = useState(true); useEffect(() => { if (data && data.length > 0) { // Ambil keys dari row pertama, filter geometry const keys = Object.keys(data[0]).filter((k) => k !== "geometry"); setColumns(keys); } }, [data]); useEffect(() => { if (!iconGlobal) return; const img = new Image(); img.onload = () => setValidIcon(true); img.onerror = () => { setValidIcon(false); toast.error("URL icon tidak valid, Mohon ganti."); } img.src = iconGlobal; }, [iconGlobal]); const generateUniqueRules = (column: string) => { const values = [...new Set(data.map((d) => d[column]))].slice(0, 20); // Limit 20 unique values agar tidak berat const rules = values.map((v) => ({ value: v, color: randomColor(), })); setUniqueRules(rules); }; const submit = () => { if (selectedStyle === "icon" && !validIcon) { return } let xml = ""; if (selectedStyle === "single") { xml = singleColorSLD(singleColor, geometryType); } else if (selectedStyle === "unique_value") { xml = uniqueValueSLD(uniqueColumn, uniqueRules, geometryType); } else if (selectedStyle === "icon") { const iconCode = 'https://cdn-icons-png.flaticon.com/512/0/614.png' // xml = globalIconSLD(iconCode); xml = globalIconSLD(iconGlobal); } // Kirim SLD string ke parent onSubmit({ styleType: "sld", sldContent: xml }); }; return ( {/* 🎨 Pengaturan Style */} Jenis Styling setSelectedStyle(e.target.value)} > Single Color Kategori (Unique Value) {selectedStyle === "icon" && geometryType === "Point" && ( URL Icon )} {/* --- SINGLE COLOR --- */} {selectedStyle === "single" && ( Warna Layer setSingleColor(e.target.value)} /> {singleColor} )} {/* --- UNIQUE VALUE --- */} {selectedStyle === "unique_value" && ( Pilih Kolom Kategori { setUniqueColumn(e.target.value); generateUniqueRules(e.target.value); }} > -- Pilih Kolom -- {columns.map((c) => ( {c} ))} {uniqueRules.length > 0 && ( Preview Kategori (Max 20) {uniqueRules.map((r, i) => ( { const copy = [...uniqueRules]; copy[i].color = e.target.value; setUniqueRules(copy); }} /> {String(r.value)} ))} )} )} {/* ---------------- ICON PER FEATURE ---------------- */} {selectedStyle === "icon" && geometryType === "Point" && ( Masukkan URL Icon setIconGlobal(e.target.value)} /> )} Terapkan Style ); }; export default CustomLayerStyle;
Preview Kategori (Max 20)