Mirxa1's picture
Continue completing
3353981 verified
// SoulSync Global JavaScript
class SoulSyncApp {
constructor() {
this.currentUser = null;
this.conversationHistory = [];
this.isRecording = false;
this.isSpeaking = false;
this.init();
}
init() {
this.setupEventListeners();
this.loadUserData();
this.setupVoiceRecognition();
console.log('SoulSync initialized - Ready to explore the shadows');
}
setupEventListeners() {
// Theme toggle
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => this.toggleTheme());
}
// Voice recording
const voiceBtn = document.getElementById('voiceBtn');
if (voiceBtn) {
voiceBtn.addEventListener('click', () => this.toggleVoiceRecording());
}
// Navigation
document.addEventListener('click', (e) => {
if (e.target.matches('[data-nav]')) {
this.handleNavigation(e.target.getAttribute('data-nav'));
}
});
}
toggleTheme() {
const html = document.documentElement;
html.classList.toggle('dark');
const isDark = html.classList.contains('dark');
localStorage.setItem('soulsync-theme', isDark ? 'dark' : 'light');
// Update icon
const themeIcon = document.querySelector('#themeToggle i');
if (themeIcon) {
themeIcon.setAttribute('data-feather', isDark ? 'sun' : 'moon');
feather.replace();
}
}
async toggleVoiceRecording() {
if (!this.isRecording) {
await this.startVoiceRecording();
} else {
this.stopVoiceRecording();
}
}
async startVoiceRecording() {
try {
if (!('webkitSpeechRecognition' in window)) {
this.showNotification('Voice recognition not supported in your browser', 'error');
return;
}
this.isRecording = true;
const voiceBtn = document.getElementById('voiceBtn');
if (voiceBtn) {
voiceBtn.classList.add('recording');
voiceBtn.innerHTML = '<i data-feather="square"></i>';
feather.replace();
}
// Initialize speech recognition
const recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = 'en-US';
recognition.onresult = (event) => {
let transcript = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
if (event.results[i].isFinal) {
transcript += event.results[i][0].transcript;
}
}
if (transcript) {
this.processVoiceInput(transcript);
}
};
recognition.onerror = (event) => {
console.error('Speech recognition error:', event.error);
this.isRecording = false;
this.updateVoiceButton();
};
recognition.onend = () => {
this.isRecording = false;
this.updateVoiceButton();
};
recognition.start();
} catch (error) {
console.error('Voice recording failed:', error);
this.isRecording = false;
this.updateVoiceButton();
}
}
stopVoiceRecording() {
this.isRecording = false;
this.updateVoiceButton();
}
updateVoiceButton() {
const voiceBtn = document.getElementById('voiceBtn');
if (voiceBtn) {
voiceBtn.classList.remove('recording');
voiceBtn.innerHTML = '<i data-feather="mic"></i>';
feather.replace();
}
}
processVoiceInput(transcript) {
console.log('Voice input:', transcript);
// Here you would send the transcript to your AI backend
this.sendMessageToAI(transcript);
}
async sendMessageToAI(message) {
// Show typing indicator
this.showTypingIndicator();
try {
// Simulate AI response - Replace with actual API call
const response = await this.simulateAIResponse(message);
// Hide typing indicator
this.hideTypingIndicator();
// Display AI response
this.displayAIResponse(response);
// Add to conversation history
this.conversationHistory.push({
user: message,
ai: response,
timestamp: new Date().toISOString()
});
// Save conversation
this.saveConversation();
} catch (error) {
console.error('AI response error:', error);
this.hideTypingIndicator();
this.showNotification('Failed to get response from NewMe', 'error');
}
}
async simulateAIResponse(message) {
// This is a simulation - replace with actual OpenAI API call
return new Promise((resolve) => {
setTimeout(() => {
const responses = [
`I hear the space between your words, habibti. That pause where you almost told the truth... tell me more about that.`,
`You're smiling as you say that, but your words don't match your energy. What's really happening behind that smile?`,
`Remember that picture you sent me last week? The one with the morning light? You said it made you feel peaceful. What's different about today?`,
`I'm noticing a pattern here. You use humor when you're uncomfortable. Let's sit with that discomfort for a moment.`,
`Your voice tells me you're tired of pretending. What if we just... stopped?`
];
resolve(responses[Math.floor(Math.random() * responses.length)]);
}, 2000);
});
}
showTypingIndicator() {
const chatContainer = document.getElementById('chatContainer');
if (chatContainer) {
const typingElement = document.createElement('div');
typingElement.id = 'typingIndicator';
typingElement.className = 'flex items-center space-x-1 p-4';
typingElement.innerHTML = `
<div class="w-8 h-8 bg-gradient-to-r from-fuchsia-500 to-violet-500 rounded-full flex items-center justify-center">
<i data-feather="moon" class="w-4 h-4 text-white"></i>
</div>
<div class="flex space-x-1">
<div class="typing-dot w-2 h-2 bg-fuchsia-400 rounded-full"></div>
<div class="typing-dot w-2 h-2 bg-fuchsia-400 rounded-full"></div>
<div class="typing-dot w-2 h-2 bg-fuchsia-400 rounded-full"></div>
</div>
`;
chatContainer.appendChild(typingElement);
feather.replace();
}
}
hideTypingIndicator() {
const typingIndicator = document.getElementById('typingIndicator');
if (typingIndicator) {
typingIndicator.remove();
}
}
displayAIResponse(response) {
const chatContainer = document.getElementById('chatContainer');
if (chatContainer) {
const messageElement = document.createElement('div');
messageElement.className = 'chat-bubble bg-dark-100 border border-gray-700 rounded-2xl p-4 mb-4';
messageElement.innerHTML = `
<div class="flex items-start space-x-3">
<div class="w-8 h-8 bg-gradient-to-r from-fuchsia-500 to-violet-500 rounded-full flex items-center justify-center flex-shrink-0">
<i data-feather="moon" class="w-4 h-4 text-white"></i>
</div>
<div class="flex-1">
<p class="text-white leading-relaxed">${response}</p>
<div class="flex items-center space-x-2 mt-2">
<button class="text-xs text-fuchsia-400 hover:text-fuchsia-300">Reply</button>
<button class="text-xs text-violet-400 hover:text-violet-300">Voice Response</button>
</div>
</div>
</div>
`;
chatContainer.appendChild(messageElement);
feather.replace();
// Scroll to bottom
chatContainer.scrollTop = chatContainer.scrollHeight;
}
}
showNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 p-4 rounded-lg z-50 transform transition-all duration-300 ${
type === 'error' ? 'bg-red-500' :
type === 'success' ? 'bg-green-500' :
'bg-fuchsia-500'
} text-white shadow-lg`;
notification.textContent = message;
document.body.appendChild(notification);
// Remove after 3 seconds
setTimeout(() => {
notification.remove();
}, 3000);
}
handleNavigation(page) {
// Handle navigation between pages
window.location.href = `${page}.html`;
}
loadUserData() {
const savedUser = localStorage.getItem('soulsync-user');
const savedConversations = localStorage.getItem('soulsync-conversations');
if (savedUser) {
this.currentUser = JSON.parse(savedUser);
}
if (savedConversations) {
this.conversationHistory = JSON.parse(savedConversations);
}
}
saveConversation() {
localStorage.setItem('soulsync-conversations', JSON.stringify(this.conversationHistory));
}
// Shadow Work Assessment
startShadowWork() {
const questions = [
"What roles do you most often play in front of others?",
"Which emotions do you feel ashamed to show?",
"What beliefs echo in your mind during hard moments?",
"What do you tolerate that hurts you?",
"Describe your most free, authentic self",
"What compliment do you find hardest to accept?",
"When was the last time you felt truly seen?",
"What part of yourself do you hide because you think it's 'too much'?",
"What would you do if you weren't afraid of being judged?",
"What childhood dream did you abandon and why?",
"What truth about yourself are you ready to acknowledge today?"
];
this.showShadowWorkQuestion(0, questions);
}
showShadowWorkQuestion(index, questions) {
if (index >= questions.length) {
this.generateShadowWorkInsights();
return;
}
// Display question in chat interface
const question = questions[index];
this.displayAIResponse(question);
// Store current question index
this.currentQuestionIndex = index;
}
generateShadowWorkInsights() {
const insights = {
patterns: ["People-pleasing tendency", "Emotional suppression", "Perfectionism"],
strengths: ["Deep empathy", "Intuitive wisdom", "Resilient spirit"],
actions: ["Practice saying no once daily", "Journal about suppressed emotions", "Allow yourself to be imperfect"],
affirmations: ["I am worthy of taking up space", "My feelings are valid", "I embrace all parts of myself"]
};
this.displayShadowWorkResults(insights);
}
displayShadowWorkResults(insights) {
const resultsHTML = `
<div class="bg-dark-300 rounded-2xl p-6 border border-fuchsia-500/30">
<h3 class="text-lg font-semibold text-fuchsia-400 mb-4">Your Shadow Work Insights</h3>
<div class="space-y-4">
<div>
<h4 class="text-violet-400 font-medium mb-2">Core Patterns</h4>
<p class="text-gray-300">${insights.patterns.join(', ')}</p>
</div>
<div>
<h4 class="text-violet-400 font-medium mb-2">Hidden Strengths</h4>
<p class="text-gray-300">${insights.strengths.join(', ')}</p>
</div>
<div>
<h4 class="text-violet-400 font-medium mb-2">Action Steps</h4>
<p class="text-gray-300">${insights.actions.join(', ')}</p>
</div>
<div>
<h4 class="text-violet-400 font-medium mb-2">Daily Affirmations</h4>
<p class="text-gray-300 italic">${insights.affirmations.join(' • ')}</p>
</div>
</div>
</div>
`;
this.displayAIResponse(resultsHTML);
}
}
// Initialize the app when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
window.soulSyncApp = new SoulSyncApp();
});
// Utility functions
const SoulSyncUtils = {
formatTime: (date) => {
return new Date(date).toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit'
});
},
getEmotionColor: (emotion) => {
const colors = {
happy: '#10b981',
sad: '#ef4444',
angry: '#dc2626',
excited: '#f59e0b',
calm: '#3b82f6',
anxious: '#f97316',
peaceful: '#06b6d4'
};
return colors[emotion] || '#6b7280';
},
debounce: (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
};
// Export for use in other files
if (typeof module !== 'undefined' && module.exports) {
module.exports = { SoulSyncApp, SoulSyncUtils };
}