Footer enhancements and performance optimizations #9
3 changed files with 20 additions and 14 deletions
|
@ -1,13 +1,20 @@
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { getDatabase } from '../../../lib/database';
|
import { getDatabase } from '../../../lib/database';
|
||||||
import { Stream } from '@/types';
|
import { StreamWithTeam } from '@/types';
|
||||||
import { TABLE_NAMES } from '../../../lib/constants';
|
import { TABLE_NAMES } from '../../../lib/constants';
|
||||||
import { createSuccessResponse, createDatabaseError, withErrorHandling } from '../../../lib/apiHelpers';
|
import { createSuccessResponse, createDatabaseError, withErrorHandling } from '../../../lib/apiHelpers';
|
||||||
|
|
||||||
async function getStreamsHandler() {
|
async function getStreamsHandler() {
|
||||||
try {
|
try {
|
||||||
const db = await getDatabase();
|
const db = await getDatabase();
|
||||||
const streams: Stream[] = await db.all(`SELECT * FROM ${TABLE_NAMES.STREAMS}`);
|
const streams: StreamWithTeam[] = await db.all(`
|
||||||
|
SELECT
|
||||||
|
s.*,
|
||||||
|
t.team_name,
|
||||||
|
t.group_name
|
||||||
|
FROM ${TABLE_NAMES.STREAMS} s
|
||||||
|
LEFT JOIN ${TABLE_NAMES.TEAMS} t ON s.team_id = t.team_id
|
||||||
|
`);
|
||||||
return createSuccessResponse(streams);
|
return createSuccessResponse(streams);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return createDatabaseError('fetch streams', error);
|
return createDatabaseError('fetch streams', error);
|
||||||
|
|
|
@ -7,17 +7,12 @@ import { useToast } from '@/lib/useToast';
|
||||||
import { ToastContainer } from '@/components/Toast';
|
import { ToastContainer } from '@/components/Toast';
|
||||||
import { useActiveSourceLookup, useDebounce, PerformanceMonitor } from '@/lib/performance';
|
import { useActiveSourceLookup, useDebounce, PerformanceMonitor } from '@/lib/performance';
|
||||||
|
|
||||||
type Stream = {
|
import { StreamWithTeam } from '@/types';
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
obs_source_name: string;
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ScreenType = 'large' | 'left' | 'right' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
|
type ScreenType = 'large' | 'left' | 'right' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [streams, setStreams] = useState<Stream[]>([]);
|
const [streams, setStreams] = useState<StreamWithTeam[]>([]);
|
||||||
const [activeSources, setActiveSources] = useState<Record<ScreenType, string | null>>({
|
const [activeSources, setActiveSources] = useState<Record<ScreenType, string | null>>({
|
||||||
large: null,
|
large: null,
|
||||||
left: null,
|
left: null,
|
||||||
|
|
|
@ -38,13 +38,17 @@ export function useThrottle<T extends (...args: unknown[]) => unknown>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memoized stream lookup utilities
|
// Memoized stream lookup utilities
|
||||||
export function createStreamLookupMaps(streams: Array<{ id: number; obs_source_name: string; name: string }>) {
|
export function createStreamLookupMaps(streams: Array<{ id: number; obs_source_name: string; name: string; team_name?: string; group_name?: string | null }>) {
|
||||||
const sourceToIdMap = new Map<string, number>();
|
const sourceToIdMap = new Map<string, number>();
|
||||||
const idToStreamMap = new Map<number, { id: number; obs_source_name: string; name: string }>();
|
const idToStreamMap = new Map<number, { id: number; obs_source_name: string; name: string; team_name?: string; group_name?: string | null }>();
|
||||||
|
|
||||||
streams.forEach(stream => {
|
streams.forEach(stream => {
|
||||||
// Generate stream group name to match what's written to files
|
// Generate stream group name to match what's written to files
|
||||||
const streamGroupName = `${stream.name.toLowerCase().replace(/\s+/g, '_')}_stream`;
|
// Format: {team_name}_{stream_name}_stream (matching obsClient.js logic)
|
||||||
|
const cleanTeamName = stream.team_name ? stream.team_name.toLowerCase().replace(/\s+/g, '_') : 'unknown';
|
||||||
|
const cleanStreamName = stream.name.toLowerCase().replace(/\s+/g, '_');
|
||||||
|
const streamGroupName = `${cleanTeamName}_${cleanStreamName}_stream`;
|
||||||
|
|
||||||
sourceToIdMap.set(streamGroupName, stream.id);
|
sourceToIdMap.set(streamGroupName, stream.id);
|
||||||
idToStreamMap.set(stream.id, stream);
|
idToStreamMap.set(stream.id, stream);
|
||||||
});
|
});
|
||||||
|
@ -53,7 +57,7 @@ export function createStreamLookupMaps(streams: Array<{ id: number; obs_source_n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook version for React components
|
// Hook version for React components
|
||||||
export function useStreamLookupMaps(streams: Array<{ id: number; obs_source_name: string; name: string }>) {
|
export function useStreamLookupMaps(streams: Array<{ id: number; obs_source_name: string; name: string; team_name?: string; group_name?: string | null }>) {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return createStreamLookupMaps(streams);
|
return createStreamLookupMaps(streams);
|
||||||
}, [streams]);
|
}, [streams]);
|
||||||
|
@ -61,7 +65,7 @@ export function useStreamLookupMaps(streams: Array<{ id: number; obs_source_name
|
||||||
|
|
||||||
// Efficient active source lookup
|
// Efficient active source lookup
|
||||||
export function useActiveSourceLookup(
|
export function useActiveSourceLookup(
|
||||||
streams: Array<{ id: number; obs_source_name: string; name: string }>,
|
streams: Array<{ id: number; obs_source_name: string; name: string; team_name?: string; group_name?: string | null }>,
|
||||||
activeSources: Record<string, string | null>
|
activeSources: Record<string, string | null>
|
||||||
) {
|
) {
|
||||||
const { sourceToIdMap } = useStreamLookupMaps(streams);
|
const { sourceToIdMap } = useStreamLookupMaps(streams);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue