map layer management
This commit is contained in:
66
app/page.tsx
66
app/page.tsx
@@ -3,10 +3,19 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import Map from "@/components/Map";
|
||||
import Editor from "@/components/Editor";
|
||||
import BackgroundLayersPanel from "@/components/BackgroundLayersPanel";
|
||||
import { ApiError } from "@/api/http";
|
||||
import { fetchGeometriesByBBox, saveGeometryBatchChanges } from "@/api/geometries";
|
||||
import {
|
||||
FeatureCollection,
|
||||
useEditorState,
|
||||
} from "@/lib/useEditorState";
|
||||
import {
|
||||
BackgroundLayerId,
|
||||
BackgroundLayerVisibility,
|
||||
DEFAULT_BACKGROUND_LAYER_VISIBILITY,
|
||||
HIDDEN_BACKGROUND_LAYER_VISIBILITY,
|
||||
} from "@/lib/backgroundLayers";
|
||||
|
||||
const EMPTY_FC: FeatureCollection = { type: "FeatureCollection", features: [] };
|
||||
|
||||
@@ -14,22 +23,21 @@ export default function Page() {
|
||||
const [mode, setMode] = useState<"idle" | "draw" | "select" | "add-point">("idle");
|
||||
const [initialData, setInitialData] = useState<FeatureCollection>(EMPTY_FC);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [backgroundVisibility, setBackgroundVisibility] = useState<BackgroundLayerVisibility>(
|
||||
() => ({ ...DEFAULT_BACKGROUND_LAYER_VISIBILITY })
|
||||
);
|
||||
|
||||
const editor = useEditorState(initialData);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadInitial() {
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
minLng: "-180",
|
||||
minLat: "-90",
|
||||
maxLng: "180",
|
||||
maxLat: "90",
|
||||
const data = await fetchGeometriesByBBox({
|
||||
minLng: -180,
|
||||
minLat: -90,
|
||||
maxLng: 180,
|
||||
maxLat: 90,
|
||||
});
|
||||
|
||||
const res = await fetch(`http://localhost:3000/geometries?${params.toString()}`);
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
setInitialData(data);
|
||||
} catch (err) {
|
||||
console.error("Load initial data failed", err);
|
||||
@@ -44,26 +52,36 @@ export default function Page() {
|
||||
if (!payload.length) return;
|
||||
setIsSaving(true);
|
||||
try {
|
||||
const res = await fetch("http://localhost:3000/geometries/batch", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ changes: payload }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
console.error("Save failed", text);
|
||||
return;
|
||||
}
|
||||
await saveGeometryBatchChanges(payload);
|
||||
editor.clearChanges();
|
||||
} catch (err) {
|
||||
if (err instanceof ApiError) {
|
||||
console.error("Save failed", err.body);
|
||||
return;
|
||||
}
|
||||
console.error("Save error", err);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleBackgroundLayer = (id: BackgroundLayerId) => {
|
||||
setBackgroundVisibility((prev) => ({
|
||||
...prev,
|
||||
[id]: !prev[id],
|
||||
}));
|
||||
};
|
||||
|
||||
const handleShowAllBackgroundLayers = () => {
|
||||
setBackgroundVisibility({ ...DEFAULT_BACKGROUND_LAYER_VISIBILITY });
|
||||
};
|
||||
|
||||
const handleHideAllBackgroundLayers = () => {
|
||||
setBackgroundVisibility({ ...HIDDEN_BACKGROUND_LAYER_VISIBILITY });
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex" }}>
|
||||
<div style={{ display: "flex", minHeight: "100vh" }}>
|
||||
<Editor
|
||||
mode={mode}
|
||||
setMode={setMode}
|
||||
@@ -80,6 +98,14 @@ export default function Page() {
|
||||
onCreateFeature={editor.createFeature}
|
||||
onDeleteFeature={editor.deleteFeature}
|
||||
onUpdateFeature={editor.updateFeature}
|
||||
backgroundVisibility={backgroundVisibility}
|
||||
/>
|
||||
|
||||
<BackgroundLayersPanel
|
||||
visibility={backgroundVisibility}
|
||||
onToggleLayer={handleToggleBackgroundLayer}
|
||||
onShowAll={handleShowAllBackgroundLayers}
|
||||
onHideAll={handleHideAllBackgroundLayers}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user