reactions, match sse, etc

This commit is contained in:
yohlo
2025-09-19 14:08:36 -05:00
parent 602e6e3473
commit f99d6efaf9
20 changed files with 474 additions and 100 deletions

View File

@@ -5,43 +5,27 @@ import {
Tabs,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useState, useRef } from "react";
import { useState, useRef, useCallback } from "react";
import Sheet from "@/components/sheet/sheet";
import { PlayerInfo } from "@/features/players/types";
import PlayerList from "@/features/players/components/player-list";
import EmojiPicker from "./emoji-picker";
interface Reaction {
emoji: string;
count: number;
players: PlayerInfo[];
hasReacted: boolean;
}
import { useMatchReactions, useToggleMatchReaction } from "../queries";
import { useAuth } from "@/contexts/auth-context";
import { Reaction } from "@/features/matches/server";
interface EmojiBarProps {
reactions?: Reaction[];
matchId: string;
onReactionPress?: (emoji: string) => void;
}
const EXAMPLE_DATA: Reaction[] = [
{
emoji: "👍",
count: 1,
players: [{ id: "dasfasdf", first_name: "Kyle", last_name: "Yohler" }],
hasReacted: true,
},
{
emoji: "❤️",
count: 1,
players: [{ id: "f3234f", first_name: "Salah", last_name: "Atiyeh" }],
hasReacted: false,
},
];
const EmojiBar = ({
reactions = EXAMPLE_DATA,
matchId,
onReactionPress,
}: EmojiBarProps) => {
const { user } = useAuth();
const { data: reactions } = useMatchReactions(matchId);
const toggleReaction = useToggleMatchReaction(matchId);
const [opened, { open, close }] = useDisclosure(false);
const [activeTab, setActiveTab] = useState<string | null>(null);
const longPressTimeout = useRef<NodeJS.Timeout | null>(null);
@@ -61,10 +45,20 @@ const EmojiBar = ({
const handleReactionClick = (emoji: string) => {
handleLongPressEnd();
onReactionPress?.(emoji);
if (onReactionPress) {
onReactionPress(emoji);
} else {
toggleReaction.mutate({ data: { matchId, emoji } });
}
};
if (!reactions.length) return null;
const hasReacted = useCallback((reaction: Reaction) => {
return reaction.players.map(p => p.id).includes(user?.id || "");
}, []);
if (!reactions) return;
console.log(reactions)
return (
<>
@@ -73,8 +67,9 @@ const EmojiBar = ({
{reactions.map((reaction) => (
<Button
key={reaction.emoji}
variant={reaction.hasReacted ? "filled" : "light"}
color={reaction.hasReacted ? "var(--mantine-primary-color-filled)" : "gray"}
variant={hasReacted(reaction) ? "filled" : "light"}
color="gray"
bd={hasReacted(reaction) ? "1px solid var(--mantine-primary-color-filled)" : undefined}
size="compact-xs"
radius="xl"
onMouseDown={() => handleLongPressStart(reaction.emoji)}
@@ -90,18 +85,18 @@ const EmojiBar = ({
msUserSelect: "none",
}}
>
<Group gap={4} align="center">
<Text size="10px" style={{ lineHeight: 1 }}>
<Group gap={2} align="center">
<Text size="xs" style={{ lineHeight: 1 }}>
{reaction.emoji}
</Text>
<Text size="10px" fw={600}>
<Text size="xs" fw={600}>
{reaction.count}
</Text>
</Group>
</Button>
))}
</Group>
<EmojiPicker onSelect={onReactionPress || (() => {})} />
<EmojiPicker onSelect={onReactionPress || ((emoji) => toggleReaction.mutate({ data: { matchId, emoji } }))} />
</Group>
<Sheet title="Reactions" opened={opened} onChange={() => close()}>

View File

@@ -0,0 +1,34 @@
import { useServerQuery, useServerMutation } from "@/lib/tanstack-query/hooks";
import { getMatchReactions, toggleMatchReaction } from "@/features/matches/server";
import { useQueryClient } from "@tanstack/react-query";
import { matchKeys } from "@/features/matches/queries";
export const reactionKeys = {
match: (matchId: string) => ['reactions', 'match', matchId] as const,
};
export const reactionQueries = {
match: (matchId: string) => ({
queryKey: reactionKeys.match(matchId),
queryFn: () => getMatchReactions({ data: matchId }),
}),
};
export const useMatchReactions = (matchId: string) =>
useServerQuery(reactionQueries.match(matchId));
export const useToggleMatchReaction = (matchId: string) => {
const queryClient = useQueryClient();
return useServerMutation({
mutationFn: toggleMatchReaction,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: reactionKeys.match(matchId)
});
queryClient.invalidateQueries({
queryKey: matchKeys.reactions(matchId)
});
},
});
};