enroll team polish?
This commit is contained in:
18
src/features/teams/components/team-card-skeleton.tsx
Normal file
18
src/features/teams/components/team-card-skeleton.tsx
Normal 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;
|
||||
78
src/features/teams/components/team-card.tsx
Normal file
78
src/features/teams/components/team-card.tsx
Normal 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;
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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%"
|
||||
>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user