pulse-flow / script.js
CSNET's picture
ทำต่อให้เสร็จ
8b26d10 verified
Raw
History Blame Contribute Delete
9.75 kB
class PulseApp {
constructor() {
this.userData = this.loadUserData();
this.init();
}
init() {
this.setupThemeToggle();
this.setupQuickActions();
this.startRealTimeUpdates();
this.setupVitalRings();
this.setupAICoach();
}
// Theme Management
setupThemeToggle() {
const themeToggle = document.querySelector('#theme-toggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const html = document.documentElement;
const isDark = html.classList.contains('dark');
html.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'light' : 'dark');
});
}
// Load saved theme
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.documentElement.classList.add('dark');
}
}
// Quick Actions Handler
setupQuickActions() {
const quickActionButtons = document.querySelectorAll('quick-action');
quickActionButtons.forEach(button => {
button.addEventListener('click', (e) => {
const action = e.currentTarget.getAttribute('data-action');
this.handleQuickAction(action);
});
});
}
handleQuickAction(action) {
const actions = {
'food': () => this.showNotification('กำลังเปิดบันทึกอาหาร...', 'orange'),
'exercise': () => this.showNotification('กำลังเริ่มจับเวลาออกกำลังกาย...', 'red'),
'mood': () => this.showNotification('กำลังเปิดบันทึกอารมณ์...', 'pink'),
'fasting': () => this.startFastingTimer(),
};
if (actions[action]) {
actions[action]();
}
}
// Fasting Timer
startFastingTimer() {
const startTime = Date.now();
const timerInterval = setInterval(() => {
const elapsed = Date.now() - startTime;
const hours = Math.floor(elapsed / 3600000);
const minutes = Math.floor((elapsed % 3600000) / 60000);
const timerElement = document.querySelector('#fasting-timer');
if (timerElement) {
timerElement.textContent = `${hours}ชม. ${minutes}น.`;
}
}, 60000);
this.showNotification('จับเวลาการ IF เริ่มแล้ว!', 'teal');
}
// Real-time Data Updates
startRealTimeUpdates() {
// Simulate real-time vital changes
setInterval(() => {
this.updateVitalRings();
this.updateContextualData();
}, 30000); // Update every 30 seconds
}
updateVitalRings() {
const rings = [
{ selector: '.text-emerald-500', key: 'recovery', variance: 2 },
{ selector: '.text-orange-500', key: 'strain', variance: 0.5 },
{ selector: '.text-purple-500', key: 'sleep', variance: 3 }
];
rings.forEach(ring => {
const element = document.querySelector(ring.selector);
if (element) {
const currentValue = parseFloat(element.textContent);
const change = (Math.random() - 0.5) * ring.variance;
const newValue = Math.max(0, Math.min(100, currentValue + change));
element.textContent = ring.key === 'strain' ? newValue.toFixed(1) : Math.round(newValue) + '%';
}
});
}
updateContextualData() {
// Simulate AQI changes
const aqiElement = document.querySelector('contextual-vital[title="คุณภาพอากาศ"]');
if (aqiElement) {
const currentAQI = parseInt(aqiElement.getAttribute('value').match(/\d+/)[0]);
const newAQI = Math.max(30, Math.min(200, currentAQI + (Math.random() - 0.5) * 10));
const status = newAQI < 50 ? 'safe' : newAQI < 100 ? 'warning' : 'danger';
const statusText = status === 'safe' ? 'ดี' : status === 'warning' ? 'ปานกลาง' : 'ไม่ดี';
aqiElement.setAttribute('value', `${statusText} (${Math.round(newAQI)})`);
aqiElement.setAttribute('status', status);
}
}
// Vital Rings Animation
setupVitalRings() {
const rings = document.querySelectorAll('.relative.w-24.h-24');
rings.forEach((ring, index) => {
setTimeout(() => {
ring.classList.add('vital-pulse');
}, index * 200);
});
}
// AI Coach Interactions
setupAICoach() {
const aiButton = document.querySelector('.bg-gradient-to-r button');
if (aiButton) {
aiButton.addEventListener('click', () => {
this.showDetailedRecommendations();
});
}
}
showDetailedRecommendations() {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4';
modal.innerHTML = `
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 max-w-md w-full shadow-2xl">
<h3 class="text-lg font-semibold mb-4 text-slate-800 dark:text-white">คำแนะนำเพิ่มเติม</h3>
<div class="space-y-3 mb-4">
<div class="flex items-start space-x-3">
<i data-feather="shield" class="w-5 h-5 text-green-500 mt-1"></i>
<div>
<p class="text-sm font-medium text-slate-800 dark:text-white">ใส่หน้ากาก N95</p>
<p class="text-xs text-slate-500 dark:text-slate-400">เมื่อออกนอกบ้านในวันฝุ่นสูง</p>
</div>
</div>
<div class="flex items-start space-x-3">
<i data-feather="droplet" class="w-5 h-5 text-blue-500 mt-1"></i>
<div>
<p class="text-sm font-medium text-slate-800 dark:text-white">ดื่มน้ำมากขึ้น 20%</p>
<p class="text-xs text-slate-500 dark:text-slate-400">ช่วยขับสารพิษจากฝุ่น</p>
</div>
</div>
<div class="flex items-start space-x-3">
<i data-feather="home" class="w-5 h-5 text-purple-500 mt-1"></i>
<div>
<p class="text-sm font-medium text-slate-800 dark:text-white">ใช้เครื่องฟอกอากาศ</p>
<p class="text-xs text-slate-500 dark:text-slate-400">อย่างน้อย 2 ชม. ก่อนนอน</p>
</div>
</div>
</div>
<button onclick="this.closest('.fixed').remove()" class="w-full bg-violet-600 text-white py-2 rounded-lg hover:bg-violet-700 transition">
ปิด
</button>
</div>
`;
document.body.appendChild(modal);
feather.replace();
}
// Notifications
showNotification(message, color = 'violet') {
const notification = document.createElement('div');
notification.className = `fixed top-20 right-4 z-50 transform translate-x-full transition-transform duration-300`;
notification.innerHTML = `
<div class="bg-${color}-500 text-white px-4 py-3 rounded-lg shadow-lg flex items-center space-x-2">
<i data-feather="check" class="w-4 h-4"></i>
<span class="text-sm">${message}</span>
</div>
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => notification.remove(), 300);
}, 3000);
feather.replace();
}
// Data Persistence
loadUserData() {
const defaultData = {
recovery: 72,
strain: 14.2,
sleep: 85,
theme: 'light'
};
const saved = localStorage.getItem('pulseData');
return saved ? JSON.parse(saved) : defaultData;
}
saveUserData() {
localStorage.setItem('pulseData', JSON.stringify(this.userData));
}
}
// Initialize App
document.addEventListener('DOMContentLoaded', () => {
new PulseApp();
});
// Global Utilities
window.showNotification = function(message, color) {
const notification = document.createElement('div');
notification.className = `fixed top-20 right-4 z-50 transform translate-x-full transition-transform duration-300`;
notification.innerHTML = `
<div class="bg-${color}-500 text-white px-4 py-3 rounded-lg shadow-lg flex items-center space-x-2">
<i data-feather="check" class="w-4 h-4"></i>
<span class="text-sm">${message}</span>
</div>
`;
document.body.appendChild(notification);
setTimeout(() => notification.classList.remove('translate-x-full'), 100);
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => notification.remove(), 300);
}, 3000);
feather.replace();
};