import { useCallback, useEffect, useRef, useState } from 'react'; import { ApiError, request } from './client'; import type { components } from './generated/v1'; export type DashboardChannel = components['schemas']['ChannelResponseModel']; export type DashboardChannelState = components['schemas']['ChannelStateResponseModel']; type DashboardHealthCheck = components['schemas']['HealthCheckResponseModel']; type DashboardMediaSource = components['schemas']['MediaSourceResponseModel']; type DashboardPlayouts = components['schemas']['PagedPlayoutsResponseModel']; export type DashboardVersion = components['schemas']['CombinedVersion']; export interface DashboardData { channels: DashboardChannel[]; channelStates: DashboardChannelState[]; mediaSources: DashboardMediaSource[]; playouts: DashboardPlayouts; } export type DashboardQueryState = | { data: DashboardData; error: null; status: 'success' } | { data: null; error: string; status: 'error' } | { data: null; error: null; status: 'loading' }; export type DashboardHealthQueryState = | { checks: DashboardHealthCheck[]; error: null; refresh: () => void; status: 'success' } | { checks: null; error: string; refresh: () => void; status: 'error' } | { checks: null; error: null; refresh: () => void; status: 'loading' }; export type DashboardVersionQueryState = | { error: null; status: 'success'; version: DashboardVersion } | { error: string; status: 'error'; version: null } | { error: null; status: 'loading'; version: null }; type DashboardHealthState = | { checks: DashboardHealthCheck[]; error: null; status: 'success' } | { checks: null; error: string; status: 'error' } | { checks: null; error: null; status: 'loading' }; export async function getDashboardData(): Promise { const [channels, channelStates, mediaSources, playouts] = await Promise.all([ request('/api/channels'), request('/api/channels/state'), request('/api/media-sources'), request('/api/playouts') ]); return { channels, channelStates, mediaSources, playouts }; } export function getDashboardHealth(): Promise { return request('/api/health'); } export function getDashboardVersion(): Promise { return request('/api/version'); } export function useDashboardQuery(): DashboardQueryState { const [state, setState] = useState({ data: null, error: null, status: 'loading' }); useEffect(() => { let active = true; getDashboardData() .then((data) => { if (active) { setState({ data, error: null, status: 'success' }); } }) .catch((error: unknown) => { if (active) { setState({ data: null, error: messageFromError(error), status: 'error' }); } }); return () => { active = false; }; }, []); return state; } export function useDashboardHealthQuery(): DashboardHealthQueryState { const [state, setState] = useState({ checks: null, error: null, status: 'loading' }); const activeRef = useRef(true); useEffect(() => { activeRef.current = true; return () => { activeRef.current = false; }; }, []); const loadHealth = useCallback(() => { getDashboardHealth() .then((checks) => { if (activeRef.current) { setState({ checks, error: null, status: 'success' }); } }) .catch((error: unknown) => { if (activeRef.current) { setState({ checks: null, error: messageFromError(error), status: 'error' }); } }); }, []); const refresh = useCallback(() => { setState({ checks: null, error: null, status: 'loading' }); loadHealth(); }, [loadHealth]); useEffect(() => { loadHealth(); }, [loadHealth]); if (state.status === 'success') { return { checks: state.checks, error: null, refresh, status: 'success' }; } if (state.status === 'error') { return { checks: null, error: state.error, refresh, status: 'error' }; } return { checks: null, error: null, refresh, status: 'loading' }; } export function useDashboardVersionQuery(): DashboardVersionQueryState { const [state, setState] = useState({ error: null, status: 'loading', version: null }); useEffect(() => { let active = true; getDashboardVersion() .then((version) => { if (active) { setState({ error: null, status: 'success', version }); } }) .catch((error: unknown) => { if (active) { setState({ error: messageFromError(error), status: 'error', version: null }); } }); return () => { active = false; }; }, []); return state; } function messageFromError(error: unknown): string { if (error instanceof ApiError) { return error.detail ?? error.message; } if (error instanceof Error) { return error.message; } return 'Unable to load dashboard'; }