Add store location map manager #20
@ -12,7 +12,7 @@ export const MAP_DISPLAY_CONTROLS = [
|
|||||||
["showUnmapped", "Unmapped"],
|
["showUnmapped", "Unmapped"],
|
||||||
];
|
];
|
||||||
|
|
||||||
const UNMAPPED_PREVIEW_LIMIT = 8;
|
const MAP_ITEM_PREVIEW_LIMIT = 8;
|
||||||
|
|
||||||
function MapItemActionRow({ item, onSelectItem }) {
|
function MapItemActionRow({ item, onSelectItem }) {
|
||||||
const isBought = Boolean(item.bought);
|
const isBought = Boolean(item.bought);
|
||||||
@ -35,6 +35,44 @@ function MapItemActionRow({ item, onSelectItem }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function MapItemActionList({ items, onSelectItem, itemGroupLabel }) {
|
||||||
|
const [showAllItems, setShowAllItems] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (items.length <= MAP_ITEM_PREVIEW_LIMIT) {
|
||||||
|
setShowAllItems(false);
|
||||||
|
}
|
||||||
|
}, [items.length]);
|
||||||
|
|
||||||
|
const visibleItems = showAllItems ? items : items.slice(0, MAP_ITEM_PREVIEW_LIMIT);
|
||||||
|
const overflowItemCount = items.length - visibleItems.length;
|
||||||
|
const hasOverflow = items.length > MAP_ITEM_PREVIEW_LIMIT;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{visibleItems.map((item) => (
|
||||||
|
<MapItemActionRow key={item.id} item={item} onSelectItem={onSelectItem} />
|
||||||
|
))}
|
||||||
|
{hasOverflow ? (
|
||||||
|
<li className="location-map-list-more">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="location-map-list-more-button"
|
||||||
|
onClick={() => setShowAllItems((current) => !current)}
|
||||||
|
aria-label={
|
||||||
|
showAllItems
|
||||||
|
? `Show fewer ${itemGroupLabel}`
|
||||||
|
: `Show ${overflowItemCount} more ${itemGroupLabel}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{showAllItems ? "Show fewer" : `+${overflowItemCount} more`}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
) : null}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function LocationMapLayerPanel({ filters, setFilters }) {
|
export function LocationMapLayerPanel({ filters, setFilters }) {
|
||||||
return (
|
return (
|
||||||
<div className="location-map-display-panel">
|
<div className="location-map-display-panel">
|
||||||
@ -159,11 +197,11 @@ export function SelectedZoneItemsPanel({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="location-map-zone-items">
|
<div className="location-map-zone-items">
|
||||||
<ul>
|
<MapItemActionList
|
||||||
{selectedZoneItems.map((item) => (
|
items={selectedZoneItems}
|
||||||
<MapItemActionRow key={item.id} item={item} onSelectItem={onSelectZoneItem} />
|
onSelectItem={onSelectZoneItem}
|
||||||
))}
|
itemGroupLabel="zone items"
|
||||||
</ul>
|
/>
|
||||||
{hasHiddenSelectedItems ? (
|
{hasHiddenSelectedItems ? (
|
||||||
<div className="location-map-zone-hidden-note">
|
<div className="location-map-zone-hidden-note">
|
||||||
<p className="location-map-muted">
|
<p className="location-map-muted">
|
||||||
@ -185,14 +223,6 @@ export function UnmappedItemsPanel({
|
|||||||
onShowUnmappedItems,
|
onShowUnmappedItems,
|
||||||
onSelectUnmappedItem,
|
onSelectUnmappedItem,
|
||||||
}) {
|
}) {
|
||||||
const [showAllUnmappedItems, setShowAllUnmappedItems] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (visibleUnmappedItems.length <= UNMAPPED_PREVIEW_LIMIT) {
|
|
||||||
setShowAllUnmappedItems(false);
|
|
||||||
}
|
|
||||||
}, [visibleUnmappedItems.length]);
|
|
||||||
|
|
||||||
if (visibleUnmappedItems.length === 0 && hasHiddenUnmappedItems) {
|
if (visibleUnmappedItems.length === 0 && hasHiddenUnmappedItems) {
|
||||||
return (
|
return (
|
||||||
<div className="location-map-unmapped-list">
|
<div className="location-map-unmapped-list">
|
||||||
@ -213,36 +243,14 @@ export function UnmappedItemsPanel({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unmappedItemPreview = showAllUnmappedItems
|
|
||||||
? visibleUnmappedItems
|
|
||||||
: visibleUnmappedItems.slice(0, UNMAPPED_PREVIEW_LIMIT);
|
|
||||||
const overflowUnmappedItemCount = visibleUnmappedItems.length - unmappedItemPreview.length;
|
|
||||||
const hasUnmappedOverflow = visibleUnmappedItems.length > UNMAPPED_PREVIEW_LIMIT;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="location-map-unmapped-list">
|
<div className="location-map-unmapped-list">
|
||||||
<strong>Unmapped Items</strong>
|
<strong>Unmapped Items</strong>
|
||||||
<ul>
|
<MapItemActionList
|
||||||
{unmappedItemPreview.map((item) => (
|
items={visibleUnmappedItems}
|
||||||
<MapItemActionRow key={item.id} item={item} onSelectItem={onSelectUnmappedItem} />
|
onSelectItem={onSelectUnmappedItem}
|
||||||
))}
|
itemGroupLabel="unmapped items"
|
||||||
{hasUnmappedOverflow ? (
|
/>
|
||||||
<li className="location-map-unmapped-more">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="location-map-list-more-button"
|
|
||||||
onClick={() => setShowAllUnmappedItems((current) => !current)}
|
|
||||||
aria-label={
|
|
||||||
showAllUnmappedItems
|
|
||||||
? "Show fewer unmapped items"
|
|
||||||
: `Show ${overflowUnmappedItemCount} more unmapped items`
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{showAllUnmappedItems ? "Show fewer" : `+${overflowUnmappedItemCount} more`}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
) : null}
|
|
||||||
</ul>
|
|
||||||
{hiddenUnmappedItemCount > 0 ? (
|
{hiddenUnmappedItemCount > 0 ? (
|
||||||
<div className="location-map-zone-hidden-note">
|
<div className="location-map-zone-hidden-note">
|
||||||
<p className="location-map-muted">
|
<p className="location-map-muted">
|
||||||
|
|||||||
@ -827,7 +827,7 @@
|
|||||||
margin-bottom: 0.45rem;
|
margin-bottom: 0.45rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.location-map-unmapped-list .location-map-unmapped-more {
|
.location-map-list-more {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
|
|||||||
@ -2696,9 +2696,16 @@ test("viewer handles empty and many-item zone panels without default pins", asyn
|
|||||||
|
|
||||||
await page.locator('[data-object-key="1561"]').locator("rect").first().click();
|
await page.locator('[data-object-key="1561"]').locator("rect").first().click();
|
||||||
await expect(page.locator(".location-map-sheet-count")).toHaveText("14 items");
|
await expect(page.locator(".location-map-sheet-count")).toHaveText("14 items");
|
||||||
await expect(page.locator(".location-map-zone-items li")).toHaveCount(14);
|
await expect(page.locator(".location-map-zone-items .location-map-item-row")).toHaveCount(8);
|
||||||
await expect(page.locator(".location-map-zone-items li").first()).toContainText("bulk item 1");
|
await expect(page.locator(".location-map-zone-items .location-map-item-row").first()).toContainText("bulk item 1");
|
||||||
await expect(page.locator(".location-map-zone-items li").last()).toContainText("bulk item 14");
|
await expect(page.getByText("bulk item 9")).toHaveCount(0);
|
||||||
|
await expect(page.getByRole("button", { name: "Show 6 more zone items" })).toHaveText("+6 more");
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "Show 6 more zone items" }).click();
|
||||||
|
|
||||||
|
await expect(page.locator(".location-map-zone-items .location-map-item-row")).toHaveCount(14);
|
||||||
|
await expect(page.locator(".location-map-zone-items .location-map-item-row").last()).toContainText("bulk item 14");
|
||||||
|
await expect(page.getByRole("button", { name: "Show fewer zone items" })).toHaveText("Show fewer");
|
||||||
await expect(page.locator(".location-map-pin")).toHaveCount(0);
|
await expect(page.locator(".location-map-pin")).toHaveCount(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user