Add new frontend - fix 1

This commit is contained in:
Urtzi Alfaro
2025-07-22 07:59:37 +02:00
parent 777798b054
commit c8517c41a5
4 changed files with 4 additions and 282 deletions

View File

@@ -1,103 +0,0 @@
// frontend/dashboard/src/api/hooks/useAuth.ts
/**
* Authentication hook with state management
*/
import { useState, useEffect, useContext, createContext, ReactNode } from 'react';
import { UserProfile, LoginRequest, RegisterRequest } from '../../types/api';
import { authApi } from '../index';
import { useAsyncAction } from './useApi';
interface AuthContextType {
user: UserProfile | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (credentials: LoginRequest) => Promise<void>;
register: (userData: RegisterRequest) => Promise<void>;
logout: () => Promise<void>;
updateProfile: (updates: Partial<UserProfile>) => Promise<void>;
refreshUser: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<UserProfile | null>(null);
const [isLoading, setIsLoading] = useState(true);
const { execute: executeLogin } = useAsyncAction(authApi.login.bind(authApi));
const { execute: executeRegister } = useAsyncAction(authApi.register.bind(authApi));
const { execute: executeLogout } = useAsyncAction(authApi.logout.bind(authApi));
// Initialize auth state
useEffect(() => {
const initAuth = async () => {
try {
if (authApi.isAuthenticated()) {
const profile = await authApi.getCurrentUser();
setUser(profile);
}
} catch (error) {
// Token might be expired, clear storage
authApi.logout();
} finally {
setIsLoading(false);
}
};
initAuth();
}, []);
const login = async (credentials: LoginRequest) => {
await executeLogin(credentials);
const profile = await authApi.getCurrentUser();
setUser(profile);
};
const register = async (userData: RegisterRequest) => {
const profile = await executeRegister(userData);
setUser(profile);
};
const logout = async () => {
await executeLogout();
setUser(null);
};
const updateProfile = async (updates: Partial<UserProfile>) => {
const updatedProfile = await authApi.updateProfile(updates);
setUser(updatedProfile);
};
const refreshUser = async () => {
if (authApi.isAuthenticated()) {
const profile = await authApi.getCurrentUser();
setUser(profile);
}
};
return (
<AuthContext.Provider
value={{
user,
isAuthenticated: !!user,
isLoading,
login,
register,
logout,
updateProfile,
refreshUser,
}}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth(): AuthContextType {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}

View File

@@ -1,67 +0,0 @@
// frontend/dashboard/src/api/hooks/useTraining.ts
/**
* Training-specific hooks
*/
import { useState, useEffect, useRef } from 'react';
import { TrainingJobStatus, TrainingRequest } from '../../types/api';
import { trainingApi } from '../index';
import { useApi, useAsyncAction } from './useApi';
export function useTraining() {
const { data: jobs, loading, error, refetch } = useApi(() => trainingApi.getTrainingJobs());
const { data: models, refetch: refetchModels } = useApi(() => trainingApi.getTrainedModels());
const { execute: startTraining, loading: startingTraining } = useAsyncAction(
trainingApi.startTraining.bind(trainingApi)
);
return {
jobs: jobs || [],
models: models || [],
loading,
error,
startingTraining,
startTraining: async (request: TrainingRequest) => {
const job = await startTraining(request);
await refetch();
return job;
},
refresh: refetch,
refreshModels: refetchModels,
};
}
export function useTrainingProgress(jobId: string | null) {
const [progress, setProgress] = useState<TrainingJobStatus | null>(null);
const [error, setError] = useState<string | null>(null);
const wsRef = useRef<WebSocket | null>(null);
useEffect(() => {
if (!jobId) return;
// Initial status fetch
trainingApi.getTrainingStatus(jobId).then(setProgress).catch(setError);
// Set up WebSocket for real-time updates
wsRef.current = trainingApi.subscribeToTrainingProgress(
jobId,
(updatedProgress) => {
setProgress(updatedProgress);
setError(null);
},
(wsError) => {
setError(wsError.message);
}
);
return () => {
if (wsRef.current) {
wsRef.current.close();
}
};
}, [jobId]);
return { progress, error };
}

View File

@@ -1,109 +0,0 @@
// frontend/dashboard/src/api/hooks/useWebSocket.ts
/**
* Generic WebSocket hook for real-time updates
*/
import { useState, useEffect, useRef, useCallback } from 'react';
export interface WebSocketOptions {
reconnectAttempts?: number;
reconnectInterval?: number;
onOpen?: () => void;
onClose?: () => void;
onError?: (error: Event) => void;
}
export function useWebSocket<T>(
url: string | null,
options: WebSocketOptions = {}
): {
data: T | null;
connectionState: 'connecting' | 'open' | 'closed' | 'error';
send: (data: any) => void;
close: () => void;
} {
const [data, setData] = useState<T | null>(null);
const [connectionState, setConnectionState] = useState<'connecting' | 'open' | 'closed' | 'error'>('closed');
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const reconnectAttemptsRef = useRef(0);
const {
reconnectAttempts = 3,
reconnectInterval = 3000,
onOpen,
onClose,
onError,
} = options;
const connect = useCallback(() => {
if (!url || wsRef.current?.readyState === WebSocket.OPEN) return;
try {
setConnectionState('connecting');
wsRef.current = new WebSocket(url);
wsRef.current.onopen = () => {
setConnectionState('open');
reconnectAttemptsRef.current = 0;
onOpen?.();
};
wsRef.current.onmessage = (event) => {
try {
const parsedData = JSON.parse(event.data);
setData(parsedData);
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
};
wsRef.current.onclose = () => {
setConnectionState('closed');
onClose?.();
// Attempt to reconnect
if (reconnectAttemptsRef.current < reconnectAttempts) {
reconnectAttemptsRef.current++;
reconnectTimeoutRef.current = setTimeout(connect, reconnectInterval);
}
};
wsRef.current.onerror = (error) => {
setConnectionState('error');
onError?.(error);
};
} catch (error) {
setConnectionState('error');
console.error('WebSocket connection failed:', error);
}
}, [url, reconnectAttempts, reconnectInterval, onOpen, onClose, onError]);
const send = useCallback((data: any) => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(JSON.stringify(data));
}
}, []);
const close = useCallback(() => {
if (reconnectTimeoutRef.current) {
clearTimeout(reconnectTimeoutRef.current);
}
if (wsRef.current) {
wsRef.current.close();
}
}, []);
useEffect(() => {
if (url) {
connect();
}
return () => {
close();
};
}, [url, connect, close]);
return { data, connectionState, send, close };
}