HydroFlux 0.0.7

This commit is contained in:
2026-02-10 08:50:53 +11:00
parent bc2e6f70cc
commit 3c8efbacdd
3 changed files with 75 additions and 25 deletions

View File

@@ -7,37 +7,37 @@ export class SleepView {
}
render() {
// Real Sleep Data
// Real Sleep Data from Health Connect
const healthData = JSON.parse(localStorage.getItem('hydroflux_health_data') || '{"steps": 0, "sleep": 0}');
const sleepHoursTotal = healthData.sleep;
const sleepHours = Math.floor(sleepHoursTotal);
const sleepMins = Math.round((sleepHoursTotal - sleepHours) * 60);
const sleepHoursTotal = healthData.sleep; // e.g. 7.5
// Calculate Stages (Estimated breakdown if not provided by native yet)
// Light: 55%, Deep: 20%, REM: 25% - Standard healthy breakdown
const lightHours = sleepHoursTotal * 0.55;
const deepHours = sleepHoursTotal * 0.20;
const remHours = sleepHoursTotal * 0.25;
// Formatter: 7.5 -> 7h 30m
const formatTime = (h) => {
const hours = Math.floor(h);
const mins = Math.round((h - hours) * 60);
return `${hours}h ${mins}m`;
};
this.container.innerHTML = `
<div class="w-full max-w-md bg-white min-h-screen relative overflow-hidden mx-auto bg-gradient-to-br from-blue-50 to-white flex flex-col p-6">
<!-- Header -->
<div class="flex justify-between items-center mb-8">
<button id="backBtn" class="w-10 h-10 rounded-full bg-white flex items-center justify-center shadow-md text-gray-700">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
<div class="w-full max-w-md bg-white min-h-screen relative overflow-hidden mx-auto bg-gradient-to-br from-indigo-50 to-purple-50 flex flex-col p-6">
<!-- Header -->
<div class="flex justify-between items-center mb-6 relative z-10">
<button id="backBtn" class="w-10 h-10 rounded-full bg-white bg-opacity-50 backdrop-blur-md flex items-center justify-center shadow-sm">
<svg class="w-6 h-6 text-indigo-900" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
</button>
<span class="text-lg font-bold text-gray-800">Sleep Analysis</span>
<span class="text-lg font-bold text-indigo-900">Sleep Analysis</span>
<div class="w-10"></div>
</div>
<!-- Main Stat -->
<div class="text-center mb-10">
<div class="flex items-baseline justify-center gap-1">
<span class="text-6xl font-bold text-blue-600">${sleepHours}</span>
<span class="text-xl font-medium text-gray-400">h</span>
<span class="text-6xl font-bold text-blue-600">${sleepMins}</span>
<span class="text-xl font-medium text-gray-400">m</span>
</div>
<div class="text-gray-500 text-sm mt-2">Total Sleep Duration</div>
</div>
<!-- Chart -->
<div class="bg-white rounded-3xl p-6 mb-6 shadow-sm border border-gray-100">
<h3 class="text-sm font-semibold text-gray-500 mb-6 uppercase tracking-wider">Sleep Stages</h3>
<!-- Main Sleep Card -->
<div class="bg-white rounded-3xl p-8 shadow-xl mb-6 relative overflow-hidden">
<div class="absolute top-0 right-0 w-32 h-32 bg-indigo-100 rounded-full blur-3xl -mr-10 -mt-10"></div>
<div class="space-y-4">
<!-- REM -->

View File

@@ -20,7 +20,10 @@ export class WaterView {
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
</button>
<span class="text-lg font-bold text-gray-800">Hydration</span>
<div class="w-10"></div>
<!-- Settings Cog -->
<button id="settingsBtn" class="w-10 h-10 rounded-full bg-white bg-opacity-50 backdrop-blur-md flex items-center justify-center shadow-sm">
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
</button>
</div>
<!-- Main Content Scrollable Area -->
@@ -116,6 +119,24 @@ export class WaterView {
<button id="closeModal" class="w-full py-3 rounded-xl bg-gray-100 text-gray-600 font-bold">Cancel</button>
</div>
</div>
<!-- Goal Settings Modal (New) -->
<div id="goalModal" class="hidden absolute bottom-0 left-0 w-full z-50 h-full flex flex-col justify-end">
<div class="absolute inset-0 bg-black bg-opacity-20 backdrop-blur-sm" id="closeGoalModalMask"></div>
<div class="bg-white rounded-t-3xl p-8 shadow-[0_-10px_40px_rgba(0,0,0,0.1)] relative animate-slide-up z-50">
<div class="w-12 h-1 bg-gray-200 rounded-full mx-auto mb-6"></div>
<h3 class="font-bold text-gray-800 text-lg mb-2 text-center">Daily Goal</h3>
<p class="text-center text-gray-400 text-sm mb-6">Set your hydration target</p>
<div class="flex items-center justify-center gap-4 mb-8">
<button id="decreaseGoal" class="w-12 h-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center font-bold text-xl hover:bg-blue-200"></button>
<div class="text-4xl font-bold text-gray-800 w-24 text-center" id="goalDisplay">${data.goal.toFixed(1)}</div>
<button id="increaseGoal" class="w-12 h-12 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center font-bold text-xl hover:bg-blue-200">+</button>
</div>
<button id="saveGoal" class="w-full py-4 rounded-xl bg-blue-500 text-white font-bold shadow-lg shadow-blue-200">Save Goal</button>
</div>
</div>
</div>
<style>
@keyframes slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
@@ -192,5 +213,34 @@ export class WaterView {
this.attachEvents();
}
});
// Goal Modal Logic
const goalModal = this.container.querySelector('#goalModal');
const openGoalModal = () => goalModal.classList.remove('hidden');
const closeGoalModal = () => goalModal.classList.add('hidden');
this.container.querySelector('#settingsBtn').addEventListener('click', openGoalModal);
this.container.querySelector('#closeGoalModalMask').addEventListener('click', closeGoalModal);
let tempGoal = parseFloat(this.container.querySelector('#goalDisplay').innerText);
this.container.querySelector('#increaseGoal').addEventListener('click', () => {
tempGoal = Math.min(tempGoal + 0.5, 10.0);
this.container.querySelector('#goalDisplay').innerText = tempGoal.toFixed(1);
});
this.container.querySelector('#decreaseGoal').addEventListener('click', () => {
tempGoal = Math.max(tempGoal - 0.5, 0.5);
this.container.querySelector('#goalDisplay').innerText = tempGoal.toFixed(1);
});
this.container.querySelector('#saveGoal').addEventListener('click', () => {
const data = JSON.parse(localStorage.getItem('hydroflux_data') || '{"current":0,"goal":3.0}');
data.goal = tempGoal;
localStorage.setItem('hydroflux_data', JSON.stringify(data));
closeGoalModal();
this.render();
this.attachEvents();
});
}
}

Binary file not shown.