badge redesign again

This commit is contained in:
yohlo
2025-10-01 21:28:27 -05:00
parent 1f4f66f8c5
commit a376f98fe7
3 changed files with 62 additions and 78 deletions

View File

@@ -1,45 +1,45 @@
import { Box, Card, Skeleton, Text } from "@mantine/core"; import { Box, Skeleton, Text } from "@mantine/core";
const BadgeShowcaseSkeleton = () => { const BadgeShowcaseSkeleton = () => {
return ( return (
<Box mb="lg"> <Box mb="lg">
<Card <Box
withBorder px="md"
radius="md"
p={0}
style={{ style={{
overflow: 'hidden', maxHeight: '220px',
overflowY: 'auto',
overflowX: 'hidden',
width: '100%',
}} }}
> >
<Box <Box
p="md"
style={{
background: 'light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-6))',
borderBottom: '1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4))',
}}
>
<Text size="sm" fw={600} tt="uppercase" c="dimmed" style={{ letterSpacing: '0.5px' }}>
Badges
</Text>
</Box>
<Box
p="md"
style={{ style={{
display: 'grid', display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(110px, 1fr))', gridTemplateColumns: 'repeat(auto-fill, minmax(85px, 1fr))',
gap: 'var(--mantine-spacing-sm)', gap: 'var(--mantine-spacing-md)',
paddingBottom: 'var(--mantine-spacing-sm)',
width: '100%',
}} }}
> >
{[1, 2, 3, 4, 5, 6].map((i) => ( {[1, 2, 3, 4, 5, 6].map((i) => (
<Skeleton <Box
key={i} key={i}
height={70} style={{
radius="md" aspectRatio: '1',
/> position: 'relative',
}}
>
<Skeleton
height="100%"
radius="12px"
style={{
aspectRatio: '1',
}}
/>
</Box>
))} ))}
</Box> </Box>
</Card> </Box>
</Box> </Box>
); );
}; };

View File

@@ -88,18 +88,13 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
return ( return (
<Box mb="lg"> <Box mb="lg">
<Box mb="sm" px="md">
<Text size="sm" fw={600} tt="uppercase" c="dimmed" style={{ letterSpacing: '0.5px' }}>
Badges
</Text>
</Box>
<Box <Box
px="md" px="md"
style={{ style={{
maxHeight: '200px', maxHeight: '220px',
overflowY: 'auto', overflowY: 'auto',
overflowX: 'hidden', overflowX: 'hidden',
width: '100%',
}} }}
> >
<Box <Box
@@ -108,13 +103,13 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
gridTemplateColumns: 'repeat(auto-fill, minmax(85px, 1fr))', gridTemplateColumns: 'repeat(auto-fill, minmax(85px, 1fr))',
gap: 'var(--mantine-spacing-md)', gap: 'var(--mantine-spacing-md)',
paddingBottom: 'var(--mantine-spacing-sm)', paddingBottom: 'var(--mantine-spacing-sm)',
width: '100%',
}} }}
> >
{badgesToDisplay.map((display) => { {badgesToDisplay.map((display) => {
const isStackableBadge = display.badge.criteria?.tournament_wins !== undefined || const isStackableBadge = ['winner_badge', 'silver_medal_badge', 'bronze_medal_badge'].includes(display.badge.key);
display.badge.criteria?.placement !== undefined;
const stackCount = display.earned && isStackableBadge const stackCount = display.earned && isStackableBadge
? Math.floor((display.progress?.progress || 0) / getTargetProgress(display.badge)) ? (display.progress?.progress || 0)
: 1; : 1;
const showStack = stackCount > 1; const showStack = stackCount > 1;
@@ -133,32 +128,32 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
{[...Array(Math.min(stackCount - 1, 2))].map((_, i) => ( {[...Array(Math.min(stackCount - 1, 2))].map((_, i) => (
<Box <Box
key={i} key={i}
style={(theme) => ({ style={{
aspectRatio: '1', aspectRatio: '1',
borderRadius: '12px', borderRadius: '12px',
background: `linear-gradient(135deg, ${theme.colors[theme.primaryColor][5]} 0%, ${theme.colors[theme.primaryColor][7]} 100%)`, background: 'transparent',
border: `2px solid ${theme.colors[theme.primaryColor][6]}`, border: '2px solid var(--mantine-primary-color-5)',
position: 'absolute', position: 'absolute',
top: `${(i + 1) * 3}px`, top: `${(i + 1) * 3}px`,
left: `${(i + 1) * 3}px`, left: `${(i + 1) * 3}px`,
right: `-${(i + 1) * 3}px`, right: `-${(i + 1) * 3}px`,
bottom: `-${(i + 1) * 3}px`, bottom: `-${(i + 1) * 3}px`,
opacity: 0.6 - (i * 0.2), opacity: 0.4 - (i * 0.15),
zIndex: -(i + 1), zIndex: -(i + 1),
})} }}
/> />
))} ))}
</> </>
)} )}
<Box <Box
style={(theme) => ({ style={{
aspectRatio: '1', aspectRatio: '1',
borderRadius: '12px', borderRadius: '12px',
background: display.earned background: 'light-dark(var(--mantine-color-white), var(--mantine-color-dark-7))',
? `linear-gradient(135deg, ${theme.colors[theme.primaryColor][5]} 0%, ${theme.colors[theme.primaryColor][7]} 100%)` border: display.earned
: 'light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-6))', ? '2px solid var(--mantine-primary-color-6)'
border: `2px solid ${display.earned ? theme.colors[theme.primaryColor][6] : 'light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4))'}`, : '2px dashed var(--mantine-primary-color-4)',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
@@ -167,46 +162,33 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
padding: 'var(--mantine-spacing-xs)', padding: 'var(--mantine-spacing-xs)',
position: 'relative', position: 'relative',
boxShadow: display.earned boxShadow: display.earned
? `0 2px 8px ${theme.colors[theme.primaryColor][6]}30` ? '0 0 0 1px color-mix(in srgb, var(--mantine-primary-color-6) 20%, transparent)'
: '0 1px 3px rgba(0, 0, 0, 0.1)', : 'none',
opacity: display.earned ? 1 : 0.5, opacity: display.earned ? 1 : 0.4,
zIndex: 1, zIndex: 1,
':hover': { }}
transform: 'translateY(-2px)',
boxShadow: display.earned
? `0 4px 12px ${theme.colors[theme.primaryColor][6]}40`
: '0 2px 6px rgba(0, 0, 0, 0.15)',
},
})}
> >
{display.earned ? ( {display.earned ? (
<MedalIcon <MedalIcon
size={32} size={32}
weight="fill" weight="fill"
style={{ color="var(--mantine-primary-color-6)"
color: 'white',
filter: 'drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))',
}}
/> />
) : ( ) : (
<LockKeyIcon <LockKeyIcon
size={28} size={28}
weight="regular" weight="regular"
style={{ color="var(--mantine-color-dimmed)"
color: 'var(--mantine-color-dimmed)',
}}
/> />
)} )}
{showStack && ( {showStack && (
<Box <Box
style={(theme) => ({ style={{
position: 'absolute', position: 'absolute',
top: '4px', top: '4px',
right: '4px', right: '4px',
background: theme.colors[theme.primaryColor][8], color: 'var(--mantine-primary-color-6)',
color: 'white',
borderRadius: '50%',
width: '20px', width: '20px',
height: '20px', height: '20px',
display: 'flex', display: 'flex',
@@ -214,11 +196,9 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
justifyContent: 'center', justifyContent: 'center',
fontSize: '10px', fontSize: '10px',
fontWeight: 700, fontWeight: 700,
border: '2px solid white', }}
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.3)',
})}
> >
{stackCount} x{stackCount}
</Box> </Box>
)} )}
@@ -226,10 +206,9 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
size="xs" size="xs"
fw={display.earned ? 600 : 500} fw={display.earned ? 600 : 500}
ta="center" ta="center"
c={display.earned ? 'white' : 'dimmed'} c={display.earned ? undefined : 'dimmed'}
style={{ style={{
lineHeight: 1.2, lineHeight: 1.2,
textShadow: display.earned ? '0 1px 2px rgba(0, 0, 0, 0.3)' : 'none',
}} }}
> >
{display.badge.name} {display.badge.name}

View File

@@ -1,4 +1,4 @@
import { Box } from "@mantine/core"; import { Box, Stack, Text, Divider } from "@mantine/core";
import { Suspense } from "react"; import { Suspense } from "react";
import Header from "./header"; import Header from "./header";
import SwipeableTabs from "@/components/swipeable-tabs"; import SwipeableTabs from "@/components/swipeable-tabs";
@@ -21,14 +21,19 @@ const Profile = ({ id }: ProfileProps) => {
const tabs = [ const tabs = [
{ {
label: "Overview", label: "Overview",
content: ( content: <>
<> <Stack px="md">
<Text size="md" fw={700}>Badges</Text>
<Suspense fallback={<BadgeShowcaseSkeleton />}> <Suspense fallback={<BadgeShowcaseSkeleton />}>
<BadgeShowcase playerId={id} /> <BadgeShowcase playerId={id} />
</Suspense> </Suspense>
</Stack>
<Divider my="md" />
<Stack>
<Text px="md" size="md" fw={700}>Statistics</Text>
<StatsOverview statsData={stats} isLoading={statsLoading} /> <StatsOverview statsData={stats} isLoading={statsLoading} />
</> </Stack>
), </>,
}, },
{ {
label: "Matches", label: "Matches",