diff options
Diffstat (limited to 'templates')
| -rw-r--r-- | templates/admin.html | 138 | ||||
| -rw-r--r-- | templates/admin_edit_game.html | 66 | ||||
| -rw-r--r-- | templates/admin_manage_teams.html | 76 | ||||
| -rw-r--r-- | templates/base.html | 54 | ||||
| -rw-r--r-- | templates/game.html | 185 | ||||
| -rw-r--r-- | templates/login.html | 16 | ||||
| -rw-r--r-- | templates/season.html | 285 | ||||
| -rw-r--r-- | templates/team.html | 65 |
8 files changed, 885 insertions, 0 deletions
diff --git a/templates/admin.html b/templates/admin.html new file mode 100644 index 0000000..19c7bd9 --- /dev/null +++ b/templates/admin.html @@ -0,0 +1,138 @@ +{% extends "base.html" %} + +{% block content %} + <h2>League Administration</h2> + + <div style="display: flex; gap: 2rem; flex-wrap: wrap;"> + <div style="flex: 1; min-width: 300px;"> + <h3>Create New Season</h3> + <form method="POST"> + <input type="hidden" name="action" value="create_season"> + <div> + <label for="name">Season Name:</label> + <input type="text" id="name" name="name" required> + </div> + <button type="submit">Create Season</button> + </form> + </div> + + <div style="flex: 1; min-width: 300px;"> + <h3>Create Team/User</h3> + <form method="POST"> + <input type="hidden" name="action" value="create_team"> + <div> + <label for="username">Username:</label> + <input type="text" id="username" name="username" required> + </div> + <div> + <label for="password">Password:</label> + <input type="password" id="password" name="password" required> + </div> + <div> + <label for="team_name">Team Name:</label> + <input type="text" id="team_name" name="team_name" required> + </div> + <button type="submit">Create Team</button> + </form> + </div> + </div> + + <div style="margin-top: 2rem;"> + <h3>Manage Seasons</h3> + {% if seasons %} + <table> + <tr> + <th>ID</th> + <th>Name</th> + <th>Status</th> + <th>Actions</th> + </tr> + {% for season in seasons %} + <tr> + <td>{{ season.id }}</td> + <td>{{ season.name }}</td> + <td>{{ season.status }}</td> + <td> + <form method="GET" action="{{ url_for('admin_manage_teams', season_id=season.id) }}" style="display:inline;"> + <button type="submit">Manage Teams</button> + </form> + <button onclick="toggleScheduleForm({{ season.id }})">Generate Schedule/Playoffs</button> + + <div id="form-{{ season.id }}" style="display:none; background: #f0f0f0; padding: 1rem; border: 1px solid #ccc; margin-top: 10px; text-align: left;"> + <form id="sched-form-{{ season.id }}" onsubmit="submitGenerate(event, {{ season.id }})"> + <div> + <label>Total Games (per team):</label> + <input type="number" name="total_games" value="10" required style="width: 60px;"> + </div> + <div> + <label>Games Per Week:</label> + <input type="number" name="games_per_week" value="3" required style="width: 60px;"> + </div> + <div> + <label>Playoff Teams (2 or 4):</label> + <input type="number" name="playoff_teams" value="4" required style="width: 60px;"> + </div> + <div> + <label>Series Length (1, 3, 5):</label> + <input type="number" name="playoff_series_length" value="3" required style="width: 60px;"> + </div> + <button type="submit" style="margin-top: 10px;">Generate</button> + </form> + </div> + <form method="POST" action="{{ url_for('admin_delete_season', season_id=season.id) }}" style="display:inline;" onsubmit="return confirm('Are you sure you want to delete this season and all its games?')"> + <button type="submit" style="background-color: #cc0000; color: white;">Delete</button> + </form> + </td> + </tr> + {% endfor %} + </table> + + <script> + function toggleScheduleForm(id) { + var f = document.getElementById('form-' + id); + f.style.display = f.style.display === 'none' ? 'block' : 'none'; + } + + function submitGenerate(event, id, confirmed = false) { + event.preventDefault(); + var form = document.getElementById('sched-form-' + id); + var formData = new FormData(form); + if (confirmed) formData.append('confirm', 'true'); + + fetch('/admin/season/' + id + '/generate_schedule', { + method: 'POST', + body: formData, + headers: {'X-Requested-With': 'XMLHttpRequest'} + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'confirm_required') { + if (confirm(data.message)) { + submitGenerate(event, id, true); + } + } else if (data.status === 'success') { + window.location.href = data.redirect; + } else { + alert('An error occurred.'); + } + }); + } + </script> + {% else %} + <p>No seasons created yet.</p> + {% endif %} + </div> + + <div style="margin-top: 2rem;"> + <h3>Registered Teams</h3> + {% if teams %} + <ul> + {% for team in teams %} + <li>{{ team.team_name }} ({{ team.username }})</li> + {% endfor %} + </ul> + {% else %} + <p>No teams registered yet.</p> + {% endif %} + </div> +{% endblock %}
\ No newline at end of file diff --git a/templates/admin_edit_game.html b/templates/admin_edit_game.html new file mode 100644 index 0000000..2651185 --- /dev/null +++ b/templates/admin_edit_game.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Admin: Edit Game {{ game.id }}</h2> + <p>Matchup: {{ game.away_team if game.away_team else 'TBD' }} @ {{ game.home_team if game.home_team else 'TBD' }}</p> + + <form method="POST" style="max-width: 100%;"> + <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border); width: 100%; box-sizing: border-box;"> + <div style="display: flex; gap: 2rem; flex-wrap: wrap;"> + <div style="flex: 1; min-width: 200px;"> + <label for="scheduled_date">Scheduled Date (YYYY-MM-DD):</label> + <input type="text" id="scheduled_date" name="scheduled_date" value="{{ game.scheduled_date }}" style="width: 100%;"> + </div> + <div style="flex: 1; min-width: 200px;"> + <label for="status">Status:</label> + <select id="status" name="status" style="width: 100%;"> + <option value="Scheduled" {% if game.status == 'Scheduled' %}selected{% endif %}>Scheduled</option> + <option value="Final" {% if game.status == 'Final' %}selected{% endif %}>Final</option> + <option value="TBD" {% if game.status == 'TBD' %}selected{% endif %}>TBD</option> + <option value="Canceled" {% if game.status == 'Canceled' %}selected{% endif %}>Canceled</option> + </select> + </div> + </div> + + <div style="display: flex; gap: 2rem; margin-top: 1rem; flex-wrap: wrap;"> + <div style="flex: 1; min-width: 200px;"> + <label for="away_score">{{ game.away_team if game.away_team else 'Away' }} Score:</label> + <input type="number" id="away_score" name="away_score" value="{{ game.away_score if game.away_score is not none else '' }}" style="width: 100%;"> + </div> + <div style="flex: 1; min-width: 200px;"> + <label for="home_score">{{ game.home_team if game.home_team else 'Home' }} Score:</label> + <input type="number" id="home_score" name="home_score" value="{{ game.home_score if game.home_score is not none else '' }}" style="width: 100%;"> + </div> + </div> + + <div style="margin-top: 2rem; overflow-x: auto;"> + <label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Box Score (Optional):</label> + <table style="width: 100%; border: 1px solid var(--deco-border); background: #fff; min-width: 600px;"> + <tr style="background: #eee;"> + <th>Team</th> + <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Ex</th><th>R</th><th>H</th><th>E</th> + </tr> + <tr> + <td style="font-weight: bold; font-size: 0.8rem; padding: 5px;">{{ game.away_team if game.away_team else 'Away' }}</td> + {% set bs_a = game.box_score.away if game.box_score else [0,0,0,0,0,0,0,0,0,0,0,0,0] %} + {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %} + <td style="padding: 2px;"><input type="number" name="away_inn_{{ col }}" value="{{ bs_a[loop.index0] }}" style="width: 35px; padding: 2px; text-align: center;"></td> + {% endfor %} + </tr> + <tr> + <td style="font-weight: bold; font-size: 0.8rem; padding: 5px;">{{ game.home_team if game.home_team else 'Home' }}</td> + {% set bs_h = game.box_score.home if game.box_score else [0,0,0,0,0,0,0,0,0,0,0,0,0] %} + {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %} + <td style="padding: 2px;"><input type="number" name="home_inn_{{ col }}" value="{{ bs_h[loop.index0] }}" style="width: 35px; padding: 2px; text-align: center;"></td> + {% endfor %} + </tr> + </table> + </div> + + <div style="margin-top: 2rem; display: flex; gap: 1rem;"> + <button type="submit" style="padding: 10px 30px;">Update Game</button> + <a href="{{ url_for('game', game_id=game.id) }}" style="display: inline-block; background: #ddd; color: #333; padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; border: 1px solid #ccc;">Cancel</a> + </div> + </div> + </form> +{% endblock %}
\ No newline at end of file diff --git a/templates/admin_manage_teams.html b/templates/admin_manage_teams.html new file mode 100644 index 0000000..669d622 --- /dev/null +++ b/templates/admin_manage_teams.html @@ -0,0 +1,76 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Manage Teams for Season: {{ season.name }}</h2> + + <div style="display: flex; gap: 2rem; flex-wrap: wrap;"> + <!-- Left Column: Pending and Approved Teams --> + <div style="flex: 1; min-width: 300px;"> + <h3>Pending Requests</h3> + {% if pending_teams %} + <ul style="list-style: none; padding: 0;"> + {% for team in pending_teams %} + <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;"> + <span>{{ team.team_name }} ({{ team.username }})</span> + <div style="display: flex; gap: 0.5rem;"> + <form method="POST" style="margin:0; width: auto;"> + <input type="hidden" name="action" value="approve"> + <input type="hidden" name="user_id" value="{{ team.id }}"> + <button type="submit" style="background-color: green; font-size: 0.8rem; padding: 4px 8px;">Approve</button> + </form> + <form method="POST" style="margin:0; width: auto;"> + <input type="hidden" name="action" value="deny"> + <input type="hidden" name="user_id" value="{{ team.id }}"> + <button type="submit" style="background-color: red; font-size: 0.8rem; padding: 4px 8px;">Deny</button> + </form> + </div> + </li> + {% endfor %} + </ul> + {% else %} + <p>No pending requests.</p> + {% endif %} + + <h3 style="margin-top: 2rem;">Approved Teams</h3> + {% if approved_teams %} + <ul style="list-style: none; padding: 0;"> + {% for team in approved_teams %} + <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;"> + <span>{{ team.team_name }} ({{ team.username }})</span> + <form method="POST" style="margin:0; width: auto;"> + <input type="hidden" name="action" value="remove"> + <input type="hidden" name="user_id" value="{{ team.id }}"> + <button type="submit" style="background-color: red; font-size: 0.8rem; padding: 4px 8px;">Remove</button> + </form> + </li> + {% endfor %} + </ul> + {% else %} + <p>No approved teams.</p> + {% endif %} + </div> + + <!-- Right Column: Add Teams Directly --> + <div style="flex: 1; min-width: 300px; background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border);"> + <h3>Directly Add Teams</h3> + <p>Select teams to bypass the request process and approve immediately.</p> + <form method="POST"> + <input type="hidden" name="action" value="add"> + <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 1.5rem;"> + {% for team in all_teams %} + {% if team.id not in enrolled_ids %} + <label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;"> + <input type="checkbox" name="team_ids" value="{{ team.id }}"> + {{ team.team_name }} + </label> + {% endif %} + {% endfor %} + </div> + <button type="submit">Add Selected Teams</button> + </form> + <div style="margin-top: 2rem;"> + <a href="{{ url_for('admin') }}" style="color: var(--text-accent); text-decoration: underline; font-weight: bold;">← Back to Admin Dashboard</a> + </div> + </div> + </div> +{% endblock %}
\ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..9172079 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>The Orchard League</title> + <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> +</head> +<body> + <img src="{{ url_for('static', filename='img/orchards_left.png') }}" class="side-image left"> + <img src="{{ url_for('static', filename='img/orchards_right.png') }}" class="side-image right"> + <header> + <div class="logo-container"> + <img src="{{ url_for('static', filename='img/logo.png') }}"/> + <div class="text-wrap"> + <h1>THE ORCHARD LEAGUE</h1> + <p class="subtitle">Established 2026</p> + </div> + </div> + <nav> + <a href="{{ url_for('index') }}">Seasons</a> + {% if current_user.is_authenticated %} + <a href="{{ url_for('team') }}">Team Management ({{ current_user.team_name }})</a> + {% if current_user.is_admin %} + <a href="{{ url_for('admin') }}">Admin</a> + {% endif %} + <a href="{{ url_for('logout') }}">Logout ({{ current_user.username }})</a> + {% else %} + <a href="{{ url_for('login') }}">Login</a> + {% endif %} + </nav> + </header> + + <main> + <div class="flashes"> + {% with messages = get_flashed_messages() %} + {% if messages %} + <ul class="flash-messages"> + {% for message in messages %} + <li>{{ message }}</li> + {% endfor %} + </ul> + {% endif %} + {% endwith %} + </div> + + {% block content %}{% endblock %} + </main> + + <footer> + <p>© Blessings; WWCH -Chairman of the Orchard League.</p> + </footer> +</body> +</html>
\ No newline at end of file diff --git a/templates/game.html b/templates/game.html new file mode 100644 index 0000000..690e16d --- /dev/null +++ b/templates/game.html @@ -0,0 +1,185 @@ +{% extends "base.html" %} + +{% block content %} + <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem;"> + <a href="{{ url_for('index', season_id=game.season_id, tab='schedule') }}" + style="text-decoration: none; background: #ddd; color: #333; padding: 5px 15px; font-family: var(--sans-font); font-weight: bold; border: 1px solid #ccc;"> + ← Back to Schedule + </a> + <h2 style="margin: 0; flex: 1; border: none;">Game Details</h2> + </div> + + {% if game %} + <div style="display: flex; justify-content: center; gap: 4rem; align-items: center; margin: 2rem 0; background: var(--bg-primary); padding: 2rem; border: 2px solid var(--deco-border);"> + <div style="text-align: center;"> + <h3>Away</h3> + {% set is_away_team = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %} + {% if game.away_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" style="width:100px; height:100px; border-radius:50%; border: {{ '5px solid gold' if is_away_team else '2px solid var(--text-accent)' }};"> + {% else %} + <div style="width: 100px; height: 100px; border-radius: 50%; background-color: var(--deco-border); display: inline-block; border: {{ '5px solid gold' if is_away_team else 'none' }};"></div> + {% endif %} + <h4>{{ game.away_team if game.away_team else 'TBD' }}</h4> + <div style="font-size: 3rem; font-weight: bold; color: var(--deco-highlight);">{{ game.away_score if game.status == 'Final' else '-' }}</div> + </div> + + <div style="text-align: center;"> + <div style="color: var(--text-accent); font-size: 2rem; margin-bottom: 1rem;">VS</div> + <div style="color: var(--text-primary);">Date: {{ game.scheduled_date }}</div> + <div style="color: var(--deco-highlight); font-weight: bold; margin-top: 1rem; text-transform: uppercase;"> + {{ game.status }} + {% if game.is_conditional %}<span class="conditional-game" title="Conditional Game">*</span>{% endif %} + </div> + + {% if current_user.is_admin %} + <div style="margin-top: 1rem;"> + <a href="{{ url_for('admin_edit_game', game_id=game.id) }}" style="background: var(--deco-border); color: var(--bg-primary); padding: 5px 10px; text-decoration: none;">✎ Edit Game</a> + </div> + {% endif %} + </div> + + <div style="text-align: center;"> + <h3>Home</h3> + {% set is_home_team = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %} + {% if game.home_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" style="width:100px; height:100px; border-radius:50%; border: {{ '5px solid gold' if is_home_team else '2px solid var(--text-accent)' }};"> + {% else %} + <div style="width: 100px; height: 100px; border-radius: 50%; background-color: var(--deco-border); display: inline-block; border: {{ '5px solid gold' if is_home_team else 'none' }};"></div> + {% endif %} + <h4>{{ game.home_team if game.home_team else 'TBD' }}</h4> + <div style="font-size: 3rem; font-weight: bold; color: var(--deco-highlight);">{{ game.home_score if game.status == 'Final' else '-' }}</div> + </div> + </div> + + {% if game.status == 'Final' and game.box_score and (game.box_score.away|sum + game.box_score.home|sum) > 0 %} + <div style="margin-top: 2rem; overflow-x: auto;"> + <h3>Box Score</h3> + <table style="width: 100%; font-family: var(--sans-font); border: 2px solid #000;"> + <tr style="background: #eee;"> + <th>Team</th> + <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Extra</th> + <th style="background: #ddd;">R</th><th>H</th><th>E</th> + </tr> + <tr> + <td style="font-weight: bold;">{{ game.away_team }}</td> + {% for val in game.box_score.away %} + <td style="{{ 'background: #f9f9f9; font-weight: bold;' if loop.index > 10 else '' }}">{{ val }}</td> + {% endfor %} + </tr> + <tr> + <td style="font-weight: bold;">{{ game.home_team }}</td> + {% for val in game.box_score.home %} + <td style="{{ 'background: #f9f9f9; font-weight: bold;' if loop.index > 10 else '' }}">{{ val }}</td> + {% endfor %} + </tr> + </table> + </div> + {% endif %} + + {% if game.status != 'Final' and submissions %} + <div style="margin-top: 2rem;"> + <h3>Active Proposals</h3> + {% for s in submissions %} + {% set show_score = s.away_score is not none and (s.away_score != game.away_score or s.home_score != game.home_score) %} + {% set show_date = s.proposed_date and s.proposed_date != game.scheduled_date %} + + {% if show_score or show_date %} + <div style="background: #fff; border: 1px solid var(--deco-border); padding: 1rem; margin-bottom: 1rem; display: flex; justify-content: space-between; align-items: flex-start;"> + <div> + <p style="margin: 0;"><strong>From:</strong> {{ s.team_name }} ({{ s.username }})</p> + {% if show_score %} + <p style="margin: 0.5rem 0 0 0;"><strong>Score:</strong> {{ game.away_team }} {{ s.away_score }} - {{ game.home_team }} {{ s.home_score }}</p> + {% if s.box_score %} + <details style="margin-top: 0.5rem;"> + <summary style="cursor: pointer; font-size: 0.85rem; color: #555;">View Proposed Box Score</summary> + <table style="width: 100%; font-size: 0.75rem; margin-top: 0.5rem; border: 1px solid #ddd;"> + <tr style="background: #f5f5f5;"> + <th>Team</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Ex</th><th>R</th><th>H</th><th>E</th> + </tr> + <tr><td>Away</td>{% for v in s.box_score.away %}<td>{{ v }}</td>{% endfor %}</tr> + <tr><td>Home</td>{% for v in s.box_score.home %}<td>{{ v }}</td>{% endfor %}</tr> + </table> + </details> + {% endif %} + {% endif %} + {% if show_date %} + <p style="margin: 0.5rem 0 0 0;"><strong>Date Proposal:</strong> {{ s.proposed_date }}</p> + {% endif %} + </div> + <div style="display: flex; gap: 0.5rem;"> + {% if current_user.id|string == s.submitted_by_id|string %} + <form method="POST" action="{{ url_for('retract_submission', game_id=game.id) }}"> + <button type="submit" style="background-color: #cc0000; font-size: 0.8rem; padding: 5px 10px;">Retract</button> + </form> + {% elif current_user.is_authenticated and (current_user.id|string == game.away_team_id|string or current_user.id|string == game.home_team_id|string) %} + <form method="POST" action="{{ url_for('agree_submission', game_id=game.id, submission_id=s.id) }}"> + <button type="submit" style="background-color: #008800; font-size: 0.8rem; padding: 5px 10px;">Agree & Finalize</button> + </form> + {% endif %} + </div> + </div> + {% endif %} + {% endfor %} + </div> + {% endif %} + + {% if game.status != 'Final' and current_user.is_authenticated and (current_user.id|string == game.away_team_id|string or current_user.id|string == game.home_team_id|string) %} + <div style="margin-top: 2rem; display: flex; flex-direction: column; gap: 2rem;"> + <!-- Score Submission Form (Full Width) --> + <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border);"> + <h3>Submit Game Results</h3> + <form method="POST" action="{{ url_for('submit_game', game_id=game.id) }}" style="max-width: 100%;"> + <div style="display: flex; gap: 1rem; margin-bottom: 1rem; max-width: 400px;"> + <div style="flex: 1;"> + <label for="away_score" style="display: block; margin-bottom: 0.5rem;">{{ game.away_team }} Score:</label> + <input type="number" id="away_score" name="away_score" required style="width: 100%;"> + </div> + <div style="flex: 1;"> + <label for="home_score" style="display: block; margin-bottom: 0.5rem;">{{ game.home_team }} Score:</label> + <input type="number" id="home_score" name="home_score" required style="width: 100%;"> + </div> + </div> + + <div style="margin-bottom: 1rem; overflow-x: auto;"> + <label style="display: block; margin-bottom: 0.5rem;">Box Score (Optional):</label> + <table style="width: 100%; border: 1px solid var(--deco-border); background: #fff;"> + <tr style="background: #eee;"> + <th>Team</th> + <th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th><th>8</th><th>9</th><th>Extra</th><th>R</th><th>H</th><th>E</th> + </tr> + <tr> + <td style="font-weight: bold; font-size: 0.8rem;">{{ game.away_team if game.away_team else 'Away' }}</td> + {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %} + <td><input type="number" name="away_inn_{{ col }}" value="0" style="width: 35px; padding: 2px; text-align: center;"></td> + {% endfor %} + </tr> + <tr> + <td style="font-weight: bold; font-size: 0.8rem;">{{ game.home_team if game.home_team else 'Home' }}</td> + {% for col in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "extra", "runs", "hits", "errors"] %} + <td><input type="number" name="home_inn_{{ col }}" value="0" style="width: 35px; padding: 2px; text-align: center;"></td> + {% endfor %} + </tr> + </table> + </div> + + <button type="submit" style="width: 200px;">Submit Scores</button> + </form> + </div> + + <!-- Date Change Form --> + <div style="background: var(--bg-primary); padding: 2rem; border: 1px solid var(--deco-border); max-width: 400px;"> + <h3>Propose Date Change</h3> + <form method="POST" action="{{ url_for('submit_game', game_id=game.id) }}" style="max-width: 100%;"> + <div style="margin-bottom: 1rem;"> + <label for="proposed_date" style="display: block; margin-bottom: 0.5rem;">New Date:</label> + <input type="text" id="proposed_date" name="proposed_date" placeholder="YYYY-MM-DD" style="width: 100%;"> + </div> + <button type="submit" style="width: 100%; background-color: var(--deco-highlight); color: white;">Propose Date</button> + </form> + </div> + </div> + {% endif %} + {% else %} + <p>Game not found.</p> + {% endif %} +{% endblock %}
\ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..f8f19b6 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Team Owner Login</h2> + <form method="POST" action="{{ url_for('login') }}"> + <div> + <label for="username">Username:</label> + <input type="text" id="username" name="username" required> + </div> + <div> + <label for="password">Password:</label> + <input type="password" id="password" name="password" required> + </div> + <button type="submit">Login</button> + </form> +{% endblock %}
\ No newline at end of file diff --git a/templates/season.html b/templates/season.html new file mode 100644 index 0000000..43ca0de --- /dev/null +++ b/templates/season.html @@ -0,0 +1,285 @@ +{% extends "base.html" %} + +{% block content %} + <div style="margin-bottom: 2rem;"> + <form method="GET" style="flex-direction: row; align-items: center; max-width: 100%; border: none; padding: 0;"> + <label for="season_id" style="margin-right: 10px; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;">Select Season:</label> + <select id="season_id" name="season_id" onchange="this.form.submit()" style="padding: 5px 10px;"> + {% for season in seasons %} + <option value="{{ season.id }}" {% if season.id|string == selected_season_id|string %}selected{% endif %}>{{ season.name }}</option> + {% endfor %} + </select> + <input type="hidden" name="tab" value="{{ active_tab }}"> + </form> + </div> + + <!-- Tabs Navigation --> + <div style="border-bottom: 2px solid var(--text-accent); margin-bottom: 1rem; display: flex; gap: 5px;"> + <a href="{{ url_for('index', season_id=selected_season_id, tab='overview') }}" + style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'overview' else 'background: #ddd; color: #555;' }}"> + Season Overview + </a> + <a href="{{ url_for('index', season_id=selected_season_id, tab='standings') }}" + style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'standings' else 'background: #ddd; color: #555;' }}"> + Standings + </a> + <a href="{{ url_for('index', season_id=selected_season_id, tab='schedule') }}" + style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'schedule' else 'background: #ddd; color: #555;' }}"> + Schedule + </a> + <a href="{{ url_for('index', season_id=selected_season_id, tab='playoffs') }}" + style="padding: 10px 20px; text-decoration: none; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase; border: 1px solid var(--deco-border); border-bottom: none; {{ 'background: white; color: black;' if active_tab == 'playoffs' else 'background: #ddd; color: #555;' }}"> + Playoffs + </a> + </div> + + {% if active_tab == 'overview' %} + <div class="tab-content"> + <h3>{{ season_info.name }} - Overview</h3> + <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 1rem;"> + <div style="background: white; padding: 1.5rem; border: 1px solid var(--deco-border);"> + <p><strong>Total Games (Per Team):</strong> {{ season_info.total_games }}</p> + <p><strong>Games Per Week:</strong> {{ season_info.games_per_week }}</p> + <p><strong>Season Start:</strong> {{ season_info.start_date }}</p> + <p><strong>Season End:</strong> {{ season_info.end_date }}</p> + {% if season_info.total_games %} + <p><strong>Playoff Teams:</strong> {{ season_info.playoff_teams }}</p> + {% endif %} + <p><strong>Status:</strong> {{ season_info.status }} {% if season_info.is_finished %}(Finished){% else %}(In Progress){% endif %}</p> + </div> + + <div style="background: white; padding: 1.5rem; border: 1px solid var(--deco-border);"> + {% if season_info.is_finished %} + <h4>Final Standings</h4> + {% if standings %} + <table style="margin-top: 0; width: 100%;"> + {% for row in standings %} + <tr> + <td>{{ loop.index }}. <strong>{{ row.team_name }}</strong></td> + <td>{{ row.wins }} - {{ row.losses }}</td> + </tr> + {% endfor %} + </table> + {% else %} + <p>No teams enrolled.</p> + {% endif %} + {% else %} + <h4>League Action</h4> + <p>The season is currently active or upcoming.</p> + + {% if current_user.is_authenticated and not current_user.is_admin %} + {% if user_season_status == 'Approved' %} + <div style="background: #f0fff0; border: 1px solid green; padding: 10px; margin-top: 10px;"> + <p style="color: green; font-weight: bold; margin: 0;">You are currently enrolled in this season.</p> + </div> + {% elif user_season_status == 'Pending' %} + <div style="background: #fffbe6; border: 1px solid orange; padding: 10px; margin-top: 10px;"> + <p style="color: orange; font-weight: bold; margin: 0;">Your request to join is pending approval.</p> + </div> + {% else %} + <form method="POST" action="{{ url_for('join_season', season_id=selected_season_id) }}"> + <button type="submit" style="width: 100%; padding: 12px; font-size: 1.1rem;">Apply to Join Season</button> + </form> + {% endif %} + {% elif not current_user.is_authenticated %} + <p style="border: 1px solid #ccc; padding: 10px; background: #eee;"> + <a href="{{ url_for('login') }}" style="font-weight: bold; color: black; text-decoration: underline;">Login</a> to apply for this season. + </p> + {% endif %} + {% endif %} + </div> + </div> + </div> + + {% elif active_tab == 'standings' %} + <div class="tab-content"> + <h3>{{ season_info.name }} - Standings</h3> + {% if standings %} + <table> + <tr> + <th>Team</th> + <th>Wins (W)</th> + <th>Losses (L)</th> + <th>Runs For (RF)</th> + <th>Runs Against (RA)</th> + <th>Games Back (GB)</th> + </tr> + {% for row in standings %} + {% set is_my_team = current_user.is_authenticated and current_user.id|string == row.user_id|string %} + {% set is_cutoff = loop.index == season_info.playoff_teams %} + <tr style="{{ 'background-color: #ffffcc;' if is_my_team else '' }} {{ 'border-bottom: 4px solid #333;' if is_cutoff else '' }}"> + <td style="display: flex; align-items: center; justify-content: center; gap: 10px;"> + {% if row.team_icon %} + <img src="{{ url_for('static', filename='uploads/' + row.team_icon) }}" alt="{{ row.team_name }}" + class="{{ 'team-icon-highlight' if is_my_team else '' }}" + style="width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--deco-border);"> + {% else %} + <div class="{{ 'team-icon-highlight' if is_my_team else '' }}" + style="width: 30px; height: 30px; border-radius: 50%; background-color: var(--deco-highlight); display: inline-block;"></div> + {% endif %} + {{ row.team_name }} + {% if row.clinch %}<span class="clinch-marker" title="Clinched Playoff Spot {{ '(1st Seed)' if row.clinch == '**' else '' }}">{{ row.clinch }}</span>{% endif %} + </td> + <td>{{ row.wins }}</td> + <td>{{ row.losses }}</td> + <td>{{ row.runs_for }}</td> + <td>{{ row.runs_against }}</td> + <td>{{ row.games_back }}</td> + </tr> + {% endfor %} + </table> + {% else %} + <p>No standings available for the selected season.</p> + {% endif %} + </div> + + {% elif active_tab == 'schedule' %} + <div class="tab-content"> + <h3>{{ season_info.name }} - Schedule</h3> + + <form method="GET" style="flex-direction: row; align-items: center; max-width: 100%; margin-bottom: 1.5rem; border: none; padding: 0;"> + <input type="hidden" name="season_id" value="{{ selected_season_id }}"> + <input type="hidden" name="tab" value="schedule"> + <label for="team_id" style="margin-right: 10px; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;">Filter by Team:</label> + <select id="team_id" name="team_id" onchange="this.form.submit()" style="padding: 5px 10px;"> + <option value="all">All Teams</option> + {% for team in all_teams %} + <option value="{{ team.id }}" {% if team.id|string == selected_team_id|string %}selected{% endif %}>{{ team.team_name }}</option> + {% endfor %} + </select> + </form> + + {% for month in months %} + <div class="calendar-month"> + <h4>{{ month.name }}</h4> + <div class="calendar-grid"> + {% for day in ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] %} + <div class="calendar-day-head">{{ day }}</div> + {% endfor %} + + {% for week in month.weeks %} + {% for day in week %} + {% set date_str = "%04d-%02d-%02d" % (month.year, month.month, day) if day != 0 else "" %} + <div class="calendar-day {{ 'other-month' if day == 0 else '' }} {{ 'today' if date_str == today else '' }}"> + {% if day != 0 %} + <span class="calendar-day-num">{{ day }}</span> + {% if date_str in games_by_date %} + {% for game in games_by_date[date_str] %} + {% set is_away_mine = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %} + {% set is_home_mine = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %} + <div class="calendar-game-item" onclick="window.location='{{ url_for('game', game_id=game.id) }}'"> + <span title="{{ game.away_team if game.away_team else 'TBD' }} @ {{ game.home_team if game.home_team else 'TBD' }}"> + {% if game.away_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}"> + {% else %} + <div class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}" style="display:inline-block; background:#ccc;"></div> + {% endif %} + {{ game.away_score if game.status == 'Final' else '' }} @ + {{ game.home_score if game.status == 'Final' else '' }} + {% if game.home_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}"> + {% else %} + <div class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}" style="display:inline-block; background:#ccc;"></div> + {% endif %} + {% if game.is_conditional %}*{% endif %} + {% if game.pending_proposals > 0 %} + <span class="pending-icon" title="Game has pending proposals!">⚠</span> + {% endif %} + </span> + </div> + {% endfor %} + {% endif %} + {% endif %} + </div> + {% endfor %} + {% endfor %} + </div> + </div> + {% endfor %} + + {% if games_by_date['TBD'] %} + <h3>TBD Games</h3> + <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem;"> + {% for game in games_by_date['TBD'] %} + <div class="calendar-game-item" onclick="window.location='{{ url_for('game', game_id=game.id) }}'" style="padding: 1rem; font-size: 0.9rem;"> + TBD @ TBD (Playoff) + </div> + {% endfor %} + </div> + {% endif %} + </div> + {% elif active_tab == 'playoffs' %} + <div class="tab-content"> + <h3>{{ season_info.name }} - Playoffs</h3> + + {% if bracket %} + <div class="bracket-container"> + {% for round_games in bracket %} + <div class="bracket-round"> + <h4 style="border: none; text-align: center; font-size: 0.9rem;">Round {{ loop.index }}</h4> + {% for g in round_games %} + <div class="bracket-game {{ 'winner' if g.status == 'Final' }}" onclick="window.location='{{ url_for('game', game_id=g.id) }}'" style="cursor: pointer;"> + <div class="bracket-team"> + <span>{{ g.away_team if g.away_team else 'TBD' }} {{ g.away_record if g.away_team else '' }}</span> + <span style="font-weight: bold; margin-left: 10px;">{{ g.away_series_wins }}</span> + </div> + <div class="bracket-team"> + <span>{{ g.home_team if g.home_team else 'TBD' }} {{ g.home_record if g.home_team else '' }}</span> + <span style="font-weight: bold; margin-left: 10px;">{{ g.home_series_wins }}</span> + </div> + <div style="font-size: 0.6rem; color: #777; margin-top: 3px;"> + Best of {{ season_info.playoff_series_length }} + </div> + </div> + {% endfor %} + </div> + {% endfor %} + </div> + {% else %} + <p>Playoff bracket not yet generated.</p> + {% endif %} + + <h3>Playoff Schedule</h3> + {% if playoff_games %} + <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem;"> + {% for game in playoff_games %} + {% set is_away_mine = current_user.is_authenticated and current_user.id|string == game.away_team_id|string %} + {% set is_home_mine = current_user.is_authenticated and current_user.id|string == game.home_team_id|string %} + <div style="border: 1px solid var(--deco-border); padding: 1rem; background: white; cursor: pointer;" + onclick="window.location='{{ url_for('game', game_id=game.id) }}'"> + <div style="font-size: 0.8rem; color: var(--deco-highlight); margin-bottom: 0.5rem; font-family: var(--sans-font); font-weight: bold; text-transform: uppercase;"> + {{ game.scheduled_date }} - {{ game.status }} + {% if game.is_conditional %}<span class="conditional-game">*</span>{% endif %} + {% if game.pending_proposals > 0 %}<span class="pending-icon">⚠</span>{% endif %} + </div> + <div style="display: flex; justify-content: space-between; align-items: center;"> + <div style="text-align: center; flex: 1;"> + {% if game.away_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.away_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}"> + {% else %} + <div class="team-icon-small {{ 'team-icon-highlight' if is_away_mine else '' }}" style="display:inline-block; background:#ccc; border-radius: 50%;"></div> + {% endif %} + <br><strong style="font-size: 0.8rem;">{{ game.away_team if game.away_team else 'TBD' }}</strong> + <br><span style="font-weight: bold;">{{ game.away_score if game.status == 'Final' else '-' }}</span> + </div> + <div style="font-weight: bold;">@</div> + <div style="text-align: center; flex: 1;"> + {% if game.home_icon %} + <img src="{{ url_for('static', filename='uploads/' + game.home_icon) }}" class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}"> + {% else %} + <div class="team-icon-small {{ 'team-icon-highlight' if is_home_mine else '' }}" style="display:inline-block; background:#ccc; border-radius: 50%;"></div> + {% endif %} + <br><strong style="font-size: 0.8rem;">{{ game.home_team if game.home_team else 'TBD' }}</strong> + <br><span style="font-weight: bold;">{{ game.home_score if game.status == 'Final' else '-' }}</span> + </div> + </div> + </div> + {% endfor %} + </div> + {% else %} + <p>No playoff games scheduled.</p> + {% endif %} + </div> + {% endif %} + +{% endblock %}
\ No newline at end of file diff --git a/templates/team.html b/templates/team.html new file mode 100644 index 0000000..e7098be --- /dev/null +++ b/templates/team.html @@ -0,0 +1,65 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Team Management: {{ current_user.team_name }}</h2> + + {% if current_user.team_icon %} + <div style="margin-bottom: 1rem;"> + <img src="{{ url_for('static', filename='uploads/' + current_user.team_icon) }}" alt="Team Icon" style="max-width: 150px; border: 1px solid var(--deco-border);"> + </div> + {% endif %} + + <div style="display: flex; gap: 2rem; flex-wrap: wrap;"> + <div style="flex: 1; min-width: 300px;"> + <h3>Update Profile</h3> + <form method="POST" enctype="multipart/form-data"> + <div> + <label for="team_name">Team Name:</label> + <input type="text" id="team_name" name="team_name" value="{{ current_user.team_name }}"> + </div> + <div> + <label for="new_password">New Password (leave blank to keep current):</label> + <input type="password" id="new_password" name="new_password"> + </div> + <div> + <label for="team_icon">Upload Team Icon:</label> + <input type="file" id="team_icon" name="team_icon" accept="image/*"> + </div> + <button type="submit">Save Changes</button> + </form> + </div> + + <div style="flex: 1; min-width: 300px;"> + <h3>Seasons</h3> + {% if seasons %} + <ul style="list-style: none; padding: 0;"> + {% for season in seasons %} + <li style="background: var(--bg-primary); padding: 1rem; margin-bottom: 0.5rem; border: 1px solid var(--deco-border); display: flex; justify-content: space-between; align-items: center;"> + <span><strong>{{ season.name }}</strong> ({{ season.status }})</span> + + {% if not current_user.is_admin %} + {% if season.id in my_seasons %} + {% if my_seasons[season.id] == 'Approved' %} + <span style="color: green; font-weight: bold;">Joined</span> + {% else %} + <span style="color: orange; font-weight: bold;">Pending Approval</span> + {% endif %} + {% else %} + <form method="POST" action="{{ url_for('join_season', season_id=season.id) }}" style="margin: 0;"> + <button type="submit" style="padding: 4px 8px; font-size: 0.8rem;">Request to Join</button> + </form> + {% endif %} + {% endif %} + </li> + {% endfor %} + </ul> + {% else %} + <p>No seasons available right now.</p> + {% endif %} + + <h3 style="margin-top: 2rem;">Your Schedule</h3> + <p>Below is your team's schedule for the active season.</p> + <a href="{{ url_for('index', tab='schedule', team_id=current_user.id) }}" style="display: inline-block; background-color: var(--text-accent); color: white; padding: 8px 16px; text-decoration: none; font-weight: bold;">View Full Team Schedule</a> + </div> + </div> +{% endblock %}
\ No newline at end of file |
