diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js
index 7205d13..769c971 100644
--- a/src/app/ItemPage.js
+++ b/src/app/ItemPage.js
@@ -15,7 +15,6 @@ import {
useTheme,
useToast,
useToken,
- Stack,
Wrap,
WrapItem,
Flex,
@@ -826,7 +825,29 @@ function ItemPageOutfitPreview({ itemId }) {
/>
-
+
);
@@ -1255,14 +1276,91 @@ function SpeciesFaceOption({
);
}
-function ItemZonesInfo() {
+function ItemZonesInfo({ zonesAndTheirBodies }) {
+ const sortedZonesAndTheirBodies = [...zonesAndTheirBodies].sort((a, b) =>
+ zonesAndTheirBodiesSortKey(a).localeCompare(zonesAndTheirBodiesSortKey(b))
+ );
+
+ // We only show body info if there's more than one group of bodies to talk
+ // about. If they all have the same zones, it's clear from context that any
+ // preview available in the list has the zones listed here.
+ const bodyGroups = new Set(
+ zonesAndTheirBodies.map(({ bodies }) => bodies.map((b) => b.id).join(","))
+ );
+ const showBodyInfo = bodyGroups.size > 1;
+
return (
- {/* TODO */}
+
+ Zones:
+ {" "}
+
+ {sortedZonesAndTheirBodies.map(({ zone, bodies }) => (
+
+
+
+ ))}
+
);
}
+function ItemZonesInfoListItem({ zone, bodies, showBodyInfo }) {
+ let content = zone.label;
+
+ if (showBodyInfo) {
+ if (bodies.some((b) => b.representsAllBodies)) {
+ content = <>{content} (all species)>;
+ } else {
+ // TODO: This is a bit reductive, if it's different for like special
+ // colors, e.g. Blue Acara vs Mutant Acara, this will just show
+ // "Acara" in either case! (We are at least gonna be defensive here
+ // and remove duplicates, though, in case both the Blue Acara and
+ // Mutant Acara body end up in the same list.)
+ const speciesNames = new Set(bodies.map((b) => b.species.name));
+ const speciesListString = [...speciesNames].sort().join(", ");
+
+ content = (
+ <>
+ {content}{" "}
+
+
+ {/* Show the speciesNames count, even though it's less info,
+ * because it's more important that the tooltip content matches
+ * the count we show! */}
+ ({speciesNames.size} species)
+
+
+ >
+ );
+ }
+ }
+
+ return content;
+}
+
+function zonesAndTheirBodiesSortKey({ zone, bodies }) {
+ // Sort by "represents all bodies", then by body count, then alphabetically.
+ const representsAllBodies = bodies.some((body) => body.representsAllBodies);
+ const bodyCountString = bodies.length.toString().padStart(4, "0");
+ return `${representsAllBodies ? "A" : "Z"}-${bodyCountString}-${zone.label}`;
+}
+
/**
* CrossFadeImage is like , but listens for successful load events, and
* fades from the previous image to the new image once it loads.