Development #24
@@ -1,7 +1,7 @@
|
|||||||
import { createFileRoute } from "@tanstack/react-router";
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
import { playerQueries } from "@/features/players/queries";
|
import { playerQueries } from "@/features/players/queries";
|
||||||
import PlayerStatsTable from "@/features/players/components/player-stats-table";
|
import PlayerStatsTable from "@/features/players/components/player-stats-table";
|
||||||
import { Suspense, useState, useDeferredValue, useEffect } from "react";
|
import { Suspense, useState, useDeferredValue, useEffect, useRef } from "react";
|
||||||
import PlayerStatsTableSkeleton from "@/features/players/components/player-stats-table-skeleton";
|
import PlayerStatsTableSkeleton from "@/features/players/components/player-stats-table-skeleton";
|
||||||
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
|
import { prefetchServerQuery } from "@/lib/tanstack-query/utils/prefetch";
|
||||||
import LeagueHeadToHead from "@/features/players/components/league-head-to-head";
|
import LeagueHeadToHead from "@/features/players/components/league-head-to-head";
|
||||||
@@ -33,8 +33,11 @@ function Stats() {
|
|||||||
const isStale = viewType !== deferredViewType;
|
const isStale = viewType !== deferredViewType;
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const viewTypeRef = useRef(viewType);
|
||||||
const changeViewType = (next: typeof viewType) => {
|
const changeViewType = (next: typeof viewType) => {
|
||||||
if (viewType !== next) track("stats_filtered", { value: next });
|
if (viewTypeRef.current === next) return;
|
||||||
|
viewTypeRef.current = next;
|
||||||
|
track("stats_filtered", { value: next });
|
||||||
setViewType(next);
|
setViewType(next);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ const BadgeStatRow: React.FC<BadgeStatRowProps> = ({
|
|||||||
<Box key={badge.id}>
|
<Box key={badge.id}>
|
||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
track("badge_viewed", { badge: badge.key });
|
track("badge_viewed", { value: badge.key });
|
||||||
badgeSheet.open();
|
badgeSheet.open();
|
||||||
}}
|
}}
|
||||||
w='100%'
|
w='100%'
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ const MatchDock = ({ match, onClose }: MatchDockProps) => {
|
|||||||
variant="subtle"
|
variant="subtle"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
track("h2h_viewed", { source: "match_card" });
|
track("h2h_viewed", { source: "match_dock" });
|
||||||
h2hSheet.open();
|
h2hSheet.open();
|
||||||
}}
|
}}
|
||||||
aria-label={t`View head-to-head`}
|
aria-label={t`View head-to-head`}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Stack, Text, Divider, Group, Button } from "@mantine/core";
|
import { Box, Stack, Text, Divider, Group, Button } from "@mantine/core";
|
||||||
import { Suspense, useState, useDeferredValue } from "react";
|
import { Suspense, useState, useDeferredValue, useRef } from "react";
|
||||||
import { Trans, useLingui } from "@lingui/react/macro";
|
import { Trans, useLingui } from "@lingui/react/macro";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
import Header from "./header";
|
import Header from "./header";
|
||||||
@@ -21,8 +21,10 @@ const StatsWithFilter = ({ id }: { id: string }) => {
|
|||||||
const deferredViewType = useDeferredValue(viewType);
|
const deferredViewType = useDeferredValue(viewType);
|
||||||
const isStale = viewType !== deferredViewType;
|
const isStale = viewType !== deferredViewType;
|
||||||
|
|
||||||
|
const viewTypeRef = useRef(viewType);
|
||||||
const changeViewType = (next: typeof viewType) => {
|
const changeViewType = (next: typeof viewType) => {
|
||||||
if (next === viewType) return;
|
if (viewTypeRef.current === next) return;
|
||||||
|
viewTypeRef.current = next;
|
||||||
track("stats_filtered", { value: next, source: "profile" });
|
track("stats_filtered", { value: next, source: "profile" });
|
||||||
setViewType(next);
|
setViewType(next);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -202,10 +202,7 @@ const EmojiBar = ({
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</Group>
|
</Group>
|
||||||
<EmojiPicker
|
<EmojiPicker
|
||||||
onSelect={onReactionPress || ((emoji) => {
|
onSelect={handleReactionClick}
|
||||||
if (!userReactions.includes(emoji)) track("reaction_sent", { emoji, source });
|
|
||||||
toggleReaction.mutate({ data: { matchId, emoji } });
|
|
||||||
})}
|
|
||||||
userReactions={userReactions}
|
userReactions={userReactions}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import { DatePickerInput } from "@mantine/dates";
|
||||||
import { ListSkeleton, StatTileSkeleton } from "@/components/skeletons";
|
import { ListSkeleton, StatTileSkeleton } from "@/components/skeletons";
|
||||||
import { useRollupRange } from "../queries";
|
import { useRollupRange } from "../queries";
|
||||||
import type { RollupRow } from "../types";
|
import type { RollupRow } from "../types";
|
||||||
import { DatePickerInput } from "@mantine/dates";
|
|
||||||
import { fillDailySeries, lastNDays, latestValue, listDays, sumByDim } from "../range";
|
import { fillDailySeries, lastNDays, latestValue, listDays, sumByDim } from "../range";
|
||||||
import { BarList, Sparkline, StatTile } from "./charts";
|
import { BarList, Sparkline, StatTile } from "./charts";
|
||||||
import { DetailSheet } from "./shared";
|
import { DetailSheet } from "./shared";
|
||||||
|
|||||||
@@ -165,8 +165,6 @@ export function useServerEvents() {
|
|||||||
// an expired session rather than a network blip. Try to refresh; if the
|
// an expired session rather than a network blip. Try to refresh; if the
|
||||||
// session is genuinely gone, stop retrying so we don't hammer the
|
// session is genuinely gone, stop retrying so we don't hammer the
|
||||||
// endpoint forever — a real re-login (or a wake event) will reconnect.
|
// endpoint forever — a real re-login (or a wake event) will reconnect.
|
||||||
// Cooldown: a flaky stream (proxy idle timeouts) must not turn every
|
|
||||||
// reconnect into a refresh call.
|
|
||||||
let sessionValid = true;
|
let sessionValid = true;
|
||||||
if (Date.now() - lastRefreshAttemptAt > REFRESH_ATTEMPT_COOLDOWN_MS) {
|
if (Date.now() - lastRefreshAttemptAt > REFRESH_ATTEMPT_COOLDOWN_MS) {
|
||||||
lastRefreshAttemptAt = Date.now();
|
lastRefreshAttemptAt = Date.now();
|
||||||
|
|||||||
Reference in New Issue
Block a user