settings link, uneroll team server fn
This commit is contained in:
@@ -12,10 +12,11 @@ export const Route = createFileRoute("/_authed/profile/$playerId")({
|
|||||||
player
|
player
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
loader: ({ params }) => ({
|
loader: ({ params, context }) => ({
|
||||||
header: {
|
header: {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
withBackButton: true
|
withBackButton: true,
|
||||||
|
settingsLink: context?.auth.user.id === params.playerId ? 'settings' : undefined
|
||||||
},
|
},
|
||||||
refresh: {
|
refresh: {
|
||||||
toRefresh: [playerQueries.details(params.playerId).queryKey],
|
toRefresh: [playerQueries.details(params.playerId).queryKey],
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ export const Route = createFileRoute('/_authed/tournaments/$tournamentId')({
|
|||||||
const { queryClient } = context;
|
const { queryClient } = context;
|
||||||
await queryClient.ensureQueryData(tournamentQueries.details(params.tournamentId))
|
await queryClient.ensureQueryData(tournamentQueries.details(params.tournamentId))
|
||||||
},
|
},
|
||||||
loader: ({ params }) => ({
|
loader: ({ params, context }) => ({
|
||||||
header: {
|
header: {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
withBackButton: true
|
withBackButton: true,
|
||||||
|
settingsLink: context.auth.roles.includes("Admin") ? `/admin/tournaments/${params.tournamentId}` : undefined
|
||||||
},
|
},
|
||||||
refresh: {
|
refresh: {
|
||||||
toRefresh: tournamentQueries.details(params.tournamentId).queryKey,
|
toRefresh: tournamentQueries.details(params.tournamentId).queryKey,
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ import { Title, AppShell, Flex } from "@mantine/core";
|
|||||||
import { HeaderConfig } from "../types/header-config";
|
import { HeaderConfig } from "../types/header-config";
|
||||||
import BackButton from "./back-button";
|
import BackButton from "./back-button";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
import SettingsButton from "./settings-button";
|
||||||
interface HeaderProps extends HeaderConfig {
|
interface HeaderProps extends HeaderConfig {
|
||||||
scrollPosition: { x: number, y: number };
|
scrollPosition: { x: number, y: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
const Header = ({ withBackButton, collapsed, title, scrollPosition }: HeaderProps) => {
|
const Header = ({ withBackButton, settingsLink, collapsed, title, scrollPosition }: HeaderProps) => {
|
||||||
const offsetY = useMemo(() => {
|
const offsetY = useMemo(() => {
|
||||||
return collapsed ? scrollPosition.y : 0;
|
return collapsed ? scrollPosition.y : 0;
|
||||||
}, [collapsed, scrollPosition.y]);
|
}, [collapsed, scrollPosition.y]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{settingsLink && <SettingsButton to={settingsLink} offsetY={offsetY} />}
|
||||||
{withBackButton && <BackButton offsetY={offsetY} />}
|
{withBackButton && <BackButton offsetY={offsetY} />}
|
||||||
<AppShell.Header id='app-header' display={collapsed ? 'none' : 'block'}>
|
<AppShell.Header id='app-header' display={collapsed ? 'none' : 'block'}>
|
||||||
<Flex justify='center' align='center' h='100%' px='md'>
|
<Flex justify='center' align='center' h='100%' px='md'>
|
||||||
|
|||||||
26
src/features/core/components/settings-button.tsx
Normal file
26
src/features/core/components/settings-button.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Box } from "@mantine/core"
|
||||||
|
import { GearIcon } from "@phosphor-icons/react"
|
||||||
|
import { useNavigate } from "@tanstack/react-router"
|
||||||
|
|
||||||
|
interface SettingButtonProps {
|
||||||
|
offsetY: number;
|
||||||
|
to: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingsButton = ({ offsetY, to }: SettingButtonProps) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
style={{ cursor: 'pointer', zIndex: 1000, transform: `translateY(-${offsetY}px)` }}
|
||||||
|
onClick={() => navigate({ to })}
|
||||||
|
pos='absolute'
|
||||||
|
right={{ base: 0, sm: 100, md: 200, lg: 300 }}
|
||||||
|
m={20}
|
||||||
|
>
|
||||||
|
<GearIcon weight='bold' size={20} />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingsButton;
|
||||||
@@ -2,6 +2,7 @@ interface HeaderConfig {
|
|||||||
title?: string;
|
title?: string;
|
||||||
withBackButton?: boolean;
|
withBackButton?: boolean;
|
||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
|
settingsLink?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { HeaderConfig };
|
export type { HeaderConfig };
|
||||||
|
|||||||
30
src/features/tournaments/hooks/use-unenroll-team.ts
Normal file
30
src/features/tournaments/hooks/use-unenroll-team.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { unenrollTeam } from "@/features/tournaments/server";
|
||||||
|
import toast from '@/lib/sonner';
|
||||||
|
|
||||||
|
const useUnenrollTeam = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (data: { tournamentId: string, teamId: string }) => {
|
||||||
|
return unenrollTeam({ data });
|
||||||
|
},
|
||||||
|
onSuccess: (data, { tournamentId }) => {
|
||||||
|
if (!data) {
|
||||||
|
toast.error('There was an issue unenrolling. Please try again later.');
|
||||||
|
} else {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['tournaments', 'detail', tournamentId] });
|
||||||
|
toast.success('Team unenrolled successfully.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error: any) => {
|
||||||
|
if (error.message) {
|
||||||
|
toast.error(error.message);
|
||||||
|
} else {
|
||||||
|
toast.error('An unexpected error occurred when trying to unenroll the team. Please try again later.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useUnenrollTeam;
|
||||||
@@ -70,3 +70,20 @@ export const enrollTeam = createServerFn()
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const unenrollTeam = createServerFn()
|
||||||
|
.validator(z.object({
|
||||||
|
tournamentId: z.string(),
|
||||||
|
teamId: z.string()
|
||||||
|
}))
|
||||||
|
.middleware([superTokensAdminFunctionMiddleware])
|
||||||
|
.handler(async ({ data: { tournamentId, teamId }, context }) => {
|
||||||
|
try {
|
||||||
|
logger.info('Enrolling team in tournament', { tournamentId, teamId, context });
|
||||||
|
const tournament = await pbAdmin.unenrollTeam(tournamentId, teamId);
|
||||||
|
return tournament;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error enrolling team', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -57,5 +57,16 @@ export function createTournamentsService(pb: PocketBase) {
|
|||||||
);
|
);
|
||||||
return transformTournament(result);
|
return transformTournament(result);
|
||||||
},
|
},
|
||||||
|
async unenrollTeam(
|
||||||
|
tournamentId: string,
|
||||||
|
teamId: string
|
||||||
|
): Promise<Tournament> {
|
||||||
|
const result = await pb.collection("tournaments").update<Tournament>(
|
||||||
|
tournamentId,
|
||||||
|
{ "teams-": teamId },
|
||||||
|
{ expand: "teams, teams.players" }
|
||||||
|
);
|
||||||
|
return transformTournament(result);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ import { Tournament } from "@/features/tournaments/types";
|
|||||||
|
|
||||||
export function transformPlayer(record: any): Player {
|
export function transformPlayer(record: any): Player {
|
||||||
const sadf: string[] = [];
|
const sadf: string[] = [];
|
||||||
const teams = record.expand?.teams
|
const teams =
|
||||||
?.sort((a: Team, b: Team) => new Date(a.created) < new Date(b.created) ? -1 : 0)
|
record.expand?.teams
|
||||||
|
?.sort((a: Team, b: Team) =>
|
||||||
|
new Date(a.created) < new Date(b.created) ? -1 : 0
|
||||||
|
)
|
||||||
?.map(transformTeam) ?? [];
|
?.map(transformTeam) ?? [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -23,8 +26,11 @@ export function transformPlayer(record: any): Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function transformTeam(record: any): Team {
|
export function transformTeam(record: any): Team {
|
||||||
const players = record.expand?.players
|
const players =
|
||||||
?.sort((a: Player, b: Player) => new Date(a.created!) < new Date(b.created!) ? -1 : 0)
|
record.expand?.players
|
||||||
|
?.sort((a: Player, b: Player) =>
|
||||||
|
new Date(a.created!) < new Date(b.created!) ? -1 : 0
|
||||||
|
)
|
||||||
?.map(transformPlayer) ?? [];
|
?.map(transformPlayer) ?? [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -48,8 +54,11 @@ export function transformTeam(record: any): Team {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function transformTournament(record: any): Tournament {
|
export function transformTournament(record: any): Tournament {
|
||||||
const teams = record.expand?.teams
|
const teams =
|
||||||
?.sort((a: Team, b: Team) => new Date(a.created) < new Date(b.created) ? -1 : 0)
|
record.expand?.teams
|
||||||
|
?.sort((a: Team, b: Team) =>
|
||||||
|
new Date(a.created) < new Date(b.created) ? -1 : 0
|
||||||
|
)
|
||||||
?.map(transformTeam) ?? [];
|
?.map(transformTeam) ?? [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user