Initialize voicebox project with backend, frontend, and Tauri setup. Added configuration files, dependencies, and basic structure for components, hooks, and utilities. Included README and setup documentation for guidance.

This commit is contained in:
Jamie Pine
2026-01-25 02:19:06 -08:00
commit 01e3065692
166 changed files with 22764 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
# React Query hooks will be placed here
+15
View File
@@ -0,0 +1,15 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api/client';
import type { GenerationRequest } from '@/lib/api/types';
export function useGeneration() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: GenerationRequest) => apiClient.generateSpeech(data),
onSuccess: () => {
// Invalidate history to show new generation
queryClient.invalidateQueries({ queryKey: ['history'] });
},
});
}
+29
View File
@@ -0,0 +1,29 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api/client';
import type { HistoryQuery } from '@/lib/api/types';
export function useHistory(query?: HistoryQuery) {
return useQuery({
queryKey: ['history', query],
queryFn: () => apiClient.listHistory(query),
});
}
export function useGenerationDetail(generationId: string) {
return useQuery({
queryKey: ['history', generationId],
queryFn: () => apiClient.getGeneration(generationId),
enabled: !!generationId,
});
}
export function useDeleteGeneration() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (generationId: string) => apiClient.deleteGeneration(generationId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['history'] });
},
});
}
+98
View File
@@ -0,0 +1,98 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api/client';
import type { VoiceProfileCreate } from '@/lib/api/types';
export function useProfiles() {
return useQuery({
queryKey: ['profiles'],
queryFn: () => apiClient.listProfiles(),
});
}
export function useProfile(profileId: string) {
return useQuery({
queryKey: ['profiles', profileId],
queryFn: () => apiClient.getProfile(profileId),
enabled: !!profileId,
});
}
export function useCreateProfile() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: VoiceProfileCreate) => apiClient.createProfile(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['profiles'] });
},
});
}
export function useUpdateProfile() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ profileId, data }: { profileId: string; data: VoiceProfileCreate }) =>
apiClient.updateProfile(profileId, data),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ['profiles'] });
queryClient.invalidateQueries({
queryKey: ['profiles', variables.profileId],
});
},
});
}
export function useDeleteProfile() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (profileId: string) => apiClient.deleteProfile(profileId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['profiles'] });
},
});
}
export function useProfileSamples(profileId: string) {
return useQuery({
queryKey: ['profiles', profileId, 'samples'],
queryFn: () => apiClient.listProfileSamples(profileId),
enabled: !!profileId,
});
}
export function useAddSample() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
profileId,
file,
referenceText,
}: {
profileId: string;
file: File;
referenceText: string;
}) => apiClient.addProfileSample(profileId, file, referenceText),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: ['profiles', variables.profileId, 'samples'],
});
queryClient.invalidateQueries({
queryKey: ['profiles', variables.profileId],
});
},
});
}
export function useDeleteSample() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (sampleId: string) => apiClient.deleteProfileSample(sampleId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['profiles'] });
},
});
}
+14
View File
@@ -0,0 +1,14 @@
import { useQuery } from '@tanstack/react-query';
import { apiClient } from '@/lib/api/client';
import { useServerStore } from '@/stores/serverStore';
export function useServerHealth() {
const serverUrl = useServerStore((state) => state.serverUrl);
return useQuery({
queryKey: ['server', 'health', serverUrl],
queryFn: () => apiClient.getHealth(),
refetchInterval: 30000, // Check every 30 seconds
retry: 1,
});
}
+9
View File
@@ -0,0 +1,9 @@
import { useMutation } from '@tanstack/react-query';
import { apiClient } from '@/lib/api/client';
export function useTranscription() {
return useMutation({
mutationFn: ({ file, language }: { file: File; language?: 'en' | 'zh' }) =>
apiClient.transcribeAudio(file, language),
});
}