diff --git a/.gitignore b/.gitignore index 54204f2..cbc4127 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules/ -step_competition.db -*.db +# step_competition.db +# *.db .DS_Store *.log npm-debug.log* diff --git a/public/app.js b/public/app.js index 0ded3e4..16a5d6b 100644 --- a/public/app.js +++ b/public/app.js @@ -1,10 +1,38 @@ const API_URL = window.location.origin; +// Humorous step tips +const STEP_TIPS = [ + "Never underestimate a 5-minute dance break. Your step count (and mood) will thank you.", + "Don't let the high-stepping jet-setters get you down. Focus on crushing whoever's ranked right above you.", + "Pacing while on phone calls counts. Your colleagues will understand the extra enthusiasm.", + "Pro tip: Park in the farthest spot. It's not laziness, it's strategy.", + "Taking the stairs? That's just vertical stepping with extra credit.", + "Your fitness tracker thinks you're training for a marathon. Let's not disappoint it.", + "Remember: Every journey to the fridge and back is an opportunity for greatness.", + "Walking meetings are just step competitions in disguise. You're welcome.", + "Forgot something upstairs? That's not forgetfulness, that's bonus cardio.", + "Why run when you can aggressively walk? Same steps, less judgment.", + "Your dog wants a walk. Your step count wants a walk. It's basically a win-win-woof.", + "A monster a day keeps the last place away.", + "Reading this tip instead of walking? Bold strategy. Let's see how it plays out.", + "Pro tip about tips: They're less effective if you're sitting down while reading them.", + "Winners log their steps before noon. Legends log them before breakfast. -Mike (probably)", + "Infrastructure as a Service is down? Legs as a Service is always running.", + "Strapping the tracker to a ceiling fan was attempted in 2019. It didn't work then either.", + "Following your dog around the house may not be the most efficient way to get steps, but it's definitely the most confusing for the dog.", + "Dancing in the school pickup line may not be the most efficient way to get steps, but it's definitely the most embarrassing for your kids.", + "4 out of 5 dentists agree: this has nothing to do with teeth, but walking is still good.", + "Rumor has it the winner of the last competition was just trying to learn the latest Katseye choreo.", + +]; + // State let teams = []; let participants = []; let charts = {}; let selectedParticipant = null; +let currentTipIndex = 0; +let tipRotationInterval = null; // Initialize app document.addEventListener('DOMContentLoaded', () => { @@ -14,6 +42,7 @@ document.addEventListener('DOMContentLoaded', () => { setDefaultDate(); handleRouting(); checkAdminMode(); + initializeTipRotation(); }); // Admin mode @@ -918,3 +947,59 @@ function formatDate(dateStr) { day: 'numeric' }); } + +// Tip rotation functionality +function shuffleTips(array) { + // Fisher-Yates shuffle algorithm for true randomization + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled; +} + +function initializeTipRotation() { + // Clear any existing interval to prevent duplicates + if (tipRotationInterval) { + clearInterval(tipRotationInterval); + } + + // Shuffle the tips array for randomized order + window.shuffledTips = shuffleTips(STEP_TIPS); + currentTipIndex = 0; + + // Display first tip + displayTip(); + + // Rotate every 20 seconds + tipRotationInterval = setInterval(rotateTip, 20000); +} + +function displayTip() { + const tipTextElement = document.getElementById('tip-text'); + if (!tipTextElement || !window.shuffledTips) return; + + tipTextElement.textContent = window.shuffledTips[currentTipIndex]; +} + +function rotateTip() { + const tipTextElement = document.getElementById('tip-text'); + if (!tipTextElement || !window.shuffledTips) return; + + // Fade out + tipTextElement.classList.add('fade-out'); + + // After fade out, change text and fade in + setTimeout(() => { + currentTipIndex = (currentTipIndex + 1) % window.shuffledTips.length; + + // If we've completed a full cycle, re-shuffle for next cycle + if (currentTipIndex === 0) { + window.shuffledTips = shuffleTips(STEP_TIPS); + } + + tipTextElement.textContent = window.shuffledTips[currentTipIndex]; + tipTextElement.classList.remove('fade-out'); + }, 500); +} diff --git a/public/index.html b/public/index.html index 76aaf75..4168282 100644 --- a/public/index.html +++ b/public/index.html @@ -20,6 +20,12 @@ + +
+ 💡 + +
+
diff --git a/public/styles.css b/public/styles.css index 5a78967..5394ea1 100644 --- a/public/styles.css +++ b/public/styles.css @@ -39,6 +39,40 @@ header h1 { letter-spacing: 2px; } +/* Tip Banner */ +.tip-banner { + background: linear-gradient(135deg, #8a2be2 0%, #ff7700 100%); + padding: 15px 30px; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + border-bottom: 2px solid #ff7700; + box-shadow: 0 4px 15px rgba(138, 43, 226, 0.3); + min-height: 60px; +} + +.tip-icon { + font-size: 1.5rem; + flex-shrink: 0; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3)); +} + +.tip-text { + color: white; + font-size: 1.1rem; + font-weight: 500; + line-height: 1.4; + text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3); + opacity: 1; + transition: opacity 0.5s ease-in-out; +} + +.tip-text.fade-out { + opacity: 0; +} + .header-logo { max-width: 600px; width: 100%; @@ -720,6 +754,19 @@ nav { padding: 20px; } + .tip-banner { + padding: 12px 20px; + min-height: 50px; + } + + .tip-text { + font-size: 0.95rem; + } + + .tip-icon { + font-size: 1.2rem; + } + .stats-grid { grid-template-columns: 1fr; } diff --git a/step_competition.db b/step_competition.db index 36d3a1d..01ecfd3 100644 Binary files a/step_competition.db and b/step_competition.db differ