Files
History-client/app/page.tsx
2026-04-07 23:32:38 +07:00

113 lines
3.5 KiB
TypeScript

"use client";
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: [] };
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 data = await fetchGeometriesByBBox({
minLng: -180,
minLat: -90,
maxLng: 180,
maxLat: 90,
});
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 {
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", minHeight: "100vh" }}>
<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}
backgroundVisibility={backgroundVisibility}
/>
<BackgroundLayersPanel
visibility={backgroundVisibility}
onToggleLayer={handleToggleBackgroundLayer}
onShowAll={handleShowAllBackgroundLayers}
onHideAll={handleHideAllBackgroundLayers}
/>
</div>
);
}