RosterHash/templates/loading.html
efigueroa 1837590a79 Add loading states and performance optimizations
Performance Improvements:
- Added loading template with skeleton UI and progress animations
- Split routes: show loading state immediately, then fetch data
- Added memory cache for API responses (5-minute TTL)
- Cached expensive calls: user lookup, NFL state, user leagues
- Meta refresh redirect instead of JavaScript for no-JS requirement

User Experience:
- Immediate page load with branded loading screen
- Skeleton UI shows expected layout structure
- Progress bar and spinner animations during load
- Users see something instantly instead of blank page

Technical Details:
- /<username> and /<username>/<week> now show loading.html first
- /<username>/<week>/data route handles actual API calls
- Simple memory cache with fallback to stale data on errors
- CSS animations for loading states and skeleton placeholders

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-06 23:20:09 -07:00

95 lines
No EOL
3.1 KiB
HTML

{% extends "base.html" %}
{% block title %}Loading {{ username }} - Week {{ week }}{% endblock %}
{% block head %}
<!-- Auto-redirect to data route after 2 seconds -->
<meta http-equiv="refresh" content="2;url=/{{ username }}/{{ week }}/data">
{% endblock %}
{% block content %}
<!-- Header with user name and week navigation -->
<header class="dashboard-header">
<h1>{{ username }} <span class="loading-indicator"></span></h1>
<div class="week-nav">
<span class="week-btn disabled">← Week {{ week - 1 }}</span>
<span class="current-week">Week {{ week }}</span>
<span class="week-btn disabled">Week {{ week + 1 }} →</span>
</div>
<!-- Loading refresh button -->
<div class="refresh-nav">
<button class="refresh-btn disabled" disabled>🔄 Loading...</button>
</div>
</header>
<!-- Loading message -->
<section class="loading-section">
<div class="loading-container">
<div class="loading-spinner"></div>
<h2>Loading your fantasy data...</h2>
<p>Fetching leagues and player information</p>
<div class="loading-progress">
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
</div>
</div>
</section>
<!-- Skeleton loading for leagues -->
<section class="scores-summary">
<div class="skeleton-score-row">
<div class="skeleton-league-info">
<div class="skeleton-dot"></div>
<div class="skeleton-text skeleton-league-name"></div>
</div>
<div class="skeleton-score-compact">
<div class="skeleton-text skeleton-score"></div>
</div>
</div>
<div class="skeleton-score-row">
<div class="skeleton-league-info">
<div class="skeleton-dot"></div>
<div class="skeleton-text skeleton-league-name"></div>
</div>
<div class="skeleton-score-compact">
<div class="skeleton-text skeleton-score"></div>
</div>
</div>
<div class="skeleton-score-row">
<div class="skeleton-league-info">
<div class="skeleton-dot"></div>
<div class="skeleton-text skeleton-league-name"></div>
</div>
<div class="skeleton-score-compact">
<div class="skeleton-text skeleton-score"></div>
</div>
</div>
</section>
<!-- Skeleton loading for games -->
<section class="schedule-section">
<h2>Week {{ week }} Games <br><span class="skeleton-text skeleton-timezone"></span></h2>
<div class="calendar-rows">
<div class="skeleton-day-row">
<div class="skeleton-day-header">
<div class="skeleton-text skeleton-day-name"></div>
</div>
</div>
<div class="skeleton-day-row">
<div class="skeleton-day-header">
<div class="skeleton-text skeleton-day-name"></div>
</div>
</div>
<div class="skeleton-day-row">
<div class="skeleton-day-header">
<div class="skeleton-text skeleton-day-name"></div>
</div>
</div>
</div>
</section>
{% endblock %}