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