fe7696b72d
- Refactored state from single selectedFeatureId to selectedFeatureIds array in Editor and Viewer - Updated Map component to support multi-select filtering for geometry binding visibility - Made entity, wiki, and geometry side panels scrollable for better overflow handling - Fixed viewer mode wiki link navigation for independent wikis - Improved geometry binding UX and state synchronization
127 lines
4.4 KiB
TypeScript
127 lines
4.4 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback } from "react";
|
|
import type { Dispatch, SetStateAction } from "react";
|
|
import type { Entity } from "@/uhm/types/entities";
|
|
import type { Feature, FeatureProperties } from "@/uhm/types/geo";
|
|
import { ApiError } from "@/uhm/api/http";
|
|
import { buildFeatureEntityPatch } from "@/uhm/lib/editor/entity/entityBinding";
|
|
import { buildGeometryMetadataPatch } from "@/uhm/lib/editor/geometry/geometryMetadata";
|
|
import { uniqueEntityIds } from "@/uhm/lib/editor/snapshot/editorSnapshot";
|
|
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
|
|
|
|
type EditorDraftApi = {
|
|
patchFeatureProperties: (id: FeatureProperties["id"], patch: Partial<FeatureProperties>) => void;
|
|
};
|
|
|
|
type Options = {
|
|
editor: EditorDraftApi;
|
|
selectedFeatures: Feature[];
|
|
geometryMetaForm: GeometryMetaFormState;
|
|
setGeometryMetaForm: Dispatch<SetStateAction<GeometryMetaFormState>>;
|
|
selectedGeometryEntityIds: string[];
|
|
setSelectedGeometryEntityIds: Dispatch<SetStateAction<string[]>>;
|
|
entities: Entity[];
|
|
setIsEntitySubmitting: Dispatch<SetStateAction<boolean>>;
|
|
setEntityFormStatus: Dispatch<SetStateAction<string | null>>;
|
|
};
|
|
|
|
export function useFeatureCommands(options: Options) {
|
|
const {
|
|
editor,
|
|
selectedFeatures,
|
|
geometryMetaForm,
|
|
setGeometryMetaForm,
|
|
selectedGeometryEntityIds,
|
|
setSelectedGeometryEntityIds,
|
|
entities,
|
|
setIsEntitySubmitting,
|
|
setEntityFormStatus,
|
|
} = options;
|
|
|
|
const applyGeometryMetadata = useCallback(async (): Promise<{ ok: boolean; error?: string }> => {
|
|
if (!selectedFeatures || selectedFeatures.length === 0) {
|
|
const msg = "Hãy chọn ít nhất một geometry trước.";
|
|
setEntityFormStatus(msg);
|
|
return { ok: false, error: msg };
|
|
}
|
|
|
|
if (!geometryMetaForm.time_start.trim() || !geometryMetaForm.time_end.trim()) {
|
|
const msg = "time_start và time_end là bắt buộc.";
|
|
setEntityFormStatus(msg);
|
|
return { ok: false, error: msg };
|
|
}
|
|
|
|
let metadata;
|
|
try {
|
|
metadata = buildGeometryMetadataPatch(geometryMetaForm);
|
|
} catch (err) {
|
|
const msg = err instanceof Error ? err.message : "Thời gian không hợp lệ.";
|
|
setEntityFormStatus(msg);
|
|
return { ok: false, error: msg };
|
|
}
|
|
|
|
setIsEntitySubmitting(true);
|
|
setEntityFormStatus(null);
|
|
try {
|
|
for (const feature of selectedFeatures) {
|
|
editor.patchFeatureProperties(feature.properties.id, metadata.patch);
|
|
}
|
|
setGeometryMetaForm(metadata.formState);
|
|
setEntityFormStatus("Đã cập nhật thuộc tính GEO. Commit khi sẵn sàng.");
|
|
return { ok: true };
|
|
} finally {
|
|
setIsEntitySubmitting(false);
|
|
}
|
|
}, [
|
|
editor,
|
|
geometryMetaForm,
|
|
selectedFeatures,
|
|
setEntityFormStatus,
|
|
setGeometryMetaForm,
|
|
setIsEntitySubmitting,
|
|
]);
|
|
|
|
const applyEntitiesToSelectedGeometry = useCallback(async () => {
|
|
if (!selectedFeatures || selectedFeatures.length === 0) {
|
|
setEntityFormStatus("Hãy chọn ít nhất một geometry trước.");
|
|
return;
|
|
}
|
|
|
|
const entityIds = uniqueEntityIds(selectedGeometryEntityIds);
|
|
setIsEntitySubmitting(true);
|
|
setEntityFormStatus(null);
|
|
try {
|
|
for (const feature of selectedFeatures) {
|
|
editor.patchFeatureProperties(
|
|
feature.properties.id,
|
|
buildFeatureEntityPatch(feature, entityIds, entities)
|
|
);
|
|
}
|
|
setSelectedGeometryEntityIds(entityIds);
|
|
setEntityFormStatus("Đã cập nhật danh sách entity. Commit khi sẵn sàng.");
|
|
} catch (err) {
|
|
if (err instanceof ApiError) {
|
|
setEntityFormStatus(`Lưu thất bại: ${err.body}`);
|
|
} else {
|
|
setEntityFormStatus("Lưu thất bại.");
|
|
}
|
|
} finally {
|
|
setIsEntitySubmitting(false);
|
|
}
|
|
}, [
|
|
editor,
|
|
entities,
|
|
selectedFeatures,
|
|
selectedGeometryEntityIds,
|
|
setEntityFormStatus,
|
|
setIsEntitySubmitting,
|
|
setSelectedGeometryEntityIds,
|
|
]);
|
|
|
|
return {
|
|
applyGeometryMetadata,
|
|
applyEntitiesToSelectedGeometry,
|
|
};
|
|
}
|