'use client'; import React, { useState, useEffect } from 'react'; import { IconButton, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions, Button, Box, Typography, CircularProgress, Alert, Chip, } from '@mui/material'; import MicIcon from '@mui/icons-material/Mic'; import MicOffIcon from '@mui/icons-material/MicOff'; import { useVoiceInput } from '@/hooks/useVoiceInput'; export interface VoiceInputButtonProps { onTranscript: (transcript: string) => void; onClassifiedIntent?: (result: any) => void; size?: 'small' | 'medium' | 'large'; variant?: 'icon' | 'fab'; } /** * Voice input button component * * Displays microphone button that opens dialog for voice recording. * Uses Web Speech API for real-time transcription. */ export function VoiceInputButton({ onTranscript, onClassifiedIntent, size = 'medium', variant = 'icon', }: VoiceInputButtonProps) { const [open, setOpen] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const [classificationResult, setClassificationResult] = useState(null); const { isListening, isSupported, transcript, error, usesFallback, startListening, stopListening, reset } = useVoiceInput(); // Auto-classify when we get a final transcript useEffect(() => { if (transcript && !isListening && !isProcessing) { classifyTranscript(transcript); } }, [transcript, isListening, isProcessing]); const handleOpen = () => { console.log('[VoiceButton] Opening dialog, isSupported:', isSupported, 'usesFallback:', usesFallback); if (!isSupported) { alert('Voice input is not supported in your browser. Please use Chrome, Edge, or Safari.'); return; } setOpen(true); reset(); setClassificationResult(null); }; const handleClose = () => { if (isListening) { stopListening(); } setOpen(false); reset(); setClassificationResult(null); }; const handleStartListening = () => { console.log('[VoiceButton] Starting listening, usesFallback:', usesFallback); reset(); setClassificationResult(null); startListening(); }; const handleStopListening = () => { stopListening(); }; const classifyTranscript = async (text: string) => { setIsProcessing(true); try { const response = await fetch('/api/voice/transcribe', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ text }), }); const data = await response.json(); if (response.ok && data.success) { setClassificationResult(data.classification); if (onClassifiedIntent) { onClassifiedIntent(data.classification); } } else { setClassificationResult({ error: true, message: data.message || 'Could not understand command', }); } } catch (error) { console.error('[Voice] Classification error:', error); setClassificationResult({ error: true, message: 'Failed to process command', }); } finally { setIsProcessing(false); } }; const handleUseTranscript = () => { if (transcript) { onTranscript(transcript); handleClose(); } }; const renderButton = () => { const icon = isListening ? : ; const title = isSupported ? 'Voice input' : 'Voice input not supported in this browser'; if (variant === 'fab') { return ( {icon} ); } return ( {icon} ); }; return ( <> {renderButton()} Voice Command {classificationResult && !classificationResult.error && ( )} {/* Microphone animation */} {isListening ? : } {/* Status text */} {isListening ? usesFallback ? 'Recording... Speak now' : 'Listening... Speak now' : 'Click the microphone to start'} {usesFallback && !isListening && !transcript && ( Using audio recording mode (iOS Safari) )} {/* Transcript */} {transcript && ( Transcript: {transcript} )} {/* Processing indicator */} {isProcessing && ( Processing command... )} {/* Classification result */} {classificationResult && !classificationResult.error && ( Understood: {classificationResult.intent} {classificationResult.structuredData && ( {JSON.stringify(classificationResult.structuredData, null, 2)} )} )} {/* Error messages */} {(error || (classificationResult && classificationResult.error)) && ( {error || classificationResult.message} )} {/* Examples */} {!transcript && !isListening && ( Example commands: • "Fed baby 120 ml"
• "Nursed on left breast for 15 minutes"
• "Changed wet diaper"
• "Baby napped for 45 minutes"
)}
{transcript && ( )}
); }