267 lines
12 KiB
Plaintext
267 lines
12 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Hydro Flux Dashboard</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<style>
|
|
@keyframes wave {
|
|
0%, 100% { transform: translateY(0); }
|
|
50% { transform: translateY(-10px); }
|
|
}
|
|
|
|
.wave-animation {
|
|
animation: wave 3s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes float {
|
|
0%, 100% { transform: translateY(0px); }
|
|
50% { transform: translateY(-5px); }
|
|
}
|
|
|
|
.float-animation {
|
|
animation: float 2s ease-in-out infinite;
|
|
}
|
|
|
|
.water-container {
|
|
transition: height 0.5s ease-out;
|
|
}
|
|
|
|
/* Custom scrollbar for notes */
|
|
textarea::-webkit-scrollbar {
|
|
width: 4px;
|
|
}
|
|
|
|
textarea::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
textarea::-webkit-scrollbar-thumb {
|
|
background: #cbd5e1;
|
|
border-radius: 2px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-gradient-to-br from-gray-100 to-gray-200 min-h-screen flex items-center justify-center p-4">
|
|
|
|
<div class="w-full max-w-md bg-white rounded-[3rem] shadow-2xl p-6 relative overflow-hidden">
|
|
<!-- Background decoration -->
|
|
<div class="absolute top-0 right-0 w-64 h-64 bg-blue-200 opacity-20 rounded-full blur-3xl -z-10"></div>
|
|
<div class="absolute bottom-0 left-0 w-64 h-64 bg-purple-200 opacity-20 rounded-full blur-3xl -z-10"></div>
|
|
|
|
<!-- Header -->
|
|
<div class="flex flex-col items-center gap-2 mb-6">
|
|
<div class="flex items-center justify-between w-full px-4">
|
|
<!-- Avatar -->
|
|
<div class="flex flex-col items-center">
|
|
<div class="w-14 h-14 rounded-full bg-gradient-to-br from-blue-400 to-blue-600 flex items-center justify-center mb-1 shadow-lg">
|
|
<div class="w-12 h-12 rounded-full bg-white bg-opacity-90 flex items-center justify-center text-sm font-semibold text-gray-700">
|
|
JD
|
|
</div>
|
|
</div>
|
|
<span class="text-xs text-blue-600 font-medium">Level 14</span>
|
|
</div>
|
|
|
|
<!-- Title and DateTime -->
|
|
<div class="flex flex-col items-center flex-1">
|
|
<h1 class="text-2xl font-bold text-gray-800 mb-1">Hydro Flux</h1>
|
|
<div id="currentDate" class="text-sm text-gray-600"></div>
|
|
<div id="currentTime" class="text-sm text-gray-500"></div>
|
|
</div>
|
|
|
|
<!-- Streak -->
|
|
<div class="flex items-center gap-1">
|
|
<svg class="w-5 h-5 fill-blue-500 text-blue-500" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"/>
|
|
</svg>
|
|
<svg class="w-5 h-5 fill-blue-400 text-blue-400" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"/>
|
|
</svg>
|
|
<span class="text-sm font-semibold text-gray-700 ml-1">14 Days</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Water Tracker -->
|
|
<div class="relative h-64 bg-gradient-to-b from-blue-50 to-blue-100 rounded-3xl overflow-hidden shadow-lg mb-6">
|
|
<!-- Water fill -->
|
|
<div id="waterFill" class="absolute bottom-0 left-0 right-0 water-container" style="height: 40%; background: linear-gradient(180deg, rgba(96, 165, 250, 0.8) 0%, rgba(59, 130, 246, 0.9) 100%);">
|
|
<!-- Wave SVG -->
|
|
<svg class="absolute top-0 left-0 w-full wave-animation" viewBox="0 0 1200 120" preserveAspectRatio="none" style="height: 60px; transform: translateY(-50%);">
|
|
<path d="M0,50 Q300,10 600,50 T1200,50 L1200,120 L0,120 Z" fill="rgba(96, 165, 250, 0.5)"/>
|
|
</svg>
|
|
</div>
|
|
|
|
<!-- Add button -->
|
|
<button id="addWaterBtn" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-16 h-16 bg-blue-400 bg-opacity-50 hover:bg-opacity-70 backdrop-blur-sm rounded-full flex items-center justify-center shadow-xl transition-all hover:scale-110 z-10">
|
|
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Amount display -->
|
|
<div class="absolute bottom-6 left-0 right-0 text-center z-10">
|
|
<span id="waterAmount" class="text-2xl font-bold text-gray-700">1.2L / 3.0L</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Grid 1: Steps and Strava -->
|
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
|
<!-- Steps Tracker -->
|
|
<div class="bg-gradient-to-br from-blue-50 to-white rounded-2xl p-6 shadow-md">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-4">Steps Tracker</h3>
|
|
<div class="flex items-center justify-center">
|
|
<div class="relative w-32 h-32">
|
|
<svg class="transform -rotate-90 w-32 h-32">
|
|
<circle cx="64" cy="64" r="45" stroke="#E5E7EB" stroke-width="8" fill="none"/>
|
|
<circle id="stepsCircle" cx="64" cy="64" r="45" stroke="#60A5FA" stroke-width="8" fill="none" stroke-linecap="round" style="stroke-dasharray: 282.74; stroke-dashoffset: 56.55; transition: stroke-dashoffset 0.5s;"/>
|
|
</svg>
|
|
<div class="absolute inset-0 flex flex-col items-center justify-center">
|
|
<span class="text-2xl font-bold text-gray-800">8,432</span>
|
|
<span class="text-xs text-gray-500">steps</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Strava Integration -->
|
|
<div class="bg-gradient-to-br from-orange-50 to-white rounded-2xl p-6 shadow-md">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-4">Strava Integration</h3>
|
|
<div class="flex flex-col items-center justify-center py-4">
|
|
<div class="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-2xl flex items-center justify-center mb-3 shadow-lg transform rotate-12">
|
|
<span class="text-3xl font-bold text-white transform -rotate-12">S</span>
|
|
</div>
|
|
<span class="text-lg font-bold text-gray-800">5.2km Run</span>
|
|
<span class="text-xs text-gray-500 mt-1">Last Sync: 2h ago</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sleep Tracker -->
|
|
<div class="bg-gradient-to-br from-blue-50 to-white rounded-2xl p-6 shadow-md mb-4">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-4">Sleep Tracker</h3>
|
|
<div class="h-24 mb-3">
|
|
<svg id="sleepChart" class="w-full h-full" viewBox="0 0 300 100" preserveAspectRatio="none">
|
|
<polyline id="sleepLine" points="" fill="none" stroke="#60A5FA" stroke-width="2"/>
|
|
</svg>
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-xl font-bold text-gray-800">7h 20m</span>
|
|
<span class="text-sm text-blue-600 font-medium">Light Sleep</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Grid 2: Goals and Notes -->
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<!-- Goals -->
|
|
<div class="bg-gradient-to-br from-blue-50 to-white rounded-2xl p-6 shadow-md">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-4">Goals</h3>
|
|
<div class="space-y-3">
|
|
<button class="goal-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl transition-all bg-blue-500 text-white shadow-lg" data-completed="true">
|
|
<div class="w-5 h-5 rounded-full flex items-center justify-center bg-white bg-opacity-30">
|
|
<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium">Drink 3L of water</span>
|
|
</button>
|
|
|
|
<button class="goal-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl transition-all bg-blue-100 text-gray-700 hover:bg-blue-200" data-completed="false">
|
|
<div class="w-5 h-5 rounded-full flex items-center justify-center bg-white"></div>
|
|
<span class="text-sm font-medium">Walk 10K steps</span>
|
|
</button>
|
|
|
|
<button class="goal-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl transition-all bg-blue-100 text-gray-700 hover:bg-blue-200" data-completed="false">
|
|
<div class="w-5 h-5 rounded-full flex items-center justify-center bg-white"></div>
|
|
<span class="text-sm font-medium">Sleep 8 hours</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notes -->
|
|
<div class="bg-gradient-to-br from-blue-50 to-white rounded-2xl p-6 shadow-md">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-4">Notes</h3>
|
|
<textarea id="notesInput" placeholder="Add your notes here..." class="w-full h-24 bg-white bg-opacity-50 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-400 border-none outline-none resize-none">Feeling hydrated today. Remember to add those gym sessions!</textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Water tracking
|
|
let waterAmount = 1.2;
|
|
const maxWater = 3.0;
|
|
const waterIncrement = 0.25;
|
|
|
|
function updateWaterDisplay() {
|
|
const percentage = (waterAmount / maxWater) * 100;
|
|
document.getElementById('waterFill').style.height = percentage + '%';
|
|
document.getElementById('waterAmount').textContent = waterAmount.toFixed(1) + 'L / ' + maxWater.toFixed(1) + 'L';
|
|
}
|
|
|
|
document.getElementById('addWaterBtn').addEventListener('click', function() {
|
|
if (waterAmount < maxWater) {
|
|
waterAmount = Math.min(waterAmount + waterIncrement, maxWater);
|
|
updateWaterDisplay();
|
|
}
|
|
});
|
|
|
|
// DateTime update
|
|
function updateDateTime() {
|
|
const now = new Date();
|
|
const dateOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
|
|
const timeOptions = { hour: 'numeric', minute: '2-digit', hour12: true };
|
|
|
|
document.getElementById('currentDate').textContent = now.toLocaleDateString('en-US', dateOptions);
|
|
document.getElementById('currentTime').textContent = now.toLocaleTimeString('en-US', timeOptions) + ' AEDT';
|
|
}
|
|
|
|
updateDateTime();
|
|
setInterval(updateDateTime, 1000);
|
|
|
|
// Steps circle calculation
|
|
const steps = 8432;
|
|
const goal = 10000;
|
|
const percentage = Math.min((steps / goal) * 100, 100);
|
|
const circumference = 2 * Math.PI * 45;
|
|
const strokeDashoffset = circumference - (percentage / 100) * circumference;
|
|
document.getElementById('stepsCircle').style.strokeDasharray = circumference;
|
|
document.getElementById('stepsCircle').style.strokeDashoffset = strokeDashoffset;
|
|
|
|
// Sleep chart
|
|
const sleepData = [30, 35, 25, 40, 55, 45, 60, 75, 70, 80, 65, 55, 50, 45, 40];
|
|
const chartWidth = 300;
|
|
const chartHeight = 100;
|
|
const points = sleepData.map((value, index) => {
|
|
const x = (index / (sleepData.length - 1)) * chartWidth;
|
|
const y = chartHeight - (value / 100) * chartHeight;
|
|
return x + ',' + y;
|
|
}).join(' ');
|
|
document.getElementById('sleepLine').setAttribute('points', points);
|
|
|
|
// Goals toggle
|
|
document.querySelectorAll('.goal-btn').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
const isCompleted = this.getAttribute('data-completed') === 'true';
|
|
const newState = !isCompleted;
|
|
|
|
this.setAttribute('data-completed', newState);
|
|
|
|
if (newState) {
|
|
this.className = 'goal-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl transition-all bg-blue-500 text-white shadow-lg';
|
|
this.querySelector('div').className = 'w-5 h-5 rounded-full flex items-center justify-center bg-white bg-opacity-30';
|
|
this.querySelector('div').innerHTML = '<svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>';
|
|
} else {
|
|
this.className = 'goal-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl transition-all bg-blue-100 text-gray-700 hover:bg-blue-200';
|
|
this.querySelector('div').className = 'w-5 h-5 rounded-full flex items-center justify-center bg-white';
|
|
this.querySelector('div').innerHTML = '';
|
|
}
|
|
});
|
|
});
|
|
|
|
// Initialize
|
|
updateWaterDisplay();
|
|
</script>
|
|
</body>
|
|
</html>
|