This commit is contained in:
yohlo
2025-08-20 22:35:40 -05:00
commit f51c278cd3
169 changed files with 8173 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
import { Outlet, redirect, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute('/_authed/admin')({
component: Outlet,
beforeLoad: ({ context }) => {
if (!context.auth?.roles?.includes('Admin')) {
throw redirect({ to: '/' })
}
return {
header: {
...context.header,
title: 'Admin',
withBackButton: true
},
};
}
})

View File

@@ -0,0 +1,22 @@
import { createFileRoute } from "@tanstack/react-router"
import { Title } from "@mantine/core";
import Page from "@/components/page";
import { playerQueries } from "@/features/players/queries";
import { useQuery } from "@tanstack/react-query";
import PlayerList from "@/features/players/components/player-list";
export const Route = createFileRoute("/_authed/admin/")({
loader: async ({ context }) => {
const { queryClient } = context;
await queryClient.ensureQueryData(playerQueries.list())
},
component: RouteComponent,
})
function RouteComponent() {
const { data: players, isLoading } = useQuery(playerQueries.list());
return <Page>
<Title order={2} mb='md'>Players</Title>
<PlayerList players={players!} loading={isLoading} />
</Page>
}

View File

@@ -0,0 +1,10 @@
import { PreviewBracketPage } from '@/features/bracket/components/bracket-page'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_authed/admin/preview')({
component: RouteComponent,
})
function RouteComponent() {
return <PreviewBracketPage />
}

View File

@@ -0,0 +1,29 @@
import { createFileRoute } from "@tanstack/react-router";
import Page from "@/components/page";
import { TrophyIcon } from "@phosphor-icons/react";
import ListLink from "@/components/list-link";
import { tournamentQueries } from "@/features/tournaments/queries";
import { Box, Divider, Text } from "@mantine/core";
export const Route = createFileRoute("/_authed/")({
component: Home,
beforeLoad: async ({ context }) => {
await context.queryClient.ensureQueryData(tournamentQueries.list());
},
});
function Home() {
return (
<Page noPadding>
<Box h='60vh' p="md">
<Text m='16vh' fw={500}>Some Content Here</Text>
</Box>
<Box>
<Text pl='md'>Quick Links</Text>
<Divider />
<ListLink label="All Tournaments" to="/tournaments" Icon={TrophyIcon} />
</Box>
</Page>
);
}

View File

@@ -0,0 +1,28 @@
import Page from "@/components/page";
import Profile from "@/features/players/components/profile";
import { playerQueries } from "@/features/players/queries";
import { redirect, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/_authed/profile/$playerId")({
beforeLoad: async ({ params, context }) => {
const { queryClient } = context;
const player = await queryClient.ensureQueryData(playerQueries.details(params.playerId))
if (!player) throw redirect({ to: '/' });
return {
player
}
},
loader: ({ params }) => ({
header: {
collapsed: true,
withBackButton: true
},
refresh: {
toRefresh: [playerQueries.details(params.playerId).queryKey],
}
}),
component: () => {
const { player } = Route.useRouteContext();
return <Page><Profile player={player} /></Page>
},
})

View File

@@ -0,0 +1,34 @@
import { createFileRoute } from "@tanstack/react-router"
import { Box, Title, Stack } from "@mantine/core"
import { ColorSchemePicker } from "@/features/settings/components/color-scheme-picker"
import AccentColorPicker from "@/features/settings/components/accent-color-picker"
import { SignOutIcon } from "@phosphor-icons/react"
import ListLink from "@/components/list-link"
import Page from "@/components/page"
export const Route = createFileRoute("/_authed/settings")({
loader: () => ({
header: {
title: 'Settings',
withBackButton: true,
},
}),
component: RouteComponent,
})
function RouteComponent() {
return <Page noPadding>
<Box px='md' py='sm' style={{ borderBottom: '1px solid var(--mantine-color-default-border)' }}>
<Title order={3}>Appearance</Title>
<Stack>
<AccentColorPicker />
<ColorSchemePicker />
</Stack>
</Box>
<ListLink
label='Sign Out'
to='/logout'
Icon={SignOutIcon}
/>
</Page>
}

View File

@@ -0,0 +1,26 @@
import Page from "@/components/page";
import TeamProfile from "@/features/teams/components/team-profile";
import { teamQueries } from "@/features/teams/queries";
import { redirect, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/_authed/teams/$teamId")({
beforeLoad: async ({ params, context }) => {
const { queryClient } = context;
const team = await queryClient.ensureQueryData(teamQueries.details(params.teamId))
if (!team) throw redirect({ to: '/' });
return { team }
},
loader: ({ params }) => ({
header: {
collapsed: true,
withBackButton: true
},
refresh: {
toRefresh: [teamQueries.details(params.teamId).queryKey],
}
}),
component: () => {
const { team } = Route.useRouteContext();
return <Page><TeamProfile team={team} /></Page>
},
})

View File

@@ -0,0 +1,67 @@
import { createFileRoute } from '@tanstack/react-router'
import { tournamentQueries } from '@/features/tournaments/queries';
import Page from '@/components/page'
import { useQuery } from '@tanstack/react-query';
import { Box, Button } from '@mantine/core';
import { useSheet } from '@/hooks/use-sheet';
import Sheet from '@/components/sheet/sheet';
import { Tournament } from '@/features/tournaments/types';
import { UsersIcon } from '@phosphor-icons/react';
import ListButton from '@/components/list-button';
import TeamList from '@/features/teams/components/team-list';
export const Route = createFileRoute('/_authed/tournaments/$tournamentId')({
beforeLoad: async ({ context, params }) => {
const { queryClient } = context;
await queryClient.ensureQueryData(tournamentQueries.details(params.tournamentId))
},
loader: ({ params }) => ({
header: {
collapsed: true,
withBackButton: true
},
refresh: {
toRefresh: tournamentQueries.details(params.tournamentId).queryKey,
}
}),
component: RouteComponent,
})
function RouteComponent() {
const { data: tournament } = useQuery(tournamentQueries.details(Route.useParams().tournamentId));
const sheet = useSheet()
return <Page noPadding>
<Box mt='xl' p='md'>
<h3 style={{ marginTop: 0 }}>
{tournament?.name}
</h3>
<Button onClick={() => sheet.open()}>
View Teams
</Button>
</Box>
<ListButton
label='Teams'
onClick={() => sheet.open()}
Icon={UsersIcon}
/>
<Sheet
{...sheet.props}
title='Teams'
>
<TeamDrawer tournament={tournament!} />
</Sheet>
</Page>
}
const TeamDrawer = ({ tournament }: { tournament: Tournament }) => {
return (
<TeamList teams={tournament?.teams!} />
);
}

View File

@@ -0,0 +1,54 @@
import Page from '@/components/page'
import { Button, Stack } from '@mantine/core'
import { createFileRoute } from '@tanstack/react-router'
import { TournamentCard } from '@/features/tournaments/components/tournament-card'
import { tournamentQueries } from '@/features/tournaments/queries'
import { useQuery } from '@tanstack/react-query'
import { useAuth } from '@/contexts/auth-context'
import { useSheet } from '@/hooks/use-sheet'
import Sheet from '@/components/sheet/sheet'
import CreateTournament from '@/features/admin/components/create-tournament'
import { PlusIcon } from '@phosphor-icons/react'
export const Route = createFileRoute('/_authed/tournaments/')({
beforeLoad: async ({ context }) => {
const { queryClient } = context;
await queryClient.ensureQueryData(tournamentQueries.list())
},
loader: () => ({
header: {
withBackButton: true,
title: 'Tournaments',
},
refresh: {
toRefresh: tournamentQueries.list().queryKey,
}
}),
component: RouteComponent,
})
function RouteComponent() {
const { data: tournaments } = useQuery(tournamentQueries.list());
const { roles } = useAuth();
const sheet = useSheet();
return <Page>
<Stack>
{
roles?.includes("Admin") ? (
<>
<Button leftSection={<PlusIcon />} variant='subtle' onClick={sheet.open}>Create Tournament</Button>
<Sheet {...sheet.props} title='Create Tournament'>
<CreateTournament close={sheet.close} />
</Sheet>
</>
) : null
}
{
tournaments?.map((tournament: any) => (
<TournamentCard key={tournament.id} tournament={tournament} />
))
}
</Stack>
</Page>
}