Big refactoring
Deploy / lint (push) Failing after 21s
Deploy / test (push) Has been skipped
Deploy / deploy (push) Has been skipped

This commit is contained in:
Dennis Thiessen
2026-03-03 15:20:18 +01:00
parent 181cfe6588
commit 0a011d4ce9
55 changed files with 6898 additions and 544 deletions
+88 -3
View File
@@ -1,6 +1,7 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import * as adminApi from '../api/admin';
import { useToast } from '../components/ui/Toast';
import type { TickerUniverse } from '../lib/types';
// ── Users ──
@@ -89,13 +90,93 @@ export function useUpdateSetting() {
});
}
export function useRecommendationSettings() {
return useQuery({
queryKey: ['admin', 'recommendation-settings'],
queryFn: () => adminApi.getRecommendationSettings(),
});
}
export function useUpdateRecommendationSettings() {
const qc = useQueryClient();
const { addToast } = useToast();
return useMutation({
mutationFn: (payload: Record<string, number>) =>
adminApi.updateRecommendationSettings(payload),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['admin', 'recommendation-settings'] });
addToast('success', 'Recommendation settings updated');
},
onError: (error: Error) => {
addToast('error', error.message || 'Failed to update recommendation settings');
},
});
}
export function useTickerUniverseSetting() {
return useQuery({
queryKey: ['admin', 'ticker-universe'],
queryFn: () => adminApi.getTickerUniverseSetting(),
});
}
export function useUpdateTickerUniverseSetting() {
const qc = useQueryClient();
const { addToast } = useToast();
return useMutation({
mutationFn: (universe: TickerUniverse) => adminApi.updateTickerUniverseSetting(universe),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['admin', 'ticker-universe'] });
addToast('success', 'Default ticker universe updated');
},
onError: (error: Error) => {
addToast('error', error.message || 'Failed to update default ticker universe');
},
});
}
export function useBootstrapTickers() {
const qc = useQueryClient();
const { addToast } = useToast();
return useMutation({
mutationFn: ({ universe, pruneMissing }: { universe: TickerUniverse; pruneMissing: boolean }) =>
adminApi.bootstrapTickers(universe, pruneMissing),
onSuccess: (result) => {
qc.invalidateQueries({ queryKey: ['tickers'] });
qc.invalidateQueries({ queryKey: ['admin', 'ticker-universe'] });
addToast(
'success',
`Bootstrap done: +${result.added}, existing ${result.already_tracked}, deleted ${result.deleted}`,
);
},
onError: (error: Error) => {
addToast('error', error.message || 'Failed to bootstrap tickers');
},
});
}
// ── Jobs ──
export function useJobs() {
return useQuery({
queryKey: ['admin', 'jobs'],
queryFn: () => adminApi.listJobs(),
refetchInterval: 15_000,
refetchInterval: (query) => {
const jobs = (query.state.data ?? []) as adminApi.JobStatus[];
const hasRunning = jobs.some((job) => job.running);
return hasRunning ? 2_000 : 15_000;
},
});
}
export function usePipelineReadiness() {
return useQuery({
queryKey: ['admin', 'pipeline-readiness'],
queryFn: () => adminApi.getPipelineReadiness(),
refetchInterval: 20_000,
});
}
@@ -121,9 +202,13 @@ export function useTriggerJob() {
return useMutation({
mutationFn: (jobName: string) => adminApi.triggerJob(jobName),
onSuccess: () => {
onSuccess: (result) => {
qc.invalidateQueries({ queryKey: ['admin', 'jobs'] });
addToast('success', 'Job triggered successfully');
if (result.status === 'triggered') {
addToast('success', result.message || 'Job triggered successfully');
return;
}
addToast('info', result.message || 'Job could not be triggered');
},
onError: (error: Error) => {
addToast('error', error.message || 'Failed to trigger job');