significant refactor
This commit is contained in:
@@ -1,59 +1,63 @@
|
||||
import '@mantine/core/styles.css';
|
||||
import '@mantine/dates/styles.css';
|
||||
import '@mantine/carousel/styles.css';
|
||||
import "@mantine/core/styles.css";
|
||||
import "@mantine/dates/styles.css";
|
||||
import "@mantine/carousel/styles.css";
|
||||
import {
|
||||
HeadContent,
|
||||
Navigate,
|
||||
Outlet,
|
||||
Scripts,
|
||||
createRootRouteWithContext
|
||||
} from '@tanstack/react-router'
|
||||
import * as React from 'react'
|
||||
import { DefaultCatchBoundary } from '@/components/DefaultCatchBoundary'
|
||||
import { type QueryClient } from '@tanstack/react-query'
|
||||
import { ensureSuperTokensFrontend } from '@/lib/supertokens/client'
|
||||
import { AuthContextType, authQueryConfig } from '@/contexts/auth-context'
|
||||
import Providers from '@/features/core/components/providers'
|
||||
import { ColorSchemeScript, mantineHtmlProps } from '@mantine/core';
|
||||
import { HeaderConfig } from '@/features/core/types/header-config';
|
||||
createRootRouteWithContext,
|
||||
} from "@tanstack/react-router";
|
||||
import * as React from "react";
|
||||
import { DefaultCatchBoundary } from "@/components/DefaultCatchBoundary";
|
||||
import { type QueryClient } from "@tanstack/react-query";
|
||||
import { ensureSuperTokensFrontend } from "@/lib/supertokens/client";
|
||||
import { AuthContextType } from "@/contexts/auth-context";
|
||||
import Providers from "@/features/core/components/providers";
|
||||
import { ColorSchemeScript, mantineHtmlProps } from "@mantine/core";
|
||||
import { HeaderConfig } from "@/features/core/types/header-config";
|
||||
import { playerQueries } from "@/features/players/queries";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
|
||||
|
||||
export const Route = createRootRouteWithContext<{
|
||||
queryClient: QueryClient,
|
||||
auth: AuthContextType,
|
||||
header: HeaderConfig,
|
||||
refresh: string[]
|
||||
withPadding: boolean
|
||||
queryClient: QueryClient;
|
||||
auth: AuthContextType;
|
||||
header: HeaderConfig;
|
||||
refresh: string[];
|
||||
withPadding: boolean;
|
||||
}>()({
|
||||
head: () => ({
|
||||
meta: [
|
||||
{
|
||||
charSet: 'utf-8'
|
||||
charSet: "utf-8",
|
||||
},
|
||||
{
|
||||
name: 'viewport',
|
||||
content: 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, interactive-widget=overlays-content',
|
||||
}
|
||||
name: "viewport",
|
||||
content:
|
||||
"width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, interactive-widget=overlays-content",
|
||||
},
|
||||
],
|
||||
links: [
|
||||
{
|
||||
rel: 'apple-touch-icon',
|
||||
sizes: '180x180',
|
||||
href: '/apple-touch-icon.png',
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "180x180",
|
||||
href: "/apple-touch-icon.png",
|
||||
},
|
||||
{
|
||||
rel: 'icon',
|
||||
type: 'image/png',
|
||||
sizes: '32x32',
|
||||
href: '/favicon-32x32.png',
|
||||
rel: "icon",
|
||||
type: "image/png",
|
||||
sizes: "32x32",
|
||||
href: "/favicon-32x32.png",
|
||||
},
|
||||
{
|
||||
rel: 'icon',
|
||||
type: 'image/png',
|
||||
sizes: '16x16',
|
||||
href: '/favicon-16x16.png',
|
||||
rel: "icon",
|
||||
type: "image/png",
|
||||
sizes: "16x16",
|
||||
href: "/favicon-16x16.png",
|
||||
},
|
||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
||||
{ rel: 'icon', href: '/favicon.ico' },
|
||||
{ rel: "manifest", href: "/site.webmanifest" },
|
||||
{ rel: "icon", href: "/favicon.ico" },
|
||||
],
|
||||
}),
|
||||
errorComponent: (props) => {
|
||||
@@ -61,25 +65,24 @@ export const Route = createRootRouteWithContext<{
|
||||
<RootDocument>
|
||||
<DefaultCatchBoundary {...props} />
|
||||
</RootDocument>
|
||||
)
|
||||
);
|
||||
},
|
||||
component: RootComponent,
|
||||
notFoundComponent: () => <Navigate to="/" />,
|
||||
beforeLoad: async ({ context }) => {
|
||||
// I don't really like this. I wish there was some way before the router is rendered to useAuth() and pass context there.
|
||||
// See: https://github.com/TanStack/router/discussions/3531
|
||||
const auth = await context.queryClient.ensureQueryData(authQueryConfig)
|
||||
return {
|
||||
auth
|
||||
};
|
||||
}
|
||||
})
|
||||
const auth = await ensureServerQueryData(
|
||||
context.queryClient,
|
||||
playerQueries.auth()
|
||||
);
|
||||
return { auth };
|
||||
},
|
||||
pendingComponent: () => <p>Loading...</p>,
|
||||
});
|
||||
|
||||
function RootComponent() {
|
||||
|
||||
React.useEffect(() => {
|
||||
ensureSuperTokensFrontend()
|
||||
}, [])
|
||||
ensureSuperTokensFrontend();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<RootDocument>
|
||||
@@ -87,25 +90,38 @@ function RootComponent() {
|
||||
<Outlet />
|
||||
</Providers>
|
||||
</RootDocument>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// todo: analytics -> process.env data-website-id
|
||||
function RootDocument({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html {...mantineHtmlProps} style={{ overflowX: 'hidden', overflowY: 'hidden', position: 'fixed', width: '100%' }}>
|
||||
<html
|
||||
{...mantineHtmlProps}
|
||||
style={{
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
position: "fixed",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<head>
|
||||
<HeadContent />
|
||||
<ColorSchemeScript />
|
||||
<link rel="stylesheet" href="/styles.css" />
|
||||
<script defer src="https://analytics.yohler.net/script.js" data-website-id="0280f304-17a6-400c-8021-4d83a62d0c1b"></script>
|
||||
</head>
|
||||
<body style={{ overflowX: 'hidden', overflowY: 'hidden', position: 'fixed', width: '100%' }}>
|
||||
<div className='app'>
|
||||
{children}
|
||||
</div>
|
||||
<body
|
||||
style={{
|
||||
overflowX: "hidden",
|
||||
overflowY: "hidden",
|
||||
position: "fixed",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div className="app">{children}</div>
|
||||
<Scripts />
|
||||
<ReactQueryDevtools />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import { redirect, createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
import Layout from "@/features/core/components/layout";
|
||||
import { useServerEvents } from "@/hooks/use-server-events";
|
||||
import { Loader } from "@mantine/core";
|
||||
|
||||
export const Route = createFileRoute('/_authed')({
|
||||
export const Route = createFileRoute("/_authed")({
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.auth?.user) {
|
||||
throw redirect({ to: '/login' })
|
||||
throw redirect({ to: "/login" });
|
||||
}
|
||||
|
||||
return {
|
||||
auth: {
|
||||
...context.auth,
|
||||
user: context.auth.user
|
||||
}
|
||||
user: context.auth.user,
|
||||
},
|
||||
};
|
||||
},
|
||||
component: () => {
|
||||
@@ -21,6 +22,11 @@ export const Route = createFileRoute('/_authed')({
|
||||
<Layout>
|
||||
<Outlet />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
pendingComponent: () => (
|
||||
<Layout>
|
||||
<Loader size="xl" />
|
||||
</Layout>
|
||||
),
|
||||
});
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { Outlet, redirect, createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute('/_authed/admin')({
|
||||
export const Route = createFileRoute("/_authed/admin")({
|
||||
component: Outlet,
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.auth?.roles?.includes('Admin')) {
|
||||
throw redirect({ to: '/' })
|
||||
if (!context.auth?.roles?.includes("Admin")) {
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
|
||||
return {
|
||||
header: {
|
||||
...context.header,
|
||||
title: 'Admin',
|
||||
withBackButton: true
|
||||
title: "Admin",
|
||||
withBackButton: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { createFileRoute } from "@tanstack/react-router"
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { AdminPage } from "@/features/admin";
|
||||
|
||||
export const Route = createFileRoute("/_authed/admin/")({
|
||||
loader: () => ({
|
||||
header: {
|
||||
withBackButton: true,
|
||||
title: "Admin"
|
||||
title: "Admin",
|
||||
},
|
||||
withPadding: false
|
||||
withPadding: false,
|
||||
}),
|
||||
component: () => <AdminPage />
|
||||
})
|
||||
component: () => <AdminPage />,
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { PreviewBracket } from '@/features/bracket/components/preview'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { PreviewBracket } from "@/features/bracket/components/preview";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute('/_authed/admin/preview')({
|
||||
export const Route = createFileRoute("/_authed/admin/preview")({
|
||||
component: RouteComponent,
|
||||
loader: () => ({
|
||||
header: {
|
||||
withBackButton: true,
|
||||
title: "Bracket Preview"
|
||||
title: "Bracket Preview",
|
||||
},
|
||||
withPadding: false
|
||||
})
|
||||
})
|
||||
withPadding: false,
|
||||
}),
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <PreviewBracket />
|
||||
return <PreviewBracket />;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
import { tournamentQueries } from '@/features/tournaments/queries'
|
||||
import ManageTournament from '@/features/tournaments/components/manage-tournament'
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { tournamentQueries } from "@/features/tournaments/queries";
|
||||
import ManageTournament from "@/features/tournaments/components/manage-tournament";
|
||||
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
|
||||
|
||||
export const Route = createFileRoute('/_authed/admin/tournaments/$id')({
|
||||
export const Route = createFileRoute("/_authed/admin/tournaments/$id")({
|
||||
beforeLoad: async ({ context, params }) => {
|
||||
const { queryClient } = context;
|
||||
const tournament = await queryClient.ensureQueryData(tournamentQueries.details(params.id))
|
||||
if (!tournament) throw redirect({ to: '/admin/tournaments' });
|
||||
const tournament = await ensureServerQueryData(
|
||||
queryClient,
|
||||
tournamentQueries.details(params.id)
|
||||
);
|
||||
if (!tournament) throw redirect({ to: "/admin/tournaments" });
|
||||
return {
|
||||
tournament
|
||||
}
|
||||
tournament,
|
||||
};
|
||||
},
|
||||
loader: ({ context }) => ({
|
||||
header: {
|
||||
withBackButton: true,
|
||||
title: `Manage ${context.tournament.name}`,
|
||||
},
|
||||
withPadding: false
|
||||
withPadding: false,
|
||||
}),
|
||||
component: RouteComponent,
|
||||
})
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { id } = Route.useParams()
|
||||
return <ManageTournament tournamentId={id} />
|
||||
}
|
||||
const { id } = Route.useParams();
|
||||
return <ManageTournament tournamentId={id} />;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import Page from "@/components/page";
|
||||
import ManageTournaments from "@/features/admin/components/manage-tournaments";
|
||||
import { tournamentQueries } from "@/features/tournaments/queries";
|
||||
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/_authed/admin/tournaments/")({
|
||||
beforeLoad: async ({ context }) => {
|
||||
const { queryClient } = context;
|
||||
await queryClient.ensureQueryData(tournamentQueries.list());
|
||||
await prefetchServerQuery(queryClient, tournamentQueries.list());
|
||||
},
|
||||
loader: () => ({
|
||||
header: {
|
||||
@@ -14,11 +14,11 @@ export const Route = createFileRoute("/_authed/admin/tournaments/")({
|
||||
title: "Manage Tournaments",
|
||||
},
|
||||
refresh: tournamentQueries.list().queryKey,
|
||||
withPadding: false
|
||||
withPadding: false,
|
||||
}),
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <ManageTournaments />
|
||||
return <ManageTournaments />;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
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());
|
||||
},
|
||||
loader: () => ({
|
||||
withPadding: false
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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";
|
||||
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { z } from "zod";
|
||||
|
||||
const searchSchema = z.object({
|
||||
@@ -12,22 +12,22 @@ export const Route = createFileRoute("/_authed/profile/$playerId")({
|
||||
validateSearch: searchSchema,
|
||||
beforeLoad: async ({ params, context }) => {
|
||||
const { queryClient } = context;
|
||||
const player = await queryClient.ensureQueryData(playerQueries.details(params.playerId))
|
||||
if (!player) throw redirect({ to: '/' });
|
||||
return {
|
||||
player
|
||||
}
|
||||
await prefetchServerQuery(
|
||||
queryClient,
|
||||
playerQueries.details(params.playerId)
|
||||
);
|
||||
},
|
||||
loader: ({ params, context }) => ({
|
||||
header: {
|
||||
collapsed: true,
|
||||
withBackButton: true,
|
||||
settingsLink: context?.auth.user.id === params.playerId ? 'settings' : undefined
|
||||
settingsLink:
|
||||
context?.auth.user.id === params.playerId ? "/settings" : undefined,
|
||||
},
|
||||
refresh: [playerQueries.details(params.playerId).queryKey]
|
||||
refresh: [playerQueries.details(params.playerId).queryKey],
|
||||
}),
|
||||
component: () => {
|
||||
const { player } = Route.useRouteContext();
|
||||
return <Profile player={player} />
|
||||
const { playerId } = Route.useParams();
|
||||
return <Profile id={playerId} />;
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
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 { 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";
|
||||
|
||||
export const Route = createFileRoute("/_authed/settings")({
|
||||
loader: () => ({
|
||||
header: {
|
||||
title: 'Settings',
|
||||
title: "Settings",
|
||||
withBackButton: true,
|
||||
},
|
||||
withPadding: false
|
||||
withPadding: false,
|
||||
}),
|
||||
component: RouteComponent,
|
||||
})
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <>
|
||||
<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}
|
||||
/>
|
||||
</>
|
||||
return (
|
||||
<>
|
||||
<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} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Page from "@/components/page";
|
||||
import TeamProfile from "@/features/teams/components/team-profile";
|
||||
import { teamQueries } from "@/features/teams/queries";
|
||||
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
|
||||
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
|
||||
import { redirect, createFileRoute } from "@tanstack/react-router";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -12,19 +13,17 @@ export const Route = createFileRoute("/_authed/teams/$teamId")({
|
||||
validateSearch: searchSchema,
|
||||
beforeLoad: async ({ params, context }) => {
|
||||
const { queryClient } = context;
|
||||
const team = await queryClient.ensureQueryData(teamQueries.details(params.teamId))
|
||||
if (!team) throw redirect({ to: '/' });
|
||||
return { team }
|
||||
await prefetchServerQuery(queryClient, teamQueries.details(params.teamId));
|
||||
},
|
||||
loader: ({ params }) => ({
|
||||
header: {
|
||||
collapsed: true,
|
||||
withBackButton: true
|
||||
withBackButton: true,
|
||||
},
|
||||
refresh: [teamQueries.details(params.teamId).queryKey]
|
||||
refresh: [teamQueries.details(params.teamId).queryKey],
|
||||
}),
|
||||
component: () => {
|
||||
const { team } = Route.useRouteContext();
|
||||
return <TeamProfile team={team} />
|
||||
const { teamId } = Route.useParams();
|
||||
return <TeamProfile id={teamId} />;
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
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, Group, Title } from '@mantine/core';
|
||||
import { useSheet } from '@/hooks/use-sheet';
|
||||
import Sheet from '@/components/sheet/sheet';
|
||||
import { Tournament } from '@/features/tournaments/types';
|
||||
import TeamList from '@/features/teams/components/team-list';
|
||||
import Button from '@/components/button';
|
||||
import Avatar from '@/components/avatar';
|
||||
import Profile from '@/features/tournaments/components/profile';
|
||||
import { z } from "zod";
|
||||
import { prefetchServerQuery } from '@/lib/tanstack-query/utils/prefetch';
|
||||
|
||||
const searchSchema = z.object({
|
||||
tab: z.string().optional(),
|
||||
@@ -20,7 +12,7 @@ export const Route = createFileRoute('/_authed/tournaments/$tournamentId')({
|
||||
validateSearch: searchSchema,
|
||||
beforeLoad: async ({ context, params }) => {
|
||||
const { queryClient } = context;
|
||||
await queryClient.ensureQueryData(tournamentQueries.details(params.tournamentId))
|
||||
await prefetchServerQuery(queryClient, tournamentQueries.details(params.tournamentId))
|
||||
},
|
||||
loader: ({ params, context }) => ({
|
||||
header: {
|
||||
@@ -35,6 +27,6 @@ export const Route = createFileRoute('/_authed/tournaments/$tournamentId')({
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
const { data: tournament } = useQuery(tournamentQueries.details(Route.useParams().tournamentId));
|
||||
return <Profile tournament={tournament!} />
|
||||
const tournamentId = Route.useParams().tournamentId;
|
||||
return <Profile id={tournamentId} />
|
||||
}
|
||||
|
||||
@@ -2,19 +2,19 @@ import Page from '@/components/page'
|
||||
import { 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 { tournamentQueries, useTournaments } from '@/features/tournaments/queries'
|
||||
import { useAuth } from '@/contexts/auth-context'
|
||||
import { useSheet } from '@/hooks/use-sheet'
|
||||
import Sheet from '@/components/sheet/sheet'
|
||||
import TournamentForm from '@/features/tournaments/components/tournament-form'
|
||||
import { PlusIcon } from '@phosphor-icons/react'
|
||||
import Button from '@/components/button'
|
||||
import { prefetchServerQuery } from '@/lib/tanstack-query/utils/prefetch'
|
||||
|
||||
export const Route = createFileRoute('/_authed/tournaments/')({
|
||||
beforeLoad: async ({ context }) => {
|
||||
const { queryClient } = context;
|
||||
await queryClient.ensureQueryData(tournamentQueries.list())
|
||||
await prefetchServerQuery(queryClient, tournamentQueries.list())
|
||||
},
|
||||
loader: () => ({
|
||||
header: {
|
||||
@@ -27,7 +27,7 @@ export const Route = createFileRoute('/_authed/tournaments/')({
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
const { data: tournaments } = useQuery(tournamentQueries.list());
|
||||
const { data: tournaments } = useTournaments();
|
||||
const { roles } = useAuth();
|
||||
const sheet = useSheet();
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { createServerFileRoute } from '@tanstack/react-start/server';
|
||||
import { superTokensRequestMiddleware } from '@/utils/supertokens';
|
||||
|
||||
// Simple test route for testing the auth middleware
|
||||
export const ServerRoute = createServerFileRoute('/api/test').middleware([superTokensRequestMiddleware]).methods({
|
||||
GET: () => {
|
||||
return new Response('Hello from the authenticated API!')
|
||||
},
|
||||
})
|
||||
@@ -4,17 +4,16 @@ import { redirect, createFileRoute } from "@tanstack/react-router";
|
||||
import z from "zod";
|
||||
|
||||
const loginSearchSchema = z.object({
|
||||
stage: z.enum(['code', 'name']).optional(),
|
||||
stage: z.enum(["code", "name"]).optional(),
|
||||
number: z.string().optional(),
|
||||
callback: z.string().optional()
|
||||
callback: z.string().optional(),
|
||||
});
|
||||
|
||||
|
||||
export const Route = createFileRoute("/login")({
|
||||
validateSearch: loginSearchSchema,
|
||||
beforeLoad: async ({ context }) => {
|
||||
if (context.auth?.user) {
|
||||
throw redirect({ to: '/' })
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
},
|
||||
component: () => {
|
||||
@@ -22,6 +21,6 @@ export const Route = createFileRoute("/login")({
|
||||
<LoginLayout>
|
||||
<LoginFlow />
|
||||
</LoginLayout>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { LoadingOverlay } from '@mantine/core'
|
||||
import { signOut } from 'supertokens-web-js/recipe/passwordless'
|
||||
import { redirect, createFileRoute } from '@tanstack/react-router'
|
||||
import { authQueryConfig, defaultAuthData } from '@/contexts/auth-context'
|
||||
import { LoadingOverlay } from "@mantine/core";
|
||||
import { signOut } from "supertokens-web-js/recipe/passwordless";
|
||||
import { redirect, createFileRoute } from "@tanstack/react-router";
|
||||
import { defaultAuthData } from "@/contexts/auth-context";
|
||||
import { playerKeys } from "@/features/players/queries";
|
||||
|
||||
export const Route = createFileRoute('/logout')({
|
||||
export const Route = createFileRoute("/logout")({
|
||||
preload: false,
|
||||
loader: async ({ context }) => {
|
||||
await context.queryClient.setQueryData(authQueryConfig.queryKey, defaultAuthData);
|
||||
await context.queryClient.setQueryData(playerKeys.auth, defaultAuthData);
|
||||
await signOut();
|
||||
throw redirect({ to: '/login' });
|
||||
throw redirect({ to: "/login" });
|
||||
},
|
||||
pendingComponent: () => <LoadingOverlay visible />
|
||||
})
|
||||
pendingComponent: () => <LoadingOverlay visible />,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user