From f6eb815240d05fa9b5ff2ed309f2afd8d7891b90 Mon Sep 17 00:00:00 2001 From: JSC Date: Wed, 16 Jul 2025 13:56:02 +0200 Subject: [PATCH] feat: implement real-time updates for credits and sound play counts using custom events --- src/components/sidebar/NavPlan.tsx | 20 +++++++++----------- src/contexts/SocketContext.tsx | 15 ++++++++++++--- src/pages/AdminSoundsPage.tsx | 3 +-- src/pages/DashboardPage.tsx | 2 +- src/pages/SoundboardPage.tsx | 27 +++++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/components/sidebar/NavPlan.tsx b/src/components/sidebar/NavPlan.tsx index 2e6bf51..ec122e1 100644 --- a/src/components/sidebar/NavPlan.tsx +++ b/src/components/sidebar/NavPlan.tsx @@ -1,6 +1,5 @@ import type { User } from "@/services/auth" import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar" -import { useSocket } from "@/contexts/SocketContext" import NumberFlow from '@number-flow/react' import { useEffect, useState } from "react" @@ -10,7 +9,6 @@ interface NavPlanProps { export function NavPlan({ user }: NavPlanProps) { const [credits, setCredits] = useState(0) - const { socket, isConnected } = useSocket() useEffect(() => { setCredits(user.credits) @@ -18,19 +16,19 @@ export function NavPlan({ user }: NavPlanProps) { // Listen for real-time credits updates useEffect(() => { - if (!socket || !isConnected) return - - const handleCreditsChanged = (data: { credits: number }) => { - setCredits(data.credits) + const handleCreditsChanged = (/*data: { credits: number }*/ event: CustomEvent) => { + const { credits } = event.detail + setCredits(credits) } - socket.on("credits_changed", handleCreditsChanged) + // Listen for the custom event + window.addEventListener('credits_changed', handleCreditsChanged as EventListener); - // Cleanup listener on unmount + // Cleanup return () => { - socket.off("credits_changed", handleCreditsChanged) - } - }, [socket, isConnected]) + window.removeEventListener('credits_changed', handleCreditsChanged as EventListener); + }; + }, []) return ( diff --git a/src/contexts/SocketContext.tsx b/src/contexts/SocketContext.tsx index ed5cf5e..8278f33 100644 --- a/src/contexts/SocketContext.tsx +++ b/src/contexts/SocketContext.tsx @@ -68,13 +68,22 @@ export const SocketProvider: React.FC = ({ children }) => { setIsConnected(false); }); - // Global socket event listeners for toasts + // Global events + newSocket.on("error", (data) => { + toast.error(data.message || "An error occurred"); + }); + newSocket.on("credits_required", (data) => { toast.error(`Insufficient credits. Need ${data.credits_needed} credits.`); }); - newSocket.on("error", (data) => { - toast.error(data.message || "An error occurred"); + // Page or component events + newSocket.on("credits_changed", (data) => { + window.dispatchEvent(new CustomEvent('credits_changed', { detail: data })); + }); + + newSocket.on("sound_play_count_changed", (data) => { + window.dispatchEvent(new CustomEvent('sound_play_count_changed', { detail: data })); }); setSocket(newSocket); diff --git a/src/pages/AdminSoundsPage.tsx b/src/pages/AdminSoundsPage.tsx index 44711a7..a5f3dc7 100644 --- a/src/pages/AdminSoundsPage.tsx +++ b/src/pages/AdminSoundsPage.tsx @@ -53,8 +53,7 @@ export function AdminSoundsPage() { return (
-
-

Sound Management

+
+
) } \ No newline at end of file diff --git a/src/pages/SoundboardPage.tsx b/src/pages/SoundboardPage.tsx index 223b7fe..5fc898a 100644 --- a/src/pages/SoundboardPage.tsx +++ b/src/pages/SoundboardPage.tsx @@ -115,6 +115,30 @@ export function SoundboardPage() { fetchSounds() }, []) + // Listen for sound_play_count_changed events from socket + useEffect(() => { + const handleSoundPlayCountChanged = (event: CustomEvent) => { + const { sound_id, play_count } = event.detail; + + // Update the sound in the local state + setSounds(prevSounds => + prevSounds.map(sound => + sound.id === sound_id + ? { ...sound, play_count } + : sound + ) + ); + }; + + // Listen for the custom event + window.addEventListener('sound_play_count_changed', handleSoundPlayCountChanged as EventListener); + + // Cleanup + return () => { + window.removeEventListener('sound_play_count_changed', handleSoundPlayCountChanged as EventListener); + }; + }, []); + const { theme } = useTheme() useEffect(() => { @@ -203,8 +227,7 @@ export function SoundboardPage() { return (
-
-

Soundboard

+