import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from "react"; import { FaMicrophone, FaMicrophoneSlash } from "react-icons/fa"; import './VoiceToText.scss' import { Capacitor } from "@capacitor/core"; import { SpeechRecognition } from "@capacitor-community/speech-recognition"; const VoiceToTextItemCard = forwardRef(({ setVoiceData, setprodQty, uomNames = [] }, ref) => { const [formData, setFormData] = useState({ product: "", qty: "", uom: "" }); const [transcript, setTranscript] = useState(""); const [isListening, setIsListening] = useState(false); const recognitionRef = useRef(null); const numberWords = { one: "1", two: "2", three: "3", four: "4", five: "5", six: "6", seven: "7", eight: "8", nine: "9", ten: "10" }; const listening = () => { console.log('Voice listening started'); // your voice start logic here if (isListening) { stopListening(); } else { startListening(); } }; useImperativeHandle(ref, () => ({ listening, })); const extractEntities = (text) => { if (typeof text !== "string") return { product: "", qty: "", uom: "" }; const lowerUomNames = (uomNames?.length ? uomNames : [ "kg", "kgs", "gram", "grams", "litre", "litres", "pack", "packs", "piece", "pieces" ]).map(u => u?.toLowerCase()); const words = text?.toLowerCase().split(/\s+/); const numberWords = { one: "1", two: "2", three: "3", four: "4", five: "5", six: "6", seven: "7", eight: "8", nine: "9", ten: "10" }; let qty = ""; let uom = ""; const productWords = []; for (let i = 0; i < words.length; i++) { const word = words[i]; const numVal = numberWords[word] || (isNaN(word) ? null : word); if (lowerUomNames.includes(word)) { uom = word; } else if (numVal) { qty = numVal; } else { productWords.push(word); } } const cleanProduct = productWords .filter(w => w !== qty && w !== uom) .join(" ") .trim(); return { product: cleanProduct, qty, uom }; }; useEffect(() => { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (!SpeechRecognition) { alert("Speech Recognition not supported"); return; } const recognition = new SpeechRecognition(); recognition.lang = "en-US"; recognition.continuous = false; recognition.onresult = (event) => { const spokenText = event.results[0][0].transcript; setTranscript(spokenText); const { product, qty, uom } = extractEntities(spokenText); setFormData({ product, qty, uom }); // Send to parent component if (setVoiceData) setVoiceData({ product, qty, uom }); if (setprodQty) setprodQty(qty); // optional }; recognition.onerror = (err) => console.error("Speech recognition error:", err); recognition.onend = () => { setIsListening(false); }; recognitionRef.current = recognition; }, [setVoiceData, setprodQty, uomNames]); // const startListening = () => { // recognitionRef.current?.start(); // setIsListening(true); // setTranscript(""); // setVoiceData && setVoiceData(""); // }; //sree coment line // const startListening = async () => { // try { // // Step 1: Check microphone access // const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); // stream.getTracks().forEach(track => track.stop()); // stop test mic stream // // Step 2: Try starting speech recognition // try { // recognitionRef.current?.start(); // setIsListening(true); // setTranscript(""); // if (setVoiceData) setVoiceData(""); // } catch (err) { // console.error("SpeechRecognition start error:", err); // alert("Unable to start speech recognition. Please check mic access or try again."); // setIsListening(false); // } // } catch (error) { // console.error("Microphone access denied or not available", error); // alert("Microphone not connected or permission denied."); // setIsListening(false); // } // }; const startListening = async () => { // Detect platform const platform = Capacitor.getPlatform(); if (platform === "web") { try { // Check microphone permission const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); stream.getTracks().forEach(track => track.stop()); recognitionRef.current?.start(); setIsListening(true); setTranscript(""); if (setVoiceData) setVoiceData(""); } catch (error) { console.error("Microphone access denied or not available", error); alert("Microphone not connected or permission denied."); setIsListening(false); } } else { // 📱 Capacitor Android / iOS try { const permission = await SpeechRecognition.requestPermissions(); if (!permission.speechRecognition) { alert("Speech recognition permission denied"); return; } setIsListening(true); const result = await SpeechRecognition.start({ language: "en-US", maxResults: 1, partialResults: false, }); if (result.matches && result.matches.length > 0) { const spokenText = result.matches[0]; setTranscript(spokenText); const { product, qty, uom } = extractEntities(spokenText); setFormData({ product, qty, uom }); if (setVoiceData) setVoiceData({ product, qty, uom }); if (setprodQty) setprodQty(qty); } setIsListening(false); } catch (err) { console.error(err); setIsListening(false); } } }; // const stopListening = () => { // if (recognitionRef.current) { // console.log("Stopping voice recognition..."); // recognitionRef.current.stop(); // } else { // console.warn("Recognition not initialized"); // } // setIsListening(false); // }; const stopListening = async () => { const platform = Capacitor.getPlatform(); try { if (platform === "web") { if (recognitionRef.current) { recognitionRef.current.stop(); console.log("Stopping voice recognition..."); } } else { await SpeechRecognition.stop(); console.log("Stopping native speech recognition..."); } } catch (error) { console.error("Error stopping speech recognition:", error); } setIsListening(false); }; return (
{isListening && (
)} {!isListening &&
Voice
}
{/*
Transcript: {transcript}
Product: {formData.product}
Qty: {formData.qty}
UOM: {formData.uom}
*/}
); }); export default VoiceToTextItemCard; // Style for dots (voice loader) const dotStyle = (delay = 0) => ({ width: "8px", height: "8px", borderRadius: "50%", background: "#ff1744", animation: "pulse-color 1s infinite ease-in-out", animationDelay: `${delay}s`, });