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.
This commit is contained in:
Jamie Pine
2026-01-25 12:39:56 -08:00
parent e5bfa4cbbe
commit c876fabcd4
@@ -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<SampleFormValues>({
@@ -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 (
<Dialog open={open} onOpenChange={onOpenChange}>
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Add Audio Sample</DialogTitle>
@@ -105,9 +147,23 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
}}
{...field}
/>
{selectedFile && (
<Button
type="button"
variant="outline"
onClick={handleTranscribe}
disabled={transcribe.isPending}
className="flex items-center gap-2"
>
<Mic className="h-4 w-4" />
{transcribe.isPending ? 'Transcribing...' : 'Transcribe'}
</Button>
)}
</div>
</FormControl>
<FormDescription>Supported formats: WAV, MP3, M4A</FormDescription>
<FormDescription>
Supported formats: WAV, MP3, M4A. Click "Transcribe" to automatically extract text from the audio.
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -135,7 +191,7 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
/>
<div className="flex gap-2 justify-end">
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
<Button type="button" variant="outline" onClick={() => handleOpenChange(false)}>
Cancel
</Button>
<Button type="submit" disabled={addSample.isPending}>