Refactoring fixes and adding functionality back
This commit is contained in:
parent
d5350aa4cb
commit
a6febae8a8
@ -261,9 +261,9 @@ class DatabaseConfigManager:
|
||||
|
||||
# Create sample fixtures (only if they don't exist)
|
||||
fixtures_data = [
|
||||
{'fixture_number': 1, 'date': datetime(2024, 1, 15), 'home_team': 'HKFC C', 'away_team': 'KCC A', 'venue': 'HKFC'},
|
||||
{'fixture_number': 2, 'date': datetime(2024, 1, 22), 'home_team': 'USRC A', 'away_team': 'HKFC C', 'venue': 'USRC'},
|
||||
{'fixture_number': 3, 'date': datetime(2024, 1, 29), 'home_team': 'HKFC C', 'away_team': 'Valley A', 'venue': 'HKFC'},
|
||||
{'fixture_number': 1, 'date': datetime(2025, 1, 15), 'home_team': 'HKFC C', 'away_team': 'KCC A', 'venue': 'HKFC'},
|
||||
{'fixture_number': 2, 'date': datetime(2025, 1, 22), 'home_team': 'USRC A', 'away_team': 'HKFC C', 'venue': 'USRC'},
|
||||
{'fixture_number': 3, 'date': datetime(2025, 1, 29), 'home_team': 'HKFC C', 'away_team': 'Valley A', 'venue': 'HKFC'},
|
||||
]
|
||||
|
||||
for fixture_data in fixtures_data:
|
||||
|
||||
@ -269,8 +269,21 @@ def match_comments():
|
||||
return render_template('error.html', message="Database not initialized. Please go to Database Setup to initialize the database.")
|
||||
|
||||
_oppo = row[0]['nextclub']
|
||||
commentDate = row[0]['nextdate'].strftime('%Y-%m-%d')
|
||||
_matchDate = row[0]['nextdate'].strftime('%Y_%m_%d')
|
||||
|
||||
# Handle case where nextdate is None - use most recent comment date
|
||||
if row[0]['nextdate']:
|
||||
commentDate = row[0]['nextdate'].strftime('%Y-%m-%d')
|
||||
_matchDate = row[0]['nextdate'].strftime('%Y-%m-%d')
|
||||
else:
|
||||
# Get the most recent comment date
|
||||
sql_recent = text("SELECT matchDate FROM _motmcomments ORDER BY matchDate DESC LIMIT 1")
|
||||
recent_result = sql_read(sql_recent)
|
||||
if recent_result:
|
||||
commentDate = recent_result[0]['matchDate']
|
||||
_matchDate = recent_result[0]['matchDate']
|
||||
else:
|
||||
commentDate = '2025-01-15' # Fallback
|
||||
_matchDate = '2025-01-15'
|
||||
|
||||
# Get HKFC logo from clubs table using signed URLs (with authentication)
|
||||
hkfcLogo = s3_asset_service.get_asset_url('images/hkfc_logo.png') # Default fallback
|
||||
@ -376,7 +389,24 @@ def vote_thanks():
|
||||
sql3 = text("INSERT INTO _motmcomments (matchDate, comment) VALUES (:match_date, :comment)")
|
||||
sql_write(sql3, {'match_date': _matchDate, 'comment': _fixed_comments})
|
||||
|
||||
return render_template('vote_thanks.html')
|
||||
# Get Simpsons monkeys image URL with fallback
|
||||
try:
|
||||
# First try to get from S3
|
||||
simpsons_url = s3_asset_service.get_asset_url('images/simpsons-monkeys.jpg')
|
||||
print(f"DEBUG: Simpsons image URL: {simpsons_url}")
|
||||
|
||||
# If S3 is disabled or URL is fallback, use static
|
||||
if simpsons_url.startswith('/static/'):
|
||||
print("DEBUG: Using fallback static URL")
|
||||
else:
|
||||
print("DEBUG: Using S3 URL")
|
||||
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Error getting Simpsons image: {e}")
|
||||
# Fallback to static URL
|
||||
simpsons_url = "/static/images/simpsons-monkeys.jpg"
|
||||
|
||||
return render_template('vote_thanks.html', simpsons_image_url=simpsons_url)
|
||||
else:
|
||||
return 'Ouch ... something went wrong here'
|
||||
except Exception as e:
|
||||
@ -513,7 +543,15 @@ def motm_admin():
|
||||
form.nextOppoClub.choices = [(oppo['hockeyclub'], oppo['hockeyclub']) for oppo in clubs]
|
||||
form.currMotM.choices = [(player['playernumber'], player['playerforenames'] + " " + player['playersurname']) for player in players]
|
||||
form.currDotD.choices = [(player['playernumber'], player['playerforenames'] + " " + player['playersurname']) for player in players]
|
||||
clubLogo = settings[0]['oppologo']
|
||||
# Get the opposition logo using S3 service
|
||||
clubLogo = s3_asset_service.get_asset_url('images/default_logo.png') # Default fallback
|
||||
if settings and settings[0]['nextclub']:
|
||||
nextClub = settings[0]['nextclub']
|
||||
# Get the club logo from the clubs table
|
||||
sql_club_logo = text("SELECT logo_url FROM clubs WHERE hockey_club = :club_name")
|
||||
club_logo_result = sql_read(sql_club_logo, {'club_name': nextClub})
|
||||
if club_logo_result and club_logo_result[0]['logo_url']:
|
||||
clubLogo = s3_asset_service.get_logo_url(club_logo_result[0]['logo_url'], nextClub)
|
||||
|
||||
return render_template('motm_admin.html', form=form, nextOppoLogo=clubLogo)
|
||||
|
||||
@ -1451,6 +1489,11 @@ def get_next_fixture():
|
||||
# Get opponent club information
|
||||
opponent_club_info = get_opponent_club_info(fixture['opponent'])
|
||||
|
||||
# Get the opponent logo URL using S3 service
|
||||
opponent_logo_url = s3_asset_service.get_asset_url('images/default_logo.png') # Default fallback
|
||||
if opponent_club_info and opponent_club_info.get('logo_url'):
|
||||
opponent_logo_url = s3_asset_service.get_logo_url(opponent_club_info['logo_url'], opponent_club_info['club_name'])
|
||||
|
||||
# Format the fixture data for JSON response
|
||||
fixture_data = {
|
||||
'success': True,
|
||||
@ -1461,6 +1504,7 @@ def get_next_fixture():
|
||||
'opponent': fixture['opponent'],
|
||||
'opponent_club': get_opponent_club_name(fixture['opponent']),
|
||||
'opponent_club_info': opponent_club_info,
|
||||
'opponent_logo_url': opponent_logo_url,
|
||||
'is_home': fixture['is_home'],
|
||||
'home_team': fixture['home_team'],
|
||||
'away_team': fixture['away_team'],
|
||||
@ -1683,9 +1727,9 @@ def poty_results():
|
||||
# Only include players with votes
|
||||
if motm_total > 0 or dotd_total > 0:
|
||||
results.append({
|
||||
'playername': player['playername'],
|
||||
'motmtotal': motm_total,
|
||||
'dotdtotal': dotd_total
|
||||
'playerName': player['playername'], # Fixed field name to match JavaScript
|
||||
'motmTotal': motm_total, # Fixed field name to match JavaScript
|
||||
'dotdTotal': dotd_total # Fixed field name to match JavaScript
|
||||
})
|
||||
|
||||
print(f"Dynamic POTY Results: {results}")
|
||||
@ -1703,7 +1747,7 @@ def voting_chart():
|
||||
if date_result:
|
||||
matchDate = str(date_result[0]['nextdate']).replace('-', '')
|
||||
else:
|
||||
matchDate = '20251012' # Default fallback
|
||||
matchDate = '20251015' # Default fallback
|
||||
|
||||
return render_template('vote_chart.html', _matchDate=matchDate)
|
||||
|
||||
|
||||
@ -203,7 +203,13 @@ class S3AssetService:
|
||||
region_name=config.get('aws_region', 'us-east-1'),
|
||||
endpoint_url=endpoint_url,
|
||||
use_ssl=use_ssl,
|
||||
verify=True # Enable SSL certificate verification
|
||||
verify=True, # Enable SSL certificate verification
|
||||
config=boto3.session.Config(
|
||||
s3={
|
||||
'addressing_style': 'path'
|
||||
},
|
||||
signature_version='s3v4'
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Create AWS S3 client
|
||||
|
||||
1
motm_app/static/images/simpsons-monkeys.jpg
Normal file
1
motm_app/static/images/simpsons-monkeys.jpg
Normal file
@ -0,0 +1 @@
|
||||
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
|
||||
@ -56,6 +56,15 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<a href="/admin/motm/manage" class="btn btn-outline-danger w-100">
|
||||
<i class="fas fa-database me-2"></i>
|
||||
<div class="text-start">
|
||||
<div class="fw-bold">MOTM Management</div>
|
||||
<small class="text-muted">Reset & drop columns</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<a href="/admin/profile" class="btn btn-outline-secondary w-100">
|
||||
<i class="fas fa-user-cog me-2"></i>
|
||||
@ -150,6 +159,76 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Analytics & Reports Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-chart-bar me-2"></i>Analytics & Reports
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 mb-3">
|
||||
<div class="card h-100 border-info">
|
||||
<div class="card-header bg-light">
|
||||
<h6 class="card-title mb-0">
|
||||
<i class="fas fa-poll text-info me-2"></i>Vote Charts
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">View current vote counts and MOTM/DotD results for the current match.</p>
|
||||
<div class="d-grid gap-2">
|
||||
<a href="/admin/voting" class="btn btn-info">
|
||||
<i class="fas fa-chart-pie me-2"></i>View Vote Charts
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 mb-3">
|
||||
<div class="card h-100 border-success">
|
||||
<div class="card-header bg-light">
|
||||
<h6 class="card-title mb-0">
|
||||
<i class="fas fa-trophy text-success me-2"></i>Player of the Year
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">View Player of the Year standings and cumulative MOTM votes.</p>
|
||||
<div class="d-grid gap-2">
|
||||
<a href="/admin/poty" class="btn btn-success">
|
||||
<i class="fas fa-medal me-2"></i>View POTY Chart
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 mb-3">
|
||||
<div class="card h-100 border-warning">
|
||||
<div class="card-header bg-light">
|
||||
<h6 class="card-title mb-0">
|
||||
<i class="fas fa-futbol text-warning me-2"></i>Goals & Assists
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Manage goals and assists statistics for matches.</p>
|
||||
<div class="d-grid gap-2">
|
||||
<a href="/admin/stats" class="btn btn-warning">
|
||||
<i class="fas fa-plus me-2"></i>Add Stats
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Management Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
|
||||
@ -278,3 +278,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -306,7 +306,7 @@
|
||||
<div class="col-md-6 text-md-end">
|
||||
<p class="mb-0">
|
||||
<i class="fas fa-calendar-alt me-1"></i>
|
||||
{% if current_year %}{{ current_year }}{% else %}2024{% endif %}
|
||||
{% if current_year %}{{ current_year }}{% else %}2025{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -33,3 +33,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -227,7 +227,7 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6><i class="fas fa-calendar-alt me-2"></i>Current Season</h6>
|
||||
<p class="text-muted">2024-2025 Hockey Season</p>
|
||||
<p class="text-muted">2025-2026 Hockey Season</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -227,7 +227,7 @@
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6><i class="fas fa-calendar-alt me-2"></i>Current Season</h6>
|
||||
<p class="text-muted">2024-2025 Hockey Season</p>
|
||||
<p class="text-muted">2025-2026 Hockey Season</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -235,3 +235,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -74,3 +74,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -1,176 +1,212 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>HKFC Men's C Team - MotM and DotD vote admin</title>
|
||||
<link rel="stylesheet" media="screen" href ="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
|
||||
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
<h2>HKFC Men's C Team MotM and DotD online vote admin page</h2>
|
||||
<div style="margin-bottom: 15px;">
|
||||
<a href="/admin" class="btn btn-default btn-sm">
|
||||
<span class="glyphicon glyphicon-arrow-left"></span> Back to Admin Dashboard
|
||||
</a>
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}MOTM Management - HKFC Men's C Team MOTM System{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Page Header -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body text-center">
|
||||
<h1 class="card-title">
|
||||
<i class="fas fa-trophy text-warning me-2"></i>
|
||||
MOTM Management
|
||||
</h1>
|
||||
<p class="lead text-muted">Manage Man of the Match and Dick of the Day settings</p>
|
||||
<a href="/admin" class="btn btn-outline-primary">
|
||||
<i class="fas fa-arrow-left me-2"></i>Back to Admin Dashboard
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<body onload="myFunction()">
|
||||
|
||||
<dl>
|
||||
<p>
|
||||
</div>
|
||||
<!-- Match Configuration Card -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-calendar-alt me-2"></i>Next Match Configuration
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ form.csrf_token }}
|
||||
<b>HKFC C Next Opponent:</b>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<form class="col-sm-6" method="post" action="/admin/motm">
|
||||
<!-- Load Next Fixture Button -->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-info" style="margin-bottom: 15px;">
|
||||
<button type="button" class="btn btn-info btn-sm" id="loadFixtureBtn" onclick="loadNextFixture()">
|
||||
<span class="glyphicon glyphicon-download-alt"></span> Load Next HKFC C Fixture
|
||||
<form method="post" action="/admin/motm">
|
||||
<!-- Load Next Fixture Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap">
|
||||
<div class="d-flex align-items-center">
|
||||
<button type="button" class="btn btn-info me-3" id="loadFixtureBtn" onclick="loadNextFixture()">
|
||||
<i class="fas fa-download me-2"></i>Load Next HKFC C Fixture
|
||||
</button>
|
||||
<a href="https://hockey.org.hk/MenFixture.asp" target="_blank" class="btn btn-default btn-sm" style="margin-left: 5px;">
|
||||
<span class="glyphicon glyphicon-new-window"></span> View HK Hockey Fixtures
|
||||
<a href="https://hockey.org.hk/MenFixture.asp" target="_blank" class="btn btn-outline-info">
|
||||
<i class="fas fa-external-link-alt me-2"></i>View HK Hockey Fixtures
|
||||
</a>
|
||||
<span id="fixtureStatus" style="margin-left: 10px;"></span>
|
||||
<div id="fixtureInfo" style="margin-top: 10px; display: none;"></div>
|
||||
</div>
|
||||
<span id="fixtureStatus" class="ms-3"></span>
|
||||
</div>
|
||||
<div id="fixtureInfo" class="mt-3" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<div class = "row">
|
||||
<div class = "col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="basic-addon1">Date:</span>
|
||||
{{ form.nextMatchDate(class_="form-control", id="nextMatchDate") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</br>
|
||||
<div class = "row">
|
||||
<div class = "col-sm-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="basic-addon1">Opposition</span>
|
||||
{{ form.nextOppoTeam(class_="form-control", id="nextOppoTeam") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class = "row">
|
||||
<div class = "col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="basic-addon1">Current Man of the Match:</span>
|
||||
{{ form.currMotM(class_="form-control") }}
|
||||
</div>
|
||||
</div>
|
||||
<div class = "col-sm-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="basic-addon1">Current Dick of the Day:</span>
|
||||
{{ form.currDotD(class_="form-control") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not form.currMotM.choices or form.currMotM.choices|length == 0 %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alert-warning" style="margin-top: 10px;">
|
||||
<small><strong>Note:</strong> No players available for previous MOTM/DotD. This is normal if you haven't set up a match squad yet. You can still save the match details.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p>
|
||||
{{ form.saveButton(class_="btn btn-success") }}
|
||||
{{ form.activateButton(class_="btn btn-primary") }}
|
||||
<a class="btn btn-danger" href="/" role="button">Cancel</a>
|
||||
</p>
|
||||
</form>
|
||||
<div class="col-sm-4">
|
||||
<img src="{{ nextOppoLogo }}" height="90" id="nextOppoLogo"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
</dl>
|
||||
|
||||
<!-- Match Details Form -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="nextMatchDate" class="form-label">
|
||||
<i class="fas fa-calendar me-2"></i>Match Date
|
||||
</label>
|
||||
{{ form.nextMatchDate(class_="form-control", **{"id": "nextMatchDate"}) }}
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="nextOppoTeam" class="form-label">
|
||||
<i class="fas fa-users me-2"></i>Opposition Team
|
||||
</label>
|
||||
{{ form.nextOppoTeam(class_="form-control", **{"id": "nextOppoTeam"}) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Current Winners Section -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="currMotM" class="form-label">
|
||||
<i class="fas fa-trophy me-2 text-warning"></i>Current Man of the Match
|
||||
</label>
|
||||
{{ form.currMotM(class_="form-select") }}
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="currDotD" class="form-label">
|
||||
<i class="fas fa-user-times me-2 text-danger"></i>Current Dick of the Day
|
||||
</label>
|
||||
{{ form.currDotD(class_="form-select") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Warning Message -->
|
||||
{% if not form.currMotM.choices or form.currMotM.choices|length == 0 %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>
|
||||
<strong>Note:</strong> No players available for previous MOTM/DotD. This is normal if you haven't set up a match squad yet. You can still save the match details.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
{{ form.saveButton(class_="btn btn-success") }}
|
||||
{{ form.activateButton(class_="btn btn-primary") }}
|
||||
<a class="btn btn-outline-secondary" href="/admin" role="button">
|
||||
<i class="fas fa-times me-2"></i>Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function loadNextFixture() {
|
||||
// Show loading status
|
||||
var statusElement = document.getElementById('fixtureStatus');
|
||||
var infoElement = document.getElementById('fixtureInfo');
|
||||
var loadBtn = document.getElementById('loadFixtureBtn');
|
||||
|
||||
statusElement.innerHTML = '<span class="text-info">Loading...</span>';
|
||||
loadBtn.disabled = true;
|
||||
|
||||
// Fetch the next fixture from the API
|
||||
fetch('/admin/api/next-fixture')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Update the form fields
|
||||
document.getElementById('nextMatchDate').value = data.date;
|
||||
document.getElementById('nextOppoTeam').value = data.opponent;
|
||||
|
||||
// Show fixture information
|
||||
let clubInfo = '';
|
||||
if (data.opponent_club_info) {
|
||||
const club = data.opponent_club_info;
|
||||
const confidence = club.match_result ? club.match_result.confidence : 'unknown';
|
||||
const matchType = club.match_result ? club.match_result.match_type : 'unknown';
|
||||
|
||||
clubInfo = '<br><small class="text-muted">';
|
||||
clubInfo += 'Club: ' + club.club_name;
|
||||
if (club.logo_url) {
|
||||
clubInfo += ' | <a href="' + club.logo_url + '" target="_blank">Logo</a>';
|
||||
}
|
||||
clubInfo += ' | Match: ' + matchType + ' (' + confidence + ')';
|
||||
clubInfo += '</small>';
|
||||
}
|
||||
|
||||
infoElement.innerHTML = '<strong>Next Match:</strong> ' +
|
||||
data.date_formatted + ' vs ' + data.opponent +
|
||||
' (' + (data.is_home ? 'Home' : 'Away') + ' - ' + data.venue + ')' +
|
||||
'<br><small>Division: ' + data.division + ' | Time: ' + data.time + '</small>' +
|
||||
clubInfo;
|
||||
infoElement.style.display = 'block';
|
||||
|
||||
statusElement.innerHTML = '<span class="text-success">✓ Fixture loaded!</span>';
|
||||
|
||||
// Clear status message after 3 seconds
|
||||
setTimeout(function() {
|
||||
statusElement.innerHTML = '';
|
||||
}, 3000);
|
||||
} else {
|
||||
statusElement.innerHTML = '<span class="text-danger">✗ ' + data.message + '</span>';
|
||||
infoElement.style.display = 'none';
|
||||
<!-- Opposition Logo Card -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-image me-2"></i>Opposition Team Logo
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<img src="{{ nextOppoLogo }}" height="120" id="nextOppoLogo" class="img-fluid rounded" alt="Opposition Team Logo"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>
|
||||
function loadNextFixture() {
|
||||
// Show loading status
|
||||
const statusElement = document.getElementById('fixtureStatus');
|
||||
const infoElement = document.getElementById('fixtureInfo');
|
||||
const loadBtn = document.getElementById('loadFixtureBtn');
|
||||
|
||||
statusElement.innerHTML = '<span class="text-info"><i class="fas fa-spinner fa-spin me-2"></i>Loading...</span>';
|
||||
loadBtn.disabled = true;
|
||||
|
||||
// Fetch the next fixture from the API
|
||||
fetch('/admin/api/next-fixture')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Update the form fields
|
||||
document.getElementById('nextMatchDate').value = data.date;
|
||||
document.getElementById('nextOppoTeam').value = data.opponent;
|
||||
|
||||
// Update the opponent logo if provided
|
||||
if (data.opponent_logo_url) {
|
||||
const logoElement = document.getElementById('nextOppoLogo');
|
||||
if (logoElement) {
|
||||
logoElement.src = data.opponent_logo_url;
|
||||
}
|
||||
loadBtn.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
statusElement.innerHTML = '<span class="text-danger">✗ Error loading fixture</span>';
|
||||
infoElement.style.display = 'none';
|
||||
loadBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-load fixture on page load
|
||||
function myFunction() {
|
||||
// Optional: Auto-load the next fixture when the page loads
|
||||
// Uncomment the next line if you want this behavior
|
||||
// loadNextFixture();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
// Show fixture information
|
||||
let clubInfo = '';
|
||||
if (data.opponent_club_info) {
|
||||
const club = data.opponent_club_info;
|
||||
const confidence = club.match_result ? club.match_result.confidence : 'unknown';
|
||||
const matchType = club.match_result ? club.match_result.match_type : 'unknown';
|
||||
|
||||
clubInfo = '<br><small class="text-muted">';
|
||||
clubInfo += 'Club: ' + club.club_name;
|
||||
if (club.logo_url) {
|
||||
clubInfo += ' | <a href="' + club.logo_url + '" target="_blank">Logo</a>';
|
||||
}
|
||||
clubInfo += ' | Match: ' + matchType + ' (' + confidence + ')';
|
||||
clubInfo += '</small>';
|
||||
}
|
||||
|
||||
infoElement.innerHTML = '<strong>Next Match:</strong> ' +
|
||||
data.date_formatted + ' vs ' + data.opponent +
|
||||
' (' + (data.is_home ? 'Home' : 'Away') + ' - ' + data.venue + ')' +
|
||||
'<br><small>Division: ' + data.division + ' | Time: ' + data.time + '</small>' +
|
||||
clubInfo;
|
||||
infoElement.style.display = 'block';
|
||||
|
||||
statusElement.innerHTML = '<span class="text-success"><i class="fas fa-check me-2"></i>Fixture loaded!</span>';
|
||||
|
||||
// Clear status message after 3 seconds
|
||||
setTimeout(function() {
|
||||
statusElement.innerHTML = '';
|
||||
}, 3000);
|
||||
} else {
|
||||
statusElement.innerHTML = '<span class="text-danger"><i class="fas fa-times me-2"></i>' + data.message + '</span>';
|
||||
infoElement.style.display = 'none';
|
||||
}
|
||||
loadBtn.disabled = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
statusElement.innerHTML = '<span class="text-danger"><i class="fas fa-exclamation-triangle me-2"></i>Error loading fixture</span>';
|
||||
infoElement.style.display = 'none';
|
||||
loadBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-load fixture on page load (optional)
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Uncomment the next line if you want to auto-load the fixture when the page loads
|
||||
// loadNextFixture();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Random Comment -->
|
||||
{% if comment and comment != "No comments added yet" %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
@ -47,28 +48,27 @@
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% for item in comment %}
|
||||
<blockquote class="blockquote text-center">
|
||||
<p class="mb-0">
|
||||
<i class="fas fa-quote-left text-muted me-2"></i>
|
||||
<em>{{ item.comment }}</em>
|
||||
<i class="fas fa-quote-right text-muted ms-2"></i>
|
||||
</p>
|
||||
</blockquote>
|
||||
{% endfor %}
|
||||
<blockquote class="blockquote text-center">
|
||||
<p class="mb-0">
|
||||
<i class="fas fa-quote-left text-muted me-2"></i>
|
||||
<em>{{ comment }}</em>
|
||||
<i class="fas fa-quote-right text-muted ms-2"></i>
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Voting Forms -->
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-4">
|
||||
<!-- Man of the Match -->
|
||||
<div class="col-lg-8 mx-auto mb-4">
|
||||
<!-- Vote for MOTM and DotD -->
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-trophy me-2"></i>Man of the Match
|
||||
<i class="fas fa-vote-yea me-2"></i>Vote for MOTM and DotD
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@ -79,7 +79,7 @@
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="motmSelect" class="form-label">Select Player:</label>
|
||||
<select class="form-select" id="motmSelect" name="motmSelect" required>
|
||||
<select class="form-select" id="motmSelect" name="motmVote" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
@ -89,45 +89,26 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="dotdSelect" class="form-label">Dick of the Day:</label>
|
||||
<select class="form-select" id="dotdSelect" name="dotdVote" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
{% if player.playernickname %}"{{ player.playernickname }}"{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="motmComment" class="form-label">Optional Comment:</label>
|
||||
<textarea class="form-control" id="motmComment" name="motmComment" rows="3" placeholder="Share your thoughts about the match..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-success btn-lg">
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit MOTM Vote
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 mb-4">
|
||||
<!-- Dick of the Day -->
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-award me-2"></i>Dick of the Day
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="/motm/dotd-thanks" id="dotdForm">
|
||||
{{ form.csrf_token }}
|
||||
<input type="hidden" id="matchNumber" name="matchNumber" value="{{ matchNumber }}">
|
||||
<input type="hidden" id="oppo" name="oppo" value="{{ oppo }}">
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="dotdSelect" class="form-label">Select Player:</label>
|
||||
<select class="form-select" id="dotdSelect" name="dotdSelect" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
{% if player.playernickname %}"{{ player.playernickname }}"{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-warning btn-lg">
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit DotD Vote
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit Votes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -198,18 +179,27 @@
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Form validation
|
||||
$('#motmForm, #dotdForm').on('submit', function(e) {
|
||||
const selectElement = $(this).find('select');
|
||||
if (!selectElement.val()) {
|
||||
$('#motmForm').on('submit', function(e) {
|
||||
const motmSelect = $('#motmSelect');
|
||||
const dotdSelect = $('#dotdSelect');
|
||||
|
||||
if (!motmSelect.val()) {
|
||||
e.preventDefault();
|
||||
alert('Please select a player before submitting your vote.');
|
||||
selectElement.focus();
|
||||
alert('Please select a player for Man of the Match.');
|
||||
motmSelect.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dotdSelect.val()) {
|
||||
e.preventDefault();
|
||||
alert('Please select a player for Dick of the Day.');
|
||||
dotdSelect.focus();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Add loading state to buttons
|
||||
$('#motmForm, #dotdForm').on('submit', function() {
|
||||
// Add loading state to button
|
||||
$('#motmForm').on('submit', function() {
|
||||
const button = $(this).find('button[type="submit"]');
|
||||
const originalText = button.html();
|
||||
button.html('<span class="loading-spinner"></span> Submitting...').prop('disabled', true);
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Random Comment -->
|
||||
{% if comment and comment != "No comments added yet" %}
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
@ -47,28 +48,27 @@
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% for item in comment %}
|
||||
<blockquote class="blockquote text-center">
|
||||
<p class="mb-0">
|
||||
<i class="fas fa-quote-left text-muted me-2"></i>
|
||||
<em>{{ item.comment }}</em>
|
||||
<i class="fas fa-quote-right text-muted ms-2"></i>
|
||||
</p>
|
||||
</blockquote>
|
||||
{% endfor %}
|
||||
<blockquote class="blockquote text-center">
|
||||
<p class="mb-0">
|
||||
<i class="fas fa-quote-left text-muted me-2"></i>
|
||||
<em>{{ comment }}</em>
|
||||
<i class="fas fa-quote-right text-muted ms-2"></i>
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Voting Forms -->
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-4">
|
||||
<!-- Man of the Match -->
|
||||
<div class="col-lg-8 mx-auto mb-4">
|
||||
<!-- Vote for MOTM and DotD -->
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-trophy me-2"></i>Man of the Match
|
||||
<i class="fas fa-vote-yea me-2"></i>Vote for MOTM and DotD
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@ -79,7 +79,7 @@
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="motmSelect" class="form-label">Select Player:</label>
|
||||
<select class="form-select" id="motmSelect" name="motmSelect" required>
|
||||
<select class="form-select" id="motmSelect" name="motmVote" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
@ -89,45 +89,26 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="dotdSelect" class="form-label">Dick of the Day:</label>
|
||||
<select class="form-select" id="dotdSelect" name="dotdVote" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
{% if player.playernickname %}"{{ player.playernickname }}"{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="motmComment" class="form-label">Optional Comment:</label>
|
||||
<textarea class="form-control" id="motmComment" name="motmComment" rows="3" placeholder="Share your thoughts about the match..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-success btn-lg">
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit MOTM Vote
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 mb-4">
|
||||
<!-- Dick of the Day -->
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fas fa-award me-2"></i>Dick of the Day
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="/motm/dotd-thanks" id="dotdForm">
|
||||
{{ form.csrf_token }}
|
||||
<input type="hidden" id="matchNumber" name="matchNumber" value="{{ matchNumber }}">
|
||||
<input type="hidden" id="oppo" name="oppo" value="{{ oppo }}">
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="dotdSelect" class="form-label">Select Player:</label>
|
||||
<select class="form-select" id="dotdSelect" name="dotdSelect" required>
|
||||
<option value="">Choose a player...</option>
|
||||
{% for player in data %}
|
||||
<option value="{{ player.playernumber }}">{{ player.playerforenames }} {{ player.playersurname }}
|
||||
{% if player.playernickname %}"{{ player.playernickname }}"{% endif %}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-warning btn-lg">
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit DotD Vote
|
||||
<i class="fas fa-vote-yea me-2"></i>Submit Votes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -198,18 +179,27 @@
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Form validation
|
||||
$('#motmForm, #dotdForm').on('submit', function(e) {
|
||||
const selectElement = $(this).find('select');
|
||||
if (!selectElement.val()) {
|
||||
$('#motmForm').on('submit', function(e) {
|
||||
const motmSelect = $('#motmSelect');
|
||||
const dotdSelect = $('#dotdSelect');
|
||||
|
||||
if (!motmSelect.val()) {
|
||||
e.preventDefault();
|
||||
alert('Please select a player before submitting your vote.');
|
||||
selectElement.focus();
|
||||
alert('Please select a player for Man of the Match.');
|
||||
motmSelect.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dotdSelect.val()) {
|
||||
e.preventDefault();
|
||||
alert('Please select a player for Dick of the Day.');
|
||||
dotdSelect.focus();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Add loading state to buttons
|
||||
$('#motmForm, #dotdForm').on('submit', function() {
|
||||
// Add loading state to button
|
||||
$('#motmForm').on('submit', function() {
|
||||
const button = $(this).find('button[type="submit"]');
|
||||
const originalText = button.html();
|
||||
button.html('<span class="loading-spinner"></span> Submitting...').prop('disabled', true);
|
||||
@ -217,3 +207,4 @@ $(document).ready(function() {
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -36,6 +36,12 @@ google.charts.load('current', {
|
||||
|
||||
// load json data
|
||||
function loadData(jsonData) {
|
||||
if (jsonData.length === 0) {
|
||||
// Show message when no data
|
||||
$('#chart_div').html('<div class="alert alert-info text-center"><h4>No Vote Data Available</h4><p>No players have received MOTM or DotD votes yet.</p><p>Votes will appear here once players start receiving votes.</p></div>');
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(jsonData, function(index, row) {
|
||||
data.addRow([
|
||||
row.playerName,
|
||||
|
||||
@ -23,10 +23,11 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<img src="http://icarus.ipa.champion:9000/hockey-app/assets/simpsons-monkeys.jpg"
|
||||
<img src="{{ simpsons_image_url }}"
|
||||
alt="Counting votes"
|
||||
class="img-fluid rounded"
|
||||
style="max-height: 300px;">
|
||||
style="max-height: 300px;"
|
||||
onerror="this.src='/static/images/simpsons-monkeys.jpg';">
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
|
||||
@ -23,10 +23,11 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<img src="http://icarus.ipa.champion:9000/hockey-app/assets/simpsons-monkeys.jpg"
|
||||
<img src="{{ simpsons_image_url }}"
|
||||
alt="Counting votes"
|
||||
class="img-fluid rounded"
|
||||
style="max-height: 300px;">
|
||||
style="max-height: 300px;"
|
||||
onerror="this.src='/static/images/simpsons-monkeys.jpg';">
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
|
||||
@ -42,3 +43,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user