refactor: rename entity type configuration to geometry type and relocate to dedicated map utilities.

This commit is contained in:
taDuc
2026-05-12 04:49:57 +07:00
parent 16fce9da7a
commit 8f911abe35
6 changed files with 51 additions and 51 deletions
@@ -4,12 +4,12 @@ import { type CSSProperties, useMemo, useState } from "react";
import { Entity } from "@/uhm/api/entities";
import { Feature } from "@/uhm/lib/editor/state/useEditorState";
import {
EntityGeometryPreset,
EntityTypeGroupId,
EntityTypeOption,
findEntityTypeOption,
groupEntityTypeOptions,
} from "@/uhm/lib/utils/entityTypeOptions";
GeometryPreset,
GeometryTypeGroupId,
GeometryTypeOption,
findGeometryTypeOption,
groupGeometryTypeOptions,
} from "@/uhm/lib/map/geo/geometryTypeOptions";
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
type Props = {
@@ -19,7 +19,7 @@ type Props = {
entities: Entity[];
selectedGeometryEntityIds: string[];
onEntityIdsChange: (values: string[]) => void;
entityTypeOptions: EntityTypeOption[];
entityTypeOptions: GeometryTypeOption[];
geometryMetaForm: GeometryMetaFormState;
onGeometryMetaFormChange: (key: keyof GeometryMetaFormState, value: string) => void;
isEntitySubmitting: boolean;
@@ -81,13 +81,13 @@ export default function SelectedGeometryPanel({
if (!selectedFeatures || selectedFeatures.length === 0) return null;
const representativeFeature = selectedFeatures[0];
const groupedEntityTypeOptions = groupEntityTypeOptions(entityTypeOptions);
const groupedGeometryTypeOptions = groupGeometryTypeOptions(entityTypeOptions);
const featureGeometryPreset = resolveFeatureGeometryPreset(representativeFeature);
const allowedGroupIds = getAllowedGroupIdsForPreset(featureGeometryPreset);
const groupedGeoTypeOptions = groupedEntityTypeOptions.filter((group) =>
const groupedGeoTypeOptions = groupedGeometryTypeOptions.filter((group) =>
allowedGroupIds.includes(group.id)
);
const selectedTypeOption = findEntityTypeOption(geometryMetaForm.type_key);
const selectedTypeOption = findGeometryTypeOption(geometryMetaForm.type_key);
const hasCurrentVisibleTypeOption = groupedGeoTypeOptions.some((group) =>
group.options.some((option) => option.value === geometryMetaForm.type_key)
);
@@ -342,20 +342,20 @@ function MinusIcon() {
);
}
function resolveFeatureGeometryPreset(feature: Feature): EntityGeometryPreset {
function resolveFeatureGeometryPreset(feature: Feature): GeometryPreset {
const explicitPreset = normalizeGeometryPreset(feature.properties.geometry_preset);
if (explicitPreset) return explicitPreset;
const semanticType = normalizeTypeId(feature.properties.type) || normalizeTypeId(feature.properties.entity_type_id);
if (semanticType) {
const option = findEntityTypeOption(semanticType);
const option = findGeometryTypeOption(semanticType);
if (option) return option.geometryPreset;
}
return mapGeometryTypeToPreset(feature.geometry.type);
}
function normalizeGeometryPreset(value: unknown): EntityGeometryPreset | null {
function normalizeGeometryPreset(value: unknown): GeometryPreset | null {
if (typeof value !== "string") return null;
const normalized = value.trim().toLowerCase();
if (
@@ -377,7 +377,7 @@ function normalizeTypeId(value: unknown): string | null {
function mapGeometryTypeToPreset(
geometryType: Feature["geometry"]["type"]
): EntityGeometryPreset {
): GeometryPreset {
if (geometryType === "Point" || geometryType === "MultiPoint") {
return "point";
}
@@ -388,8 +388,8 @@ function mapGeometryTypeToPreset(
}
function getAllowedGroupIdsForPreset(
geometryPreset: EntityGeometryPreset
): EntityTypeGroupId[] {
geometryPreset: GeometryPreset
): GeometryTypeGroupId[] {
if (geometryPreset === "point") {
return ["point"];
}
@@ -405,7 +405,7 @@ function getAllowedGroupIdsForPreset(
return ["polygon"];
}
function formatGeometryPresetLabel(preset: EntityGeometryPreset | null): string {
function formatGeometryPresetLabel(preset: GeometryPreset | null): string {
if (preset === "point") return "point - Điểm";
if (preset === "line") return "line - Tuyến";
if (preset === "circle-area") return "circle - Tròn";
+2 -2
View File
@@ -1,4 +1,4 @@
import type { EntityGeometryPreset } from "@/uhm/lib/utils/entityTypeOptions";
import type { GeometryPreset } from "@/uhm/lib/map/geo/geometryTypeOptions";
export type EditorMode =
| "idle"
@@ -38,4 +38,4 @@ export type CreatedEntitySummary = {
name: string;
};
export type GeometryPreset = EntityGeometryPreset;
export type { GeometryPreset };
@@ -1,4 +1,4 @@
import { DEFAULT_ENTITY_TYPE_ID } from "@/uhm/lib/utils/entityTypeOptions";
import { DEFAULT_GEOMETRY_TYPE_ID } from "@/uhm/lib/map/geo/geometryTypeOptions";
import { geoTypeCodeToTypeKey, typeKeyToGeoTypeCode } from "@/uhm/lib/map/geo/geoTypeMap";
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
import type { EntitySnapshot } from "@/uhm/types/entities";
@@ -659,7 +659,7 @@ export function getDefaultTypeIdForFeature(feature: Feature): string {
if (preset === "line") return "defense_line";
if (preset === "point") return "city";
if (preset === "circle-area") return "war";
if (preset === "polygon") return DEFAULT_ENTITY_TYPE_ID;
if (preset === "polygon") return DEFAULT_GEOMETRY_TYPE_ID;
const geometryType = feature.geometry.type;
if (geometryType === "LineString" || geometryType === "MultiLineString") {
@@ -668,7 +668,7 @@ export function getDefaultTypeIdForFeature(feature: Feature): string {
if (geometryType === "Point" || geometryType === "MultiPoint") {
return "city";
}
return DEFAULT_ENTITY_TYPE_ID;
return DEFAULT_GEOMETRY_TYPE_ID;
}
export function normalizeFeatureEntityIds(feature: Feature): string[] {
@@ -1,27 +1,27 @@
export type EntityTypeGroupId =
export type GeometryTypeGroupId =
| "line"
| "polygon"
| "circle"
| "point";
export type EntityGeometryPreset = "line" | "polygon" | "circle-area" | "point";
export type GeometryPreset = "line" | "polygon" | "circle-area" | "point";
export type EntityTypeGroup = {
id: EntityTypeGroupId;
export type GeometryTypeGroup = {
id: GeometryTypeGroupId;
label: string;
geometryLabel: string;
description: string;
};
export type EntityTypeOption = {
export type GeometryTypeOption = {
value: string;
label: string;
groupId: EntityTypeGroupId;
groupId: GeometryTypeGroupId;
groupLabel: string;
geometryPreset: EntityGeometryPreset;
geometryPreset: GeometryPreset;
};
export const ENTITY_TYPE_GROUPS: EntityTypeGroup[] = [
export const GEOMETRY_TYPE_GROUPS: GeometryTypeGroup[] = [
{
id: "line",
label: "line - Tuyến",
@@ -48,18 +48,18 @@ export const ENTITY_TYPE_GROUPS: EntityTypeGroup[] = [
},
];
const GROUP_BY_ID: Record<EntityTypeGroupId, EntityTypeGroup> = {
line: ENTITY_TYPE_GROUPS[0],
polygon: ENTITY_TYPE_GROUPS[1],
circle: ENTITY_TYPE_GROUPS[2],
point: ENTITY_TYPE_GROUPS[3],
const GROUP_BY_ID: Record<GeometryTypeGroupId, GeometryTypeGroup> = {
line: GEOMETRY_TYPE_GROUPS[0],
polygon: GEOMETRY_TYPE_GROUPS[1],
circle: GEOMETRY_TYPE_GROUPS[2],
point: GEOMETRY_TYPE_GROUPS[3],
};
const RAW_ENTITY_TYPE_OPTIONS: Array<{
const RAW_GEOMETRY_TYPE_OPTIONS: Array<{
value: string;
label: string;
groupId: EntityTypeGroupId;
geometryPreset: EntityGeometryPreset;
groupId: GeometryTypeGroupId;
geometryPreset: GeometryPreset;
}> = [
{ value: "defense_line", label: "Defense Line", groupId: "line", geometryPreset: "line" },
@@ -94,29 +94,29 @@ const RAW_ENTITY_TYPE_OPTIONS: Array<{
{ value: "bridge", label: "Bridge", groupId: "point", geometryPreset: "point" },
];
export const ENTITY_TYPE_OPTIONS: EntityTypeOption[] = RAW_ENTITY_TYPE_OPTIONS.map((item) => ({
export const GEOMETRY_TYPE_OPTIONS: GeometryTypeOption[] = RAW_GEOMETRY_TYPE_OPTIONS.map((item) => ({
...item,
groupLabel: GROUP_BY_ID[item.groupId].label,
}));
export const DEFAULT_ENTITY_TYPE_ID = "country";
export const DEFAULT_GEOMETRY_TYPE_ID = "country";
// Gom option theo group để render select phân nhóm.
export function groupEntityTypeOptions(options: EntityTypeOption[] = ENTITY_TYPE_OPTIONS): Array<{
id: EntityTypeGroupId;
export function groupGeometryTypeOptions(options: GeometryTypeOption[] = GEOMETRY_TYPE_OPTIONS): Array<{
id: GeometryTypeGroupId;
label: string;
geometryLabel: string;
description: string;
options: EntityTypeOption[];
options: GeometryTypeOption[];
}> {
return ENTITY_TYPE_GROUPS.map((group) => ({
return GEOMETRY_TYPE_GROUPS.map((group) => ({
...group,
options: options.filter((option) => option.groupId === group.id),
})).filter((group) => group.options.length > 0);
}
// Tìm option theo type id, trả null nếu không tồn tại.
export function findEntityTypeOption(typeId: string | null | undefined): EntityTypeOption | null {
export function findGeometryTypeOption(typeId: string | null | undefined): GeometryTypeOption | null {
if (!typeId) return null;
return ENTITY_TYPE_OPTIONS.find((option) => option.value === typeId) || null;
return GEOMETRY_TYPE_OPTIONS.find((option) => option.value === typeId) || null;
}
+2 -2
View File
@@ -1,4 +1,4 @@
import type { EntityGeometryPreset } from "@/uhm/lib/utils/entityTypeOptions";
import type { GeometryPreset } from "@/uhm/lib/map/geo/geometryTypeOptions";
export type Geometry =
| { type: "Point"; coordinates: [number, number] }
@@ -13,7 +13,7 @@ export type FeatureId = string | number;
export type FeatureProperties = {
id: FeatureId;
type?: string | null;
geometry_preset?: EntityGeometryPreset | null;
geometry_preset?: GeometryPreset | null;
time_start?: number | null;
time_end?: number | null;
binding?: string[];