UI: Show achievement lists in grids (#2109)

This commit is contained in:
catloversg
2025-05-12 14:40:44 +07:00
committed by GitHub
parent 37d471fb0d
commit 562142be9f
3 changed files with 67 additions and 74 deletions

View File

@@ -1,6 +1,6 @@
import React from "react";
import { Accordion, AccordionSummary, AccordionDetails, Typography } from "@mui/material";
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box } from "@mui/material";
import { Achievement } from "./Achievements";
@@ -22,26 +22,8 @@ export function AchievementCategory({
usePadding,
children,
}: React.PropsWithChildren<IProps>): JSX.Element {
/**
* For each achievement, we need to display the icon and the detail on the same "row" (icon on the left and detail on
* the right). When the viewport is to small, the detail part of some achievements is "moved" to a separate "row". It
* looks like this:
*
* <achievement 1>
* <icon><detail>
* </achievement 1>
* <achievement 2>
* <icon>
* <detail>
* </achievement 2>
* <achievement 3>
* <icon><detail>
* </achievement 3>
*
* Using "minWidth" fixes this issue by setting a min value for the width of each row
*/
return (
<Accordion defaultExpanded={!!allAchievements} disableGutters square sx={{ minWidth: "645px" }}>
<Accordion defaultExpanded={!!allAchievements} disableGutters square>
<AccordionSummary>
{allAchievements ? (
<Typography variant="h5" sx={{ my: 1 }}>
@@ -54,7 +36,26 @@ export function AchievementCategory({
</Typography>
)}
</AccordionSummary>
<AccordionDetails sx={usePadding ? { pt: 2 } : undefined}>{children}</AccordionDetails>
<AccordionDetails sx={usePadding ? { pt: 2 } : undefined}>
{/* With each achievement, we need to display the icon and the detail on the same "row" (icon on the left and
* detail on the right). When the viewport is too small, the detail part of some achievements is "moved" to a
* separate "row". It looks like this:
*
* <achievement 1>
* <icon><detail>
* </achievement 1>
* <achievement 2>
* <icon>
* <detail>
* </achievement 2>
* <achievement 3>
* <icon><detail>
* </achievement 3>
*
* Setting the width of each achievement to 620px fixes this issue.
*/}
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, 620px)" }}>{children}</Box>
</AccordionDetails>
</Accordion>
);
}

View File

@@ -45,59 +45,51 @@ export function AchievementList({ achievements, playerAchievements }: IProps): J
.filter((entry) => !unavailable.map((u) => u.achievement.ID).includes(entry.achievement.ID));
return (
<Box sx={{ pr: 18, my: 2 }}>
<Box
sx={{
display: "flex",
flexDirection: "column",
flexWrap: "wrap",
}}
>
{unlocked.length > 0 && (
<AchievementCategory title="Acquired" achievements={unlocked} allAchievements={data} usePadding={true}>
{unlocked.map((item) => (
<AchievementEntry
key={`unlocked_${item.achievement.ID}`}
achievement={item.achievement}
unlockedOn={item.unlockedOn}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary}
/>
<Box sx={{ my: 2 }}>
{unlocked.length > 0 && (
<AchievementCategory title="Acquired" achievements={unlocked} allAchievements={data} usePadding={true}>
{unlocked.map((item) => (
<AchievementEntry
key={`unlocked_${item.achievement.ID}`}
achievement={item.achievement}
unlockedOn={item.unlockedOn}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary}
/>
))}
</AchievementCategory>
)}
{locked.length > 0 && (
<AchievementCategory title="Locked" achievements={locked} usePadding={true}>
{locked.map((item) => (
<AchievementEntry
key={`locked_${item.achievement.ID}`}
achievement={item.achievement}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary}
/>
))}
</AchievementCategory>
)}
{unavailable.length > 0 && (
<AchievementCategory title="Unavailable" achievements={unavailable}>
<Typography sx={{ mt: 1 }}>
{pluralize(unavailable.length, "additional achievement")} hidden behind content you don't have access to.
</Typography>
</AchievementCategory>
)}
{secret.length > 0 && (
<AchievementCategory title="Secret" achievements={secret}>
<Typography color="secondary" sx={{ mt: 1 }}>
{secret.map((item) => (
<span key={`secret_${item.achievement.ID}`}>
<CorruptableText content={item.achievement.ID} spoiler={true}></CorruptableText>
<br />
</span>
))}
</AchievementCategory>
)}
{locked.length > 0 && (
<AchievementCategory title="Locked" achievements={locked} usePadding={true}>
{locked.map((item) => (
<AchievementEntry
key={`locked_${item.achievement.ID}`}
achievement={item.achievement}
cssFiltersUnlocked={cssPrimary}
cssFiltersLocked={cssSecondary}
/>
))}
</AchievementCategory>
)}
{unavailable.length > 0 && (
<AchievementCategory title="Unavailable" achievements={unavailable}>
<Typography sx={{ mt: 1 }}>
{pluralize(unavailable.length, "additional achievement")} hidden behind content you don't have access to.
</Typography>
</AchievementCategory>
)}
{secret.length > 0 && (
<AchievementCategory title="Secret" achievements={secret}>
<Typography color="secondary" sx={{ mt: 1 }}>
{secret.map((item) => (
<span key={`secret_${item.achievement.ID}`}>
<CorruptableText content={item.achievement.ID} spoiler={true}></CorruptableText>
<br />
</span>
))}
</Typography>
</AchievementCategory>
)}
</Box>
</Typography>
</AchievementCategory>
)}
</Box>
);
}

View File

@@ -16,7 +16,7 @@ const useStyles = makeStyles()({
export function AchievementsRoot(): JSX.Element {
const { classes } = useStyles();
return (
<div className={classes.root} style={{ width: "90%" }}>
<div className={classes.root} style={{ width: "100%" }}>
<Typography variant="h4">Achievements</Typography>
<Box mx={2}>
<Typography>