From 81d0da91c2dafdb88ea6b3473686b9788fd8b15f Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Jun 2025 13:15:14 +0200 Subject: [PATCH] interactive module activated --- html/kidsai/script.js | 297 +++++++++--------------------------------- html/kidsai/style.css | 133 +++++++++---------- 2 files changed, 126 insertions(+), 304 deletions(-) mode change 100755 => 100644 html/kidsai/script.js diff --git a/html/kidsai/script.js b/html/kidsai/script.js old mode 100755 new mode 100644 index a403038..1e363c4 --- a/html/kidsai/script.js +++ b/html/kidsai/script.js @@ -974,52 +974,55 @@ class KidsAIExplorer { } setupThinkingInteraction(stepDiv, stepId) { - const textarea = stepDiv.querySelector('.thinking-textarea'); - const shareBtn = stepDiv.querySelector('.share-thought-btn'); - const feedbackDiv = stepDiv.querySelector('.thinking-feedback'); + const textarea = stepDiv.querySelector(`textarea[data-step="${stepId}"]`); + const shareButton = stepDiv.querySelector(`button[data-step="${stepId}"]`); + const feedbackDiv = stepDiv.querySelector(`div[data-step="${stepId}"]`); - if (!textarea || !shareBtn || !feedbackDiv) return; - - // Show share button when user types something + if (!textarea || !shareButton || !feedbackDiv) return; + + // Show share button when text is entered textarea.addEventListener('input', () => { - const hasContent = textarea.value.trim().length > 0; - shareBtn.style.display = hasContent ? 'inline-block' : 'none'; + const hasText = textarea.value.trim().length > 0; + shareButton.style.display = hasText ? 'inline-block' : 'none'; }); - - // Handle Enter key to share thought - textarea.addEventListener('keypress', (e) => { - if (e.key === 'Enter' && !e.shiftKey && textarea.value.trim()) { - e.preventDefault(); - this.shareThought(stepId, textarea.value.trim(), shareBtn, feedbackDiv); - } - }); - - // Handle share button click - shareBtn.addEventListener('click', () => { + + // Handle sharing thoughts with AI + shareButton.addEventListener('click', () => { const thought = textarea.value.trim(); if (thought) { - this.shareThought(stepId, thought, shareBtn, feedbackDiv); + this.shareThoughtWithAI(stepId, thought, feedbackDiv, shareButton); + } + }); + + // Allow Enter key to share (but Shift+Enter for new line) + textarea.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + const thought = textarea.value.trim(); + if (thought) { + this.shareThoughtWithAI(stepId, thought, feedbackDiv, shareButton); + } } }); } - async shareThought(stepId, thought, shareBtn, feedbackDiv) { + async shareThoughtWithAI(stepId, thought, feedbackDiv, shareButton) { const currentQuestion = this.questionInput.value.trim(); try { // Show loading state - shareBtn.innerHTML = `⏳ ${this.currentLanguage === 'de' ? 'Wird geteilt...' : 'Sharing...'}`; - shareBtn.disabled = true; - - const response = await fetch('/api/think-response', { + shareButton.innerHTML = `⏳ ${this.currentLanguage === 'de' ? 'Denke...' : 'Thinking...'}`; + shareButton.disabled = true; + + const response = await fetch('/api/thinking-feedback', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ question: currentQuestion, - thought: thought, stepNumber: stepId, + userThought: thought, language: this.currentLanguage }) }); @@ -1031,244 +1034,70 @@ class KidsAIExplorer { const data = await response.json(); if (data.success) { - this.displayThinkingFeedback(data.feedback, feedbackDiv, shareBtn); + this.displayThinkingFeedback(feedbackDiv, data.feedback, shareButton); } else { throw new Error(data.error || 'Failed to get feedback'); } } catch (error) { - console.error('Error sharing thought:', error); + console.error('Error getting thinking feedback:', error); - // Show fallback feedback + // Show fallback positive feedback const fallbackFeedback = { - text: this.currentLanguage === 'de' - ? 'Toller Gedanke! Du denkst wirklich gut nach.' - : 'Great thought! You\'re really thinking well.', - type: 'fallback' + response: this.currentLanguage === 'de' + ? "Interessante Gedanken! Du denkst gut nach. πŸ‘" + : "Interesting thoughts! You're thinking well. πŸ‘", + type: 'positive' }; - this.displayThinkingFeedback(fallbackFeedback, feedbackDiv, shareBtn); + this.displayThinkingFeedback(feedbackDiv, fallbackFeedback, shareButton); } } - displayThinkingFeedback(feedback, feedbackDiv, shareBtn) { - // Hide share button and show feedback - shareBtn.style.display = 'none'; + displayThinkingFeedback(feedbackDiv, feedback, shareButton) { + // Determine feedback style based on type + const feedbackClass = feedback.type === 'positive' ? 'positive-feedback' : + feedback.type === 'neutral' ? 'neutral-feedback' : 'encouraging-feedback'; feedbackDiv.innerHTML = ` -
- - - +
+ +
`; + // Show feedback with animation feedbackDiv.style.display = 'block'; feedbackDiv.style.opacity = '0'; - feedbackDiv.style.transform = 'translateY(10px)'; + feedbackDiv.style.transform = 'translateY(-10px)'; - // Animate in setTimeout(() => { feedbackDiv.style.transition = 'all 0.4s ease-out'; feedbackDiv.style.opacity = '1'; feedbackDiv.style.transform = 'translateY(0)'; }, 100); - - // Scroll into view - feedbackDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); - } - // Update checkIfChildEngaged to also check for feedback received - checkIfChildEngaged() { - // Check if any of the thinking textareas have content or received feedback - const thinkingAreas = this.thinkingSteps.querySelectorAll('.step-thinking-space textarea'); - const feedbackAreas = this.thinkingSteps.querySelectorAll('.thinking-feedback[style*="block"]'); + // Update share button to "shared" state + shareButton.innerHTML = `βœ“ ${this.currentLanguage === 'de' ? 'Geteilt!' : 'Shared!'}`; + shareButton.disabled = false; + shareButton.style.background = 'rgba(76, 175, 80, 0.8)'; - for (let textarea of thinkingAreas) { - if (textarea.value.trim().length > 0) { - return true; + // Add option to share again after editing + const textarea = feedbackDiv.parentElement.querySelector('textarea'); + textarea.addEventListener('input', () => { + if (shareButton.innerHTML.includes('βœ“')) { + shareButton.innerHTML = `πŸ’­ ${this.currentLanguage === 'de' ? 'Neue Gedanken teilen' : 'Share New Thoughts'}`; + shareButton.style.background = ''; } - } - - // If child received any feedback, they've engaged - return feedbackAreas.length > 0; + }, { once: true }); } - - // ...existing code... } -// Initialize the application when DOM is loaded -document.addEventListener('DOMContentLoaded', () => { - console.log('DOM loaded, initializing KidsAI Explorer...'); - - // Hide loading screen immediately on page load - const loadingOverlay = document.getElementById('loading'); - if (loadingOverlay) { - loadingOverlay.classList.add('hidden'); - console.log('Loading overlay hidden on page load'); - } - - // Emergency fallback - hide loading after 1 second regardless - setTimeout(() => { - if (loadingOverlay && !loadingOverlay.classList.contains('hidden')) { - loadingOverlay.classList.add('hidden'); - console.log('Emergency: Loading overlay hidden by timeout'); - } - }, 1000); - - // Check if translations are loaded - if (typeof translations === 'undefined') { - console.error('Translations not loaded! Creating fallback...'); - window.translations = { - en: { - title: "KidsAI Explorer", - tagline: "Think, Learn, Discover Together!", - encouragements: ["Great question! You're thinking like a real scientist! πŸ”¬"], - thinkingFrameworks: { - general: { - steps: [ - { - title: "🎯 Let's break this down", - content: "What's the main thing you want to understand?" - } - ] - } - }, - actionTitles: { - research: "πŸ” Research Ideas", - experiment: "πŸ§ͺ Experiment Ideas", - discuss: "πŸ’¬ Discussion Ideas" - }, - actionReminder: "Remember: The goal is to discover the answer yourself!" - }, - de: { - title: "KidsAI Explorer", - tagline: "Denken, Lernen, Entdecken - Zusammen!", - encouragements: ["Tolle Frage! Du denkst wie ein echter Wissenschaftler! πŸ”¬"], - thinkingFrameworks: { - general: { - steps: [ - { - title: "🎯 Lass uns das aufteilen", - content: "Was ist das Wichtigste, was du verstehen mΓΆchtest?" - } - ] - } - }, - actionTitles: { - research: "πŸ” Forschungsideen", - experiment: "πŸ§ͺ Experiment-Ideen", - discuss: "πŸ’¬ Diskussionsideen" - }, - actionReminder: "Denk daran: Das Ziel ist es, die Antwort selbst zu entdecken!" - } - }; - } - - try { - new KidsAIExplorer(); - console.log('KidsAI Explorer initialized successfully'); - } catch (error) { - console.error('Error initializing KidsAIExplorer:', error); - // Ensure loading is hidden even if there's an error - if (loadingOverlay) { - loadingOverlay.classList.add('hidden'); - } - } +// Initialize the app when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + window.kidsAI = new KidsAIExplorer(); }); -// Add some fun interactive effects -document.addEventListener('DOMContentLoaded', () => { - // Add sparkle effect on click - document.addEventListener('click', (e) => { - if (e.target.classList.contains('ask-btn') || e.target.classList.contains('action-btn')) { - createSparkleEffect(e.target); - } - }); - - // Add hover sound effect simulation (visual feedback) - const interactiveElements = document.querySelectorAll('.suggestion-card, .ask-btn, .action-btn'); - interactiveElements.forEach(element => { - element.addEventListener('mouseenter', () => { - element.style.transform = element.style.transform || 'translateY(-2px)'; - }); - }); -}); - -function createSparkleEffect(element) { - for (let i = 0; i < 6; i++) { - const sparkle = document.createElement('div'); - sparkle.innerHTML = '✨'; - sparkle.style.cssText = ` - position: absolute; - pointer-events: none; - font-size: 1rem; - animation: sparkle 1s ease-out forwards; - z-index: 1000; - `; - - const rect = element.getBoundingClientRect(); - sparkle.style.left = (rect.left + Math.random() * rect.width) + 'px'; - sparkle.style.top = (rect.top + Math.random() * rect.height) + 'px'; - - document.body.appendChild(sparkle); - - setTimeout(() => sparkle.remove(), 1000); - } -} - -// Add sparkle animation CSS -const sparkleCSS = ` -@keyframes sparkle { - 0% { - opacity: 1; - transform: translateY(0) scale(0); - } - 50% { - opacity: 1; - transform: translateY(-20px) scale(1); - } - 100% { - opacity: 0; - transform: translateY(-40px) scale(0); - } -} - -@keyframes slideInRight { - from { - opacity: 0; - transform: translateX(100px); - } - to { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes slideOutRight { - from { - opacity: 1; - transform: translateX(0); - } - to { - opacity: 0; - transform: translateX(100px); - } -} - -.action-guidance ul { - margin: 15px 0; - padding-left: 20px; -} - -.action-guidance li { - margin: 8px 0; - color: #4a5568; - font-weight: 500; -} -`; - -// Inject the sparkle CSS -const styleSheet = document.createElement('style'); -styleSheet.textContent = sparkleCSS; -document.head.appendChild(styleSheet); diff --git a/html/kidsai/style.css b/html/kidsai/style.css index d569e6d..57a68fe 100755 --- a/html/kidsai/style.css +++ b/html/kidsai/style.css @@ -330,11 +330,11 @@ body { .step-thinking-space { margin-top: 15px; + padding: 15px; background: rgba(255, 255, 255, 0.7); border-radius: 12px; - padding: 15px; - backdrop-filter: blur(5px); - border: 1px solid rgba(102, 126, 234, 0.1); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); } .step-thinking-space textarea { @@ -1429,20 +1429,18 @@ body { .thinking-textarea { width: 100%; padding: 12px; - border: 2px solid #e1e8ed; + border: 2px solid #e0e6ed; border-radius: 10px; - font-family: inherit; - font-size: 0.95rem; + font-size: 1rem; line-height: 1.4; resize: vertical; transition: all 0.3s ease; - background: #f8f9fa; + font-family: inherit; } .thinking-textarea:focus { outline: none; border-color: #667eea; - background: white; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); } @@ -1450,20 +1448,21 @@ body { background: linear-gradient(145deg, #667eea, #764ba2); border: none; color: white; - padding: 8px 15px; + padding: 8px 16px; border-radius: 20px; - font-size: 0.85rem; - font-weight: 600; + font-size: 0.9rem; + font-weight: 500; cursor: pointer; margin-top: 10px; transition: all 0.3s ease; - opacity: 0; - animation: fadeInUp 0.3s ease-out forwards; + display: inline-flex; + align-items: center; + gap: 5px; } .share-thought-btn:hover { - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); } .share-thought-btn:disabled { @@ -1472,93 +1471,87 @@ body { transform: none; } +/* AI Feedback Styles */ .thinking-feedback { margin-top: 15px; - background: linear-gradient(145deg, #f8f9fa, #e9ecef); - border-left: 4px solid #667eea; - border-radius: 0 10px 10px 0; - overflow: hidden; } -.feedback-content { - padding: 15px; +.ai-feedback { display: flex; align-items: flex-start; gap: 12px; + padding: 15px; + border-radius: 12px; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.positive-feedback { + background: linear-gradient(145deg, rgba(76, 175, 80, 0.9), rgba(69, 160, 73, 0.9)); + color: white; +} + +.neutral-feedback { + background: linear-gradient(145deg, rgba(33, 150, 243, 0.9), rgba(30, 136, 229, 0.9)); + color: white; +} + +.encouraging-feedback { + background: linear-gradient(145deg, rgba(255, 152, 0, 0.9), rgba(245, 124, 0, 0.9)); + color: white; } .feedback-icon { - font-size: 1.2rem; + font-size: 1.5rem; flex-shrink: 0; - margin-top: 2px; +} + +.feedback-content { + flex: 1; } .feedback-text { - flex: 1; - color: #2c3e50; - font-size: 0.95rem; - line-height: 1.5; + margin: 0 0 5px 0; + font-size: 1rem; + line-height: 1.4; font-weight: 500; } .feedback-source { - font-size: 0.75rem; - color: #6c757d; - font-weight: 500; - margin-top: 5px; - text-align: right; + opacity: 0.8; + font-size: 0.8rem; + font-style: italic; } -/* Improved step thinking space layout */ +/* Step thinking space improvements */ .step-thinking-space { margin-top: 15px; + padding: 15px; background: rgba(255, 255, 255, 0.7); border-radius: 12px; - padding: 15px; - backdrop-filter: blur(5px); - border: 1px solid rgba(102, 126, 234, 0.1); -} - -/* Animation for interactive elements */ -@keyframes fadeInUp { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Enhanced thinking step for interactive mode */ -.thinking-step { - background: rgba(255, 255, 255, 0.95); - border-radius: 15px; - padding: 20px; - margin-bottom: 20px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); - border: 1px solid rgba(102, 126, 234, 0.1); backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); } /* Mobile responsiveness for interactive thinking */ @media (max-width: 768px) { - .feedback-content { - flex-direction: column; - gap: 8px; - } - - .feedback-icon { - align-self: flex-start; - } - - .step-thinking-space { - padding: 12px; + .thinking-textarea { + font-size: 16px; /* Prevents zoom on iOS */ } .share-thought-btn { width: 100%; - padding: 10px; + justify-content: center; + padding: 10px 16px; + } + + .ai-feedback { + flex-direction: column; + text-align: center; + gap: 8px; + } + + .feedback-icon { + align-self: center; } }