RosterHash/templates/base.html
2025-10-31 10:11:05 -07:00

223 lines
9.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}RosterHash{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="icon" type="image/png" href="/favicon.ico">
<link rel="apple-touch-icon" href="/rosterhash_logo.png">
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
<meta name="theme-color" content="#8b7ff5">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
</head>
<body>
<!-- Hamburger Menu Button - Uses CSS-only solution -->
<input type="checkbox" id="menu-toggle" class="menu-toggle-checkbox">
<label for="menu-toggle" class="menu-toggle" aria-label="Toggle menu">
<span class="menu-icon"></span>
</label>
<!-- Sidebar Menu -->
<div class="sidebar" id="sidebar">
<div class="sidebar-header">
<h2 class="sidebar-title">Menu</h2>
<label for="menu-toggle" class="close-btn"></label>
</div>
<div class="sidebar-content">
<!-- About Section (Collapsible, closed by default) -->
<div class="sidebar-section">
<details class="sidebar-details">
<summary>About RosterHash</summary>
<div class="about-text">
<p>At-a-glance view of your Sleeper leagues and player schedules.</p>
<p><strong>Features:</strong></p>
<ul>
<li>View all league matchups</li>
<li>See player schedules by game</li>
<li>Track favorite NFL teams</li>
<li>League color-coding</li>
</ul>
<p class="cron-note">* * * * 4,7,1</p>
</div>
</details>
</div>
<!-- Favorite Teams Section (Collapsible, closed by default) -->
<div class="sidebar-section">
<details class="sidebar-details">
<summary>⭐ Favorite Teams</summary>
<div class="details-content">
<div id="favorites-list" class="favorites-list">
<p class="favorites-empty">Click teams below to add favorites (max 4)</p>
</div>
<!-- Select Teams subsection -->
<div class="favorites-subsection">
<h4 class="subsection-title">Select Teams</h4>
<div class="scrollable-content">
<div id="games-picker" class="games-picker">
<!-- Populated by JavaScript -->
</div>
</div>
</div>
</div>
</details>
</div>
<!-- Actions and Links (No title) -->
<div class="sidebar-section sidebar-actions">
<!-- Theme Toggle -->
<form method="post" action="/toggle_theme">
<input type="hidden" name="return_url" value="{{ request.url }}">
<button type="submit" class="sidebar-action-btn">
{% if current_theme == 'dark' %}
<span class="btn-icon">🌙</span>
<span>Change to Light Theme</span>
{% else %}
<span class="btn-icon">☀️</span>
<span>Change to Dark Theme</span>
{% endif %}
</button>
</form>
<!-- Sleeper App Link -->
<a href="https://sleeper.app" target="_blank" class="sidebar-action-btn">
<span class="btn-icon">🏈</span>
<span>Sleeper App</span>
</a>
<!-- Source Code Link -->
<a href="https://codeberg.org/edfig/RosterHash" target="_blank" class="sidebar-action-btn">
<span class="btn-icon">💻</span>
<span>Source Code</span>
</a>
</div>
</div>
</div>
<!-- Overlay for sidebar -->
<label for="menu-toggle" class="sidebar-overlay" id="sidebar-overlay"></label>
<div class="container">
{% block content %}{% endblock %}
</div>
<!-- App version footer -->
<footer class="app-footer">
<div class="version">RosterHash v{{ app_version }}</div>
</footer>
<!-- Set theme based on server-side session -->
<script>
// Apply theme immediately to prevent flash
document.documentElement.setAttribute('data-theme', '{{ current_theme }}');
// For modern browsers with light-dark() support, also set color-scheme
document.documentElement.style.colorScheme = '{{ current_theme }}';
// Detect user's timezone and send to server if not already set
{% if not session.get('user_timezone') %}
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (userTimezone) {
// Send timezone to server via hidden form submission
const form = document.createElement('form');
form.method = 'POST';
form.action = '/set_timezone';
form.style.display = 'none';
const timezoneInput = document.createElement('input');
timezoneInput.type = 'hidden';
timezoneInput.name = 'timezone';
timezoneInput.value = userTimezone;
const returnUrlInput = document.createElement('input');
returnUrlInput.type = 'hidden';
returnUrlInput.name = 'return_url';
returnUrlInput.value = window.location.href;
form.appendChild(timezoneInput);
form.appendChild(returnUrlInput);
document.body.appendChild(form);
form.submit();
}
{% endif %}
// Collapsible functionality
function toggleDay(dayKey) {
const dayRow = document.querySelector(`[data-day="${dayKey}"]`);
const dayGames = document.getElementById(`day-${dayKey}`);
const indicator = dayRow.querySelector('.collapse-indicator');
dayRow.classList.toggle('collapsed');
if (dayRow.classList.contains('collapsed')) {
indicator.textContent = '▶';
dayGames.style.display = 'none';
} else {
indicator.textContent = '▼';
dayGames.style.display = 'block';
// Expand all games in this day
const gameCards = dayGames.querySelectorAll('.game-card');
gameCards.forEach(card => {
card.classList.remove('collapsed');
const gameIndicator = card.querySelector('.game-collapse-indicator');
const gameContent = card.querySelector('.game-content');
if (gameIndicator) gameIndicator.textContent = '▼';
if (gameContent) gameContent.style.display = 'block';
});
}
}
function toggleGame(dayKey, gameIndex) {
const gameCard = document.querySelector(`[data-day="${dayKey}"] [data-game="${gameIndex}"]`);
const gameContent = document.getElementById(`game-${dayKey}-${gameIndex}`);
const indicator = gameCard.querySelector('.game-collapse-indicator');
gameCard.classList.toggle('collapsed');
if (gameCard.classList.contains('collapsed')) {
indicator.textContent = '▶';
gameContent.style.display = 'none';
} else {
indicator.textContent = '▼';
gameContent.style.display = 'block';
}
}
// Initialize collapsed states on page load
document.addEventListener('DOMContentLoaded', function() {
// Hide content for collapsed day rows
document.querySelectorAll('.day-row.collapsed .day-games').forEach(dayGames => {
dayGames.style.display = 'none';
});
// Hide content for collapsed game cards
document.querySelectorAll('.game-card.collapsed .game-content').forEach(gameContent => {
gameContent.style.display = 'none';
});
});
// Register service worker for PWA functionality
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/static/sw.js')
.then(function(registration) {
console.log('RosterHash SW: Registered successfully');
})
.catch(function(error) {
console.log('RosterHash SW: Registration failed:', error);
});
});
}
</script>
<!-- Favorites Management Script -->
<script src="{{ url_for('static', filename='favorites.js') }}"></script>
<!-- Easter Eggs Script -->
<script src="{{ url_for('static', filename='easter-eggs.js') }}"></script>
</body>
</html>