Spaces:
Runtime error
Runtime error
Update index.html
Browse files- index.html +105 -27
index.html
CHANGED
|
@@ -45,16 +45,6 @@
|
|
| 45 |
</style>
|
| 46 |
</head>
|
| 47 |
<body class="text-gray-800 flex flex-col items-center justify-center min-h-screen p-4">
|
| 48 |
-
<!-- Info Collection Modal -->
|
| 49 |
-
<div id="infoModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
| 50 |
-
<div class="bg-white p-6 rounded-lg shadow-lg max-w-sm w-full">
|
| 51 |
-
<h2 class="text-xl font-bold mb-4">Welcome! Let's Get Started</h2>
|
| 52 |
-
<input id="emailInput" type="email" class="w-full p-2 border rounded mb-4" placeholder="Enter your email" required>
|
| 53 |
-
<button id="submitInfoBtn" class="bg-blue-500 text-white px-4 py-2 rounded w-full">Submit</button>
|
| 54 |
-
<p id="errorMsg" class="text-red-500 mt-2 hidden"></p> <!-- Added for error display -->
|
| 55 |
-
</div>
|
| 56 |
-
</div>
|
| 57 |
-
|
| 58 |
<div class="avatar mb-4">
|
| 59 |
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
| 60 |
<circle cx="50" cy="50" r="45" fill="#fbbf24" stroke="#f59e0b" stroke-width="5"/>
|
|
@@ -101,14 +91,9 @@
|
|
| 101 |
const listenBtn = document.getElementById("listenBtn");
|
| 102 |
const stopBtn = document.getElementById("stopBtn");
|
| 103 |
const voiceSelect = document.getElementById("voiceSelect");
|
| 104 |
-
const infoModal = document.getElementById("infoModal");
|
| 105 |
-
const emailInput = document.getElementById("emailInput");
|
| 106 |
-
const submitInfoBtn = document.getElementById("submitInfoBtn");
|
| 107 |
-
const errorMsg = document.getElementById("errorMsg"); // Added for error display
|
| 108 |
let recognition;
|
| 109 |
let listening = false;
|
| 110 |
let currentMode = "emotional_support";
|
| 111 |
-
let userEmail = null;
|
| 112 |
|
| 113 |
const emotionColors = {
|
| 114 |
joy: ["bg-gradient-to-r from-yellow-200 to-yellow-300", "bg-gradient-to-r from-yellow-300 to-orange-200"],
|
|
@@ -120,20 +105,113 @@
|
|
| 120 |
neutral: ["bg-gradient-to-r from-gray-200 to-gray-300", "bg-gradient-to-r from-gray-300 to-slate-200"]
|
| 121 |
};
|
| 122 |
|
| 123 |
-
//
|
| 124 |
-
|
| 125 |
-
const
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
try {
|
| 133 |
-
const
|
| 134 |
method: "POST",
|
| 135 |
headers: { "Content-Type": "application/json" },
|
| 136 |
-
body: JSON.stringify({
|
| 137 |
});
|
| 138 |
-
const
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
</style>
|
| 46 |
</head>
|
| 47 |
<body class="text-gray-800 flex flex-col items-center justify-center min-h-screen p-4">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
<div class="avatar mb-4">
|
| 49 |
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
| 50 |
<circle cx="50" cy="50" r="45" fill="#fbbf24" stroke="#f59e0b" stroke-width="5"/>
|
|
|
|
| 91 |
const listenBtn = document.getElementById("listenBtn");
|
| 92 |
const stopBtn = document.getElementById("stopBtn");
|
| 93 |
const voiceSelect = document.getElementById("voiceSelect");
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
let recognition;
|
| 95 |
let listening = false;
|
| 96 |
let currentMode = "emotional_support";
|
|
|
|
| 97 |
|
| 98 |
const emotionColors = {
|
| 99 |
joy: ["bg-gradient-to-r from-yellow-200 to-yellow-300", "bg-gradient-to-r from-yellow-300 to-orange-200"],
|
|
|
|
| 105 |
neutral: ["bg-gradient-to-r from-gray-200 to-gray-300", "bg-gradient-to-r from-gray-300 to-slate-200"]
|
| 106 |
};
|
| 107 |
|
| 108 |
+
// Load chat history from localStorage
|
| 109 |
+
function loadHistory() {
|
| 110 |
+
const history = JSON.parse(localStorage.getItem("chatHistory") || "[]");
|
| 111 |
+
history.forEach(msg => appendMessage(msg.sender, msg.text, false));
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
// Save chat history to localStorage
|
| 115 |
+
function saveHistory() {
|
| 116 |
+
const messages = Array.from(chatBox.children).map(div => ({
|
| 117 |
+
sender: div.querySelector("strong").textContent.replace(":", ""),
|
| 118 |
+
text: div.textContent.split(": ")[1]
|
| 119 |
+
}));
|
| 120 |
+
localStorage.setItem("chatHistory", JSON.stringify(messages));
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
async function sendMessage(voiceConfirmed = false) {
|
| 124 |
+
const message = messageInput.value.trim();
|
| 125 |
+
if (!message) return;
|
| 126 |
+
|
| 127 |
+
if (!voiceConfirmed && recognition) {
|
| 128 |
+
if (!confirm("Send this voice message?")) return;
|
| 129 |
}
|
| 130 |
+
|
| 131 |
+
appendMessage("You", message);
|
| 132 |
+
messageInput.value = "";
|
| 133 |
+
showLoading(true);
|
| 134 |
+
|
| 135 |
try {
|
| 136 |
+
const res = await fetch("/chat", {
|
| 137 |
method: "POST",
|
| 138 |
headers: { "Content-Type": "application/json" },
|
| 139 |
+
body: JSON.stringify({ message, mode: currentMode, voice_tone: voiceSelect.value }),
|
| 140 |
});
|
| 141 |
+
const data = await res.json();
|
| 142 |
+
appendMessage("Assistant", data.reply);
|
| 143 |
+
updateBackground(data.emotion);
|
| 144 |
+
speak(data.reply);
|
| 145 |
+
saveHistory();
|
| 146 |
+
} catch (error) {
|
| 147 |
+
appendMessage("Assistant", "Oops, something went wrong. Please try again.");
|
| 148 |
+
} finally {
|
| 149 |
+
showLoading(false);
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
function appendMessage(sender, text, save = true) {
|
| 154 |
+
const div = document.createElement("div");
|
| 155 |
+
div.className = `message ${sender === "You" ? "text-right mb-2" : "text-left mb-2"}`;
|
| 156 |
+
div.innerHTML = `<strong>${sender}:</strong> ${text}`;
|
| 157 |
+
chatBox.appendChild(div);
|
| 158 |
+
chatBox.scrollTop = chatBox.scrollHeight;
|
| 159 |
+
if (save) saveHistory();
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
function updateBackground(emotion) {
|
| 163 |
+
const colors = emotionColors[emotion.toLowerCase()] || emotionColors["neutral"];
|
| 164 |
+
const randomColor = colors[Math.floor(Math.random() * colors.length)];
|
| 165 |
+
document.body.className = `transition-all min-h-screen flex flex-col items-center justify-center p-4 ${randomColor}`;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
function speak(text) {
|
| 169 |
+
if ("speechSynthesis" in window) {
|
| 170 |
+
const utterance = new SpeechSynthesisUtterance(text);
|
| 171 |
+
const voices = speechSynthesis.getVoices();
|
| 172 |
+
// Map voice tone to available voices (basic mapping; adjust based on browser)
|
| 173 |
+
let selectedVoice = voices.find(v => v.name.toLowerCase().includes(voiceSelect.value.split(' ')[0]));
|
| 174 |
+
if (!selectedVoice) selectedVoice = voices[0]; // Fallback
|
| 175 |
+
utterance.voice = selectedVoice;
|
| 176 |
+
utterance.rate = 0.8; // Calm pace
|
| 177 |
+
utterance.pitch = 1;
|
| 178 |
+
speechSynthesis.speak(utterance);
|
| 179 |
+
} else {
|
| 180 |
+
alert("Speech synthesis not supported in your browser.");
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
function startListening() {
|
| 185 |
+
if (!("webkitSpeechRecognition" in window)) {
|
| 186 |
+
alert("Speech recognition not supported in your browser.");
|
| 187 |
+
return;
|
| 188 |
+
}
|
| 189 |
+
recognition = new webkitSpeechRecognition();
|
| 190 |
+
recognition.continuous = false;
|
| 191 |
+
recognition.interimResults = false;
|
| 192 |
+
recognition.lang = "en-US";
|
| 193 |
+
|
| 194 |
+
recognition.onstart = () => {
|
| 195 |
+
listening = true;
|
| 196 |
+
listenBtn.disabled = true;
|
| 197 |
+
stopBtn.disabled = false;
|
| 198 |
+
appendMessage("System", "Listening...");
|
| 199 |
+
};
|
| 200 |
+
|
| 201 |
+
recognition.onresult = (event) => {
|
| 202 |
+
const transcript = event.results[0][0].transcript;
|
| 203 |
+
appendMessage("You (voice)", transcript);
|
| 204 |
+
messageInput.value = transcript;
|
| 205 |
+
sendMessage(true); // Auto-send with confirmation
|
| 206 |
+
};
|
| 207 |
+
|
| 208 |
+
recognition.onend = () => {
|
| 209 |
+
listening = false;
|
| 210 |
+
listenBtn.disabled = false;
|
| 211 |
+
stopBtn.disabled = true;
|
| 212 |
+
};
|
| 213 |
+
|
| 214 |
+
recognition.start();
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
function stop
|