From c876fabcd4553570def6be09b4d4d478fd7c67a4 Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Sun, 25 Jan 2026 12:39:56 -0800 Subject: [PATCH] Enhance SampleUpload component with transcription functionality - Integrated transcription feature using the useTranscription hook. - Added a button to trigger audio transcription, displaying status during the process. - Updated form handling to reset on dialog close and improved user feedback with toast notifications. - Enhanced form description to clarify supported audio formats and transcription capabilities. --- .../components/VoiceProfiles/SampleUpload.tsx | 68 +++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/app/src/components/VoiceProfiles/SampleUpload.tsx b/app/src/components/VoiceProfiles/SampleUpload.tsx index 25a96041..90d2e068 100644 --- a/app/src/components/VoiceProfiles/SampleUpload.tsx +++ b/app/src/components/VoiceProfiles/SampleUpload.tsx @@ -21,7 +21,9 @@ import { import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { useToast } from '@/components/ui/use-toast'; -import { useAddSample } from '@/lib/hooks/useProfiles'; +import { useAddSample, useProfile } from '@/lib/hooks/useProfiles'; +import { useTranscription } from '@/lib/hooks/useTranscription'; +import { Mic } from 'lucide-react'; const sampleSchema = z.object({ file: z.instanceof(File, { message: 'Please select an audio file' }), @@ -41,6 +43,8 @@ interface SampleUploadProps { export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProps) { const addSample = useAddSample(); + const transcribe = useTranscription(); + const { data: profile } = useProfile(profileId); const { toast } = useToast(); const form = useForm({ @@ -50,6 +54,38 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp }, }); + const selectedFile = form.watch('file'); + + async function handleTranscribe() { + const file = form.getValues('file'); + if (!file) { + toast({ + title: 'No file selected', + description: 'Please select an audio file first.', + variant: 'destructive', + }); + return; + } + + try { + const language = profile?.language as 'en' | 'zh' | undefined; + const result = await transcribe.mutateAsync({ file, language }); + + form.setValue('referenceText', result.text, { shouldValidate: true }); + + toast({ + title: 'Transcription complete', + description: 'Audio has been transcribed successfully.', + }); + } catch (error) { + toast({ + title: 'Transcription failed', + description: error instanceof Error ? error.message : 'Failed to transcribe audio', + variant: 'destructive', + }); + } + } + async function onSubmit(data: SampleFormValues) { try { await addSample.mutateAsync({ @@ -63,8 +99,7 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp description: 'Audio sample has been added successfully.', }); - form.reset(); - onOpenChange(false); + handleOpenChange(false); } catch (error) { toast({ title: 'Error', @@ -74,8 +109,15 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp } } + function handleOpenChange(newOpen: boolean) { + if (!newOpen) { + form.reset(); + } + onOpenChange(newOpen); + } + return ( - + Add Audio Sample @@ -105,9 +147,23 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp }} {...field} /> + {selectedFile && ( + + )} - Supported formats: WAV, MP3, M4A + + Supported formats: WAV, MP3, M4A. Click "Transcribe" to automatically extract text from the audio. + )} @@ -135,7 +191,7 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp />
-