parent
96fe35a742
commit
c6f5571d43
@ -0,0 +1,301 @@ |
||||
<!DOCTYPE html> |
||||
{% load static %} |
||||
{% load qr_code %} |
||||
<html> |
||||
<head> |
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> |
||||
<link rel="stylesheet" href="{% static 'tournaments/css/foundation.min.css' %}" /> |
||||
<link rel="stylesheet" href="{% static 'tournaments/css/basics.css' %}" /> |
||||
<link rel="stylesheet" href="{% static 'tournaments/css/style.css' %}" /> |
||||
<link rel="stylesheet" href="{% static 'tournaments/css/broadcast.css' %}" /> |
||||
<style> |
||||
.running { |
||||
background-color: #90ee90 !important; |
||||
} |
||||
.bubble-footer.score, .match-cell .bubble { |
||||
height: 8rem; |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
box-sizing: border-box; |
||||
font-size: 1.2em; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
width: 100%; |
||||
color: black; |
||||
} |
||||
.court-label .bubble { |
||||
height: 4rem; |
||||
font-weight: bold; |
||||
margin: 0; |
||||
width: 100%; |
||||
text-align: center; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
font-size: 1em; |
||||
color: black; |
||||
} |
||||
.match-cell .bubble { |
||||
background-color: white; /* Light blue */ |
||||
} |
||||
.match-cell .bubble.even { |
||||
background-color: white; /* Light mint */ |
||||
} |
||||
.match-cell .bubble.empty { |
||||
background-color: rgba(173, 216, 230, 0.3); /* Light blue */ |
||||
color: white; |
||||
} |
||||
.match-cell, .court-label { |
||||
width: 10rem; |
||||
display: flex; |
||||
} |
||||
/* Adjust width when court count is 5 or more */ |
||||
.court-label .bubble, |
||||
.match-cell .bubble { |
||||
width: 100%; |
||||
margin: 0; |
||||
} |
||||
.court-label .bubble, |
||||
.cell.large-6 { |
||||
width: 50%; |
||||
padding: 0px; |
||||
} |
||||
.court-label .bubble, |
||||
.cell.large-12 { |
||||
width: 100%; |
||||
padding: 0px; |
||||
} |
||||
.grid-x { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
} |
||||
.courts-row, |
||||
.matches-row { |
||||
display: flex; |
||||
width: 100%; |
||||
gap: 20px; |
||||
} |
||||
</style> |
||||
|
||||
<link rel="icon" type="image/png" href="{% static 'tournaments/images/favicon.png' %}" /> |
||||
|
||||
<title>Programmation</title> |
||||
|
||||
<script src="{% static 'tournaments/js/alpine.min.js' %}"></script> |
||||
<!-- Matomo --> |
||||
<script> |
||||
var _paq = window._paq = window._paq || []; |
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */ |
||||
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]); |
||||
_paq.push(["setDoNotTrack", true]); |
||||
_paq.push(['trackPageView']); |
||||
_paq.push(['enableLinkTracking']); |
||||
(function() { |
||||
var u="//matomo.padelclub.app/"; |
||||
_paq.push(['setTrackerUrl', u+'matomo.php']); |
||||
_paq.push(['setSiteId', '1']); |
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; |
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); |
||||
})(); |
||||
</script> |
||||
<!-- End Matomo Code --> |
||||
</head> |
||||
|
||||
<body x-data="{ |
||||
days: [], |
||||
currentDayIndex: 0, |
||||
currentPageIndex: 0, |
||||
matchGroups: [], |
||||
courtCount: {{ tournament.court_count|default:1 }}, |
||||
groupsPerPage: 8, |
||||
|
||||
retrieveData() { |
||||
fetch('/tournament/{{ tournament.id }}/planning/json/') |
||||
.then(res => res.json()) |
||||
.then((data) => { |
||||
this.days = data.days || []; |
||||
this.matchGroups = data.match_groups || []; |
||||
this.currentPageIndex = 0; |
||||
|
||||
if (this.days.length > 0 && this.currentDayIndex >= this.days.length) { |
||||
this.currentDayIndex = 0; |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
getMatchGroupsForDay(day) { |
||||
const formattedDay = day; |
||||
const filteredGroups = this.matchGroups.filter(group => { |
||||
if (!group.matches || group.matches.length === 0) return false; |
||||
return group.name && formattedDay && group.name.includes(formattedDay); |
||||
}); |
||||
|
||||
// If court count is 5 or more, show fewer groups per page |
||||
let groupsPerPageThreshold = this.courtCount >= 5 ? Math.ceil(this.groupsPerPage / 2) : this.groupsPerPage; |
||||
|
||||
const paginatedGroups = []; |
||||
for (let i = 0; i < Math.ceil(filteredGroups.length / groupsPerPageThreshold); i++) { |
||||
paginatedGroups.push(filteredGroups.slice(i * groupsPerPageThreshold, (i + 1) * groupsPerPageThreshold)); |
||||
} |
||||
return paginatedGroups; |
||||
}, |
||||
|
||||
getCourtNumber(courtName) { |
||||
if (!courtName) return 999; |
||||
const match = courtName.match(/(\d+)/); |
||||
return match ? parseInt(match[1]) : 999; |
||||
}, |
||||
|
||||
organizeMatchesByCourt(matches) { |
||||
// Create an array of court positions, each containing the match or null |
||||
const courtMatches = Array(this.courtCount).fill(null); |
||||
|
||||
if (matches && matches.length > 0) { |
||||
matches.forEach(match => { |
||||
if (match && match.court) { |
||||
const courtNum = this.getCourtNumber(match.court); |
||||
if (courtNum > 0 && courtNum <= this.courtCount) { |
||||
courtMatches[courtNum - 1] = match; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
return courtMatches; |
||||
}, |
||||
|
||||
loop() { |
||||
this.retrieveData(); |
||||
setInterval(() => { |
||||
if (this.days.length > 0) { |
||||
const currentDay = this.days[this.currentDayIndex]; |
||||
const pagesForDay = this.getMatchGroupsForDay(currentDay); |
||||
|
||||
if (pagesForDay && pagesForDay.length > 1) { |
||||
const _currentPageIndex = this.currentPageIndex; |
||||
this.currentPageIndex = (this.currentPageIndex + 1) % pagesForDay.length; |
||||
if (_currentPageIndex >= 1 && this.currentPageIndex === 0) { |
||||
this.currentDayIndex = (this.currentDayIndex + 1) % this.days.length; |
||||
} |
||||
} else { |
||||
this.currentPageIndex = 0; |
||||
this.currentDayIndex = (this.currentDayIndex + 1) % this.days.length; |
||||
} |
||||
} else { |
||||
this.currentDayIndex = 0; |
||||
this.currentPageIndex = 0; |
||||
} |
||||
}, 15000); |
||||
} |
||||
}" x-init="loop()"> |
||||
|
||||
<header> |
||||
<div id="header"> |
||||
<div class="left-content bubble-header"> |
||||
<img src="{% static 'tournaments/images/PadelClub_logo_512.png' %}" alt="logo" class="logo"> |
||||
<div class="left-margin"> |
||||
<h1 class="club">{{ tournament.broadcast_event_display_name }}</h1> |
||||
<h1 class="event" x-text="days[currentDayIndex]"></h1> |
||||
</div> |
||||
</div> |
||||
<div class="right-content">{% qr_from_text qr_code_url options=qr_code_options %}</div> |
||||
</div> |
||||
</header> |
||||
|
||||
<div class="wrapper"> |
||||
<main> |
||||
<div class="grid-x"> |
||||
<div class="cell" :class="{'large-12': courtCount >= 5, 'large-6': courtCount < 5}"> |
||||
<div style="display: flex; margin-bottom: 20px;"> |
||||
<div class="bubble-footer score ws bold" style="visibility: hidden; display: flex; align-items: center; justify-content: center; margin: 0; width: 7em; margin-right: 15px; height: 40px;"> |
||||
<h1 class="score ws bold" style="margin: 0; padding: 0;">00:00</h1> |
||||
</div> |
||||
<div class="courts-row"> |
||||
<template x-for="courtNum in Array.from({length: courtCount || 1}, (_, i) => i + 1)" :key="courtNum"> |
||||
<div class="court-label"> |
||||
<div class="bubble"> |
||||
<div class="score ws bold">Terrain <span x-text="courtNum"></span></div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="cell" :class="{'large-12': courtCount >= 5, 'large-6': courtCount < 5}" x-show="courtCount < 5"> |
||||
<div style="display: flex; margin-bottom: 20px;"> |
||||
<div class="bubble-footer score ws bold" style="visibility: hidden; display: flex; align-items: center; justify-content: center; margin: 0; width: 7em; margin-right: 15px; height: 40px;"> |
||||
<h1 class="score ws bold" style="margin: 0; padding: 0;">00:00</h1> |
||||
</div> |
||||
<div class="courts-row"> |
||||
<template x-for="courtNum in Array.from({length: courtCount || 1}, (_, i) => i + 1)" :key="courtNum"> |
||||
<div class="court-label"> |
||||
<div class="bubble"> |
||||
<div class="score ws bold">Terrain <span x-text="courtNum"></span></div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
||||
<template x-for="(day, dayIndex) in days" :key="day"> |
||||
<div x-show="currentDayIndex === dayIndex"> |
||||
<template x-for="(groupPage, pageIndex) in getMatchGroupsForDay(day)" :key="'page-' + pageIndex"> |
||||
<div x-show="currentPageIndex === pageIndex"> |
||||
<div class="grid-x"> |
||||
<template x-for="(group, groupIndex) in groupPage" :key="groupIndex"> |
||||
<div class="cell" :class="{'large-12': courtCount >= 5, 'large-6': courtCount < 5}"> |
||||
<div style="display: flex; margin-bottom: 20px;"> |
||||
<!-- Group name container --> |
||||
<div class="bubble-footer score ws bold" style="display: flex; align-items: center; justify-content: center; margin: 0; width: 7em; margin-right: 15px;"> |
||||
<h1 class="score ws bold" style="margin: 0; padding: 0;" x-text="group.name.slice(-5)"></h1> |
||||
</div> |
||||
|
||||
<!-- Matches container --> |
||||
<div class="matches-row"> |
||||
<template x-for="(match, courtIndex) in organizeMatchesByCourt(group.matches)" :key="courtIndex"> |
||||
<div class="match-cell"> |
||||
<template x-if="match"> |
||||
<div class="bubble" :class="{'running': !match.ended && match.started, 'even': courtIndex % 2 === 1}" style="text-align: center;"> |
||||
<div class="score ws bold" x-text="match.group_stage_name ? match.group_stage_name : match.title"></div> |
||||
<template x-if="match.tournament_title"> |
||||
<div class="minor-info semibold" x-text="match.tournament_title"></div> |
||||
</template> |
||||
</div> |
||||
</template> |
||||
<template x-if="!match"> |
||||
<div class="bubble empty" style="text-align: center;"> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</template> |
||||
</main> |
||||
</div> |
||||
|
||||
<footer class="footer-broadcast"> |
||||
{% if tournament.event.images.exists %} |
||||
<div class="bubble-footer"> |
||||
<div class="bubble-sponsor"> |
||||
{% for image in tournament.event.images.all %} |
||||
<img src="{{ image.image.url }}" alt="{{ image.title|default:'Sponsor' }}" |
||||
class="sponsor-logo-broadcast"> |
||||
{% endfor %} |
||||
</div> |
||||
</div> |
||||
{% endif %} |
||||
</footer> |
||||
</body> |
||||
</html> |
||||
Loading…
Reference in new issue