diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index c0dfcfc..ffd67ce 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useRef, useState } from "react"; +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; import { useBeforeUnload, useLocation, useNavigate, useParams } from "react-router-dom"; import { createBlankLocationMap, @@ -38,6 +38,8 @@ import { } from "../lib/locationMapUtils"; import "../styles/pages/LocationMapManager.css"; +const EMPTY_MAP_ITEMS = []; + export default function LocationMapManager() { const { storeId, locationId } = useParams(); const navigate = useNavigate(); @@ -77,16 +79,44 @@ export default function LocationMapManager() { const location = mapState?.location || stores.find((store) => String(store.id) === String(locationId)); const canManage = Boolean(mapState?.can_manage ?? ["owner", "admin"].includes(activeHousehold?.role)); const activeMap = mapForMode(mapState, mode, previewDraft); - const selectedObject = objects.find((object) => getObjectKey(object) === selectedObjectKey) || null; - const selectedZoneItems = selectedObject?.zone_id - ? itemsForZone(mapState?.items || [], selectedObject.zone_id, filters, username) - : []; - const visibleUnmappedItems = unmappedItems(mapState?.items || [], filters, username); - const visibleAssignedItemCount = (mapState?.items || []).filter((item) => ( - item.zone_id && itemMatchesMapFilters(item, filters, username) - )).length; - const unmappedItemCount = (mapState?.items || []).filter((item) => !item.zone_id).length; - const hiddenAreaCount = objects.filter((object) => object.visible === false).length; + const mapItems = mapState?.items || EMPTY_MAP_ITEMS; + const selectedObject = useMemo( + () => objects.find((object) => getObjectKey(object) === selectedObjectKey) || null, + [objects, selectedObjectKey] + ); + const selectedZoneItems = useMemo( + () => selectedObject?.zone_id + ? itemsForZone(mapItems, selectedObject.zone_id, filters, username) + : EMPTY_MAP_ITEMS, + [filters, mapItems, selectedObject?.zone_id, username] + ); + const visibleUnmappedItems = useMemo( + () => unmappedItems(mapItems, filters, username), + [filters, mapItems, username] + ); + const { visibleAssignedItemCount, unmappedItemCount } = useMemo(() => { + let nextVisibleAssignedItemCount = 0; + let nextUnmappedItemCount = 0; + + mapItems.forEach((item) => { + if (!item.zone_id) { + nextUnmappedItemCount += 1; + return; + } + if (itemMatchesMapFilters(item, filters, username)) { + nextVisibleAssignedItemCount += 1; + } + }); + + return { + visibleAssignedItemCount: nextVisibleAssignedItemCount, + unmappedItemCount: nextUnmappedItemCount, + }; + }, [filters, mapItems, username]); + const hiddenAreaCount = useMemo( + () => objects.filter((object) => object.visible === false).length, + [objects] + ); const shouldGuardLeave = canManage && hasUnsavedChanges; const mapSize = { @@ -584,7 +614,7 @@ export default function LocationMapManager() { mapSize={mapSize} zoom={zoom} selectedObjectKey={selectedObjectKey} - mapItems={mapState?.items || []} + mapItems={mapItems} username={username} svgRef={svgRef} dragState={dragState}