HydroFlux 0.0.7
This commit is contained in:
@@ -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 -->
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Hydroflux/releases/HydroFlux V3.apk
Normal file
BIN
Hydroflux/releases/HydroFlux V3.apk
Normal file
Binary file not shown.
Reference in New Issue
Block a user