Integrate React Query for data management and enhance Debug Preferences

- Added React Query for managing API calls related to assistants and voices.
- Introduced `useAssistantsQuery` and `useVoicesQuery` hooks for fetching data.
- Implemented mutations for creating, updating, and deleting voices using React Query.
- Integrated a global `QueryClient` for managing query states and configurations.
- Refactored components to utilize the new query hooks, improving data handling and performance.
- Added a Zustand store for managing debug preferences, including WebSocket URL and audio settings.
This commit is contained in:
Xin Wang
2026-03-02 22:50:57 +08:00
parent 70b4043f9b
commit eecde9f0fb
12 changed files with 247 additions and 120 deletions

59
web/services/queries.ts Normal file
View File

@@ -0,0 +1,59 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Voice } from '../types';
import {
createVoice,
deleteVoice,
fetchAssistants,
fetchVoices,
updateVoice,
} from './backendApi';
import { queryKeys } from './queryKeys';
export const useAssistantsQuery = () =>
useQuery({
queryKey: queryKeys.assistants,
queryFn: fetchAssistants,
});
export const useVoicesQuery = () =>
useQuery({
queryKey: queryKeys.voices,
queryFn: fetchVoices,
});
export const useCreateVoiceMutation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (payload: Partial<Voice>) => createVoice(payload),
onSuccess: (created) => {
queryClient.setQueryData<Voice[]>(queryKeys.voices, (prev = []) => [created, ...prev]);
},
});
};
export const useUpdateVoiceMutation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: Partial<Voice> }) => updateVoice(id, data),
onSuccess: (updated) => {
queryClient.setQueryData<Voice[]>(queryKeys.voices, (prev = []) =>
prev.map((voice) => (voice.id === updated.id ? updated : voice))
);
},
});
};
export const useDeleteVoiceMutation = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id: string) => {
await deleteVoice(id);
return id;
},
onSuccess: (deletedId) => {
queryClient.setQueryData<Voice[]>(queryKeys.voices, (prev = []) =>
prev.filter((voice) => voice.id !== deletedId)
);
},
});
};

View File

@@ -0,0 +1,12 @@
import { QueryClient } from '@tanstack/react-query';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30_000,
gcTime: 5 * 60_000,
retry: 1,
refetchOnWindowFocus: false,
},
},
});

View File

@@ -0,0 +1,4 @@
export const queryKeys = {
assistants: ['assistants'] as const,
voices: ['voices'] as const,
};