From 02cad6a319d59a2220c7569dfffce40a1b0656a1 Mon Sep 17 00:00:00 2001 From: Decobus Date: Tue, 22 Jul 2025 14:28:14 -0400 Subject: [PATCH] Add team and stream counts to footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created /api/counts endpoint for database statistics - Updated footer to display team and stream counts - Shows counts when OBS is connected (alongside OBS stats) - Shows database stats when OBS is disconnected (fallback display) - Polls counts every 60 seconds (less frequent than OBS status) - Maintains backward compatibility with API response formats Footer now shows: - Teams: X - Streams: Y 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- app/api/counts/route.ts | 25 ++++++++++++++++ components/Footer.tsx | 65 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 app/api/counts/route.ts diff --git a/app/api/counts/route.ts b/app/api/counts/route.ts new file mode 100644 index 0000000..86a638d --- /dev/null +++ b/app/api/counts/route.ts @@ -0,0 +1,25 @@ +import { NextResponse } from 'next/server'; +import { getDatabase } from '../../../lib/database'; +import { TABLE_NAMES } from '../../../lib/constants'; +import { createSuccessResponse, createDatabaseError, withErrorHandling } from '../../../lib/apiHelpers'; + +async function getCountsHandler() { + try { + const db = await getDatabase(); + + // Get counts in parallel + const [streamsResult, teamsResult] = await Promise.all([ + db.get(`SELECT COUNT(*) as count FROM ${TABLE_NAMES.STREAMS}`), + db.get(`SELECT COUNT(*) as count FROM ${TABLE_NAMES.TEAMS}`) + ]); + + return createSuccessResponse({ + streams: streamsResult.count, + teams: teamsResult.count + }); + } catch (error) { + return createDatabaseError('fetch counts', error); + } +} + +export const GET = withErrorHandling(getCountsHandler); \ No newline at end of file diff --git a/components/Footer.tsx b/components/Footer.tsx index c43a131..06a8cbe 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -19,8 +19,14 @@ type OBSStatus = { error?: string; }; +type Counts = { + streams: number; + teams: number; +}; + export default function Footer() { const [obsStatus, setObsStatus] = useState(null); + const [counts, setCounts] = useState(null); const [isLoading, setIsLoading] = useState(true); // Smart polling with performance monitoring and visibility detection @@ -40,9 +46,24 @@ export default function Footer() { } }; + const fetchCounts = async () => { + try { + const response = await fetch('/api/counts'); + const data = await response.json(); + // Handle both old and new API response formats + const countsData = data.success ? data.data : data; + setCounts(countsData); + } catch (error) { + console.error('Failed to fetch counts:', error); + } + }; + // Use smart polling that respects page visibility and adapts interval based on connection status const pollingInterval = obsStatus?.connected ? 15000 : 30000; // Poll faster when connected useSmartPolling(fetchOBSStatus, pollingInterval, [obsStatus?.connected]); + + // Poll counts less frequently (every 60 seconds) since they don't change as often + useSmartPolling(fetchCounts, 60000, []); if (isLoading) { return ( @@ -78,11 +99,27 @@ export default function Footer() { )} - {/* Live Status */} - {obsStatus?.connected && ( -
-

Live Status

- + {/* Live Status or Database Stats */} +
+

+ {obsStatus?.connected ? 'Live Status' : 'Database Stats'} +

+ + {/* Show counts when OBS is disconnected */} + {!obsStatus?.connected && counts && ( +
+
+ Teams: + {counts.teams} +
+
+ Streams: + {counts.streams} +
+
+ )} + + {obsStatus?.connected && (
{obsStatus.currentScene && (
@@ -98,6 +135,20 @@ export default function Footer() {
)} + {/* Database counts */} + {counts && ( + <> +
+ Teams: + {counts.teams} +
+
+ Streams: + {counts.streams} +
+ + )} +
@@ -110,8 +161,8 @@ export default function Footer() {
-
- )} + )} +
{/* Error Message */}