several
This commit is contained in:
123
src/features/tournaments/components/edit-enrolled-teams.tsx
Normal file
123
src/features/tournaments/components/edit-enrolled-teams.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import { Autocomplete, Stack, ActionIcon, Text, Group, Loader } from "@mantine/core";
|
||||
import { TrashIcon } from "@phosphor-icons/react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useState, useCallback, useMemo, memo } from "react";
|
||||
import { tournamentQueries } from "../queries";
|
||||
import useEnrollTeam from "../hooks/use-enroll-team";
|
||||
import useUnenrollTeam from "../hooks/use-unenroll-team";
|
||||
import Avatar from "@/components/avatar";
|
||||
import { Team } from "@/features/teams/types";
|
||||
|
||||
interface EditEnrolledTeamsProps {
|
||||
tournamentId: string;
|
||||
}
|
||||
|
||||
const TeamItem = memo(({ team, onUnenroll, disabled }: {
|
||||
team: Team;
|
||||
onUnenroll: (teamId: string) => void;
|
||||
disabled: boolean;
|
||||
}) => {
|
||||
const playerNames = useMemo(() =>
|
||||
team.players?.map(p => `${p.first_name} ${p.last_name}`).join(", ") || "",
|
||||
[team.players]
|
||||
);
|
||||
|
||||
return (
|
||||
<Group py="xs" px="sm" w="100%" gap="sm" align="center">
|
||||
<Avatar size={32} name={team.name} />
|
||||
<Stack gap={0} style={{ flex: 1, minWidth: 0 }}>
|
||||
<Text fw={500} truncate>{team.name}</Text>
|
||||
{playerNames && (
|
||||
<Text size="xs" c="dimmed" truncate>{playerNames}</Text>
|
||||
)}
|
||||
</Stack>
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
color="red"
|
||||
onClick={() => onUnenroll(team.id)}
|
||||
disabled={disabled}
|
||||
size="sm"
|
||||
>
|
||||
<TrashIcon size={14} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
const EditEnrolledTeams = ({ tournamentId }: EditEnrolledTeamsProps) => {
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const { data: tournament, isLoading: tournamentLoading } =
|
||||
useQuery(tournamentQueries.details(tournamentId));
|
||||
const { data: unenrolledTeams = [], isLoading: unenrolledLoading } =
|
||||
useQuery(tournamentQueries.unenrolled(tournamentId));
|
||||
|
||||
const { mutate: enrollTeam, isPending: isEnrolling } = useEnrollTeam();
|
||||
const { mutate: unenrollTeam, isPending: isUnenrolling } = useUnenrollTeam();
|
||||
|
||||
const autocompleteData = useMemo(() =>
|
||||
unenrolledTeams.map((team: Team) => ({ value: team.id, label: team.name })),
|
||||
[unenrolledTeams]
|
||||
);
|
||||
|
||||
const handleEnrollTeam = useCallback((teamId: string) => {
|
||||
enrollTeam({ tournamentId, teamId }, {
|
||||
onSuccess: () => {
|
||||
setSearch("");
|
||||
}
|
||||
});
|
||||
}, [enrollTeam, tournamentId, setSearch]);
|
||||
|
||||
const handleUnenrollTeam = useCallback((teamId: string) => {
|
||||
unenrollTeam({ tournamentId, teamId });
|
||||
}, [unenrollTeam, tournamentId]);
|
||||
|
||||
const isLoading = tournamentLoading || unenrolledLoading;
|
||||
const enrolledTeams = tournament?.teams || [];
|
||||
const hasEnrolledTeams = enrolledTeams.length > 0;
|
||||
|
||||
return (
|
||||
<Stack gap="lg" w="100%">
|
||||
<Stack gap="xs">
|
||||
<Text fw={600} size="sm">Add Team</Text>
|
||||
<Autocomplete
|
||||
placeholder="Search for teams to enroll..."
|
||||
data={autocompleteData}
|
||||
value={search}
|
||||
onChange={setSearch}
|
||||
onOptionSubmit={handleEnrollTeam}
|
||||
disabled={isEnrolling || unenrolledLoading}
|
||||
rightSection={isEnrolling ? <Loader size="xs" /> : null}
|
||||
maxDropdownHeight={200}
|
||||
limit={10}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Stack gap="xs">
|
||||
<Group justify="space-between">
|
||||
<Text fw={600} size="sm">Enrolled Teams</Text>
|
||||
<Text size="xs" c="dimmed">{enrolledTeams.length} teams</Text>
|
||||
</Group>
|
||||
|
||||
{isLoading ? (
|
||||
<Group justify="center" py="md"><Loader size="sm" /></Group>
|
||||
) : !hasEnrolledTeams ? (
|
||||
<Text size="sm" c="dimmed" ta="center" py="lg">No teams enrolled yet</Text>
|
||||
) : (
|
||||
<Stack gap="xs" w="100%">
|
||||
{enrolledTeams.map((team: Team) => (
|
||||
<TeamItem
|
||||
key={team.id}
|
||||
team={team}
|
||||
onUnenroll={handleUnenrollTeam}
|
||||
disabled={isUnenrolling}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditEnrolledTeams;
|
||||
Reference in New Issue
Block a user