import { useState, useCallback } from 'react';
// Use same host as the UI for API (allows access from any machine)
const API_BASE = import.meta.env.DEV
? `http://${window.location.hostname}:37778`
: '/api';
interface ApiState<T> {
data: T | null;
loading: boolean;
error: string | null;
}
export function useApi<T>() {
const [state, setState] = useState<ApiState<T>>({
data: null,
loading: false,
error: null,
});
const fetchData = useCallback(async (
endpoint: string,
options?: RequestInit
): Promise<T | null> => {
setState(prev => ({ ...prev, loading: true, error: null }));
try {
const url = `${API_BASE}${endpoint}`;
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
...options,
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`);
}
setState({ data, loading: false, error: null });
return data;
} catch (err) {
const error = err instanceof Error ? err.message : 'Unknown error';
setState({ data: null, loading: false, error });
return null;
}
}, []);
const reset = useCallback(() => {
setState({ data: null, loading: false, error: null });
}, []);
return {
...state,
fetchData,
reset,
};
}
// Helper for GET requests with query params
export function buildUrl(endpoint: string, params: Record<string, string | number | undefined>): string {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined) {
searchParams.set(key, String(value));
}
});
const query = searchParams.toString();
return query ? `${endpoint}?${query}` : endpoint;
}