images in badge popover

This commit is contained in:
yohlo
2025-10-06 02:23:25 -05:00
parent afd0b692fa
commit b458872ac1
2 changed files with 45 additions and 38 deletions

View File

@@ -1,4 +1,4 @@
import { Box, Container, Flex, Loader, useComputedColorScheme } from "@mantine/core"; import { Box, Container, Flex, Loader, Title, useComputedColorScheme } from "@mantine/core";
import { PropsWithChildren, Suspense, useEffect, useRef } from "react"; import { PropsWithChildren, Suspense, useEffect, useRef } from "react";
import { Drawer as VaulDrawer } from "vaul"; import { Drawer as VaulDrawer } from "vaul";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
@@ -120,7 +120,7 @@ const Drawer: React.FC<DrawerProps> = ({
style={{ borderRadius: "9999px" }} style={{ borderRadius: "9999px" }}
/> />
<Container mx="auto" maw="28rem" px={0}> <Container mx="auto" maw="28rem" px={0}>
<VaulDrawer.Title>{title}</VaulDrawer.Title> <VaulDrawer.Title><Title order={2}>{title}</Title></VaulDrawer.Title>
<Suspense fallback={ <Suspense fallback={
<Flex justify='center' align='center' w='100%' h={400}> <Flex justify='center' align='center' w='100%' h={400}>
<Loader size='lg' /> <Loader size='lg' />

View File

@@ -1,4 +1,4 @@
import { Box, Text, Popover, Progress, Title, Image } from "@mantine/core"; import { Box, Text, Progress, Image, Popover, Title, Stack } from "@mantine/core";
import { usePlayerBadges, useAllBadges } from "../queries"; import { usePlayerBadges, useAllBadges } from "../queries";
import { useAuth } from "@/contexts/auth-context"; import { useAuth } from "@/contexts/auth-context";
import { Badge, BadgeProgress } from "../types"; import { Badge, BadgeProgress } from "../types";
@@ -21,7 +21,7 @@ interface BadgeIconProps {
earned: boolean; earned: boolean;
} }
const BadgeIcon = ({ badge, earned }: BadgeIconProps) => { const BadgeIcon = ({ badge, earned, size = 48 }: BadgeIconProps & { size?: number }) => {
const [imageError, setImageError] = useState(false); const [imageError, setImageError] = useState(false);
const imagePath = `/static/img/${badge.key}.png`; const imagePath = `/static/img/${badge.key}.png`;
@@ -29,13 +29,13 @@ const BadgeIcon = ({ badge, earned }: BadgeIconProps) => {
// Fallback to icon if image fails to load // Fallback to icon if image fails to load
return earned ? ( return earned ? (
<MedalIcon <MedalIcon
size={48} size={size}
weight="fill" weight="fill"
color="var(--mantine-primary-color-6)" color="var(--mantine-primary-color-6)"
/> />
) : ( ) : (
<LockKeyIcon <LockKeyIcon
size={44} size={size - 4}
weight="regular" weight="regular"
color="var(--mantine-color-dimmed)" color="var(--mantine-color-dimmed)"
/> />
@@ -46,8 +46,8 @@ const BadgeIcon = ({ badge, earned }: BadgeIconProps) => {
<Image <Image
src={imagePath} src={imagePath}
alt={badge.name} alt={badge.name}
width={48} width={size}
height={48} height={size}
onError={() => setImageError(true)} onError={() => setImageError(true)}
style={{ style={{
objectFit: 'contain', objectFit: 'contain',
@@ -57,6 +57,7 @@ const BadgeIcon = ({ badge, earned }: BadgeIconProps) => {
); );
}; };
const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => { const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
const { user } = useAuth(); const { user } = useAuth();
const { data: badgeProgress } = usePlayerBadges(playerId); const { data: badgeProgress } = usePlayerBadges(playerId);
@@ -164,7 +165,7 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
const showStack = stackCount > 1; const showStack = stackCount > 1;
return ( return (
<Popover key={display.badge.id} width={220} position="top" withArrow shadow="md"> <Popover key={display.badge.id} width={280} position="top" withArrow shadow="md" withinPortal>
<Popover.Target> <Popover.Target>
<Box <Box
style={{ style={{
@@ -200,7 +201,7 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
width: '100px', width: '100px',
height: '100px', height: '100px',
borderRadius: '12px', borderRadius: '12px',
background: 'light-dark(var(--mantine-color-white), var(--mantine-color-dark-6))', background: 'light-dark(var(--mantine-color-white), var(--mantine-color-dark-7))',
border: display.earned border: display.earned
? '2px solid var(--mantine-primary-color-6)' ? '2px solid var(--mantine-primary-color-6)'
: '2px dashed var(--mantine-primary-color-4)', : '2px dashed var(--mantine-primary-color-4)',
@@ -252,20 +253,26 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
</Box> </Box>
</Popover.Target> </Popover.Target>
<Popover.Dropdown> <Popover.Dropdown>
<Box> <Stack gap={4} align="center">
<Title order={5}> <Box style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<BadgeIcon badge={display.badge} earned={display.earned} size={80} />
</Box>
<Title order={5} ta="center">
{display.badge.name} {display.badge.name}
</Title> </Title>
<Text size="xs" c="dimmed" mb={isCurrentUser ? "sm" : undefined}>
<Text size="sm" c="dimmed" ta="center">
{display.badge.description} {display.badge.description}
</Text> </Text>
{isCurrentUser && ( {isCurrentUser && (
<Box> <Box>
<Box mb="xs" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> <Box mb="xs" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Text size="xs" fw={500} c="dimmed"> <Text size="sm" fw={500} c="dimmed">
Progress Progress&nbsp;
</Text> </Text>
<Text size="xs" fw={600} c="dimmed"> <Text size="sm" fw={600} c="dimmed">
{display.progressText} {display.progressText}
</Text> </Text>
</Box> </Box>
@@ -277,7 +284,7 @@ const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => {
/> />
</Box> </Box>
)} )}
</Box> </Stack>
</Popover.Dropdown> </Popover.Dropdown>
</Popover> </Popover>
); );