Files
houseplan-card/src/space-deletion.ts
T
2026-08-23 00:35:48 +03:00

66 lines
2.7 KiB
TypeScript

/** Pure frontend preflight/candidate for an authoritative backend space delete. */
export interface SpaceDeletionDependencyReport {
markerIds: string[];
count: number;
}
const clone = <T>(value: T): T => JSON.parse(JSON.stringify(value));
export function collectSpaceMarkerDependencies(
config: any,
layout: Record<string, any>,
spaceId: string,
): SpaceDeletionDependencyReport {
const space = (config?.spaces || []).find((item: any) => item?.id === spaceId);
const roomIds = new Set(
(space?.rooms || []).map((room: any) => String(room?.id || '')).filter(Boolean),
);
const markerIds = [...new Set<string>((config?.markers || [])
.filter((marker: any) => marker?.removed !== true && typeof marker?.id === 'string')
.filter((marker: any) => marker.space === spaceId
|| (typeof marker.room_id === 'string' && roomIds.has(marker.room_id))
|| layout?.[marker.id]?.s === spaceId)
.map((marker: any) => marker.id))]
.sort((a: string, b: string) => a.localeCompare(b));
return { markerIds, count: markerIds.length };
}
export function createSpaceDeletionCandidate(
configIn: any,
layoutIn: Record<string, any>,
spaceId: string,
): { config: any; layout: Record<string, any>; dependencies: SpaceDeletionDependencyReport } {
const dependencies = collectSpaceMarkerDependencies(configIn, layoutIn, spaceId);
const config = clone(configIn);
const layout = clone(layoutIn || {});
const spaces = config.spaces || [];
const deletingLastSpace = spaces.length === 1 && spaces[0]?.id === spaceId;
if (dependencies.count && !deletingLastSpace) return { config, layout, dependencies };
const space = (config.spaces || []).find((item: any) => item?.id === spaceId);
const roomIds = new Set(
(space?.rooms || []).map((room: any) => String(room?.id || '')).filter(Boolean),
);
config.spaces = (config.spaces || []).filter((item: any) => item?.id !== spaceId);
for (const marker of config.markers || []) {
const markerOwnsPosition = typeof marker?.id === 'string'
&& layout?.[marker.id]?.s === spaceId;
const referencesDeletedSpace = marker?.space === spaceId
|| (typeof marker?.room_id === 'string' && roomIds.has(marker.room_id))
|| markerOwnsPosition;
if (deletingLastSpace && referencesDeletedSpace) {
delete marker.space;
delete marker.room_id;
continue;
}
if (marker?.removed !== true) continue;
if (marker.space === spaceId) delete marker.space;
if (typeof marker.room_id === 'string' && roomIds.has(marker.room_id)) delete marker.room_id;
}
for (const [key, position] of Object.entries(layout)) {
if ((position as any)?.s === spaceId) delete layout[key];
}
return { config, layout, dependencies };
}