enroll team polish?

This commit is contained in:
yohlo
2025-09-17 20:20:52 -05:00
parent cac42c9b29
commit 285a33c488
22 changed files with 411 additions and 124 deletions

View File

@@ -0,0 +1,18 @@
import { Paper, Group, Skeleton, Box } from "@mantine/core";
const TeamCardSkeleton = () => {
return (
<Paper p="sm" withBorder radius="md">
<Group gap="sm" align="center">
<Skeleton height={32} width={32} radius="sm" />
<Box style={{ flex: 1 }}>
<Skeleton height={16} width="70%" mb={4} />
<Skeleton height={12} width="40%" />
</Box>
<Skeleton height={20} width={60} radius="xl" />
</Group>
</Paper>
);
};
export default TeamCardSkeleton;

View File

@@ -0,0 +1,78 @@
import {
Paper,
Text,
Group,
Box,
Stack,
Divider
} from "@mantine/core";
import { useTeam } from "../queries";
import Avatar from "@/components/avatar";
import SongSummary from "./team-form/song-summary";
interface TeamCardProps {
teamId: string;
}
const TeamCard = ({ teamId }: TeamCardProps) => {
const { data: team, error } = useTeam(teamId);
console.log(team)
if (error || !team) {
return (
<Paper p="sm" withBorder radius="md">
<Text c="red" ta="center" size="sm">
Failed to load team
</Text>
</Paper>
);
}
const song = {
song_id: team.song_id,
song_name: team.song_name,
song_artist: team.song_artist,
song_album: team.song_album,
song_start: team.song_start,
song_end: team.song_end,
song_image_url: team.song_image_url,
};
return (
<Paper
withBorder
radius="lg"
shadow="xs"
>
<Stack gap={2}>
<Group gap="md" align="center" p="xs">
<Avatar
name={team.name}
size={40}
radius="md"
src={team.logo ? `/api/files/teams/${team.id}/${team.logo}` : undefined}
style={{
backgroundColor: team.primary_color || undefined,
color: team.accent_color || undefined,
}}
/>
<Box style={{ flex: 1, minWidth: 0 }}>
<Text size="md" fw={600} lineClamp={1} mb={2}>
{team.name}
</Text>
<Text size="sm" c="dimmed" lineClamp={1}>
{team.players?.map(p => `${p.first_name} ${p.last_name}`).join(', ')}
</Text>
</Box>
</Group>
<Divider />
<Box p="sm">
<SongSummary song={song} />
</Box>
</Stack>
</Paper>
);
};
export default TeamCard;

View File

@@ -21,6 +21,7 @@ interface TeamFormProps {
initialValues?: Partial<TeamInput>;
teamId?: string;
tournamentId?: string;
onSubmit?: (teamId: string) => void;
}
const TeamForm = ({
@@ -28,6 +29,7 @@ const TeamForm = ({
initialValues,
teamId,
tournamentId,
onSubmit
}: TeamFormProps) => {
const isEditMode = !!teamId;
@@ -103,7 +105,13 @@ const TeamForm = ({
: "Failed to create team";
mutation(teamData, {
onSuccess: async (team) => {
onSuccess: async (team: any) => {
console.log(team)
queryClient.invalidateQueries({ queryKey: teamKeys.list });
queryClient.invalidateQueries({
queryKey: teamKeys.details(team.id),
});
if (logo && team) {
try {
const formData = new FormData();
@@ -122,10 +130,8 @@ const TeamForm = ({
const result = await response.json();
queryClient.invalidateQueries({ queryKey: teamKeys.list });
queryClient.invalidateQueries({
queryKey: teamKeys.details(result.team!.id),
});
console.log('here for some reason', result)
queryClient.setQueryData(
tournamentKeys.details(result.team!.id),
result.team
@@ -137,7 +143,10 @@ const TeamForm = ({
toast.error(logoErrorMessage);
logger.error("Team logo upload error", error);
}
} else {
}
if (team && team.id) {
onSubmit?.(team.id)
}
close();
},

View File

@@ -16,7 +16,6 @@ interface SongSummaryProps {
}
const SongSummary = ({ song }: SongSummaryProps) => {
// Format time helper
const formatTime = (seconds: number | undefined) => {
if (seconds === undefined) return null;
const minutes = Math.floor(seconds / 60);
@@ -24,7 +23,6 @@ const SongSummary = ({ song }: SongSummaryProps) => {
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
};
// If no song selected
if (!song?.song_name) {
return (
<Group gap="xs" c="dimmed">

View File

@@ -1,4 +1,12 @@
import { Divider, Group, List, ListItem, Skeleton, Stack, Text } from "@mantine/core";
import {
Divider,
Group,
List,
ListItem,
Skeleton,
Stack,
Text,
} from "@mantine/core";
import Avatar from "@/components/avatar";
import { TeamInfo } from "@/features/teams/types";
import { useNavigate } from "@tanstack/react-router";
@@ -15,14 +23,14 @@ const TeamListItem = React.memo(({ team }: TeamListItemProps) => {
);
return (
<Group justify="space-between" w='100%'>
<Group justify="space-between" w="100%">
<Text fw={500}>{`${team.name}`}</Text>
<Stack ml="auto" gap={0}>
{playerNames.map((name) => (
<Text size="xs" c="dimmed" ta="right">
{name}
</Text>
))}
<Text size="xs" c="dimmed" ta="right">
{name}
</Text>
))}
</Stack>
</Group>
);
@@ -62,12 +70,23 @@ const TeamList = ({ teams, loading = false }: TeamListProps) => {
<div key={team.id}>
<ListItem
p="xs"
icon={<Avatar radius="sm" size={40} name={`${team.name}`} />}
icon={
<Avatar
radius="sm"
size={40}
name={`${team.name}`}
src={
team.logo
? `/api/files/teams/${team.id}/${team.logo}`
: undefined
}
/>
}
style={{ cursor: "pointer" }}
onClick={() => handleClick(team.id)}
styles={{
itemWrapper: { width: "100%" },
itemLabel: { width: "100%" }
itemLabel: { width: "100%" },
}}
w="100%"
>

View File

@@ -5,13 +5,19 @@ import { Team } from "../../types";
interface HeaderProps {
name: string;
logo?: string;
id?: string;
}
const Header = ({ name, logo }: HeaderProps) => {
const Header = ({ name, logo, id }: HeaderProps) => {
return (
<>
<Flex px="xl" w="100%" align="self-end" gap="md">
<Avatar radius="sm" name={name} size={125} />
<Avatar
radius="sm"
name={name}
size={125}
src={logo && id ? `/api/files/teams/${id}/${logo}` : undefined}
/>
<Flex align="center" justify="center" gap={4} pb={20} w="100%">
<Title ta="center" order={2}>
{name}

View File

@@ -36,7 +36,7 @@ const TeamProfile = ({ id }: ProfileProps) => {
];
return (
<>
<Header name={team.name} logo={team.logo} />
<Header name={team.name} logo={team.logo} id={team.id} />
<Box mt="lg">
<SwipeableTabs tabs={tabs} />
</Box>

View File

@@ -12,9 +12,6 @@ const useCreateTeam = () => {
onMutate: (data) => {
logger.info('Creating team', data);
},
onSuccess: (team) => {
navigate({ to: '/teams/$id', params: { id: team.id } });
},
successMessage: 'Team created successfully!',
});
};