"use client"; import { UndoAction } from "@/lib/useEditorState"; type Mode = "draw" | "select" | "idle" | "add-point" | "add-line" | "add-path" | "add-circle"; type EntityOption = { id: string; name: string; geometry_count?: number; }; type Props = { mode: Mode; setMode: (mode: Mode) => void; entities: EntityOption[]; selectedEntityId: string | null; onSelectEntityId: (entityId: string | null) => void; entityStatus?: string | null; onUndo: () => void; onSave: () => void; isSaving: boolean; changesCount: number; undoStack: UndoAction[]; }; export default function Editor({ mode, setMode, entities, selectedEntityId, onSelectEntityId, entityStatus, onUndo, onSave, isSaving, changesCount, undoStack, }: Props) { const toggleMode = (newMode: Mode) => { if (mode === newMode) { setMode("idle"); // bấm lại → tắt } else { setMode(newMode); // chuyển mode } }; // Lấy tối đa 8 tác vụ mới nhất, bỏ trùng nhãn (cùng loại/cùng id) const recentUndoLabels = (() => { const seen = new Set(); const labels: string[] = []; for (let i = undoStack.length - 1; i >= 0 && labels.length < 8; i -= 1) { const label = formatUndoLabel(undoStack[i]); if (seen.has(label)) continue; seen.add(label); labels.push(label); } return labels.reverse(); })(); const getButtonStyle = (btnMode: Mode) => ({ width: "100%", padding: "8px", marginBottom: "6px", border: "none", cursor: "pointer", background: mode === btnMode ? "#4caf50" : "#222", color: "white", borderRadius: "4px", }); return (

Editor

Mode: {mode}
{mode === "add-line" ? (
Click để thêm điểm, Enter để hoàn tất, Esc để hủy.
) : null} {mode === "add-path" ? (
Click để thêm điểm, Enter để hoàn tất, Esc để hủy.
) : null} {mode === "add-circle" ? (
Giữ chuột trái kéo để mở bán kính, thả chuột để hoàn tất.
) : null}
Entity mặc định cho geometry mới
Geometry mới tạo sẽ gắn sẵn entity này, bạn có thể thêm nhiều entity ở panel bên phải.
{entityStatus ? (
{entityStatus}
) : null}
Tác vụ có thể undo ({recentUndoLabels.length})
{recentUndoLabels.length === 0 ? (
Chưa có thao tác
) : (
    {recentUndoLabels.map((label, idx) => (
  • {label}
  • ))}
)}
); } function formatUndoLabel(action: UndoAction) { switch (action.type) { case "create": return `Thêm mới #${action.id}`; case "delete": return `Xóa #${action.feature.properties.id}`; case "update": return `Chỉnh sửa #${action.id}`; default: return "Tác vụ"; } }