skeletons
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import { useState, useMemo, useCallback, memo } from "react";
|
||||
import {
|
||||
Text,
|
||||
TextInput,
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
UnstyledButton,
|
||||
Popover,
|
||||
ActionIcon,
|
||||
Skeleton,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
MagnifyingGlassIcon,
|
||||
@@ -24,10 +23,7 @@ import {
|
||||
import { PlayerStats } from "../types";
|
||||
import Avatar from "@/components/avatar";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
|
||||
interface PlayerStatsTableProps {
|
||||
playerStats: PlayerStats[];
|
||||
}
|
||||
import { useAllPlayerStats } from "../queries";
|
||||
|
||||
type SortKey = keyof PlayerStats | "mmr";
|
||||
type SortDirection = "asc" | "desc";
|
||||
@@ -39,33 +35,11 @@ interface SortConfig {
|
||||
|
||||
interface PlayerListItemProps {
|
||||
stat: PlayerStats;
|
||||
index: number;
|
||||
onPlayerClick: (playerId: string) => void;
|
||||
mmr: number;
|
||||
}
|
||||
|
||||
const PlayerListItem = ({ stat, index, onPlayerClick }: PlayerListItemProps) => {
|
||||
const calculateMMR = (stat: PlayerStats): number => {
|
||||
if (stat.matches === 0) return 0;
|
||||
|
||||
const winScore = stat.win_percentage;
|
||||
const matchConfidence = Math.min(stat.matches / 15, 1);
|
||||
const avgCupsScore = Math.min(stat.avg_cups_per_match * 10, 100);
|
||||
const marginScore = stat.margin_of_victory
|
||||
? Math.min(stat.margin_of_victory * 20, 50)
|
||||
: 0;
|
||||
const volumeBonus = Math.min(stat.matches * 0.5, 10);
|
||||
|
||||
const baseMMR =
|
||||
winScore * 0.5 +
|
||||
avgCupsScore * 0.25 +
|
||||
marginScore * 0.15 +
|
||||
volumeBonus * 0.1;
|
||||
|
||||
const finalMMR = baseMMR * matchConfidence;
|
||||
return Math.round(finalMMR * 10) / 10;
|
||||
};
|
||||
|
||||
const mmr = calculateMMR(stat);
|
||||
const PlayerListItem = memo(({ stat, onPlayerClick, mmr }: PlayerListItemProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -165,9 +139,12 @@ const PlayerListItem = ({ stat, index, onPlayerClick }: PlayerListItemProps) =>
|
||||
</UnstyledButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
const PlayerStatsTable = ({ playerStats }: PlayerStatsTableProps) => {
|
||||
PlayerListItem.displayName = 'PlayerListItem';
|
||||
|
||||
const PlayerStatsTable = () => {
|
||||
const { data: playerStats } = useAllPlayerStats();
|
||||
const navigate = useNavigate();
|
||||
const [search, setSearch] = useState("");
|
||||
const [sortConfig, setSortConfig] = useState<SortConfig>({
|
||||
@@ -196,8 +173,15 @@ const PlayerStatsTable = ({ playerStats }: PlayerStatsTableProps) => {
|
||||
return Math.round(finalMMR * 10) / 10;
|
||||
};
|
||||
|
||||
const statsWithMMR = useMemo(() => {
|
||||
return playerStats.map((stat) => ({
|
||||
...stat,
|
||||
mmr: calculateMMR(stat),
|
||||
}));
|
||||
}, [playerStats]);
|
||||
|
||||
const filteredAndSortedStats = useMemo(() => {
|
||||
let filtered = playerStats.filter((stat) =>
|
||||
let filtered = statsWithMMR.filter((stat) =>
|
||||
stat.player_name.toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
|
||||
@@ -206,8 +190,8 @@ const PlayerStatsTable = ({ playerStats }: PlayerStatsTableProps) => {
|
||||
let bValue: number | string;
|
||||
|
||||
if (sortConfig.key === "mmr") {
|
||||
aValue = calculateMMR(a);
|
||||
bValue = calculateMMR(b);
|
||||
aValue = a.mmr;
|
||||
bValue = b.mmr;
|
||||
} else {
|
||||
aValue = a[sortConfig.key];
|
||||
bValue = b[sortConfig.key];
|
||||
@@ -227,11 +211,11 @@ const PlayerStatsTable = ({ playerStats }: PlayerStatsTableProps) => {
|
||||
|
||||
return 0;
|
||||
});
|
||||
}, [playerStats, search, sortConfig]);
|
||||
}, [statsWithMMR, search, sortConfig]);
|
||||
|
||||
const handlePlayerClick = (playerId: string) => {
|
||||
const handlePlayerClick = useCallback((playerId: string) => {
|
||||
navigate({ to: `/profile/${playerId}` });
|
||||
};
|
||||
}, [navigate]);
|
||||
|
||||
const handleSort = (key: SortKey) => {
|
||||
setSortConfig((prev) => ({
|
||||
@@ -351,8 +335,8 @@ const PlayerStatsTable = ({ playerStats }: PlayerStatsTableProps) => {
|
||||
<Box key={stat.id}>
|
||||
<PlayerListItem
|
||||
stat={stat}
|
||||
index={index}
|
||||
onPlayerClick={handlePlayerClick}
|
||||
mmr={stat.mmr}
|
||||
/>
|
||||
{index < filteredAndSortedStats.length - 1 && <Divider />}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user