mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-10-03 00:55:14 -07:00
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:
@@ -21,7 +21,9 @@ import {
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { useToast } from '@/components/ui/use-toast';
|
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({
|
const sampleSchema = z.object({
|
||||||
file: z.instanceof(File, { message: 'Please select an audio file' }),
|
file: z.instanceof(File, { message: 'Please select an audio file' }),
|
||||||
@@ -41,6 +43,8 @@ interface SampleUploadProps {
|
|||||||
|
|
||||||
export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProps) {
|
export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProps) {
|
||||||
const addSample = useAddSample();
|
const addSample = useAddSample();
|
||||||
|
const transcribe = useTranscription();
|
||||||
|
const { data: profile } = useProfile(profileId);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const form = useForm<SampleFormValues>({
|
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) {
|
async function onSubmit(data: SampleFormValues) {
|
||||||
try {
|
try {
|
||||||
await addSample.mutateAsync({
|
await addSample.mutateAsync({
|
||||||
@@ -63,8 +99,7 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
|
|||||||
description: 'Audio sample has been added successfully.',
|
description: 'Audio sample has been added successfully.',
|
||||||
});
|
});
|
||||||
|
|
||||||
form.reset();
|
handleOpenChange(false);
|
||||||
onOpenChange(false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
@@ -74,8 +109,15 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleOpenChange(newOpen: boolean) {
|
||||||
|
if (!newOpen) {
|
||||||
|
form.reset();
|
||||||
|
}
|
||||||
|
onOpenChange(newOpen);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Add Audio Sample</DialogTitle>
|
<DialogTitle>Add Audio Sample</DialogTitle>
|
||||||
@@ -105,9 +147,23 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
|
|||||||
}}
|
}}
|
||||||
{...field}
|
{...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>
|
</div>
|
||||||
</FormControl>
|
</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 />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@@ -135,7 +191,7 @@ export function SampleUpload({ profileId, open, onOpenChange }: SampleUploadProp
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex gap-2 justify-end">
|
<div className="flex gap-2 justify-end">
|
||||||
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
<Button type="button" variant="outline" onClick={() => handleOpenChange(false)}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" disabled={addSample.isPending}>
|
<Button type="submit" disabled={addSample.isPending}>
|
||||||
|
|||||||
Reference in New Issue
Block a user