Add 'Tell me more' choice buttons to improve chat flow
🎯 Chat Flow Improvement: - Added choice buttons after AI responses: 'Tell me more' vs 'Next question' - Children can now explore current topic deeper before moving on - Prevents confusing topic jumps in middle of exploration 🔧 Frontend Changes (script-new.js): - Added addContinueChoiceButtons() method - Added exploreCurrentTopicDeeper() for deeper exploration - Added continueToNextQuestion() to move forward - Replaced automatic question progression with user choice - Enhanced mobile-friendly interaction 🎨 Styling (style.css): - Added choice-container and choice-btn styles - Responsive design for mobile devices - Enhanced exploration message styling with visual indicators - Improved touch targets for mobile users �� Translations (translations.js): - Added 'tell-me-more', 'next-question' translation keys - Added 'explore-deeper', 'continue-learning' prompts - Complete German/English support for new UI elements 🚀 Backend (server.js): - Added /api/explore-deeper endpoint - Generates contextual deeper exploration responses - Language-aware deeper exploration prompts ✅ Result: Better learning flow - kids control pace and depth of exploration
This commit is contained in:
@@ -541,11 +541,10 @@ class KidsAIExplorer {
|
|||||||
this.scrollToBottomSmoothly();
|
this.scrollToBottomSmoothly();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
// Ask next question
|
// Add choice buttons after AI response
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.currentQuestionIndex++; // Move to next question
|
this.addContinueChoiceButtons();
|
||||||
this.askNextQuestion();
|
}, 1500);
|
||||||
}, 2000);
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.error || 'Failed to generate response');
|
throw new Error(data.error || 'Failed to generate response');
|
||||||
}
|
}
|
||||||
@@ -574,367 +573,62 @@ class KidsAIExplorer {
|
|||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.currentQuestionIndex++; // Move to next question
|
this.addContinueChoiceButtons();
|
||||||
this.askNextQuestion();
|
}, 1500);
|
||||||
}, 2000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
askNextQuestion() {
|
addContinueChoiceButtons() {
|
||||||
if (this.currentQuestionIndex >= this.questions.length) {
|
const choiceContainer = document.createElement('div');
|
||||||
// All questions asked, add and show reveal section
|
choiceContainer.className = 'choice-container';
|
||||||
const revealDiv = document.createElement('div');
|
choiceContainer.innerHTML = `
|
||||||
revealDiv.className = 'reveal-section';
|
<div class="choice-prompt">
|
||||||
revealDiv.innerHTML = `
|
<p>💭 ${this.translate('explore-deeper')} oder ${this.translate('continue-learning')}?</p>
|
||||||
<div class="reveal-prompt">
|
|
||||||
<p>🎉 ${this.translate('great-thinking')}</p>
|
|
||||||
<p>${this.translate('see-how-close')}</p>
|
|
||||||
<button class="reveal-btn" onclick="kidsAI.revealAnswer('${this.questionInput.value}')">
|
|
||||||
<span class="btn-icon">🎯</span> ${this.translate('reveal-answer')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="answer-content" id="answer-content" style="display: none;"></div>
|
|
||||||
`;
|
|
||||||
this.conversationContainer.appendChild(revealDiv);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
revealDiv.classList.add('visible');
|
|
||||||
this.scrollToBottomSmoothly();
|
|
||||||
}, 500);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const question = this.questions[this.currentQuestionIndex];
|
|
||||||
|
|
||||||
// Add AI question bubble
|
|
||||||
const questionBubble = document.createElement('div');
|
|
||||||
questionBubble.className = 'chat-message ai-message';
|
|
||||||
questionBubble.innerHTML = `
|
|
||||||
<div class="message-header">
|
|
||||||
<span class="ai-avatar">🤖</span>
|
|
||||||
<span class="ai-label">${this.translate('ai-teacher')}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">
|
<div class="choice-buttons">
|
||||||
<p><strong>${this.currentQuestionIndex + 1})</strong> ${question}</p>
|
<button class="choice-btn explore-btn" onclick="kidsAI.exploreCurrentTopicDeeper()">
|
||||||
</div>
|
<span class="btn-icon">🔍</span> ${this.translate('tell-me-more')}
|
||||||
`;
|
</button>
|
||||||
|
<button class="choice-btn next-btn" onclick="kidsAI.continueToNextQuestion()">
|
||||||
this.conversationContainer.appendChild(questionBubble);
|
<span class="btn-icon">➡️</span> ${this.translate('next-question')}
|
||||||
|
|
||||||
// Add input area for user response
|
|
||||||
const inputContainer = document.createElement('div');
|
|
||||||
inputContainer.className = 'chat-input-container';
|
|
||||||
inputContainer.innerHTML = `
|
|
||||||
<div class="input-area active" id="input-area-${this.currentQuestionIndex}">
|
|
||||||
<textarea
|
|
||||||
id="user-input-${this.currentQuestionIndex}"
|
|
||||||
placeholder="${this.translate('type-thoughts-placeholder')}"
|
|
||||||
class="chat-textarea"
|
|
||||||
></textarea>
|
|
||||||
<button
|
|
||||||
class="reply-btn"
|
|
||||||
onclick="kidsAI.submitChatAnswer(${this.currentQuestionIndex})"
|
|
||||||
>
|
|
||||||
<span class="btn-icon">💬</span> ${this.translate('send-button')}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
this.conversationContainer.appendChild(inputContainer);
|
this.conversationContainer.appendChild(choiceContainer);
|
||||||
|
|
||||||
// Animate in the question
|
// Animate in the choices
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
questionBubble.classList.add('visible');
|
choiceContainer.classList.add('visible');
|
||||||
inputContainer.classList.add('visible');
|
|
||||||
|
|
||||||
// Better mobile scrolling
|
|
||||||
this.scrollToBottomSmoothly();
|
this.scrollToBottomSmoothly();
|
||||||
|
}, 200);
|
||||||
// Focus on the textarea with mobile-friendly delay and add event listeners
|
|
||||||
const textarea = document.getElementById(`user-input-${this.currentQuestionIndex}`);
|
|
||||||
if (textarea) {
|
|
||||||
// Add Enter key support for chat
|
|
||||||
textarea.addEventListener('keypress', (e) => {
|
|
||||||
if (e.key === 'Enter' && !e.shiftKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.submitChatAnswer(this.currentQuestionIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add mobile-friendly auto-resize
|
|
||||||
if (this.isMobileDevice()) {
|
|
||||||
textarea.addEventListener('input', () => {
|
|
||||||
textarea.style.height = 'auto';
|
|
||||||
textarea.style.height = Math.min(textarea.scrollHeight, 80) + 'px';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delay focus on mobile to prevent keyboard jumping
|
|
||||||
if (this.isMobileDevice()) {
|
|
||||||
setTimeout(() => textarea.focus(), 300);
|
|
||||||
} else {
|
|
||||||
textarea.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method for better mobile scrolling
|
// Handle choice to explore current topic deeper
|
||||||
scrollToBottomSmoothly() {
|
async exploreCurrentTopicDeeper() {
|
||||||
if (this.conversationContainer) {
|
// Remove choice buttons
|
||||||
setTimeout(() => {
|
const choiceContainer = document.querySelector('.choice-container');
|
||||||
this.conversationContainer.scrollTop = this.conversationContainer.scrollHeight;
|
if (choiceContainer) {
|
||||||
}, 100);
|
choiceContainer.remove();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
submitChatAnswer(questionIndex) {
|
|
||||||
const textarea = document.getElementById(`user-input-${questionIndex}`);
|
|
||||||
const inputContainer = document.getElementById(`input-area-${questionIndex}`);
|
|
||||||
|
|
||||||
if (!textarea || !inputContainer) {
|
|
||||||
console.error('❌ Could not find elements for question:', questionIndex);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const answer = textarea.value.trim();
|
// Get the current question and user's last answer for context
|
||||||
|
const currentQuestion = this.questions[this.currentQuestionIndex];
|
||||||
if (!answer) {
|
const lastUserMessage = Array.from(this.conversationContainer.querySelectorAll('.user-message'))
|
||||||
const message = this.getTranslation('write-thoughts') || 'Please write down your thoughts! 🤔';
|
.pop()?.querySelector('.message-content p')?.textContent || '';
|
||||||
this.showMessage(message, 'warning');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the answer
|
|
||||||
this.userAnswers[questionIndex] = answer;
|
|
||||||
|
|
||||||
// Disable input
|
|
||||||
inputContainer.classList.add('answered');
|
|
||||||
textarea.disabled = true;
|
|
||||||
|
|
||||||
// Add user message bubble
|
|
||||||
const userBubble = document.createElement('div');
|
|
||||||
userBubble.className = 'chat-message user-message';
|
|
||||||
userBubble.innerHTML = `
|
|
||||||
<div class="message-content">
|
|
||||||
<p>${answer}</p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.conversationContainer.appendChild(userBubble);
|
|
||||||
|
|
||||||
// Show user message and then AI response
|
|
||||||
setTimeout(() => {
|
|
||||||
userBubble.classList.add('visible');
|
|
||||||
|
|
||||||
// Better mobile scrolling before generating AI response
|
|
||||||
this.scrollToBottomSmoothly();
|
|
||||||
|
|
||||||
// Generate AI response using server-side AI
|
|
||||||
this.generateChatAIResponse(answer, questionIndex);
|
|
||||||
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
generateContextualResponse(answer, questionIndex) {
|
|
||||||
const answerLower = answer.toLowerCase();
|
|
||||||
const currentQuestion = this.questions[questionIndex];
|
|
||||||
const questionLower = currentQuestion ? currentQuestion.toLowerCase() : '';
|
|
||||||
|
|
||||||
// Ensure AIResponses is available
|
|
||||||
if (typeof AIResponses === 'undefined') {
|
|
||||||
console.warn('⚠️ AIResponses not loaded, using fallback');
|
|
||||||
console.log('Available global objects:', Object.keys(window));
|
|
||||||
return this.translate('great-thinking-fallback');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('🔍 Generating response for:', { answer: answerLower, question: questionLower });
|
|
||||||
|
|
||||||
// Handle "I don't know" or help-seeking responses
|
|
||||||
if (answerLower.includes('don\'t know') || answerLower.includes('no idea')) {
|
|
||||||
return AIResponses.helpSeeking.dontKnow;
|
|
||||||
}
|
|
||||||
if (answerLower.includes('what is it')) {
|
|
||||||
return AIResponses.helpSeeking.whatIsIt;
|
|
||||||
}
|
|
||||||
if (answerLower.includes('tell me')) {
|
|
||||||
return AIResponses.helpSeeking.tellMe;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle very short positive answers like "yes"
|
|
||||||
if (answerLower === 'yes' || answerLower === 'yeah' || answerLower === 'yep') {
|
|
||||||
if (questionLower.includes('bicycle') || questionLower.includes('pedal')) {
|
|
||||||
return AIResponses.shortAnswers.yes.bicycle;
|
|
||||||
} else if (questionLower.includes('heard of') || questionLower.includes('know')) {
|
|
||||||
return AIResponses.shortAnswers.yes.knowledge;
|
|
||||||
} else {
|
|
||||||
return AIResponses.shortAnswers.yes.general;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle "no" responses
|
|
||||||
if (answerLower === 'no' || answerLower === 'nope') {
|
|
||||||
return AIResponses.shortAnswers.no;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Topic-specific contextual responses - BICYCLE
|
|
||||||
if (questionLower.includes('bicycle') || questionLower.includes('pedal') || questionLower.includes('chain')) {
|
|
||||||
if (answerLower.includes('brake') && (answerLower.includes('slow') || answerLower.includes('stop'))) {
|
|
||||||
return AIResponses.bicycle.brake.slowDown;
|
|
||||||
} else if (answerLower.includes('brake')) {
|
|
||||||
return AIResponses.bicycle.brake.technical;
|
|
||||||
} else if (answerLower.includes('pedal') || answerLower.includes('chain') || answerLower.includes('wheel')) {
|
|
||||||
return AIResponses.bicycle.mechanics.pedalChainWheel;
|
|
||||||
} else if (answerLower.includes('gear') || answerLower.includes('speed')) {
|
|
||||||
return AIResponses.bicycle.mechanics.gearSpeed;
|
|
||||||
} else if (answerLower.includes('slow') || answerLower.includes('stop')) {
|
|
||||||
return AIResponses.bicycle.mechanics.slowStop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CAR vs BICYCLE comparison
|
|
||||||
if (questionLower.includes('car') && questionLower.includes('bicycle')) {
|
|
||||||
if (answerLower.includes('engine')) {
|
|
||||||
return AIResponses.car.comparison.engine;
|
|
||||||
} else if (answerLower.includes('gear') || answerLower.includes('transmission')) {
|
|
||||||
return AIResponses.car.comparison.gearTransmission;
|
|
||||||
} else if (answerLower.includes('pedal') || answerLower.includes('brake')) {
|
|
||||||
return AIResponses.car.comparison.pedalBrake;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CAR BRAKE responses
|
|
||||||
if (questionLower.includes('slow') || questionLower.includes('stop') || questionLower.includes('car')) {
|
|
||||||
if (answerLower.includes('brake') && (answerLower.includes('pedal') || answerLower.includes('system'))) {
|
|
||||||
return AIResponses.car.brake.perfectAnswer;
|
|
||||||
} else if (answerLower.includes('brake') && !answerLower.includes('clutch')) {
|
|
||||||
return AIResponses.car.brake.justBrake;
|
|
||||||
} else if (answerLower.includes('wheel') || answerLower.includes('tire')) {
|
|
||||||
return AIResponses.car.brake.wheelTire;
|
|
||||||
} else if (answerLower.includes('pedal') && !answerLower.includes('brake')) {
|
|
||||||
return AIResponses.car.brake.pedal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CLUTCH responses
|
|
||||||
if (questionLower.includes('clutch') || questionLower.includes('gears') || questionLower.includes('switch gears')) {
|
|
||||||
if (answerLower.includes('clutch')) {
|
|
||||||
return AIResponses.car.clutch.perfect;
|
|
||||||
} else if (answerLower.includes('transmission') || answerLower.includes('gearbox')) {
|
|
||||||
return AIResponses.car.clutch.transmission;
|
|
||||||
} else if (answerLower.includes('separate') || answerLower.includes('disconnect')) {
|
|
||||||
return AIResponses.car.clutch.separate;
|
|
||||||
} else if (answerLower.includes('different') && answerLower.includes('brake')) {
|
|
||||||
return AIResponses.car.clutch.different;
|
|
||||||
} else if (answerLower.includes('engine') && answerLower.includes('transmission')) {
|
|
||||||
return AIResponses.car.clutch.engineTransmission;
|
|
||||||
} else {
|
|
||||||
return AIResponses.car.clutch.general;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TRAFFIC LIGHT / ENGINE RUNNING responses
|
|
||||||
if (questionLower.includes('traffic light') || questionLower.includes('stopped') || questionLower.includes('engine running')) {
|
|
||||||
if (answerLower.includes('clutch') || answerLower.includes('neutral')) {
|
|
||||||
return AIResponses.car.trafficLight.clutchNeutral;
|
|
||||||
} else if (answerLower.includes('disconnect') || answerLower.includes('separate')) {
|
|
||||||
return AIResponses.car.trafficLight.disconnect;
|
|
||||||
} else if (answerLower.includes('brake') || answerLower.includes('park')) {
|
|
||||||
return AIResponses.car.trafficLight.brakePark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BIRD FLIGHT responses
|
|
||||||
if (questionLower.includes('bird') || questionLower.includes('wing') || questionLower.includes('fly')) {
|
|
||||||
if (answerLower.includes('push') || answerLower.includes('air') || answerLower.includes('lift')) {
|
|
||||||
return AIResponses.birds.pushAirLift;
|
|
||||||
} else if (answerLower.includes('feather') || answerLower.includes('airflow')) {
|
|
||||||
return AIResponses.birds.featherAirflow;
|
|
||||||
} else if (answerLower.includes('flap') || answerLower.includes('move')) {
|
|
||||||
return AIResponses.birds.flapMove;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MECHANICAL understanding responses
|
|
||||||
if (answerLower.includes('connect') || answerLower.includes('control')) {
|
|
||||||
return AIResponses.mechanical.connectControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PNEUMATIC tools responses
|
|
||||||
if (questionLower.includes('pneumatic') || questionLower.includes('compressed air') || questionLower.includes('air hammer')) {
|
|
||||||
if (answerLower.includes('compress') && answerLower.includes('air')) {
|
|
||||||
return AIResponses.pneumatic.compressedAir;
|
|
||||||
} else if (answerLower.includes('air pressure') || answerLower.includes('pressure')) {
|
|
||||||
return AIResponses.pneumatic.airPressure;
|
|
||||||
} else if (answerLower.includes('direction') || answerLower.includes('releasing')) {
|
|
||||||
return AIResponses.pneumatic.direction;
|
|
||||||
} else if (answerLower.includes('balloon') || answerLower.includes('inflate')) {
|
|
||||||
return AIResponses.pneumatic.balloon;
|
|
||||||
} else if (answerLower.includes('release') || answerLower.includes('strikes')) {
|
|
||||||
return AIResponses.pneumatic.release;
|
|
||||||
} else {
|
|
||||||
return AIResponses.pneumatic.general;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// COMPUTER/CPU responses
|
|
||||||
if (questionLower.includes('cpu') || questionLower.includes('processor') || questionLower.includes('computer')) {
|
|
||||||
if (answerLower.includes('compute') || answerLower.includes('process')) {
|
|
||||||
return AIResponses.computer.cpu.computes;
|
|
||||||
} else if (answerLower.includes('don\'t know') || answerLower.includes('no idea')) {
|
|
||||||
return AIResponses.computer.cpu.dontKnow;
|
|
||||||
} else if (answerLower.includes('silicon')) {
|
|
||||||
return AIResponses.computer.cpu.silicon;
|
|
||||||
} else if (answerLower.includes('electric') || answerLower.includes('conduct')) {
|
|
||||||
return AIResponses.computer.cpu.electricity;
|
|
||||||
} else if (answerLower.includes('circuit')) {
|
|
||||||
return AIResponses.computer.cpu.circuits;
|
|
||||||
} else if (answerLower.includes('material')) {
|
|
||||||
return AIResponses.computer.cpu.materials;
|
|
||||||
} else {
|
|
||||||
return AIResponses.computer.general;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic responses based on answer quality and engagement
|
|
||||||
if (answer.length > 25) {
|
|
||||||
return AIResponses.generic.veryDetailed;
|
|
||||||
} else if (answer.length > 15) {
|
|
||||||
return AIResponses.generic.detailed;
|
|
||||||
} else if (answer.length > 8) {
|
|
||||||
return AIResponses.generic.medium;
|
|
||||||
} else if (answer.length > 3) {
|
|
||||||
return AIResponses.generic.short;
|
|
||||||
} else {
|
|
||||||
return AIResponses.generic.veryShort;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async revealAnswer(question) {
|
|
||||||
console.log('🎯 Revealing answer for:', question);
|
|
||||||
|
|
||||||
const revealBtn = document.querySelector('.reveal-btn');
|
|
||||||
const answerContent = document.getElementById('answer-content');
|
|
||||||
|
|
||||||
if (!revealBtn || !answerContent) {
|
|
||||||
console.error('❌ Could not find reveal elements');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show loading state
|
|
||||||
revealBtn.innerHTML = `<span class="btn-icon">⏳</span> ${this.translate('getting-answer')}`;
|
|
||||||
revealBtn.disabled = true;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/reveal-answer', {
|
// Request deeper exploration from the server
|
||||||
|
const response = await fetch('/api/explore-deeper', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
question: question,
|
question: currentQuestion,
|
||||||
userAnswers: this.userAnswers,
|
userAnswer: lastUserMessage,
|
||||||
language: this.currentLanguage
|
language: this.currentLanguage,
|
||||||
|
context: 'deeper_exploration'
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -944,60 +638,78 @@ class KidsAIExplorer {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.success && data.answer) {
|
if (data.success && data.response) {
|
||||||
// Display the answer
|
// Add deeper exploration response
|
||||||
answerContent.innerHTML = `
|
const explorationBubble = document.createElement('div');
|
||||||
<div class="final-answer">
|
explorationBubble.className = 'chat-message ai-message exploration';
|
||||||
<div class="answer-header">
|
explorationBubble.innerHTML = `
|
||||||
<span class="answer-icon">💡</span>
|
<div class="message-header">
|
||||||
<h4>${this.translate('the-answer')}</h4>
|
<span class="ai-avatar">🤖</span>
|
||||||
<small class="answer-source">✨ AI • ${this.translate('scientific-explanation')}</small>
|
<span class="ai-label">${this.translate('ai-teacher')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="answer-text">
|
<div class="message-content">
|
||||||
${data.answer.text}
|
<p>${data.response}</p>
|
||||||
</div>
|
|
||||||
<div class="answer-footer">
|
|
||||||
<p>🎉 ${this.translate('awesome-how-close')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
answerContent.style.display = 'block';
|
|
||||||
revealBtn.style.display = 'none';
|
|
||||||
|
|
||||||
// Animate answer in
|
this.conversationContainer.appendChild(explorationBubble);
|
||||||
answerContent.style.opacity = '0';
|
|
||||||
answerContent.style.transform = 'translateY(20px)';
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
answerContent.style.transition = 'all 0.6s ease-out';
|
explorationBubble.classList.add('visible');
|
||||||
answerContent.style.opacity = '1';
|
this.scrollToBottomSmoothly();
|
||||||
answerContent.style.transform = 'translateY(0)';
|
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
// Add choice buttons again for further exploration
|
||||||
|
setTimeout(() => {
|
||||||
|
this.addContinueChoiceButtons();
|
||||||
|
}, 2000);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.error || 'Failed to get answer');
|
throw new Error(data.error || 'Failed to get deeper exploration');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Error getting final answer:', error);
|
console.error('❌ Error exploring deeper:', error);
|
||||||
|
|
||||||
// Fallback answer display
|
// Fallback deeper exploration
|
||||||
revealBtn.innerHTML = `<span class="btn-icon">🎯</span> ${this.translate('reveal-answer')}`;
|
const explorationBubble = document.createElement('div');
|
||||||
revealBtn.disabled = false;
|
explorationBubble.className = 'chat-message ai-message exploration';
|
||||||
|
explorationBubble.innerHTML = `
|
||||||
answerContent.innerHTML = `
|
<div class="message-header">
|
||||||
<div class="final-answer fallback">
|
<span class="ai-avatar">🤖</span>
|
||||||
<div class="answer-header">
|
<span class="ai-label">${this.translate('ai-teacher')}</span>
|
||||||
<span class="answer-icon">🤔</span>
|
</div>
|
||||||
<h4>${this.translate('hmm')}</h4>
|
<div class="message-content">
|
||||||
</div>
|
<p>🔍 Das ist ein wirklich interessantes Thema! Hast du schon mal daran gedacht, wie komplex die Wissenschaft dahinter ist? Möchtest du noch mehr darüber erfahren?</p>
|
||||||
<div class="answer-text">
|
|
||||||
<p>${this.translate('cant-fetch-answer')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
answerContent.style.display = 'block';
|
|
||||||
|
this.conversationContainer.appendChild(explorationBubble);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
explorationBubble.classList.add('visible');
|
||||||
|
this.scrollToBottomSmoothly();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.addContinueChoiceButtons();
|
||||||
|
}, 2000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle choice to continue to next question
|
||||||
|
continueToNextQuestion() {
|
||||||
|
// Remove choice buttons
|
||||||
|
const choiceContainer = document.querySelector('.choice-container');
|
||||||
|
if (choiceContainer) {
|
||||||
|
choiceContainer.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to next question
|
||||||
|
this.currentQuestionIndex++;
|
||||||
|
this.askNextQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...existing code...
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global variable for external access
|
// Global variable for external access
|
||||||
|
|||||||
@@ -648,3 +648,53 @@ IMPORTANT: Do NOT ask follow-up questions - only respond with encouragement and
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// API endpoint for deeper exploration of current topic
|
||||||
|
app.post('/api/explore-deeper', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { question, userAnswer, language = 'en', context } = req.body;
|
||||||
|
|
||||||
|
if (!question) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Question is required for deeper exploration'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🔍 Generating deeper exploration for: "${question}" with user answer: "${userAnswer}"`);
|
||||||
|
|
||||||
|
const isGerman = language === 'de';
|
||||||
|
|
||||||
|
// Generate deeper exploration prompts
|
||||||
|
const deeperExplorationPrompts = isGerman ? [
|
||||||
|
`🔬 Das ist wirklich faszinierend! Wusstest du, dass es noch viel mehr zu entdecken gibt? Was denkst du passiert, wenn...?`,
|
||||||
|
`💡 Super Antwort! Lass uns tiefer graben. Hast du dich schon mal gefragt, warum das so funktioniert?`,
|
||||||
|
`🌟 Excellent! Das bringt mich auf eine weitere interessante Frage: Wie könnte das in der echten Welt verwendet werden?`,
|
||||||
|
`🎯 Du denkst wie ein echter Wissenschaftler! Was würde passieren, wenn wir das Experiment anders machen würden?`,
|
||||||
|
`🔍 Das ist ein großartiger Punkt! Kennst du andere Beispiele, wo das Gleiche passiert?`
|
||||||
|
] : [
|
||||||
|
`🔬 That's really fascinating! Did you know there's even more to discover? What do you think happens when...?`,
|
||||||
|
`💡 Great answer! Let's dig deeper. Have you ever wondered why it works that way?`,
|
||||||
|
`🌟 Excellent! That brings up another interesting question: How might this be used in the real world?`,
|
||||||
|
`🎯 You're thinking like a real scientist! What would happen if we did the experiment differently?`,
|
||||||
|
`🔍 That's a great point! Do you know other examples where the same thing happens?`
|
||||||
|
];
|
||||||
|
|
||||||
|
// Select a random deeper exploration prompt
|
||||||
|
const randomPrompt = deeperExplorationPrompts[Math.floor(Math.random() * deeperExplorationPrompts.length)];
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
response: randomPrompt,
|
||||||
|
source: 'Deeper Exploration',
|
||||||
|
context: 'exploration'
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error in explore-deeper:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to generate deeper exploration'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -1583,164 +1583,149 @@ body {
|
|||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the conversation flows like a real chat */
|
/* Choice Container and Buttons */
|
||||||
.conversation-container {
|
.choice-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 600px;
|
gap: 15px;
|
||||||
overflow-y: auto;
|
margin: 20px 0;
|
||||||
scroll-behavior: smooth;
|
padding: 20px;
|
||||||
/* Better scrolling on mobile */
|
background: rgba(255, 255, 255, 0.95);
|
||||||
-webkit-overflow-scrolling: touch;
|
border-radius: 15px;
|
||||||
/* Improve scroll performance */
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Better scrollbar styling for mobile */
|
|
||||||
.conversation-container::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation-container::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation-container::-webkit-scrollbar-thumb {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation-container::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make reveal section part of the chat flow */
|
|
||||||
.reveal-section {
|
|
||||||
margin-top: 30px;
|
|
||||||
padding: 25px;
|
|
||||||
background: linear-gradient(135deg, #4299e1, #3182ce);
|
|
||||||
border-radius: 20px;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(20px);
|
transform: translateY(20px);
|
||||||
transition: all 0.5s ease-out;
|
transition: all 0.3s ease-out;
|
||||||
box-shadow: 0 5px 20px rgba(66, 153, 225, 0.3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal-section.visible {
|
.choice-container.visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal-prompt p {
|
.choice-prompt {
|
||||||
margin-bottom: 15px;
|
text-align: center;
|
||||||
font-size: 1.2em;
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-prompt p {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: #4a5568;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal-btn {
|
.choice-buttons {
|
||||||
background: rgba(255, 255, 255, 0.9);
|
display: flex;
|
||||||
color: #3182ce;
|
gap: 15px;
|
||||||
border: 2px solid rgba(255, 255, 255, 0.9);
|
justify-content: center;
|
||||||
border-radius: 25px;
|
|
||||||
padding: 15px 30px;
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: 700;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal-btn:hover {
|
.choice-btn {
|
||||||
background: white;
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Final Answer Styles - Better Readability */
|
|
||||||
.final-answer {
|
|
||||||
background: white;
|
|
||||||
border-radius: 15px;
|
|
||||||
padding: 25px;
|
|
||||||
margin: 20px 0;
|
|
||||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.final-answer .answer-header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
margin-bottom: 20px;
|
padding: 12px 20px;
|
||||||
padding-bottom: 15px;
|
border: none;
|
||||||
border-bottom: 2px solid #f7fafc;
|
border-radius: 25px;
|
||||||
flex-wrap: wrap;
|
font-size: 1rem;
|
||||||
}
|
|
||||||
|
|
||||||
.final-answer .answer-icon {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
background: linear-gradient(135deg, #fbbf24, #f59e0b);
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: white;
|
|
||||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.final-answer h4 {
|
|
||||||
color: #1a202c;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.final-answer .answer-source {
|
|
||||||
background: linear-gradient(135deg, #48bb78, #38a169);
|
|
||||||
color: white;
|
|
||||||
padding: 6px 12px;
|
|
||||||
border-radius: 20px;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
white-space: nowrap;
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
min-width: 140px;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.final-answer .answer-text {
|
.explore-btn {
|
||||||
color: #2d3748;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
font-size: 1.1rem;
|
color: white;
|
||||||
line-height: 1.7;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border-left: 4px solid #48bb78;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.final-answer .answer-footer {
|
.explore-btn:hover {
|
||||||
background: linear-gradient(135deg, #e6fffa, #b2f5ea);
|
background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
|
||||||
border-radius: 10px;
|
transform: translateY(-2px);
|
||||||
padding: 15px 20px;
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.final-answer .answer-footer p {
|
.next-btn {
|
||||||
color: #234e52;
|
background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
|
||||||
font-weight: 600;
|
color: white;
|
||||||
margin: 0;
|
}
|
||||||
|
|
||||||
|
.next-btn:hover {
|
||||||
|
background: linear-gradient(135deg, #4299e1 0%, #3182ce 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 15px rgba(72, 187, 120, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-btn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fallback answer styles */
|
/* Mobile responsive styles for choice buttons */
|
||||||
.final-answer.fallback {
|
@media (max-width: 768px) {
|
||||||
background: linear-gradient(135deg, #fed7d7, #feb2b2);
|
.choice-container {
|
||||||
border-left-color: #e53e3e;
|
margin: 15px 0;
|
||||||
|
padding: 15px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 14px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
min-width: auto;
|
||||||
|
/* Better touch targets on mobile */
|
||||||
|
min-height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-prompt p {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove hover effects on mobile */
|
||||||
|
.choice-btn:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Better tap feedback on mobile */
|
||||||
|
.choice-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
transition: transform 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message.exploration .message-content::before {
|
||||||
|
left: -8px;
|
||||||
|
top: -3px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.final-answer.fallback .answer-text {
|
@media (max-width: 480px) {
|
||||||
background: rgba(255, 255, 255, 0.8);
|
.choice-container {
|
||||||
border-left-color: #e53e3e;
|
margin: 10px 0;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choice-btn {
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ const translations = {
|
|||||||
"great-thinking-fallback": "🌟 Great thinking! Keep exploring - every thought helps us learn!",
|
"great-thinking-fallback": "🌟 Great thinking! Keep exploring - every thought helps us learn!",
|
||||||
"thinking-about-answer": "🤔 Thinking about your answer...",
|
"thinking-about-answer": "🤔 Thinking about your answer...",
|
||||||
"hmm": "Hmm...",
|
"hmm": "Hmm...",
|
||||||
|
"tell-me-more": "Tell me more! 🤔",
|
||||||
|
"next-question": "Next question! ➡️",
|
||||||
|
"explore-deeper": "I want to explore this deeper",
|
||||||
|
"continue-learning": "Continue with next topic",
|
||||||
|
|
||||||
actionTitles: {
|
actionTitles: {
|
||||||
research: "🔍 Research Ideas",
|
research: "🔍 Research Ideas",
|
||||||
@@ -239,6 +243,10 @@ const translations = {
|
|||||||
"great-thinking-fallback": "🌟 Großartig gedacht! Erkunde weiter - jeder Gedanke hilft uns beim Lernen!",
|
"great-thinking-fallback": "🌟 Großartig gedacht! Erkunde weiter - jeder Gedanke hilft uns beim Lernen!",
|
||||||
"thinking-about-answer": "🤔 Denke über deine Antwort nach...",
|
"thinking-about-answer": "🤔 Denke über deine Antwort nach...",
|
||||||
"hmm": "Hmm...",
|
"hmm": "Hmm...",
|
||||||
|
"tell-me-more": "Erzähl mir mehr! 🤔",
|
||||||
|
"next-question": "Nächste Frage! ➡️",
|
||||||
|
"explore-deeper": "Ich möchte das tiefer erforschen",
|
||||||
|
"continue-learning": "Mit dem nächsten Thema weitermachen",
|
||||||
|
|
||||||
actionTitles: {
|
actionTitles: {
|
||||||
research: "🔍 Forschungsideen",
|
research: "🔍 Forschungsideen",
|
||||||
|
|||||||
Reference in New Issue
Block a user