Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>TAJ HOTEL CHATBOT</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet"> | |
| <script src="https://code.responsivevoice.org/responsivevoice.js?key=q1DbMp6Z"></script> | |
| <style> | |
| :root { | |
| --primary-color: #007bff; /* Default blue */ | |
| --bot-message-bg: #f0f2f5; /* Light Gray */ | |
| --user-message-bg: #007bff; /* User Blue */ | |
| --user-message-text: #fff; /* User Message White */ | |
| --accent-color: #6a0dad; /* Default Purple */ | |
| --background-color: #fff; /* Default Background White */ | |
| --shadow-color: rgba(0, 0, 0, 0.2); /* Default Shadow */ | |
| --input-bg: #f0f2f5; /* Default Input Background */ | |
| --input-border: #ccc; /* Default Input Border */ | |
| } | |
| /* Themes */ | |
| .theme-calm-azure { | |
| --background-color: #E3F2FD; | |
| --bot-message-bg: #BBDEFB; | |
| --user-message-bg: #2196F3; | |
| --user-message-text: #FFFFFF; | |
| --input-bg: #FFFFFF; | |
| --input-border: #BDBDBD; | |
| --accent-color: #1976D2; | |
| } | |
| .theme-elegant-charcoal { | |
| --background-color: #263238; | |
| --bot-message-bg: #37474F; | |
| --user-message-bg: #FF5722; | |
| --user-message-text: #FFFFFF; | |
| --input-bg: #455A64; | |
| --input-border: #CFD8DC; | |
| --accent-color: #FF9800; | |
| } | |
| .theme-fresh-greenery { | |
| --background-color: #E8F5E9; | |
| --bot-message-bg: #C8E6C9; | |
| --user-message-bg: #4CAF50; | |
| --user-message-text: #FFFFFF; | |
| --input-bg: #FFFFFF; | |
| --input-border: #A5D6A7; | |
| --accent-color: #388E3C; | |
| } | |
| .theme-soft-lavender { | |
| --background-color: #F3E5F5; | |
| --bot-message-bg: #E1BEE7; | |
| --user-message-bg: #9C27B0; | |
| --user-message-text: #FFFFFF; | |
| --input-bg: #FFFFFF; | |
| --input-border: #D1C4E9; | |
| --accent-color: #7B1FA2; | |
| } | |
| .theme-bright-summer { | |
| --background-color: #FFEB3B; | |
| --bot-message-bg: #FFF9C4; | |
| --user-message-bg: #F44336; | |
| --user-message-text: #FFFFFF; | |
| --input-bg: #FFFFFF; | |
| --input-border: #FBC02D; | |
| --accent-color: #C62828; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| background-color: var(--background-color); | |
| transition: background 0.5s ease; | |
| overflow: hidden; /* Prevent scroll on body */ | |
| } | |
| .container { | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| width: 100%; | |
| overflow: hidden; /* Prevent scroll on container */ | |
| } | |
| /* Header */ | |
| .header { | |
| background: var(--accent-color); | |
| color: #fff; | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| text-align: center; | |
| padding: 20px; | |
| box-shadow: 0 4px 8px var(--shadow-color); | |
| position: relative; | |
| z-index: 1000; | |
| } | |
| /* Chatbox */ | |
| .chat-box { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| overflow-y: auto; | |
| padding: 20px; | |
| background: linear-gradient(to bottom right, #f5f7fa, #c3cfe2); | |
| border-radius: 10px; | |
| margin: 20px; | |
| box-shadow: 0 4px 8px var(--shadow-color); | |
| position: relative; | |
| z-index: 10; | |
| } | |
| .message { | |
| max-width: 75%; | |
| padding: 12px 18px; | |
| border-radius: 20px; | |
| box-shadow: 0 3px 6px var(--shadow-color); | |
| margin-bottom: 10px; | |
| opacity: 0; | |
| animation: fadeIn 0.3s forwards; /* Changed to forwards for delay effect */ | |
| } | |
| .user-message { | |
| align-self: flex-end; | |
| background: var(--user-message-bg); | |
| color: var(--user-message-text); | |
| border-radius: 15px 20px 20px 20px; | |
| animation: slideInRight 0.5s forwards; /* Sliding effect on user message */ | |
| } | |
| .bot-message { | |
| align-self: flex-start; | |
| background: var(--bot-message-bg); | |
| color: #333; | |
| border-radius: 20px 15px 20px 20px; | |
| animation: slideInLeft 0.5s forwards; /* Sliding effect on bot message */ | |
| } | |
| /* Footer */ | |
| .footer { | |
| background: #ffffff; | |
| padding: 15px; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| box-shadow: 0 -4px 8px var(--shadow-color); | |
| position: relative; | |
| z-index: 1000; | |
| } | |
| .footer input[type="text"] { | |
| width: 75%; | |
| padding: 15px; | |
| border: 1px solid var(--input-border); | |
| border-radius: 20px; | |
| margin-right: 10px; | |
| box-shadow: 0 2px 4px var(--shadow-color); | |
| transition: border 0.3s, box-shadow 0.3s; /* Added shadow transition */ | |
| background-color: var(--input-bg); | |
| outline: none; | |
| } | |
| .footer input[type="text"]:focus { | |
| border-color: var(--accent-color); | |
| box-shadow: 0 0 10px var(--accent-color); | |
| } | |
| button { | |
| background: var(--accent-color); | |
| color: #fff; | |
| border: none; | |
| padding: 10px 20px; | |
| border-radius: 20px; | |
| font-size: 1rem; | |
| cursor: pointer; | |
| box-shadow: 0 4px 10px var(--shadow-color); | |
| transition: background 0.3s ease, transform 0.2s ease, box-shadow 0.2s ease; | |
| } | |
| button:hover { | |
| background: #4b0082; | |
| transform: scale(1.05); | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); /* Shadow effect on hover */ | |
| } | |
| /* Settings */ | |
| .settings { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 10px; | |
| background: #f0f2f5; | |
| box-shadow: 0 2px 5px var(--shadow-color); | |
| position: relative; | |
| z-index: 1000; | |
| } | |
| .color-picker, | |
| .theme-toggle { | |
| display: flex; | |
| align-items: center; | |
| position:relative; | |
| } | |
| .color-circle { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| margin: 0 5px; | |
| cursor: pointer; | |
| box-shadow: 0 2px 5px var(--shadow-color); | |
| transition: transform 0.3s; /* Adding circle hover effect */ | |
| } | |
| .color-circle:hover { | |
| transform: scale(1.2); /* Scale up on hover */ | |
| } | |
| /* Animations */ | |
| @keyframes fadeIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes slideInRight { | |
| from { | |
| opacity: 0; | |
| transform: translateX(100%); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| } | |
| @keyframes slideInLeft { | |
| from { | |
| opacity: 0; | |
| transform: translateX(-100%); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| } | |
| /* Background animation */ | |
| @keyframes backgroundAnimate { | |
| 0% { | |
| background-color: rgba(255, 255, 255, 0.05); | |
| } | |
| 50% { | |
| background-color: rgba(255, 255, 255, 0.1); | |
| } | |
| 100% { | |
| background-color: rgba(255, 255, 255, 0.05); | |
| } | |
| } | |
| /* VFX related styles */ | |
| .vfx { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| pointer-events: none; | |
| animation: backgroundAnimate 5s infinite; /* Continuously animate background */ | |
| z-index: 0; /* Background layer */ | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="vfx"></div> <!-- Background effects --> | |
| <div class="container"> | |
| <!-- Settings --> | |
| <div class="settings"> | |
| <div class="theme-toggle"> | |
| <label for="theme-select">Select Theme:</label> | |
| <select id="theme-select"> | |
| <option value="default">Default</option> | |
| <option value="calm-azure">Calm Azure</option> | |
| <option value="elegant-charcoal">Elegant Charcoal</option> | |
| <option value="fresh-greenery">Fresh Greenery</option> | |
| <option value="soft-lavender">Soft Lavender</option> | |
| <option value="bright-summer">Bright Summer</option> | |
| </select> | |
| </div> | |
| <div> | |
| <!-- Language dropdown --> | |
| <label for="language-select">Select Language:</label> | |
| <select id="language-select"> | |
| <option value="english">English</option> | |
| <option value="hindi">Hindi</option> | |
| <option value="bengali">Bengali</option> | |
| <option value="telugu">Telugu</option> | |
| <option value="marathi">Marathi</option> | |
| <option value="tamil">Tamil</option> | |
| <option value="gujarati">Gujarati</option> | |
| <option value="kannada">Kannada</option> | |
| <option value="malayalam">Malayalam</option> | |
| <option value="punjabi">Punjabi</option> | |
| <option value="odia">Odia</option> | |
| <option value="urdu">Urdu</option> | |
| <option value="assamese">Assamese</option> | |
| <option value="sanskrit">Sanskrit</option> | |
| <option value="arabic">Arabic</option> | |
| <option value="chinese">Chinese</option> | |
| <option value="dutch">Dutch</option> | |
| <option value="french">French</option> | |
| <option value="filipino">Filipino</option> | |
| <option value="greek">Greek</option> | |
| <option value="indonesian">Indonesian</option> | |
| <option value="italian">Italian</option> | |
| <option value="japanese">Japanese</option> | |
| <option value="korean">Korean</option> | |
| <option value="latin">Latin</option> | |
| <option value="nepali">Nepali</option> | |
| <option value="portuguese">Portuguese</option> | |
| <option value="romanian">Romanian</option> | |
| <option value="russian">Russian</option> | |
| <option value="spanish">Spanish</option> | |
| <option value="swedish">Swedish</option> | |
| <option value="thai">Thai</option> | |
| <option value="ukrainian">Ukrainian</option> | |
| <option value="turkish">Turkish</option> | |
| </select> | |
| </div> | |
| <div class="color-picker"> | |
| <label>Accent Color:</label> | |
| <div class="color-circle" style="background-color: #6a0dad;" onclick="changeColor('#6a0dad')"></div> | |
| <div class="color-circle" style="background-color: #ff4500;" onclick="changeColor('#ff4500')"></div> | |
| <div class="color-circle" style="background-color: #007bff;" onclick="changeColor('#007bff')"></div> | |
| <div class="color-circle" style="background-color: #28a745;" onclick="changeColor('#28a745')"></div> | |
| </div> | |
| </div> | |
| <!-- Header --> | |
| <div class="header">JNJ SOLUTIONS CHATBOT</div> | |
| <!-- Chatbox --> | |
| <div class="chat-box" id="chat-box"></div> | |
| <!-- Footer --> | |
| <div class="footer"> | |
| <input type="text" id="user-input" placeholder="Type your message..." /> | |
| <button id="send-btn">Send</button> | |
| <button id="voice-btn">🎤 Start Voice Input</button> | |
| </div> | |
| </div> | |
| <script> | |
| const chatBox = document.getElementById('chat-box'); | |
| const voiceBtn = document.getElementById('voice-btn'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const userInput = document.getElementById('user-input'); | |
| const themeSelect = document.getElementById('theme-select'); | |
| const languageSelect = document.getElementById('language-select'); | |
| // Add message to chatbox | |
| function addMessage(sender, text) { | |
| const msgDiv = document.createElement('div'); | |
| msgDiv.classList.add('message', sender); | |
| msgDiv.textContent = text; | |
| chatBox.appendChild(msgDiv); | |
| chatBox.scrollTop = chatBox.scrollHeight; // Scroll to the bottom of the chat | |
| } | |
| // Initialize speech recognition | |
| const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)(); | |
| function setRecognitionLanguage() { | |
| const selectedLanguage = languageSelect.value; | |
| switch (selectedLanguage) { | |
| case 'telugu': recognition.lang = 'te-IN'; break; | |
| case 'hindi': recognition.lang = 'hi-IN'; break; | |
| case 'bengali': recognition.lang = 'bn-IN'; break; | |
| case 'marathi': recognition.lang = 'mr-IN'; break; | |
| case 'tamil': recognition.lang = 'ta-IN'; break; | |
| case 'gujarati': recognition.lang = 'gu-IN'; break; | |
| case 'kannada': recognition.lang = 'kn-IN'; break; | |
| case 'malayalam': recognition.lang = 'ml-IN'; break; | |
| case 'punjabi': recognition.lang = 'pa-IN'; break; | |
| case 'odia': recognition.lang = 'or-IN'; break; | |
| case 'urdu': recognition.lang = 'ur-IN'; break; | |
| case 'assamese': recognition.lang = 'as-IN'; break; | |
| case 'sanskrit': recognition.lang = 'sa-IN'; break; | |
| case 'arabic': recognition.lang = 'ar-SA'; break; | |
| case 'chinese': recognition.lang = 'zh-CN'; break; | |
| case 'dutch': recognition.lang = 'nl-NL'; break; | |
| case 'french': recognition.lang = 'fr-FR'; break; | |
| case 'filipino': recognition.lang = 'fil-PH'; break; | |
| case 'greek': recognition.lang = 'el-GR'; break; | |
| case 'indonesian': recognition.lang = 'id-ID'; break; | |
| case 'italian': recognition.lang = 'it-IT'; break; | |
| case 'japanese': recognition.lang = 'ja-JP'; break; | |
| case 'korean': recognition.lang = 'ko-KR'; break; | |
| case 'latin': recognition.lang = 'la'; break; | |
| case 'nepali': recognition.lang = 'ne-NP'; break; | |
| case 'portuguese': recognition.lang = 'pt-PT'; break; | |
| case 'romanian': recognition.lang = 'ro-RO'; break; | |
| case 'russian': recognition.lang = 'ru-RU'; break; | |
| case 'spanish': recognition.lang = 'es-ES'; break; | |
| case 'swedish': recognition.lang = 'sv-SE'; break; | |
| case 'thai': recognition.lang = 'th-TH'; break; | |
| case 'ukrainian': recognition.lang = 'uk-UA'; break; | |
| case 'turkish': recognition.lang = 'tr-TR'; break; | |
| case 'english': | |
| default: recognition.lang = 'en-US'; break; // Default to English | |
| } | |
| } | |
| // Event listener for voice input button | |
| voiceBtn.addEventListener('click', () => { | |
| setRecognitionLanguage(); // Set language | |
| recognition.start(); // Start recognition | |
| }); | |
| // Handle results from speech recognition | |
| recognition.addEventListener('result', (e) => { | |
| const transcript = e.results[0][0].transcript; | |
| addMessage('user-message', transcript); | |
| sendUserMessage(transcript); | |
| }); | |
| // Handle errors in speech recognition | |
| recognition.addEventListener('error', (event) => { | |
| console.error("Speech recognition error", event); | |
| }); | |
| // Change the accent color | |
| function changeColor(color) { | |
| document.documentElement.style.setProperty('--accent-color', color); | |
| } | |
| // Change the theme | |
| function changeTheme(theme) { | |
| document.documentElement.classList.remove('theme-calm-azure', 'theme-elegant-charcoal', 'theme-fresh-greenery', 'theme-soft-lavender', 'theme-bright-summer'); | |
| if (theme !== 'default') { | |
| document.documentElement.classList.add('theme-' + theme); | |
| } | |
| } | |
| // Function to send user input and selected language to backend | |
| function sendUserMessage(message) { | |
| const selectedLanguage = languageSelect.value; // Get the selected language | |
| // Send the message and selected language to the backend | |
| fetch('/chat', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| message, | |
| language: selectedLanguage, // Include the selected language in the request body | |
| }), | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| const botResponse = data.response; | |
| addMessage('bot-message', botResponse); | |
| speakResponse(botResponse, selectedLanguage); | |
| }) | |
| .catch(error => { | |
| console.error("Error:", error); | |
| addMessage('bot-message', "Sorry, I couldn't process that."); | |
| }); | |
| } | |
| // // Function to get the voice list and match the language | |
| // function getVoiceForLanguage(lang) { | |
| // const voices = window.speechSynthesis.getVoices(); | |
| // const matchingVoice = voices.find(voice => voice.lang === lang); // Match exact language code | |
| // return matchingVoice || null; // Return first match or null if not found | |
| // } | |
| // // Text-to-Speech function | |
| // function speak(text, lang) { | |
| // const utterance = new SpeechSynthesisUtterance(text); | |
| // const selectedVoice = getVoiceForLanguage(lang); | |
| // if (selectedVoice) { | |
| // utterance.voice = selectedVoice; // Set the matching voice | |
| // utterance.lang = lang; // Set the language | |
| // } else { | |
| // console.warn(`No voice found for language: ${lang}. Falling back to default.`); | |
| // utterance.lang = 'en-US'; // Fallback to English | |
| // } | |
| // utterance.pitch = 1; // Set pitch | |
| // utterance.rate = 1; // Set rate | |
| // window.speechSynthesis.speak(utterance); // Speak the text | |
| // } | |
| // // Language Handling Function | |
| // function speakResponse(text, selectedLanguage) { | |
| // let lang; | |
| // switch (selectedLanguage) { | |
| // case 'hindi': lang = 'hi-IN'; break; | |
| // case 'bengali': lang = 'bn-IN'; break; | |
| // case 'telugu': lang = 'te-IN'; break; | |
| // case 'marathi': lang = 'mr-IN'; break; | |
| // case 'tamil': lang = 'ta-IN'; break; | |
| // case 'gujarati': lang = 'gu-IN'; break; | |
| // case 'kannada': lang = 'kn-IN'; break; | |
| // case 'malayalam': lang = 'ml-IN'; break; | |
| // case 'punjabi': lang = 'pa-IN'; break; | |
| // case 'odia': lang = 'or-IN'; break; | |
| // case 'urdu': lang = 'ur-IN'; break; | |
| // case 'assamese': lang = 'as-IN'; break; | |
| // case 'sanskrit': lang = 'sa-IN'; break; | |
| // default: lang = 'en-US'; break; // English (default) | |
| // } | |
| // speak(text, lang); // Call the speak function with the determined language | |
| // } | |
| // // Ensure voices are loaded before running the TTS | |
| // window.speechSynthesis.onvoiceschanged = () => { | |
| // const voices = window.speechSynthesis.getVoices(); | |
| // voices.forEach(voice => { | |
| // console.log(`Voice: ${voice.name}, Language: ${voice.lang}`); | |
| // }); | |
| // }; | |
| // // Function to initialize and fetch voices | |
| // function initializeVoices() { | |
| // return new Promise((resolve) => { | |
| // const voices = window.speechSynthesis.getVoices(); | |
| // if (voices.length) { | |
| // resolve(voices); | |
| // } else { | |
| // window.speechSynthesis.onvoiceschanged = () => { | |
| // resolve(window.speechSynthesis.getVoices()); | |
| // }; | |
| // } | |
| // }); | |
| // } | |
| // // Function to get the voice for a given language | |
| // function getVoiceForLanguage(lang, voices) { | |
| // const voice = voices.find(voice => voice.lang === lang); | |
| // if (voice) { | |
| // return voice; | |
| // } | |
| // console.warn(`No voice found for language: ${lang}.`); | |
| // return null; | |
| // } | |
| // // Text-to-Speech function | |
| // async function speak(text, lang) { | |
| // const voices = await initializeVoices(); | |
| // const selectedVoice = getVoiceForLanguage(lang, voices); | |
| // const utterance = new SpeechSynthesisUtterance(text); | |
| // if (selectedVoice) { | |
| // utterance.voice = selectedVoice; | |
| // utterance.lang = selectedVoice.lang; | |
| // } else { | |
| // console.warn(`Falling back to default language.`); | |
| // utterance.lang = 'en-US'; | |
| // } | |
| // utterance.pitch = 1; // Set pitch | |
| // utterance.rate = 1; // Set rate | |
| // window.speechSynthesis.speak(utterance); // Speak the text | |
| // } | |
| // Language Handling Function | |
| function speakResponse(text, selectedLanguage) { | |
| // Dictionary mapping specified languages to their respective voices | |
| const languageVoiceMap = { | |
| hindi: 'Hindi Female', | |
| tamil: 'Tamil Female', | |
| arabic: 'Arabic Female', | |
| chinese: 'Chinese Female', | |
| dutch: 'Dutch Female', | |
| french: 'French Female', | |
| filipino: 'Filipino Female', | |
| greek: 'Greek Female', | |
| indonesian: 'Indonesian Female', | |
| italian: 'Italian Female', | |
| japanese: 'Japanese Female', | |
| korean: 'Korean Female', | |
| portuguese: 'Portuguese Female', | |
| romanian: 'Romanian Female', | |
| russian: 'Russian Female', | |
| spanish: 'Spanish Female', | |
| swedish: 'Swedish Female', | |
| thai: 'Thai Female', | |
| ukrainian: 'Ukrainian Female', | |
| turkish: 'Turkish Female' | |
| }; | |
| // Get the voice for the selected language | |
| const voice = languageVoiceMap[selectedLanguage.toLowerCase()]; | |
| // Check if the language has a specified voice | |
| if (voice) { | |
| responsiveVoice.speak(text, voice); | |
| } else { | |
| // Use default behavior for unspecified languages | |
| responsiveVoice.speak(text); | |
| } | |
| } | |
| // // Test voices and log them | |
| // initializeVoices().then(voices => { | |
| // console.log("Available voices:"); | |
| // voices.forEach(voice => console.log(`Voice: ${voice.name}, Language: ${voice.lang}`)); | |
| // }); | |
| // Event listeners for buttons | |
| sendBtn.addEventListener('click', () => { | |
| const message = userInput.value.trim(); | |
| if (message) { | |
| addMessage('user-message', message); | |
| sendUserMessage(message); | |
| userInput.value = ''; // Clear input field after sending | |
| } | |
| }); | |
| // Handle pressing 'Enter' key for sending messages | |
| userInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| sendBtn.click(); // Trigger button click | |
| } | |
| }); | |
| // Update theme when selected from dropdown | |
| themeSelect.addEventListener('change', (e) => { | |
| changeTheme(e.target.value); | |
| }); | |
| </script> | |
| </body> | |
| </html> |