diff --git a/src/app/routes/_authed/badges.tsx b/src/app/routes/_authed/badges.tsx
index 8582299..c16290f 100644
--- a/src/app/routes/_authed/badges.tsx
+++ b/src/app/routes/_authed/badges.tsx
@@ -1,4 +1,5 @@
import BadgeStatsTable from '@/features/badges/components/badge-stats-table';
+import BadgeStatsTableSkeleton from '@/features/badges/components/badge-stats-table-skeleton';
import { badgeQueries, useAllBadges } from '@/features/badges/queries';
import PlayerStatsTableSkeleton from '@/features/players/components/player-stats-table-skeleton';
import { prefetchServerQuery } from '@/lib/tanstack-query/utils/prefetch';
@@ -16,15 +17,15 @@ export const Route = createFileRoute('/_authed/badges')({
fullWidth: true,
header: {
title: 'All Badges',
+ withBackButton: true,
},
refresh: [badgeQueries.allBadges().queryKey],
}),
});
function Badges() {
- //TODO: CHANGE FALLBACK
return (
- }>
+ }>
diff --git a/src/features/badges/components/badge-stats-table-skeleton.tsx b/src/features/badges/components/badge-stats-table-skeleton.tsx
new file mode 100644
index 0000000..f4044fa
--- /dev/null
+++ b/src/features/badges/components/badge-stats-table-skeleton.tsx
@@ -0,0 +1,67 @@
+import {
+ Stack,
+ Container,
+ Box,
+ Divider,
+ Grid,
+ Skeleton,
+} from '@mantine/core';
+
+const BadgeStatsTableSkeleton = () => {
+ return (
+
+
+
+ {Array.from({ length: 15 }).map((_, index) => (
+ = 14}
+ />
+ ))}
+
+
+
+ );
+};
+
+export default BadgeStatsTableSkeleton;
+
+interface BadgeStatRowSkeletonProps {
+ isLastRow: boolean;
+}
+
+const BadgeStatRowSkeleton: React.FC = ({
+ isLastRow,
+}) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!isLastRow && }
+
+ );
+};
diff --git a/src/features/badges/components/badge-stats-table.tsx b/src/features/badges/components/badge-stats-table.tsx
index 13cf1de..90aeb8b 100644
--- a/src/features/badges/components/badge-stats-table.tsx
+++ b/src/features/badges/components/badge-stats-table.tsx
@@ -15,6 +15,9 @@ import { Badge, EarnedBadge } from '../types';
import { useAllPlayers } from '@/features/teams/hooks/use-available-players';
import { useSheet } from '@/hooks/use-sheet';
import Sheet from '@/components/sheet/sheet';
+import PlayerList from '@/features/players/components/player-list';
+import { useAuth } from '@/contexts/auth-context';
+import { Player } from '@/features/players/types';
const BadgeStatsTable = () => {
const { data: allBadges } = useAllBadges();
@@ -79,16 +82,69 @@ const BadgeStatRow: React.FC = ({
isLastRow,
}) => {
const badgeSheet = useSheet();
+ const { user } = useAuth();
+
+ const playerNamesBlurb = useMemo(() => {
+ if (earnedBadges.length === 0) return 'No players yet';
+
+ const currentUserHasBadge = earnedBadges.some(
+ (eb) => eb.player.id === user?.id
+ );
+
+ const otherPlayers = earnedBadges.filter(
+ (eb) => eb.player.id !== user?.id
+ );
+
+ const displayPlayers = currentUserHasBadge
+ ? otherPlayers.slice(0, 2)
+ : earnedBadges.slice(0, 3);
+
+ const names = displayPlayers.map((eb) => eb.player.first_name);
+
+ if (currentUserHasBadge) {
+ const remaining = earnedBadges.length - 1 - names.length;
+ if (names.length === 0 && remaining === 0) {
+ return 'You';
+ } else if (names.length === 0 && remaining > 0) {
+ return `You and ${remaining} other${remaining > 1 ? 's' : ''}`;
+ } else if (remaining > 0) {
+ return `You, ${names.join(', ')} and ${remaining} other${remaining > 1 ? 's' : ''}`;
+ } else {
+ return `You${names.length > 0 ? ` and ${names.join(', ')}` : ''}`;
+ }
+ } else {
+ const remaining = earnedBadges.length - names.length;
+ if (remaining > 0) {
+ return `${names.join(', ')} and ${remaining} other${remaining > 1 ? 's' : ''}`;
+ } else {
+ return names.join(', ');
+ }
+ }
+ }, [earnedBadges, user?.id]);
+
+ const playersForList: Player[] = useMemo(() => {
+ return earnedBadges.map((eb) => ({
+ id: eb.player.id,
+ first_name: eb.player.first_name,
+ last_name: eb.player.last_name,
+ } as Player));
+ }, [earnedBadges]);
+
return (
-
-
+
+
- {badge.name}
- {badge.description}
+
+ {badge.name}
+ {badge.description}
+
+ {playerNamesBlurb}
+
+
= ({
}}
>
-
+
{(
((earnedBadges?.length ?? 0) / totalNumPlayers) *
100
).toFixed(0)}
%
- of players
+ of players
-
- {earnedBadges?.map((earnedBadge) => (
-
- {earnedBadge.player.first_name +
- ' ' +
- earnedBadge.player.last_name}
-
- ))}
-
+
{!isLastRow && }
diff --git a/src/features/core/hooks/use-links.ts b/src/features/core/hooks/use-links.ts
index 7f23aca..4a2b357 100644
--- a/src/features/core/hooks/use-links.ts
+++ b/src/features/core/hooks/use-links.ts
@@ -1,4 +1,4 @@
-import { HouseIcon, RankingIcon, SealIcon, ShieldIcon, TrophyIcon, UserCircleIcon } from "@phosphor-icons/react";
+import { HouseIcon, RankingIcon, ShieldIcon, TrophyIcon, UserCircleIcon } from "@phosphor-icons/react";
import { useMemo } from "react";
export const useLinks = (userId: string | undefined, roles: string[]) =>
@@ -25,11 +25,6 @@ export const useLinks = (userId: string | undefined, roles: string[]) =>
href: `/profile/${userId}`,
Icon: UserCircleIcon,
include: ['/settings']
- },
- {
- label: 'Badges',
- href: '/badges',
- Icon: SealIcon
}
]
diff --git a/src/features/players/components/profile/index.tsx b/src/features/players/components/profile/index.tsx
index ff524bb..284059b 100644
--- a/src/features/players/components/profile/index.tsx
+++ b/src/features/players/components/profile/index.tsx
@@ -1,5 +1,6 @@
-import { Box, Stack, Text, Divider, Group, Button } from "@mantine/core";
+import { Box, Stack, Text, Divider, Group, Button, Anchor } from "@mantine/core";
import { Suspense, useState, useDeferredValue } from "react";
+import { Link } from "@tanstack/react-router";
import Header from "./header";
import SwipeableTabs from "@/components/swipeable-tabs";
import { usePlayer, usePlayerMatches, usePlayerStats } from "../../queries";
@@ -51,7 +52,12 @@ const Profile = ({ id }: ProfileProps) => {
label: "Overview",
content: <>
- Badges
+
+ Badges
+
+ View all badges
+
+
}>