tons of feature

This commit is contained in:
taDuc
2026-04-04 22:24:36 +07:00
commit 2a1b4f2f2a
25 changed files with 8539 additions and 0 deletions

86
app/page.tsx Normal file
View File

@@ -0,0 +1,86 @@
"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>
);
}