Files
gemini-nexus/src/hooks/useCloudAccounts.ts
T
Sujit BiswasandDraculabo e959ee346e fix: "Check Quota Now" button not refreshing UI after polling (#42)
* feat: add React Query hooks for managing cloud accounts and update the generated route tree.

* feat: implement React Query hooks for comprehensive cloud account management.

* fix(cloud-accounts): add error handling to force poll mutation

Add an onError handler to log failures when forcing a cloud monitor poll, improving debuggability.

* fix: add error handling for cloud account polling failure

Add error toast notification when force polling fails, providing localized error message to improve user feedback.

* refactor: remove error logging from force poll cloud monitor hook

The onError handler was removed as error handling is now managed at a higher level in the application. This simplifies the hook and prevents duplicate error logging.

* fix(localization): add missing pollFailed translation keys

Add missing English and Chinese translations for the 'pollFailed' error message used when quota polling fails for all accounts.

* fix(CloudAccountList): prevent duplicate force poll requests

Add guard clause to disable button while mutation is pending to avoid duplicate API calls.

* fix: ensure UI updates after cloud quota poll and refresh

* chore: remove "peer": true flags from package-lock.json

---------

Co-authored-by: Draculabo <[email protected]>
2026-01-27 04:38:24 +08:00

123 lines
3.2 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
listCloudAccounts,
addGoogleAccount,
deleteCloudAccount,
refreshAccountQuota,
} from '@/actions/cloud';
import { CloudAccount } from '@/types/cloudAccount';
export const QUERY_KEYS = {
cloudAccounts: ['cloudAccounts'],
};
export function useCloudAccounts() {
return useQuery<CloudAccount[]>({
queryKey: QUERY_KEYS.cloudAccounts,
queryFn: listCloudAccounts,
staleTime: 1000 * 60, // 1 minute
});
}
export function useAddGoogleAccount() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: addGoogleAccount,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
},
});
}
export function useDeleteCloudAccount() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: deleteCloudAccount,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
},
});
}
export function useRefreshQuota() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: refreshAccountQuota,
onSuccess: (updatedAccount: CloudAccount) => {
// Optimistically update
queryClient.setQueryData(QUERY_KEYS.cloudAccounts, (oldData: CloudAccount[] | undefined) => {
if (!oldData) return [updatedAccount];
return oldData.map((acc) => (acc.id === updatedAccount.id ? updatedAccount : acc));
});
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
},
});
}
import {
switchCloudAccount,
getAutoSwitchEnabled,
setAutoSwitchEnabled,
forcePollCloudMonitor,
} from '@/actions/cloud';
export function useSwitchCloudAccount() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: switchCloudAccount,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
queryClient.invalidateQueries({ queryKey: ['currentAccount'] });
},
});
}
export const AUTO_SWITCH_KEY = ['autoSwitchEnabled'];
export function useAutoSwitchEnabled() {
return useQuery<boolean>({
queryKey: AUTO_SWITCH_KEY,
queryFn: getAutoSwitchEnabled,
staleTime: Infinity, // Settings don't change often unless we change them
});
}
export function useSetAutoSwitchEnabled() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: setAutoSwitchEnabled,
onSuccess: (_, variables) => {
queryClient.setQueryData(AUTO_SWITCH_KEY, variables.enabled);
},
});
}
export function useForcePollCloudMonitor() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: forcePollCloudMonitor,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
},
});
}
import { syncLocalAccount } from '@/actions/cloud';
export function useSyncLocalAccount() {
const queryClient = useQueryClient();
return useMutation<CloudAccount | null, Error, void>({
mutationFn: syncLocalAccount,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.cloudAccounts });
},
});
}
import { startAuthFlow } from '@/actions/cloud';
export { startAuthFlow };