feat(docker): añadir Dockerfile para contenerizar la aplicación

This commit is contained in:
unknown
2026-06-11 16:05:10 -04:00
parent 74a67fbab2
commit 2a58693d31
70 changed files with 3826 additions and 874 deletions

79
src/hooks/useWebSocket.ts Normal file
View File

@@ -0,0 +1,79 @@
import { useCallback, useEffect, useRef, useState } from 'react';
export type WsStatus = 'connecting' | 'open' | 'closed' | 'error';
interface UseWebSocketOptions {
url: string | null;
enabled?: boolean;
onMessage?: (data: string) => void;
reconnect?: boolean;
reconnectIntervalMs?: number;
}
export function useWebSocket({
url,
enabled = true,
onMessage,
reconnect = true,
reconnectIntervalMs = 3000,
}: UseWebSocketOptions) {
const [status, setStatus] = useState<WsStatus>('closed');
const wsRef = useRef<WebSocket | null>(null);
const onMessageRef = useRef(onMessage);
onMessageRef.current = onMessage;
const send = useCallback((data: string) => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(data);
}
}, []);
useEffect(() => {
if (!enabled || !url) {
setStatus('closed');
return;
}
let disposed = false;
let reconnectTimer: ReturnType<typeof setTimeout> | undefined;
const connect = () => {
if (disposed) return;
setStatus('connecting');
const ws = new WebSocket(url);
wsRef.current = ws;
ws.onopen = () => {
if (!disposed) setStatus('open');
};
ws.onmessage = (event) => {
onMessageRef.current?.(String(event.data));
};
ws.onerror = () => {
if (!disposed) setStatus('error');
};
ws.onclose = () => {
if (!disposed) {
setStatus('closed');
if (reconnect) {
reconnectTimer = setTimeout(connect, reconnectIntervalMs);
}
}
};
};
connect();
return () => {
disposed = true;
if (reconnectTimer) clearTimeout(reconnectTimer);
wsRef.current?.close();
wsRef.current = null;
};
}, [url, enabled, reconnect, reconnectIntervalMs]);
return { status, send };
}