diff --git a/package.json b/package.json index 21b8698..d684658 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@tanstack/react-router-devtools": "^1.130.13", "@tanstack/react-router-with-query": "^1.130.12", "@tanstack/react-start": "^1.130.15", + "@tanstack/react-virtual": "^3.13.12", "@tiptap/pm": "^3.4.3", "@tiptap/react": "^3.4.3", "@tiptap/starter-kit": "^3.4.3", diff --git a/pb_migrations/1758123221_updated_reactions.js b/pb_migrations/1758123221_updated_reactions.js new file mode 100644 index 0000000..d11f4c4 --- /dev/null +++ b/pb_migrations/1758123221_updated_reactions.js @@ -0,0 +1,28 @@ +/// +migrate((app) => { + const collection = app.findCollectionByNameOrId("pbc_1549310251") + + // add field + collection.fields.addAt(3, new Field({ + "cascadeDelete": false, + "collectionId": "pbc_2541054544", + "hidden": false, + "id": "relation2052834565", + "maxSelect": 1, + "minSelect": 0, + "name": "match", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + })) + + return app.save(collection) +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_1549310251") + + // remove field + collection.fields.removeById("relation2052834565") + + return app.save(collection) +}) diff --git a/src/app/router.tsx b/src/app/router.tsx index 7517a7d..c8a557a 100644 --- a/src/app/router.tsx +++ b/src/app/router.tsx @@ -32,7 +32,7 @@ export function createRouter() { defaultPreload: "intent", defaultErrorComponent: DefaultCatchBoundary, scrollRestoration: true, - defaultViewTransition: true, + defaultViewTransition: false, }), queryClient ); diff --git a/src/app/routes/_authed.tsx b/src/app/routes/_authed.tsx index 9cb526b..d024d51 100644 --- a/src/app/routes/_authed.tsx +++ b/src/app/routes/_authed.tsx @@ -26,8 +26,8 @@ export const Route = createFileRoute("/_authed")({ }, pendingComponent: () => ( - - + + ), diff --git a/src/features/matches/components/match-card.tsx b/src/features/matches/components/match-card.tsx index 095ba27..80e8d5c 100644 --- a/src/features/matches/components/match-card.tsx +++ b/src/features/matches/components/match-card.tsx @@ -1,11 +1,4 @@ -import { - Text, - Group, - Stack, - Paper, - Indicator, - Box, -} from "@mantine/core"; +import { Text, Group, Stack, Paper, Indicator, Box } from "@mantine/core"; import { CrownIcon } from "@phosphor-icons/react"; import { useNavigate } from "@tanstack/react-router"; import { Match } from "../types"; @@ -46,7 +39,13 @@ const MatchCard = ({ match }: MatchCardProps) => { offset={2} > - + @@ -65,7 +64,16 @@ const MatchCard = ({ match }: MatchCardProps) => { style={{ position: "relative", cursor: "pointer" }} onClick={handleHomeTeamClick} > - + {isHomeWin && ( { {match.home?.name!} - + {match.home_cups} @@ -104,7 +108,16 @@ const MatchCard = ({ match }: MatchCardProps) => { style={{ position: "relative", cursor: "pointer" }} onClick={handleAwayTeamClick} > - + {isAwayWin && ( { {match.away?.name} - + {match.away_cups} @@ -149,7 +158,8 @@ const MatchCard = ({ match }: MatchCardProps) => { paddingTop: 8, backgroundColor: "var(--mantine-color-gray-light)", borderTop: "none", - borderRadius: "0 0 var(--mantine-radius-md) var(--mantine-radius-md)", + borderRadius: + "0 0 var(--mantine-radius-md) var(--mantine-radius-md)", border: "1px solid var(--mantine-color-default-border)", }} > diff --git a/src/features/players/components/profile/index.tsx b/src/features/players/components/profile/index.tsx index 479022b..f5cf2e9 100644 --- a/src/features/players/components/profile/index.tsx +++ b/src/features/players/components/profile/index.tsx @@ -15,6 +15,8 @@ const Profile = ({ id }: ProfileProps) => { const { data: matches } = usePlayerMatches(id); const { data: stats, isLoading: statsLoading } = usePlayerStats(id); + console.log(player.teams) + const tabs = [ { label: "Overview", diff --git a/src/features/reactions/components/emoji-bar.tsx b/src/features/reactions/components/emoji-bar.tsx index 815d0aa..9bae1ba 100644 --- a/src/features/reactions/components/emoji-bar.tsx +++ b/src/features/reactions/components/emoji-bar.tsx @@ -1,6 +1,6 @@ import { Group, - UnstyledButton, + Button, Text, Tabs, } from "@mantine/core"; @@ -71,61 +71,34 @@ const EmojiBar = ({ {reactions.map((reaction) => ( - handleLongPressStart(reaction.emoji)} onMouseUp={handleLongPressEnd} onMouseLeave={handleLongPressEnd} onTouchStart={() => handleLongPressStart(reaction.emoji)} onTouchEnd={handleLongPressEnd} onClick={() => handleReactionClick(reaction.emoji)} - px="8px" - py="10px" style={{ - borderRadius: "var(--mantine-radius-xl)", - border: reaction.hasReacted - ? "1px solid var(--mantine-primary-color-filled)" - : "1px solid var(--mantine-color-default-border)", - backgroundColor: reaction.hasReacted - ? "var(--mantine-primary-color-light)" - : "transparent", - transition: "all 0.15s ease", userSelect: "none", WebkitUserSelect: "none", MozUserSelect: "none", msUserSelect: "none", }} - styles={{ - root: { - "&:hover": { - backgroundColor: reaction.hasReacted - ? "var(--mantine-primary-color-light)" - : "var(--mantine-color-gray-1)", - transform: "scale(1.05)", - }, - "&:active": { - transform: "scale(0.95)", - }, - }, - }} > {reaction.emoji} - + {reaction.count} - + ))} {})} /> diff --git a/src/features/teams/components/team-card-skeleton.tsx b/src/features/teams/components/team-card-skeleton.tsx new file mode 100644 index 0000000..5fd18fc --- /dev/null +++ b/src/features/teams/components/team-card-skeleton.tsx @@ -0,0 +1,18 @@ +import { Paper, Group, Skeleton, Box } from "@mantine/core"; + +const TeamCardSkeleton = () => { + return ( + + + + + + + + + + + ); +}; + +export default TeamCardSkeleton; diff --git a/src/features/teams/components/team-card.tsx b/src/features/teams/components/team-card.tsx new file mode 100644 index 0000000..ae415f5 --- /dev/null +++ b/src/features/teams/components/team-card.tsx @@ -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 ( + + + Failed to load team + + + ); + } + + 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 ( + + + + + + + {team.name} + + + {team.players?.map(p => `${p.first_name} ${p.last_name}`).join(', ')} + + + + + + + + + + ); +}; + +export default TeamCard; \ No newline at end of file diff --git a/src/features/teams/components/team-form/index.tsx b/src/features/teams/components/team-form/index.tsx index 28508f3..acad779 100644 --- a/src/features/teams/components/team-form/index.tsx +++ b/src/features/teams/components/team-form/index.tsx @@ -21,6 +21,7 @@ interface TeamFormProps { initialValues?: Partial; 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(); }, diff --git a/src/features/teams/components/team-form/song-summary.tsx b/src/features/teams/components/team-form/song-summary.tsx index 691f584..d01d472 100644 --- a/src/features/teams/components/team-form/song-summary.tsx +++ b/src/features/teams/components/team-form/song-summary.tsx @@ -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 ( diff --git a/src/features/teams/components/team-list.tsx b/src/features/teams/components/team-list.tsx index 28f2c30..83b381e 100644 --- a/src/features/teams/components/team-list.tsx +++ b/src/features/teams/components/team-list.tsx @@ -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 ( - + {`${team.name}`} {playerNames.map((name) => ( - - {name} - - ))} + + {name} + + ))} ); @@ -62,12 +70,23 @@ const TeamList = ({ teams, loading = false }: TeamListProps) => {
} + icon={ + + } style={{ cursor: "pointer" }} onClick={() => handleClick(team.id)} styles={{ itemWrapper: { width: "100%" }, - itemLabel: { width: "100%" } + itemLabel: { width: "100%" }, }} w="100%" > diff --git a/src/features/teams/components/team-profile/header.tsx b/src/features/teams/components/team-profile/header.tsx index 94ab769..6d08bfb 100644 --- a/src/features/teams/components/team-profile/header.tsx +++ b/src/features/teams/components/team-profile/header.tsx @@ -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 ( <> - + {name} diff --git a/src/features/teams/components/team-profile/index.tsx b/src/features/teams/components/team-profile/index.tsx index 2baaefc..9e7d1eb 100644 --- a/src/features/teams/components/team-profile/index.tsx +++ b/src/features/teams/components/team-profile/index.tsx @@ -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> diff --git a/src/features/teams/hooks/use-create-team.ts b/src/features/teams/hooks/use-create-team.ts index cbf7bdc..513b90a 100644 --- a/src/features/teams/hooks/use-create-team.ts +++ b/src/features/teams/hooks/use-create-team.ts @@ -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!', }); }; diff --git a/src/features/tournaments/components/edit-enrolled-teams.tsx b/src/features/tournaments/components/edit-enrolled-teams.tsx index 0f857e2..31b7a54 100644 --- a/src/features/tournaments/components/edit-enrolled-teams.tsx +++ b/src/features/tournaments/components/edit-enrolled-teams.tsx @@ -34,7 +34,15 @@ const TeamItem = memo(({ team, onUnenroll, disabled }: TeamItemProps) => { return ( <Group py="xs" px="sm" w="100%" gap="sm" align="center"> - <Avatar size={32} name={team.name} /> + <Avatar + size={32} + name={team.name} + src={ + team.logo + ? `/api/files/teams/${team.id}/${team.logo}` + : undefined + } + /> <Stack gap={0} style={{ flex: 1, minWidth: 0 }}> <Text fw={500} truncate> {team.name} diff --git a/src/features/tournaments/components/seed-tournament.tsx b/src/features/tournaments/components/seed-tournament.tsx index 74fdd6a..8cafb19 100644 --- a/src/features/tournaments/components/seed-tournament.tsx +++ b/src/features/tournaments/components/seed-tournament.tsx @@ -27,11 +27,11 @@ interface SeedTournamentProps { const SeedTournament: React.FC<SeedTournamentProps> = ({ tournamentId, - teams + teams, }) => { const [orderedTeams, setOrderedTeams] = useState<TeamInfo[]>(teams); const { data: bracketPreview } = useBracketPreview(teams.length); - const queryClient = useQueryClient() + const queryClient = useQueryClient(); const bracket: BracketData = useMemo( () => ({ @@ -48,7 +48,7 @@ const SeedTournament: React.FC<SeedTournamentProps> = ({ : undefined, })) ), - losers: bracketPreview.losers + losers: bracketPreview.losers, }), [bracketPreview, orderedTeams] ); @@ -58,8 +58,8 @@ const SeedTournament: React.FC<SeedTournamentProps> = ({ successMessage: "Tournament bracket generated successfully!", onSuccess: () => { queryClient.invalidateQueries({ - queryKey: tournamentKeys.details(tournamentId) - }) + queryKey: tournamentKeys.details(tournamentId), + }); }, }); @@ -99,7 +99,7 @@ const SeedTournament: React.FC<SeedTournamentProps> = ({ }; return ( - <div style={{ display: 'flex', gap: '2rem', alignItems: 'flex-start' }}> + <div style={{ display: "flex", gap: "2rem", alignItems: "flex-start" }}> <Stack gap="lg" style={{ flexShrink: 0 }}> <Stack gap={0} pos="relative" w={400}> <LoadingOverlay visible={generateBracket.isPending} /> @@ -171,7 +171,16 @@ const SeedTournament: React.FC<SeedTournamentProps> = ({ }} /> - <Avatar size={24} radius="sm" name={team.name} /> + <Avatar + size={24} + radius="sm" + name={team.name} + src={ + team.logo + ? `/api/files/teams/${team.id}/${team.logo}` + : undefined + } + /> <Text fw={500} size="sm" style={{ flex: 1 }}> {team.name} @@ -197,8 +206,8 @@ const SeedTournament: React.FC<SeedTournamentProps> = ({ Confirm Seeding </Button> </Stack> - - <div style={{ flex: 1, overflow: 'auto' }}> + + <div style={{ flex: 1, overflow: "auto" }}> <BracketView bracket={bracket} /> </div> </div> diff --git a/src/features/tournaments/components/upcoming-tournament/enroll-team/index.tsx b/src/features/tournaments/components/upcoming-tournament/enroll-team/index.tsx index 1a271d6..6f81647 100644 --- a/src/features/tournaments/components/upcoming-tournament/enroll-team/index.tsx +++ b/src/features/tournaments/components/upcoming-tournament/enroll-team/index.tsx @@ -8,12 +8,16 @@ import TeamForm from "@/features/teams/components/team-form"; import { teamQueries } from "@/features/teams/queries"; import { Team } from "@/features/teams/types"; import { useQuery } from "@tanstack/react-query"; +import { Loader } from "@mantine/core"; +import useEnrollTeam from "@/features/tournaments/hooks/use-enroll-team"; +import { useServerQuery } from "@/lib/tanstack-query/hooks"; interface EnrollTeamProps { tournamentId: string; + onSubmit: () => void; } -const EnrollTeam = ({ tournamentId }: EnrollTeamProps) => { +const EnrollTeam = ({ tournamentId, onSubmit }: EnrollTeamProps) => { const { open, isOpen, toggle } = useSheet(); const { user } = useAuth(); @@ -22,14 +26,14 @@ const EnrollTeam = ({ tournamentId }: EnrollTeamProps) => { const [showTeamForm, setShowTeamForm] = useState<boolean>(!hasTeams); const [selectedTeam, setSelectedTeam] = useState<Team | null>(null); - const { data: teamData } = useQuery({ + const { data: teamData } = useServerQuery({ ...teamQueries.details(selectedTeamId!), - enabled: !!selectedTeamId, + options: { enabled: !!selectedTeamId } }); useEffect(() => { - if (teamData?.success) { - setSelectedTeam(teamData.data); + if (teamData) { + setSelectedTeam(teamData); setShowTeamForm(true); } }, [teamData]); @@ -71,6 +75,16 @@ const EnrollTeam = ({ tournamentId }: EnrollTeamProps) => { }; }, [selectedTeam]); + const { mutate: enrollTeam, isPending: isEnrolling } = useEnrollTeam(); + const handleEnrollTeam = (teamId: string) => { + enrollTeam({ tournamentId, teamId }, { + onSuccess: () => { + toggle(); + onSubmit(); + } + }); + } + return ( <> <Button size="sm" onClick={open}> @@ -78,12 +92,14 @@ const EnrollTeam = ({ tournamentId }: EnrollTeamProps) => { </Button> <Sheet title={showTeamForm ? "Team Details" : "Enroll Team"} opened={isOpen} onChange={toggle}> - {showTeamForm ? ( + { isEnrolling && <Loader size="lg" /> } + {showTeamForm && !isEnrolling ? ( <TeamForm close={handleBack} tournamentId={tournamentId} initialValues={initialValues} teamId={selectedTeamId} + onSubmit={handleEnrollTeam} /> ) : ( <> diff --git a/src/features/tournaments/components/upcoming-tournament/index.tsx b/src/features/tournaments/components/upcoming-tournament/index.tsx index 6949d6e..056a04d 100644 --- a/src/features/tournaments/components/upcoming-tournament/index.tsx +++ b/src/features/tournaments/components/upcoming-tournament/index.tsx @@ -1,27 +1,21 @@ -import { useMemo } from "react"; +import { Suspense, useCallback, useMemo } from "react"; import { Tournament } from "../../types"; import { useAuth } from "@/contexts/auth-context"; -import { - Box, - Card, - Divider, - Group, - Stack, - Text, -} from "@mantine/core"; +import { Box, Button, Card, Divider, Group, Stack, Text } from "@mantine/core"; import Countdown from "@/components/countdown"; import ListLink from "@/components/list-link"; import ListButton from "@/components/list-button"; -import { - UsersIcon, - ListIcon, -} from "@phosphor-icons/react"; +import { UsersIcon, ListIcon } from "@phosphor-icons/react"; import EnrollTeam from "./enroll-team"; import EnrollFreeAgent from "./enroll-free-agent"; import TeamListButton from "./team-list-button"; import Header from "./header"; -import EmojiPicker from "@/features/reactions/components/emoji-picker"; -import EmojiBar from "@/features/reactions/components/emoji-bar"; +import TeamCardSkeleton from "@/features/teams/components/team-card-skeleton"; +import TeamCard from "@/features/teams/components/team-card"; +import UpdateTeam from "./update-team"; +import UnenrollTeam from "./unenroll-team"; +import { useQueryClient } from "@tanstack/react-query"; +import { tournamentKeys } from "../../queries"; const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({ tournament, @@ -43,18 +37,21 @@ const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({ : new Date(tournament.start_time); const isEnrollmentOpen = enrollmentDeadline > new Date(); + const queryClient = useQueryClient(); + const handleSubmit = () => { + queryClient.invalidateQueries({ queryKey: tournamentKeys.current }) + } + + console.log(userTeam) + return ( <Stack gap="lg"> - <Header tournament={tournament} /> - - <EmojiBar /> - {tournament.desc && <Text size="sm">{tournament.desc}</Text>} - <Card withBorder radius="md" p="lg"> + <Card withBorder radius="lg" p="lg"> <Stack gap="xs"> - <Group mb='sm' gap="xs" align="center"> + <Group mb="sm" gap="xs" align="center"> <UsersIcon size={16} /> <Text size="sm" fw={500}> Enrollment @@ -70,17 +67,29 @@ const UpcomingTournament: React.FC<{ tournament: Tournament }> = ({ )} </Group> - {!isEnrollmentOpen && !isUserEnrolled && ( - <Text fw={600} c="dimmed" size="sm">Enrollment has been closed for this tournament.</Text> + {!isUserEnrolled &&!isEnrollmentOpen && ( + <Text fw={600} c="dimmed" size="sm"> + Enrollment has been closed for this tournament. + </Text> )} - {!isUserEnrolled && isEnrollmentOpen && ( + {!isUserEnrolled &&isEnrollmentOpen && ( <> - <EnrollTeam tournamentId={tournament.id} /> + <EnrollTeam tournamentId={tournament.id} onSubmit={handleSubmit} /> <Divider my={0} label="or" /> <EnrollFreeAgent /> </> )} + + { + isUserEnrolled && <> + <Suspense fallback={<TeamCardSkeleton />}> + <TeamCard teamId={userTeam.id} /> + </Suspense> + <UpdateTeam tournamentId={tournament.id} teamId={userTeam.id} /> + { isEnrollmentOpen && <UnenrollTeam tournamentId={tournament.id} teamId={userTeam.id} onSubmit={handleSubmit} />} + </> + } </Stack> </Card> diff --git a/src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx b/src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx new file mode 100644 index 0000000..51e07a7 --- /dev/null +++ b/src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx @@ -0,0 +1,46 @@ +import Button from "@/components/button"; +import Sheet from "@/components/sheet/sheet"; +import { useSheet } from "@/hooks/use-sheet"; +import { useCallback } from "react"; +import useUnenrollTeam from "../../hooks/use-unenroll-team"; +import { Stack, Text } from "@mantine/core"; + +interface UnenrollTeamProps { + tournamentId: string; + teamId: string + onSubmit: () => void; +} + +const UnenrollTeam = ({ tournamentId, teamId, onSubmit }: UnenrollTeamProps) => { + const { open, isOpen, toggle } = useSheet(); + const { mutate: unenrollTeam } = useUnenrollTeam(); + const handleUnenrollTeam = useCallback( + async () => { + await unenrollTeam({ tournamentId, teamId }, { + onSuccess: () => { + toggle(); + onSubmit(); + } + }); + }, + [unenrollTeam, tournamentId] + ); + + return ( + <> + <Button size="sm" onClick={open} variant="subtle"> + Unenroll + </Button> + + <Sheet title={"Unenroll Team"} opened={isOpen} onChange={toggle}> + <Stack gap='xs'> + <Text size="sm" fw={500}>Are you sure you want to unenroll from this tournament? You can enroll again at any point before the deadline.</Text> + <Button onClick={handleUnenrollTeam}>Confirm</Button> + <Button variant="subtle" color="red" onClick={toggle}>Cancel</Button> + </Stack> + </Sheet> + </> + ); +}; + +export default UnenrollTeam; diff --git a/src/features/tournaments/components/upcoming-tournament/update-team.tsx b/src/features/tournaments/components/upcoming-tournament/update-team.tsx new file mode 100644 index 0000000..e34e1fc --- /dev/null +++ b/src/features/tournaments/components/upcoming-tournament/update-team.tsx @@ -0,0 +1,59 @@ +import Button from "@/components/button"; +import Sheet from "@/components/sheet/sheet"; +import { useAuth } from "@/contexts/auth-context"; +import { useSheet } from "@/hooks/use-sheet"; +import { useMemo, useState, useCallback, useEffect } from "react"; +import TeamSelectionView from "./enroll-team/team-selection-view"; +import TeamForm from "@/features/teams/components/team-form"; +import { teamQueries, useTeam } from "@/features/teams/queries"; +import { Team } from "@/features/teams/types"; +import { useQuery } from "@tanstack/react-query"; +import { Loader } from "@mantine/core"; +import useEnrollTeam from "@/features/tournaments/hooks/use-enroll-team"; + +interface UpdateTeamProps { + tournamentId: string; + teamId: string +} + +const UpdateTeam = ({ tournamentId, teamId }: UpdateTeamProps) => { + const { open, isOpen, toggle } = useSheet(); + + const { data: team } = useTeam(teamId); + + const initialValues = useMemo(() => { + if (!team) return undefined; + + return { + name: team.name, + 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, + players: team.players?.map(player => player.id), + }; + }, [team]); + + return ( + <> + <Button size="sm" onClick={open}> + Update Team + </Button> + + <Sheet title={"Update Team"} opened={isOpen} onChange={toggle}> + <TeamForm + close={toggle} + tournamentId={tournamentId} + initialValues={initialValues} + teamId={teamId} + onSubmit={(_) => close()} + /> + </Sheet> + </> + ); +}; + +export default UpdateTeam; diff --git a/src/lib/pocketbase/util/transform-types.ts b/src/lib/pocketbase/util/transform-types.ts index 99a67eb..c7789e7 100644 --- a/src/lib/pocketbase/util/transform-types.ts +++ b/src/lib/pocketbase/util/transform-types.ts @@ -22,6 +22,7 @@ export function transformTeamInfo(record: any): TeamInfo { primary_color: record.primary_color, accent_color: record.accent_color, players, + logo: record.logo }; } @@ -108,7 +109,7 @@ export function transformTeam(record: any): Team { song_artist: record.song_artist, song_album: record.song_album, song_start: record.song_start, - song_end: 0, + song_end: record.song_end, song_image_url: record.song_image_url, created: record.created, updated: record.updated,