Files
flxn-app/src/features/teams/components/team-list.tsx
2025-10-17 19:22:07 -05:00

120 lines
3.0 KiB
TypeScript

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";
import { useCallback, useMemo } from "react";
import React from "react";
interface TeamListItemProps {
team: TeamInfo;
}
const TeamListItem = React.memo(({ team }: TeamListItemProps) => {
const playerNames = useMemo(
() => team.players?.map((p) => `${p.first_name} ${p.last_name}`) || [],
[team.players]
);
const teamNameSize = useMemo(() => {
const nameLength = team.name.length;
if (nameLength > 20) return 'xs';
if (nameLength > 15) return 'sm';
return 'md';
}, [team.name]);
return (
<Group justify="space-between" w="100%" wrap="nowrap">
<Text fw={500} size={teamNameSize} style={{ flexShrink: 1, minWidth: 0, maxWidth: 170, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{`${team.name}`}
</Text>
<Stack ml="auto" gap={0} style={{ flexShrink: 0 }}>
{playerNames.map((name, idx) => (
<Text key={idx} size="xs" c="dimmed" ta="right">
{name}
</Text>
))}
</Stack>
</Group>
);
});
interface TeamListProps {
teams: TeamInfo[];
loading?: boolean;
onTeamClick?: (teamId: string) => void;
}
const TeamList = ({ teams, loading = false, onTeamClick }: TeamListProps) => {
const navigate = useNavigate();
const handleClick = useCallback(
(teamId: string, priv: boolean) => {
if (onTeamClick) {
onTeamClick(teamId);
} else if (!priv) {
navigate({ to: `/teams/${teamId}` });
}
},
[navigate, onTeamClick]
);
if (loading)
return (
<List p="0">
{Array.from({ length: 10 }).map((_, i) => (
<ListItem
key={`skeleton-${i}`}
py="xs"
icon={<Skeleton height={40} width={40} />}
>
<Skeleton height={35} width={200} />
</ListItem>
))}
</List>
);
return (
<List p="0">
{teams?.map((team) => (
<div key={team.id}>
<ListItem
key={`team-list-${team.id}`}
p="xs"
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, team.private)}
styles={{
itemWrapper: { width: "100%" },
itemLabel: { width: "100%" },
}}
w="100%"
>
<TeamListItem team={team} />
</ListItem>
<Divider />
</div>
))}
</List>
);
};
export default TeamList;