Enhance print layouts with branded headers and fix navigation consistency

- Replace plain print headers with full branded headers including logo
  - Add dynamic tournament-type styling (🎯 4-target,  20-target, 💪 40-target)
  - Remove border lines and optimize spacing for clean print appearance
  - Fix emoji positioning in league championship headers
  - Standardize navigation with proper active button indicators
  - Add missing translation keys for calculator instructions
  - Update print media queries for professional document output

  Print improvements:
  - Logo and branding now appear on printed results
  - Consistent 20px spacing between header and table
  - Clean white background with subtle borders
  - Optimized typography for print readability

  Navigation fixes:
  - Added active button highlighting across all PC pages
  - Consistent navigation order: Dashboard → Tournament → Player Analysis → Archive → Draft →
  Calculator
  - Fixed draft page active indicator

  🤖 Generated with Claude Code

  Co-Authored-By: Claude <noreply@anthropic.com>

  This commit message covers all the major improvements we made:
  - Print layout enhancements with branded headers
  - Navigation standardization and active indicators
  - Translation fixes
  - Visual styling improvements
  - Professional document output optimization
This commit is contained in:
2025-09-20 20:03:44 +02:00
parent 33758e7340
commit c61c1448e4
62 changed files with 45554 additions and 11528 deletions
+226 -95
View File
@@ -15,9 +15,8 @@
body {
font-family: Arial, sans-serif;
background: #f5f5f5;
height: 100vh;
min-height: 100vh;
color: #333;
overflow: hidden;
}
/* Enhanced Navigation Bar */
@@ -33,14 +32,14 @@
}
.navbar-title {
font-size: 1.5rem;
font-size: 1.8rem;
font-weight: bold;
color: #333;
}
.navbar-controls {
display: flex;
gap: 10px;
gap: 12px;
align-items: center;
}
@@ -66,34 +65,69 @@
color: #007bff;
}
.nav-btn.primary {
.nav-btn.active {
background: #007bff;
border-color: #0056b3;
color: white;
}
.nav-btn.primary:hover {
.nav-btn.active:hover {
background: #0056b3;
color: white;
}
/* Main Container */
/* Standardized Container */
.container {
height: calc(100vh - 60px);
padding: 15px;
display: flex;
flex-direction: column;
gap: 15px;
overflow: hidden;
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
/* Top Section - Stats and Charts */
.top-section {
/* Stats Overview */
.stats-badges {
display: grid;
grid-template-columns: 320px 1fr;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 15px;
height: 50%;
min-height: 280px;
margin-bottom: 20px;
}
.stat-badge {
background: white;
border-radius: 12px;
padding: 15px;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
border: 1px solid #e9ecef;
transition: transform 0.3s ease;
}
.stat-badge:hover {
transform: translateY(-2px);
}
.stat-icon {
font-size: 1.5rem;
margin-bottom: 8px;
display: block;
}
.stat-number {
font-size: 1.5rem;
font-weight: bold;
color: #333;
margin-bottom: 5px;
}
.stat-label {
color: #666;
font-size: 0.75rem;
font-weight: 500;
}
/* Charts Section */
.charts-section {
min-height: 450px;
flex-shrink: 0;
}
/* Stats Panel */
@@ -154,6 +188,7 @@
padding: 18px;
display: flex;
flex-direction: column;
width: 100%;
}
/* Tournament Type Buttons */
@@ -283,11 +318,24 @@
.chart-container {
position: relative;
flex: 1;
min-height: 200px;
min-height: 400px;
max-height: 500px;
background: white;
border-radius: 6px;
border: 1px solid #e9ecef;
padding: 10px;
padding: 15px;
width: 100%;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.chart-container canvas {
max-width: calc(100% - 10px) !important;
max-height: calc(100% - 10px) !important;
width: 100% !important;
height: auto !important;
}
.no-data {
@@ -308,25 +356,31 @@
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
flex: 1;
min-height: 0;
min-height: 350px;
max-height: 450px;
flex-shrink: 0;
margin-top: 30px;
}
.history-section {
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 18px;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
padding: 24px;
display: flex;
flex-direction: column;
min-height: 0;
min-height: 300px;
max-height: 100%;
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
}
.history-list {
flex: 1;
overflow-y: auto;
padding-right: 8px;
min-height: 0;
min-height: 200px;
max-height: 320px;
}
/* Custom scrollbar */
@@ -350,21 +404,41 @@
/* Tournament History Items */
.history-item {
background: linear-gradient(135deg, #f8f9fa 0%, #e3f2fd 100%);
border-radius: 8px;
padding: 12px;
margin-bottom: 8px;
background: linear-gradient(135deg, #f8f9fa 0%, #e8f4fd 100%);
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s ease;
border-left: 3px solid #2196f3;
border-left: 4px solid #2196f3;
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid rgba(33, 150, 243, 0.1);
position: relative;
overflow: hidden;
}
.history-item::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 3px;
height: 100%;
background: linear-gradient(135deg, #2196f3 0%, #64b5f6 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.history-item:hover::before {
opacity: 1;
}
.history-item:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(33, 150, 243, 0.2);
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(33, 150, 243, 0.15);
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
border-color: rgba(33, 150, 243, 0.2);
}
.history-info {
@@ -393,18 +467,38 @@
/* League History Items */
.league-history-item {
background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%);
border-radius: 8px;
padding: 12px;
margin-bottom: 8px;
background: linear-gradient(135deg, #f3e5f5 0%, #f0e6ff 100%);
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
transition: all 0.3s ease;
border-left: 3px solid #9c27b0;
border-left: 4px solid #9c27b0;
border: 1px solid rgba(156, 39, 176, 0.1);
position: relative;
overflow: hidden;
}
.league-history-item::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 3px;
height: 100%;
background: linear-gradient(135deg, #9c27b0 0%, #ba68c8 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.league-history-item:hover::before {
opacity: 1;
}
.league-history-item:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(156, 39, 176, 0.2);
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(156, 39, 176, 0.15);
background: linear-gradient(135deg, #e1bee7 0%, #ce93d8 100%);
border-color: rgba(156, 39, 176, 0.2);
}
.league-header {
@@ -504,7 +598,7 @@
@media (max-width: 1200px) {
.top-section {
grid-template-columns: 1fr;
height: 55%;
min-height: 320px;
}
}
@@ -522,7 +616,7 @@
}
.container {
height: calc(100vh - 80px);
min-height: calc(100vh - 100px);
padding: 10px;
}
@@ -535,8 +629,27 @@
}
.top-section {
height: auto;
min-height: 200px;
min-height: 250px;
}
.bottom-section {
min-height: 500px;
max-height: none;
}
.history-section {
min-height: 220px;
}
.history-list {
min-height: 150px;
max-height: 200px;
}
.chart-container {
max-height: 350px;
min-height: 300px;
padding: 10px;
}
}
</style>
@@ -544,62 +657,65 @@
<body>
<!-- Navigation Bar -->
<div class="navbar">
<div class="navbar-title">📊 {{ player.name }} - Stats</div>
<div class="navbar-title">📊 {{ player.name }} - <span data-i18n="players.player_stats">Stats</span></div>
<div class="navbar-controls">
<a href="/archive/player-analysis" class="nav-btn">👤 All Players</a>
<a href="/archive" class="nav-btn">📚 Archive</a>
<a href="/" class="nav-btn primary">🏠 Dashboard</a>
<a href="/" class="nav-btn">🏠 <span data-i18n="navigation.dashboard">Dashboard</span></a>
<a href="/tournament" class="nav-btn">🏆 <span data-i18n="navigation.tournament">Tournament</span></a>
<a href="/archive/player-analysis" class="nav-btn active">👤 <span data-i18n="players.player_analysis">Player Analysis</span></a>
<a href="/archive" class="nav-btn">📚 <span data-i18n="navigation.archive">Archive</span></a>
</div>
</div>
<div class="container">
<!-- Top Section - Stats and Charts -->
<div class="top-section">
<!-- Stats Panel -->
<div class="stats-panel">
<div class="panel-title">📊 Statistics</div>
<div class="stats-grid">
<div class="stat-item">
<div class="stat-value">{{ stats.total_tournaments }}</div>
<div class="stat-label">Tournaments</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ stats.total_leagues }}</div>
<div class="stat-label">Leagues</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ stats.best_tournament_score }}</div>
<div class="stat-label">Best Score</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ stats.average_tournament_score|round|int if stats.average_tournament_score > 0 else 0 }}</div>
<div class="stat-label">Average</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ stats.total_shots_fired|default(0) }}</div>
<div class="stat-label">Total Shots</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ stats.worst_tournament_score if stats.worst_tournament_score > 0 else 0 }}</div>
<div class="stat-label">Worst Score</div>
</div>
</div>
<!-- Stats Overview -->
<div class="stats-badges">
<div class="stat-badge">
<span class="stat-icon">🏆</span>
<div class="stat-number">{{ stats.total_tournaments }}</div>
<div class="stat-label" data-i18n="tournament.tournaments">Tournaments</div>
</div>
<div class="stat-badge">
<span class="stat-icon">🎖️</span>
<div class="stat-number">{{ stats.total_leagues }}</div>
<div class="stat-label" data-i18n="league.league">Leagues</div>
</div>
<div class="stat-badge">
<span class="stat-icon"></span>
<div class="stat-number">{{ stats.best_tournament_score }}</div>
<div class="stat-label" data-i18n="results.best_score">Best Score</div>
</div>
<div class="stat-badge">
<span class="stat-icon">📊</span>
<div class="stat-number">{{ stats.average_tournament_score|round|int if stats.average_tournament_score > 0 else 0 }}</div>
<div class="stat-label" data-i18n="results.average_score">Average</div>
</div>
<div class="stat-badge">
<span class="stat-icon">🔫</span>
<div class="stat-number">{{ stats.total_shots_fired|default(0) }}</div>
<div class="stat-label" data-i18n="results.total_shots">Total Shots</div>
</div>
<div class="stat-badge">
<span class="stat-icon">📉</span>
<div class="stat-number">{{ stats.worst_tournament_score if stats.worst_tournament_score > 0 else 0 }}</div>
<div class="stat-label" data-i18n="results.worst_score">Worst Score</div>
</div>
</div>
<!-- Performance Charts -->
<!-- Charts Section -->
<div class="charts-section">
<div class="charts-panel">
<div class="panel-title">📈 Performance by Tournament Type</div>
<div class="panel-title">📈 <span data-i18n="analysis.performance">Performance by Tournament Type</span></div>
<!-- Tournament Type Buttons -->
<div class="tournament-type-buttons">
<button class="type-btn active targets-40" data-type="40 Targets">
<span>💪</span> 40 Targets
<span>💪</span> <span data-i18n="tournament_types.40_targets">40 Targets</span>
</button>
<button class="type-btn targets-20" data-type="20 Targets">
<span></span> 20 Targets
<span></span> <span data-i18n="tournament_types.20_targets">20 Targets</span>
</button>
<button class="type-btn targets-4" data-type="4 Targets">
<span>🎯</span> 4 Targets
<span>🎯</span> <span data-i18n="tournament_types.4_targets">4 Targets</span>
</button>
</div>
@@ -608,15 +724,15 @@
<div class="chart-stats">
<div class="chart-stat">
<div class="chart-stat-value" id="gameCount">0</div>
<div class="chart-stat-label">Games</div>
<div class="chart-stat-label" data-i18n="tournament.tournaments">Games</div>
</div>
<div class="chart-stat">
<div class="chart-stat-value" id="avgScore">0</div>
<div class="chart-stat-label">Average</div>
<div class="chart-stat-label" data-i18n="results.average_score">Average</div>
</div>
<div class="chart-stat">
<div class="chart-stat-value" id="bestScore">0</div>
<div class="chart-stat-label">Best</div>
<div class="chart-stat-label" data-i18n="results.best_score">Best</div>
</div>
</div>
@@ -680,14 +796,14 @@
<div class="bottom-section">
<!-- Tournament History -->
<div class="history-section">
<div class="panel-title">🎯 Tournament History</div>
<div class="panel-title">🎯 <span data-i18n="analysis.tournament_history">Tournament History</span></div>
{% if stats.tournament_history %}
<div class="history-list">
{% for tournament in stats.tournament_history[:10] %}
<div class="history-item">
<div class="history-info">
<div class="history-date">{{ tournament.date[:10] if tournament.date != 'Unknown' else 'Unknown Date' }}</div>
<div class="history-type">{{ tournament.tournament_type.replace('_', ' ')|title }} • {{ tournament.shots_fired }} shots</div>
<div class="history-date">{{ tournament.date[:10] if tournament.date != 'Unknown' else (translations.analysis.unknown_date if translations else 'Unknown Date') }}</div>
<div class="history-type">{{ tournament.tournament_type.replace('_', ' ')|title }} • {{ tournament.shots_fired }} {{ translations.results.shots if translations else 'shots' }}</div>
</div>
<div class="history-score">{{ tournament.score }}</div>
</div>
@@ -718,7 +834,7 @@
<div class="history-date">{{ league.date[:10] if league.date != 'Unknown' else 'Unknown Date' }}</div>
<div class="history-type">
League Championship • {{ league.tournaments_participated }}/6 tournaments
{% if league.joker_used %} • 🃏 Joker Used{% endif %}
{% if league.joker_used %} • 🃏 {{ translations.league.joker_used if translations else 'Joker Used' }}{% endif %}
</div>
</div>
<div class="league-score-display">{{ league.final_score }}</div>
@@ -732,7 +848,7 @@
<div class="tournament-results">
{% for result in league.tournament_results %}
<span class="tournament-result {{ 'participated' if result.participated else 'joker' }}">
T{{ result.tournament }}: {{ result.score if result.participated else 'Joker' }}
T{{ result.tournament }}: {{ result.score if result.participated else (translations.league.joker_used if translations else 'Joker') }}
</span>
{% endfor %}
</div>
@@ -1122,5 +1238,20 @@
// Initialize page when DOM is loaded
document.addEventListener('DOMContentLoaded', initializePage);
</script>
<!-- Internationalization Support -->
<script src="/static/js/i18n.js"></script>
<script>
// Initialize translations with server data
if (typeof {{ translations|tojson }} !== 'undefined') {
currentTranslations = {{ translations|tojson }};
currentLanguage = '{{ current_language }}';
// Apply translations when DOM is ready
document.addEventListener('DOMContentLoaded', function() {
translatePage();
});
}
</script>
</body>
</html>