Add store location map manager #20
@ -1,9 +1,9 @@
|
|||||||
import { useRef, useState } from "react";
|
import { useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
clientPointToMap,
|
clientPointToMap,
|
||||||
getMapObjectDisplayLabel,
|
getMapObjectDisplayLabel,
|
||||||
getObjectKey,
|
getObjectKey,
|
||||||
itemsForZone,
|
itemMatchesMapFilters,
|
||||||
} from "../../lib/locationMapUtils";
|
} from "../../lib/locationMapUtils";
|
||||||
|
|
||||||
const DRAG_CHANGE_THRESHOLD = 2;
|
const DRAG_CHANGE_THRESHOLD = 2;
|
||||||
@ -55,6 +55,24 @@ export default function LocationMapCanvas({
|
|||||||
const objectDragHistoryCapturedRef = useRef(false);
|
const objectDragHistoryCapturedRef = useRef(false);
|
||||||
const suppressPanClickRef = useRef(false);
|
const suppressPanClickRef = useRef(false);
|
||||||
const [isPanning, setIsPanning] = useState(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) => {
|
const startDrag = (event, object, type) => {
|
||||||
if (!canEditObjects || object.locked || !svgRef.current) return;
|
if (!canEditObjects || object.locked || !svgRef.current) return;
|
||||||
@ -261,12 +279,9 @@ export default function LocationMapCanvas({
|
|||||||
if (!object.visible || !filters.showZones) return null;
|
if (!object.visible || !filters.showZones) return null;
|
||||||
const key = getObjectKey(object);
|
const key = getObjectKey(object);
|
||||||
const isSelected = key === selectedObjectKey;
|
const isSelected = key === selectedObjectKey;
|
||||||
const zoneItems = itemsForZone(mapItems, object.zone_id, filters, username);
|
const zoneKey = String(object.zone_id || "");
|
||||||
const assignedZoneItemCount = object.zone_id
|
const zoneItems = zoneKey ? zoneItemSummary.visibleItemsByZone.get(zoneKey) || [] : [];
|
||||||
? mapItems.filter(
|
const assignedZoneItemCount = zoneKey ? zoneItemSummary.assignedCounts.get(zoneKey) || 0 : 0;
|
||||||
(item) => String(item.zone_id || "") === String(object.zone_id || "")
|
|
||||||
).length
|
|
||||||
: 0;
|
|
||||||
const count = zoneItems.length;
|
const count = zoneItems.length;
|
||||||
const hasHiddenZoneItems = assignedZoneItemCount > count;
|
const hasHiddenZoneItems = assignedZoneItemCount > count;
|
||||||
const countLabel = hasHiddenZoneItems
|
const countLabel = hasHiddenZoneItems
|
||||||
|
|||||||
@ -156,32 +156,26 @@ export function prepareObjectsForSave(objects) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function itemsForZone(items, zoneId, filters, username) {
|
export function itemMatchesMapFilters(item, filters, username) {
|
||||||
return items.filter((item) => {
|
if (!filters.showCompleted && item.bought) return false;
|
||||||
if (String(item.zone_id || "") !== String(zoneId || "")) return false;
|
|
||||||
if (!filters.showCompleted && item.bought) return false;
|
|
||||||
|
|
||||||
const addedBy = Array.isArray(item.added_by_users) ? item.added_by_users : [];
|
const addedBy = Array.isArray(item.added_by_users) ? item.added_by_users : [];
|
||||||
const hasOwnershipData = addedBy.length > 0 && username;
|
const hasOwnershipData = addedBy.length > 0 && username;
|
||||||
const isMine = hasOwnershipData ? addedBy.includes(username) : true;
|
const isMine = hasOwnershipData ? addedBy.includes(username) : true;
|
||||||
if (isMine && !filters.showMyItems) return false;
|
if (isMine && !filters.showMyItems) return false;
|
||||||
if (!isMine && !filters.showOtherItems) return false;
|
if (!isMine && !filters.showOtherItems) return false;
|
||||||
return true;
|
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) {
|
export function unmappedItems(items, filters, username) {
|
||||||
return items.filter((item) => {
|
return items.filter((item) => !item.zone_id && itemMatchesMapFilters(item, filters, username));
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clientPointToMap(event, svgElement, mapSize) {
|
export function clientPointToMap(event, svgElement, mapSize) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user