fix: precompute map zone item counts

This commit is contained in:
Nico 2026-06-04 02:33:43 -07:00
parent 59b82650a6
commit bf34cc341a
2 changed files with 39 additions and 30 deletions

View File

@ -1,9 +1,9 @@
import { useRef, useState } from "react";
import { useMemo, useRef, useState } from "react";
import {
clientPointToMap,
getMapObjectDisplayLabel,
getObjectKey,
itemsForZone,
itemMatchesMapFilters,
} from "../../lib/locationMapUtils";
const DRAG_CHANGE_THRESHOLD = 2;
@ -55,6 +55,24 @@ export default function LocationMapCanvas({
const objectDragHistoryCapturedRef = useRef(false);
const suppressPanClickRef = useRef(false);
const [isPanning, setIsPanning] = useState(false);
const zoneItemSummary = useMemo(() => {
const assignedCounts = new Map();
const visibleItemsByZone = new Map();
(mapItems || []).forEach((item) => {
const zoneKey = String(item.zone_id || "");
if (!zoneKey) return;
assignedCounts.set(zoneKey, (assignedCounts.get(zoneKey) || 0) + 1);
if (!itemMatchesMapFilters(item, filters, username)) return;
const existingItems = visibleItemsByZone.get(zoneKey) || [];
existingItems.push(item);
visibleItemsByZone.set(zoneKey, existingItems);
});
return { assignedCounts, visibleItemsByZone };
}, [filters, mapItems, username]);
const startDrag = (event, object, type) => {
if (!canEditObjects || object.locked || !svgRef.current) return;
@ -261,12 +279,9 @@ export default function LocationMapCanvas({
if (!object.visible || !filters.showZones) return null;
const key = getObjectKey(object);
const isSelected = key === selectedObjectKey;
const zoneItems = itemsForZone(mapItems, object.zone_id, filters, username);
const assignedZoneItemCount = object.zone_id
? mapItems.filter(
(item) => String(item.zone_id || "") === String(object.zone_id || "")
).length
: 0;
const zoneKey = String(object.zone_id || "");
const zoneItems = zoneKey ? zoneItemSummary.visibleItemsByZone.get(zoneKey) || [] : [];
const assignedZoneItemCount = zoneKey ? zoneItemSummary.assignedCounts.get(zoneKey) || 0 : 0;
const count = zoneItems.length;
const hasHiddenZoneItems = assignedZoneItemCount > count;
const countLabel = hasHiddenZoneItems

View File

@ -156,9 +156,7 @@ export function prepareObjectsForSave(objects) {
}));
}
export function itemsForZone(items, zoneId, filters, username) {
return items.filter((item) => {
if (String(item.zone_id || "") !== String(zoneId || "")) return false;
export function itemMatchesMapFilters(item, filters, username) {
if (!filters.showCompleted && item.bought) return false;
const addedBy = Array.isArray(item.added_by_users) ? item.added_by_users : [];
@ -167,21 +165,17 @@ export function itemsForZone(items, zoneId, filters, username) {
if (isMine && !filters.showMyItems) return false;
if (!isMine && !filters.showOtherItems) return false;
return true;
});
}
export function itemsForZone(items, zoneId, filters, username) {
return items.filter((item) => (
String(item.zone_id || "") === String(zoneId || "") &&
itemMatchesMapFilters(item, filters, username)
));
}
export function unmappedItems(items, filters, username) {
return items.filter((item) => {
if (item.zone_id) return false;
if (!filters.showCompleted && item.bought) return false;
const addedBy = Array.isArray(item.added_by_users) ? item.added_by_users : [];
const hasOwnershipData = addedBy.length > 0 && username;
const isMine = hasOwnershipData ? addedBy.includes(username) : true;
if (isMine && !filters.showMyItems) return false;
if (!isMine && !filters.showOtherItems) return false;
return true;
});
return items.filter((item) => !item.zone_id && itemMatchesMapFilters(item, filters, username));
}
export function clientPointToMap(event, svgElement, mapSize) {