59 lines
2.5 KiB
TypeScript
59 lines
2.5 KiB
TypeScript
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { fetchData, type FetchDataResult, type FetchSelector } from '../api/ingestion';
|
|
import { useToast } from '../components/ui/Toast';
|
|
import { summarizeIngestionResult } from '../lib/ingestionStatus';
|
|
|
|
interface UseFetchSymbolDataOptions {
|
|
includeSymbolPrefix?: boolean;
|
|
invalidatePipelineReadiness?: boolean;
|
|
}
|
|
|
|
export interface FetchVars {
|
|
symbol: string;
|
|
sources?: FetchSelector;
|
|
}
|
|
|
|
type FetchArg = string | FetchVars;
|
|
|
|
const argSymbol = (arg: FetchArg): string => (typeof arg === 'string' ? arg : arg.symbol);
|
|
|
|
export function useFetchSymbolData(options: UseFetchSymbolDataOptions = {}) {
|
|
const { includeSymbolPrefix = false, invalidatePipelineReadiness = false } = options;
|
|
const queryClient = useQueryClient();
|
|
const { addToast } = useToast();
|
|
|
|
return useMutation({
|
|
// Accepts either a bare symbol (fetch all) or { symbol, sources } (granular)
|
|
mutationFn: (arg: FetchArg) =>
|
|
typeof arg === 'string' ? fetchData(arg) : fetchData(arg.symbol, arg.sources),
|
|
onSuccess: (result: FetchDataResult, arg: FetchArg) => {
|
|
const symbol = argSymbol(arg);
|
|
const normalized = symbol.toUpperCase();
|
|
const summary = summarizeIngestionResult(result, normalized);
|
|
const toastMessage = includeSymbolPrefix
|
|
? `${normalized}: ${summary.message}`
|
|
: summary.message;
|
|
addToast(summary.toastType, toastMessage);
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['ohlcv', symbol] });
|
|
queryClient.invalidateQueries({ queryKey: ['sentiment', symbol] });
|
|
queryClient.invalidateQueries({ queryKey: ['fundamentals', symbol] });
|
|
queryClient.invalidateQueries({ queryKey: ['sr-levels', symbol] });
|
|
queryClient.invalidateQueries({ queryKey: ['gate-target-ladder', symbol] });
|
|
queryClient.invalidateQueries({ queryKey: ['scores', symbol] });
|
|
// Fetch re-runs the scanner → setups/confidence change. Refresh both the
|
|
// per-ticker trades (['trades', symbol]) and the Overview list (['trades']).
|
|
queryClient.invalidateQueries({ queryKey: ['trades'] });
|
|
|
|
if (invalidatePipelineReadiness) {
|
|
queryClient.invalidateQueries({ queryKey: ['admin', 'pipeline-readiness'] });
|
|
}
|
|
},
|
|
onError: (err: Error, arg: FetchArg) => {
|
|
const normalized = argSymbol(arg).toUpperCase();
|
|
const prefix = includeSymbolPrefix ? `${normalized}: ` : '';
|
|
addToast('error', `${prefix}${err.message || 'Failed to fetch data'}`);
|
|
},
|
|
});
|
|
}
|