[wip] Zone info UI for item page, with fake data
This commit is contained in:
parent
048fb29c14
commit
20f9573e50
1 changed files with 102 additions and 4 deletions
|
@ -15,7 +15,6 @@ import {
|
||||||
useTheme,
|
useTheme,
|
||||||
useToast,
|
useToast,
|
||||||
useToken,
|
useToken,
|
||||||
Stack,
|
|
||||||
Wrap,
|
Wrap,
|
||||||
WrapItem,
|
WrapItem,
|
||||||
Flex,
|
Flex,
|
||||||
|
@ -826,7 +825,29 @@ function ItemPageOutfitPreview({ itemId }) {
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box gridArea="zones" alignSelf="center" justifySelf="center">
|
<Box gridArea="zones" alignSelf="center" justifySelf="center">
|
||||||
<ItemZonesInfo />
|
<ItemZonesInfo
|
||||||
|
zonesAndTheirBodies={[
|
||||||
|
{
|
||||||
|
zone: { id: "1", label: "Foreground" },
|
||||||
|
bodies: [{ id: "0", representsAllBodies: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
zone: { id: "1", label: "Background" },
|
||||||
|
bodies: [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
representsAllBodies: false,
|
||||||
|
species: { name: "Blumaroo" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
representsAllBodies: false,
|
||||||
|
species: { name: "Aisha" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
@ -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 (
|
return (
|
||||||
<Box fontSize="sm" textAlign="center">
|
<Box fontSize="sm" textAlign="center">
|
||||||
{/* TODO */}
|
<Box as="header" fontWeight="bold" display="inline">
|
||||||
|
Zones:
|
||||||
|
</Box>{" "}
|
||||||
|
<Box as="ul" listStyleType="none" display="inline">
|
||||||
|
{sortedZonesAndTheirBodies.map(({ zone, bodies }) => (
|
||||||
|
<Box
|
||||||
|
key={zone.id}
|
||||||
|
as="li"
|
||||||
|
display="inline"
|
||||||
|
_notLast={{ _after: { content: '", "' } }}
|
||||||
|
>
|
||||||
|
<ItemZonesInfoListItem
|
||||||
|
zone={zone}
|
||||||
|
bodies={bodies}
|
||||||
|
showBodyInfo={showBodyInfo}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}{" "}
|
||||||
|
<Tooltip label={speciesListString}>
|
||||||
|
<Box
|
||||||
|
as="span"
|
||||||
|
tabIndex="0"
|
||||||
|
_focus={{ outline: "none", boxShadow: "outline" }}
|
||||||
|
textDecoration="underline"
|
||||||
|
style={{ textDecorationStyle: "dashed" }}
|
||||||
|
>
|
||||||
|
{/* 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)
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <img>, but listens for successful load events, and
|
* CrossFadeImage is like <img>, but listens for successful load events, and
|
||||||
* fades from the previous image to the new image once it loads.
|
* fades from the previous image to the new image once it loads.
|
||||||
|
|
Loading…
Reference in a new issue