@broadreachalliance/q-assistant
Version:
A React-based chat window supporting both voice and text communication modes.
92 lines • 3.9 kB
JavaScript
import { useSpeech } from "../contexts";
import speakericon from "./icons/speaker.svg";
import React, { useState } from "react";
const VoiceSettings = () => {
const {
speechStatus,
setUtterence
} = useSpeech();
const [selectedVoice, setSelectedVoice] = useState(localStorage.getItem("selectedVoice"));
const [saved, setSaved] = useState(false);
const saveVoiceToLocalStorage = () => {
localStorage.setItem("selectedVoice", selectedVoice);
setSaved(true);
setTimeout(() => setSaved(false), 1000);
};
const speaksampleText = () => {
if (!selectedVoice) return;
const utterance = new SpeechSynthesisUtterance("Hello ! This is your selected voice.");
setUtterence(utterance);
const voice = speechStatus?.voices.find(v => v.name === selectedVoice);
if (voice) {
utterance.voice = voice;
}
window.speechSynthesis.speak(utterance);
};
return /*#__PURE__*/React.createElement("div", {
className: "flex flex-col p-6 max-w-lg mx-auto bg-white rounded-lg border border-gray-200"
}, /*#__PURE__*/React.createElement("h2", {
className: "text-xl font-bold mb-4"
}, "Assistant voice settings"), /*#__PURE__*/React.createElement("div", {
className: "mb-4"
}, /*#__PURE__*/React.createElement("label", {
htmlFor: "voiceSelect",
className: "block text-sm font-medium text-gray-700 mb-1"
}, "Select Voice"), /*#__PURE__*/React.createElement("div", {
className: "relative flex flex-row justify-between items-center"
}, /*#__PURE__*/React.createElement("div", {
className: "relative w-[88%]"
}, /*#__PURE__*/React.createElement("select", {
id: "voiceSelect",
value: selectedVoice,
onChange: event => setSelectedVoice(event.target.value),
className: "w-full p-3 pl-4 pr-10 border border-gray-300 rounded-lg text-sm shadow-sm focus:ring-0 focus:outline-none text-gray-700 appearance-none"
}, /*#__PURE__*/React.createElement("option", {
value: "",
disabled: true
}, "Select a voice"), speechStatus?.voices.map((voice, index) => /*#__PURE__*/React.createElement("option", {
key: index,
value: voice.name
}, voice.name, " (", voice.lang, ")"))), /*#__PURE__*/React.createElement("div", {
className: "absolute inset-y-0 right-3 flex items-center pointer-events-none text-gray-400"
}, /*#__PURE__*/React.createElement("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
className: "w-6 h-6"
}, /*#__PURE__*/React.createElement("path", {
d: "M6 9l6 6 6-6"
})))), selectedVoice && /*#__PURE__*/React.createElement("button", {
onClick: speaksampleText,
className: "flex items-center justify-center w-[10%] h-full bg-gray-100 text-gray-700 rounded-lg py-2 shadow-md hover:bg-gray-200 transition"
}, /*#__PURE__*/React.createElement("img", {
src: speakericon,
alt: "speak",
className: "w-6 h-6"
})))), /*#__PURE__*/React.createElement("button", {
onClick: saveVoiceToLocalStorage,
className: "w-[20%] bg-[#1f4745] ml-auto text-white text-sm py-2 rounded-md shadow-md hover:bg-[#2ba49e]"
}, saved ? /*#__PURE__*/React.createElement("div", {
className: "flex flex-row items-center justify-center gap-2"
}, /*#__PURE__*/React.createElement("svg", {
xmlns: "http://www.w3.org/2000/svg",
width: "18",
height: "18",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
class: "lucide lucide-circle-check-big-icon lucide-circle-check-big"
}, /*#__PURE__*/React.createElement("path", {
d: "M21.801 10A10 10 0 1 1 17 3.335"
}), /*#__PURE__*/React.createElement("path", {
d: "m9 11 3 3L22 4"
})), "Saved") : "Save"));
};
export default VoiceSettings;