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.