| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>MindBloom | Depression Cycle Tracker</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| @keyframes fadeIn { |
| from { opacity: 0; } |
| to { opacity: 1; } |
| } |
| .fade-in { |
| animation: fadeIn 0.5s ease-in-out; |
| } |
| .mood-1 { background-color: #f87171; } |
| .mood-2 { background-color: #fb923c; } |
| .mood-3 { background-color: #facc15; } |
| .mood-4 { background-color: #a3e635; } |
| .mood-5 { background-color: #4ade80; } |
| .chart-bar { |
| transition: height 0.5s ease-in-out; |
| } |
| .custom-scrollbar::-webkit-scrollbar { |
| width: 6px; |
| height: 6px; |
| } |
| .custom-scrollbar::-webkit-scrollbar-track { |
| background: #f1f1f1; |
| border-radius: 10px; |
| } |
| .custom-scrollbar::-webkit-scrollbar-thumb { |
| background: #cbd5e1; |
| border-radius: 10px; |
| } |
| .custom-scrollbar::-webkit-scrollbar-thumb:hover { |
| background: #94a3b8; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50 min-h-screen font-sans"> |
| <div class="container mx-auto px-4 py-8 max-w-6xl"> |
| |
| <header class="flex justify-between items-center mb-8"> |
| <div class="flex items-center"> |
| <div class="w-10 h-10 rounded-full bg-indigo-600 flex items-center justify-center mr-3"> |
| <i class="fas fa-brain text-white text-xl"></i> |
| </div> |
| <h1 class="text-2xl font-bold text-gray-800">MindBloom</h1> |
| </div> |
| <div class="flex items-center space-x-4"> |
| <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-200 transition"> |
| <i class="fas fa-moon text-gray-600"></i> |
| </button> |
| <div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center"> |
| <i class="fas fa-user text-indigo-600"></i> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <main class="grid grid-cols-1 lg:grid-cols-3 gap-6"> |
| |
| <div class="lg:col-span-2 space-y-6"> |
| |
| <div class="bg-white rounded-xl shadow-md p-6 fade-in"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-xl font-semibold text-gray-800">Today's Mood</h2> |
| <span class="text-sm text-gray-500" id="current-date"></span> |
| </div> |
| |
| <div class="mb-6"> |
| <p class="text-gray-600 mb-4">How are you feeling today?</p> |
| <div class="flex justify-between space-x-2"> |
| <button class="mood-btn flex-1 py-3 rounded-lg flex flex-col items-center transition hover:opacity-90" data-value="1"> |
| <i class="fas fa-face-sad-tear text-2xl mb-1"></i> |
| <span class="text-xs">Very Low</span> |
| </button> |
| <button class="mood-btn flex-1 py-3 rounded-lg flex flex-col items-center transition hover:opacity-90" data-value="2"> |
| <i class="fas fa-face-frown text-2xl mb-1"></i> |
| <span class="text-xs">Low</span> |
| </button> |
| <button class="mood-btn flex-1 py-3 rounded-lg flex flex-col items-center transition hover:opacity-90" data-value="3"> |
| <i class="fas fa-face-meh text-2xl mb-1"></i> |
| <span class="text-xs">Neutral</span> |
| </button> |
| <button class="mood-btn flex-1 py-3 rounded-lg flex flex-col items-center transition hover:opacity-90" data-value="4"> |
| <i class="fas fa-face-smile text-2xl mb-1"></i> |
| <span class="text-xs">Good</span> |
| </button> |
| <button class="mood-btn flex-1 py-3 rounded-lg flex flex-col items-center transition hover:opacity-90" data-value="5"> |
| <i class="fas fa-face-laugh-beam text-2xl mb-1"></i> |
| <span class="text-xs">Very Good</span> |
| </button> |
| </div> |
| </div> |
| |
| <div id="mood-description" class="hidden"> |
| <textarea id="mood-notes" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" rows="3" placeholder="Add any notes about how you're feeling..."></textarea> |
| <div class="flex justify-end mt-3"> |
| <button id="save-mood" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition">Save</button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-md p-6 fade-in"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-xl font-semibold text-gray-800">Mood History</h2> |
| <div class="flex space-x-2"> |
| <button class="time-btn px-3 py-1 text-sm rounded-md bg-indigo-100 text-indigo-700" data-range="7">Week</button> |
| <button class="time-btn px-3 py-1 text-sm rounded-md hover:bg-indigo-100 hover:text-indigo-700" data-range="30">Month</button> |
| <button class="time-btn px-3 py-1 text-sm rounded-md hover:bg-indigo-100 hover:text-indigo-700" data-range="90">3 Months</button> |
| </div> |
| </div> |
| <div class="h-64"> |
| <div id="mood-chart" class="h-full flex items-end justify-between pt-4"></div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="space-y-6"> |
| |
| <div class="bg-white rounded-xl shadow-md p-6 fade-in"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Your Stats</h2> |
| <div class="space-y-4"> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">Current Mood Cycle</p> |
| <div class="flex items-center"> |
| <div class="w-3 h-3 rounded-full bg-indigo-600 mr-2"></div> |
| <p class="font-medium" id="current-cycle">Neutral Phase</p> |
| </div> |
| </div> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">Average Mood</p> |
| <p class="font-medium text-2xl" id="avg-mood">3.4</p> |
| </div> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">Low Days This Month</p> |
| <p class="font-medium" id="low-days">4</p> |
| </div> |
| <div> |
| <p class="text-sm text-gray-500 mb-1">Current Streak</p> |
| <p class="font-medium" id="current-streak">2 days</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-md p-6 fade-in"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-xl font-semibold text-gray-800">Recent Journal</h2> |
| <button class="text-indigo-600 hover:text-indigo-800"> |
| <i class="fas fa-plus"></i> |
| </button> |
| </div> |
| <div class="space-y-4 max-h-64 overflow-y-auto custom-scrollbar"> |
| <div class="p-3 bg-indigo-50 rounded-lg"> |
| <div class="flex justify-between items-start mb-2"> |
| <p class="font-medium">Feeling better today</p> |
| <span class="text-xs text-gray-500">Yesterday</span> |
| </div> |
| <p class="text-sm text-gray-700">Went for a walk in the park and it helped clear my mind. The sunshine felt nice.</p> |
| </div> |
| <div class="p-3 bg-amber-50 rounded-lg"> |
| <div class="flex justify-between items-start mb-2"> |
| <p class="font-medium">Struggling</p> |
| <span class="text-xs text-gray-500">2 days ago</span> |
| </div> |
| <p class="text-sm text-gray-700">Hard to get out of bed today. Everything feels heavy.</p> |
| </div> |
| <div class="p-3 bg-indigo-50 rounded-lg"> |
| <div class="flex justify-between items-start mb-2"> |
| <p class="font-medium">Productive day</p> |
| <span class="text-xs text-gray-500">4 days ago</span> |
| </div> |
| <p class="text-sm text-gray-700">Finished my project ahead of schedule. Feeling accomplished.</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-md p-6 fade-in"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Resources</h2> |
| <div class="space-y-3"> |
| <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-50 transition"> |
| <div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-3"> |
| <i class="fas fa-head-side-virus text-green-600"></i> |
| </div> |
| <p class="text-sm">Coping Strategies</p> |
| </a> |
| <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-50 transition"> |
| <div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
| <i class="fas fa-hands-holding-child text-blue-600"></i> |
| </div> |
| <p class="text-sm">Support Groups</p> |
| </a> |
| <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-50 transition"> |
| <div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center mr-3"> |
| <i class="fas fa-book text-purple-600"></i> |
| </div> |
| <p class="text-sm">Depression Education</p> |
| </a> |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
|
|
| |
| <div id="toast" class="fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg hidden items-center"> |
| <i class="fas fa-check-circle mr-2"></i> |
| <span>Mood saved successfully!</span> |
| </div> |
|
|
| <script> |
| |
| const now = new Date(); |
| document.getElementById('current-date').textContent = now.toLocaleDateString('en-US', { |
| weekday: 'long', |
| month: 'short', |
| day: 'numeric' |
| }); |
| |
| |
| const themeToggle = document.getElementById('theme-toggle'); |
| themeToggle.addEventListener('click', () => { |
| document.documentElement.classList.toggle('dark'); |
| const icon = themeToggle.querySelector('i'); |
| if (document.documentElement.classList.contains('dark')) { |
| icon.classList.replace('fa-moon', 'fa-sun'); |
| document.body.classList.add('bg-gray-900'); |
| document.body.classList.remove('bg-gray-50'); |
| } else { |
| icon.classList.replace('fa-sun', 'fa-moon'); |
| document.body.classList.remove('bg-gray-900'); |
| document.body.classList.add('bg-gray-50'); |
| } |
| }); |
| |
| |
| const moodBtns = document.querySelectorAll('.mood-btn'); |
| const moodDescription = document.getElementById('mood-description'); |
| let selectedMood = null; |
| |
| moodBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| |
| moodBtns.forEach(b => { |
| b.classList.remove('mood-1', 'mood-2', 'mood-3', 'mood-4', 'mood-5'); |
| b.classList.add('opacity-50'); |
| }); |
| |
| |
| selectedMood = parseInt(btn.dataset.value); |
| btn.classList.add(`mood-${selectedMood}`); |
| btn.classList.remove('opacity-50'); |
| |
| |
| moodDescription.classList.remove('hidden'); |
| }); |
| }); |
| |
| |
| const saveMoodBtn = document.getElementById('save-mood'); |
| const moodNotes = document.getElementById('mood-notes'); |
| const toast = document.getElementById('toast'); |
| |
| saveMoodBtn.addEventListener('click', () => { |
| if (!selectedMood) return; |
| |
| |
| const moodData = { |
| date: now, |
| mood: selectedMood, |
| notes: moodNotes.value |
| }; |
| |
| |
| let moods = JSON.parse(localStorage.getItem('moods') || '[]'); |
| moods.push(moodData); |
| localStorage.setItem('moods', JSON.stringify(moods)); |
| |
| |
| toast.classList.remove('hidden'); |
| setTimeout(() => { |
| toast.classList.add('hidden'); |
| }, 3000); |
| |
| |
| moodBtns.forEach(b => { |
| b.classList.remove('mood-1', 'mood-2', 'mood-3', 'mood-4', 'mood-5'); |
| b.classList.remove('opacity-50'); |
| }); |
| moodNotes.value = ''; |
| moodDescription.classList.add('hidden'); |
| selectedMood = null; |
| |
| |
| updateChart(7); |
| updateStats(); |
| }); |
| |
| |
| const timeBtns = document.querySelectorAll('.time-btn'); |
| timeBtns.forEach(btn => { |
| btn.addEventListener('click', () => { |
| timeBtns.forEach(b => { |
| b.classList.remove('bg-indigo-100', 'text-indigo-700'); |
| b.classList.add('hover:bg-indigo-100', 'hover:text-indigo-700'); |
| }); |
| btn.classList.add('bg-indigo-100', 'text-indigo-700'); |
| btn.classList.remove('hover:bg-indigo-100', 'hover:text-indigo-700'); |
| |
| const range = parseInt(btn.dataset.range); |
| updateChart(range); |
| }); |
| }); |
| |
| |
| function generateMockData() { |
| if (localStorage.getItem('moods')) return; |
| |
| const moods = []; |
| const today = new Date(); |
| |
| for (let i = 0; i < 90; i++) { |
| const date = new Date(); |
| date.setDate(today.getDate() - (90 - i)); |
| |
| |
| const cyclePhase = Math.floor(i / 15) % 4; |
| let mood; |
| |
| if (cyclePhase === 0) { |
| mood = Math.floor(Math.random() * 2) + 4; |
| } else if (cyclePhase === 1) { |
| mood = 3; |
| } else if (cyclePhase === 2) { |
| mood = Math.floor(Math.random() * 2) + 1; |
| } else { |
| mood = 3; |
| } |
| |
| moods.push({ |
| date: date, |
| mood: mood, |
| notes: '' |
| }); |
| } |
| |
| localStorage.setItem('moods', JSON.stringify(moods)); |
| } |
| |
| |
| function updateChart(days) { |
| generateMockData(); |
| const moods = JSON.parse(localStorage.getItem('moods')); |
| const chart = document.getElementById('mood-chart'); |
| chart.innerHTML = ''; |
| |
| const today = new Date(); |
| const startDate = new Date(); |
| startDate.setDate(today.getDate() - days); |
| |
| const filteredMoods = moods.filter(mood => { |
| const moodDate = new Date(mood.date); |
| return moodDate >= startDate && moodDate <= today; |
| }); |
| |
| |
| const groupedMoods = {}; |
| filteredMoods.forEach(mood => { |
| const dateStr = new Date(mood.date).toLocaleDateString(); |
| if (!groupedMoods[dateStr]) { |
| groupedMoods[dateStr] = []; |
| } |
| groupedMoods[dateStr].push(mood.mood); |
| }); |
| |
| |
| const moodAverages = []; |
| Object.keys(groupedMoods).forEach(dateStr => { |
| const moods = groupedMoods[dateStr]; |
| const avg = moods.reduce((a, b) => a + b, 0) / moods.length; |
| moodAverages.push({ |
| date: dateStr, |
| avg: avg |
| }); |
| }); |
| |
| |
| moodAverages.sort((a, b) => new Date(a.date) - new Date(b.date)); |
| |
| |
| const maxHeight = 180; |
| moodAverages.forEach((day, index) => { |
| const height = (day.avg / 5) * maxHeight; |
| const date = new Date(day.date); |
| const dayName = date.toLocaleDateString('en-US', { weekday: 'short' }).charAt(0); |
| |
| const bar = document.createElement('div'); |
| bar.className = `chart-bar flex flex-col items-center w-8 mx-1`; |
| |
| const barFill = document.createElement('div'); |
| barFill.className = `w-full rounded-t-md mood-${Math.round(day.avg)}`; |
| barFill.style.height = `${height}px`; |
| |
| const dayLabel = document.createElement('span'); |
| dayLabel.className = 'text-xs text-gray-500 mt-1'; |
| dayLabel.textContent = dayName; |
| |
| bar.appendChild(barFill); |
| bar.appendChild(dayLabel); |
| chart.appendChild(bar); |
| }); |
| } |
| |
| |
| function updateStats() { |
| generateMockData(); |
| const moods = JSON.parse(localStorage.getItem('moods')); |
| |
| |
| const avgMood = moods.reduce((sum, mood) => sum + mood.mood, 0) / moods.length; |
| document.getElementById('avg-mood').textContent = avgMood.toFixed(1); |
| |
| |
| const thisMonth = new Date().getMonth(); |
| const lowDays = moods.filter(mood => { |
| const moodDate = new Date(mood.date); |
| return moodDate.getMonth() === thisMonth && mood.mood <= 2; |
| }).length; |
| document.getElementById('low-days').textContent = lowDays; |
| |
| |
| const last7Days = moods.slice(-7).map(m => m.mood); |
| const avgLast7 = last7Days.reduce((a, b) => a + b, 0) / last7Days.length; |
| |
| let cycle; |
| if (avgLast7 <= 2) { |
| cycle = "Low Phase"; |
| } else if (avgLast7 >= 4) { |
| cycle = "Good Phase"; |
| } else { |
| cycle = "Neutral Phase"; |
| } |
| document.getElementById('current-cycle').textContent = cycle; |
| |
| |
| let streak = 0; |
| let prevMood = moods[moods.length - 1].mood; |
| for (let i = moods.length - 1; i >= 0; i--) { |
| if (moods[i].mood === prevMood) { |
| streak++; |
| } else { |
| break; |
| } |
| } |
| document.getElementById('current-streak').textContent = `${streak} day${streak !== 1 ? 's' : ''}`; |
| } |
| |
| |
| updateChart(7); |
| updateStats(); |
| timeBtns[0].click(); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=twnatelo/depression-cycle-tracker-prototype" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |