Files
vip-coordinator/frontend/src/hooks/useFlights.ts
kyle f2b3f34a72 refactor: code efficiency improvements (Issues #9-13, #15, #17-20)
Backend:
- Extract shared hard-delete authorization utility (#9)
- Extract Prisma include constants per entity (#11)
- Fix N+1 query pattern in events findAll (#12)
- Extract shared date utility functions (#13)
- Move vehicle utilization filtering to DB query (#15)
- Add ParseBooleanPipe for query params
- Add CurrentDriver decorator + ResolveDriverInterceptor (#20)

Frontend:
- Extract shared form utilities (toDatetimeLocal) and enum labels (#17)
- Replace browser confirm() with styled ConfirmModal (#18)
- Add centralized query-keys.ts constants (#19)
- Clean up unused imports, add useMemo where needed (#19)
- Standardize filter button styling across list pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 16:07:19 +01:00

67 lines
2.1 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '@/lib/api';
import { Flight, FlightBudget } from '@/types';
import toast from 'react-hot-toast';
import { queryKeys } from '@/lib/query-keys';
export function useFlights() {
return useQuery<Flight[]>({
queryKey: queryKeys.flights.all,
queryFn: async () => {
const { data } = await api.get('/flights');
return data;
},
refetchInterval: 60000, // Refresh from DB every 60s (free, no API cost)
});
}
export function useFlightBudget() {
return useQuery<FlightBudget>({
queryKey: queryKeys.flights.budget,
queryFn: async () => {
const { data } = await api.get('/flights/tracking/budget');
return data;
},
refetchInterval: 300000, // Every 5 min
});
}
export function useRefreshFlight() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (flightId: string) => {
const { data } = await api.post(`/flights/${flightId}/refresh`);
return data;
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: queryKeys.flights.all });
queryClient.invalidateQueries({ queryKey: queryKeys.flights.budget });
const status = data.status || 'unknown';
toast.success(`Flight updated: ${data.flightNumber} (${status})`);
},
onError: (error: any) => {
toast.error(error.response?.data?.message || 'Failed to refresh flight');
},
});
}
export function useRefreshActiveFlights() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
const { data } = await api.post('/flights/refresh-active');
return data;
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: queryKeys.flights.all });
queryClient.invalidateQueries({ queryKey: queryKeys.flights.budget });
toast.success(`Refreshed ${data.refreshed} flights (${data.budgetRemaining} API calls remaining)`);
},
onError: (error: any) => {
toast.error(error.response?.data?.message || 'Failed to refresh flights');
},
});
}