87 lines
2.6 KiB
TypeScript
87 lines
2.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Map from "@/components/Map";
|
|
import Editor from "@/components/Editor";
|
|
import {
|
|
FeatureCollection,
|
|
useEditorState,
|
|
} from "@/lib/useEditorState";
|
|
|
|
const EMPTY_FC: FeatureCollection = { type: "FeatureCollection", features: [] };
|
|
|
|
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 editor = useEditorState(initialData);
|
|
|
|
useEffect(() => {
|
|
async function loadInitial() {
|
|
try {
|
|
const params = new URLSearchParams({
|
|
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);
|
|
}
|
|
}
|
|
|
|
loadInitial();
|
|
}, []);
|
|
|
|
const handleSave = async () => {
|
|
const payload = editor.buildPayload();
|
|
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;
|
|
}
|
|
editor.clearChanges();
|
|
} catch (err) {
|
|
console.error("Save error", err);
|
|
} finally {
|
|
setIsSaving(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div style={{ display: "flex" }}>
|
|
<Editor
|
|
mode={mode}
|
|
setMode={setMode}
|
|
onUndo={editor.undo}
|
|
onSave={handleSave}
|
|
isSaving={isSaving}
|
|
changesCount={editor.changeCount}
|
|
undoStack={editor.undoStack}
|
|
/>
|
|
|
|
<Map
|
|
mode={mode}
|
|
draft={editor.draft}
|
|
onCreateFeature={editor.createFeature}
|
|
onDeleteFeature={editor.deleteFeature}
|
|
onUpdateFeature={editor.updateFeature}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|