first commit
This commit is contained in:
148
frontend/src/hooks/useAdmin.ts
Normal file
148
frontend/src/hooks/useAdmin.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import * as adminApi from '../api/admin';
|
||||
import { useToast } from '../components/ui/Toast';
|
||||
|
||||
// ── Users ──
|
||||
|
||||
export function useUsers() {
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'users'],
|
||||
queryFn: () => adminApi.listUsers(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateUser() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
username: string;
|
||||
password: string;
|
||||
role: string;
|
||||
has_access: boolean;
|
||||
}) => adminApi.createUser(data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'users'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to create user');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateAccess() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ userId, hasAccess }: { userId: number; hasAccess: boolean }) =>
|
||||
adminApi.updateAccess(userId, hasAccess),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'users'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to update access');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useResetPassword() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ userId, password }: { userId: number; password: string }) =>
|
||||
adminApi.resetPassword(userId, password),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'users'] });
|
||||
addToast('success', 'Password reset successfully');
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to reset password');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ── Settings ──
|
||||
|
||||
export function useSettings() {
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'settings'],
|
||||
queryFn: () => adminApi.listSettings(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateSetting() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ key, value }: { key: string; value: string }) =>
|
||||
adminApi.updateSetting(key, value),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'settings'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to update setting');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ── Jobs ──
|
||||
|
||||
export function useJobs() {
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'jobs'],
|
||||
queryFn: () => adminApi.listJobs(),
|
||||
refetchInterval: 15_000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useToggleJob() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ jobName, enabled }: { jobName: string; enabled: boolean }) =>
|
||||
adminApi.toggleJob(jobName, enabled),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'jobs'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to toggle job');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useTriggerJob() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (jobName: string) => adminApi.triggerJob(jobName),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['admin', 'jobs'] });
|
||||
addToast('success', 'Job triggered successfully');
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to trigger job');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ── Data Cleanup ──
|
||||
|
||||
export function useCleanupData() {
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (olderThanDays: number) => adminApi.cleanupData(olderThanDays),
|
||||
onSuccess: (data) => {
|
||||
addToast('success', (data as { message: string }).message || 'Cleanup completed');
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to cleanup data');
|
||||
},
|
||||
});
|
||||
}
|
||||
22
frontend/src/hooks/useAuth.ts
Normal file
22
frontend/src/hooks/useAuth.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import * as authApi from '../api/auth';
|
||||
import { useAuthStore } from '../stores/authStore';
|
||||
|
||||
export function useLogin() {
|
||||
const storeLogin = useAuthStore((s) => s.login);
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ username, password }: { username: string; password: string }) =>
|
||||
authApi.login(username, password),
|
||||
onSuccess: (data) => {
|
||||
storeLogin(data.access_token);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useRegister() {
|
||||
return useMutation({
|
||||
mutationFn: ({ username, password }: { username: string; password: string }) =>
|
||||
authApi.register(username, password),
|
||||
});
|
||||
}
|
||||
26
frontend/src/hooks/useScores.ts
Normal file
26
frontend/src/hooks/useScores.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import * as scoresApi from '../api/scores';
|
||||
import { useToast } from '../components/ui/Toast';
|
||||
|
||||
export function useRankings() {
|
||||
return useQuery({
|
||||
queryKey: ['rankings'],
|
||||
queryFn: () => scoresApi.getRankings(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateWeights() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (weights: Record<string, number>) => scoresApi.updateWeights(weights),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['rankings'] });
|
||||
addToast('success', 'Weights updated successfully');
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to update weights');
|
||||
},
|
||||
});
|
||||
}
|
||||
40
frontend/src/hooks/useTickerDetail.ts
Normal file
40
frontend/src/hooks/useTickerDetail.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { getOHLCV } from '../api/ohlcv';
|
||||
import { getScores } from '../api/scores';
|
||||
import { getLevels } from '../api/sr-levels';
|
||||
import { getSentiment } from '../api/sentiment';
|
||||
import { getFundamentals } from '../api/fundamentals';
|
||||
|
||||
export function useTickerDetail(symbol: string) {
|
||||
const ohlcv = useQuery({
|
||||
queryKey: ['ohlcv', symbol],
|
||||
queryFn: () => getOHLCV(symbol),
|
||||
enabled: !!symbol,
|
||||
});
|
||||
|
||||
const scores = useQuery({
|
||||
queryKey: ['scores', symbol],
|
||||
queryFn: () => getScores(symbol),
|
||||
enabled: !!symbol,
|
||||
});
|
||||
|
||||
const srLevels = useQuery({
|
||||
queryKey: ['sr-levels', symbol],
|
||||
queryFn: () => getLevels(symbol),
|
||||
enabled: !!symbol,
|
||||
});
|
||||
|
||||
const sentiment = useQuery({
|
||||
queryKey: ['sentiment', symbol],
|
||||
queryFn: () => getSentiment(symbol),
|
||||
enabled: !!symbol,
|
||||
});
|
||||
|
||||
const fundamentals = useQuery({
|
||||
queryKey: ['fundamentals', symbol],
|
||||
queryFn: () => getFundamentals(symbol),
|
||||
enabled: !!symbol,
|
||||
});
|
||||
|
||||
return { ohlcv, scores, srLevels, sentiment, fundamentals };
|
||||
}
|
||||
40
frontend/src/hooks/useTickers.ts
Normal file
40
frontend/src/hooks/useTickers.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import * as tickersApi from '../api/tickers';
|
||||
import { useToast } from '../components/ui/Toast';
|
||||
|
||||
export function useTickers() {
|
||||
return useQuery({
|
||||
queryKey: ['tickers'],
|
||||
queryFn: () => tickersApi.list(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useAddTicker() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (symbol: string) => tickersApi.create(symbol),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['tickers'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to add ticker');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteTicker() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (symbol: string) => tickersApi.deleteTicker(symbol),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['tickers'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to delete ticker');
|
||||
},
|
||||
});
|
||||
}
|
||||
9
frontend/src/hooks/useTrades.ts
Normal file
9
frontend/src/hooks/useTrades.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import * as tradesApi from '../api/trades';
|
||||
|
||||
export function useTrades() {
|
||||
return useQuery({
|
||||
queryKey: ['trades'],
|
||||
queryFn: () => tradesApi.list(),
|
||||
});
|
||||
}
|
||||
40
frontend/src/hooks/useWatchlist.ts
Normal file
40
frontend/src/hooks/useWatchlist.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import * as watchlistApi from '../api/watchlist';
|
||||
import { useToast } from '../components/ui/Toast';
|
||||
|
||||
export function useWatchlist() {
|
||||
return useQuery({
|
||||
queryKey: ['watchlist'],
|
||||
queryFn: () => watchlistApi.list(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useAddToWatchlist() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (symbol: string) => watchlistApi.add(symbol),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['watchlist'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to add to watchlist');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useRemoveFromWatchlist() {
|
||||
const qc = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (symbol: string) => watchlistApi.remove(symbol),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['watchlist'] });
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
addToast('error', error.message || 'Failed to remove from watchlist');
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user