Add new frontend - fix 1
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
Reference in New Issue
Block a user