diff --git a/tournaments/models/enums.py b/tournaments/models/enums.py index c3f3be6..9d73142 100644 --- a/tournaments/models/enums.py +++ b/tournaments/models/enums.py @@ -138,6 +138,11 @@ class OnlineRegistrationStatus(models.IntegerChoices): WAITING_LIST_FULL = 6, 'Waiting List Full' IN_PROGRESS = 7, 'In Progress' ENDED_WITH_RESULTS = 8, 'Ended with Results' + CONFIRMED = 9, 'Confirmed' + WALKOUT = 10, 'Walkout' + WAITING_LIST = 11, 'Waiting list' + CANCELED = 12, 'Canceled' + USER_IN_PROGRESS = 13, 'User in progress' def status_localized(self) -> str: status_map = { @@ -145,13 +150,43 @@ class OnlineRegistrationStatus(models.IntegerChoices): OnlineRegistrationStatus.NOT_ENABLED: "Inscription désactivée", OnlineRegistrationStatus.NOT_STARTED: "Ouverture des inscriptions à venir", OnlineRegistrationStatus.ENDED: "Inscription terminée", - OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "Liste d'attente ouverte", - OnlineRegistrationStatus.WAITING_LIST_FULL: "Liste d'attente complète", - OnlineRegistrationStatus.IN_PROGRESS: "Tournoi en cours", - OnlineRegistrationStatus.ENDED_WITH_RESULTS: "Tournoi terminé" + OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "Liste d'attente", + OnlineRegistrationStatus.WAITING_LIST_FULL: "Complet", + OnlineRegistrationStatus.IN_PROGRESS: "En cours", + OnlineRegistrationStatus.ENDED_WITH_RESULTS: "Tournoi terminé", + OnlineRegistrationStatus.CONFIRMED: "Inscription\nconfirmée", + OnlineRegistrationStatus.WALKOUT: "Forfait", + OnlineRegistrationStatus.WAITING_LIST: "Inscription\nen attente", + OnlineRegistrationStatus.CANCELED: "Annulé", + OnlineRegistrationStatus.USER_IN_PROGRESS: "En lice", } return status_map.get(self, "") + def color(self) -> str: + status_map = { + OnlineRegistrationStatus.OPEN: "#90ee90", #orange + OnlineRegistrationStatus.NOT_ENABLED: "#90ee90", + OnlineRegistrationStatus.NOT_STARTED: "#90ee90", + OnlineRegistrationStatus.ENDED: "#90ee90", #green + OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "#90ee90", #yellow + OnlineRegistrationStatus.WAITING_LIST_FULL: "#E84038", #red + OnlineRegistrationStatus.IN_PROGRESS: "#90ee90", + OnlineRegistrationStatus.ENDED_WITH_RESULTS: "#F39200", + OnlineRegistrationStatus.CONFIRMED: "#F39200", + OnlineRegistrationStatus.WALKOUT: "#E84038", + OnlineRegistrationStatus.WAITING_LIST: "#F39200", + OnlineRegistrationStatus.CANCELED: "#E84038", + OnlineRegistrationStatus.USER_IN_PROGRESS: "#F39200", + } + return status_map.get(self, "") + + def text_color(self) -> str: + status_map = { + OnlineRegistrationStatus.OPEN: "#707070", #orange + OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "#707070", #yellow + } + return status_map.get(self, "#FFFFFF") + class UserOrigin(models.IntegerChoices): ADMIN = 0, 'Admin' SITE = 1, 'Site' diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index 3740561..fe9a284 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -14,6 +14,7 @@ from zoneinfo import ZoneInfo from tournaments.utils.player_search import get_player_name_from_csv from shared.cryptography import encryption_util from ..utils.extensions import plural_format +from ..utils.licence_validator import LicenseValidator class TeamSortingType(models.IntegerChoices): RANK = 1, 'Rank' @@ -170,7 +171,10 @@ class Tournament(models.Model): return self.get_federal_age_category_display() def formatted_start_date(self): - return self.start_date.strftime("%d/%m/%y") + return formats.date_format(self.start_date, format='d/m/Y') + + def formatted_start_date_short(self): + return formats.date_format(self.start_date, format='l d/m/Y') def in_progress(self): return self.end_date is None @@ -210,36 +214,95 @@ class Tournament(models.Model): else: return None + def status_header(self): + if self.supposedly_in_progress() or self.end_date is not None or self.should_be_over(): + return "Statut" + if self.end_date is not None or self.should_be_over(): + return "Classement" + return "Inscriptions" + def tournament_status_display(self): - if self.is_canceled() is True: - return "Annulé" - - teams = self.teams(True) - if self.supposedly_in_progress() or self.end_date is not None or self.should_be_over(): - teams = [t for t in teams if t.stage != "Attente"] - if teams is not None and len(teams) > 0: - word = "équipe" - if len(teams) > 1: - word = word + "s" - return f"{len(teams)} {word}" - else: - return None - - registration_status = None - if self.enable_online_registration == True: - registration_status = self.get_online_registration_status().status_localized() - if teams is not None and len(teams) > 0: - word = "inscription" - if len(teams) > 1: - word = word + "s" - if registration_status is not None: - return f"{registration_status}\n{len(teams)} {word}" - else: - return f"{len(teams)} {word}" - else: - if registration_status is not None: - return f"{registration_status}" - return None + teams = self.teams(True) + if self.supposedly_in_progress() or self.end_date is not None or self.should_be_over(): + teams = [t for t in teams if t.stage != "Attente"] + return f"{len(teams)}" + + return f"{len(teams)}" + + + def tournament_user_team(self, user): + team_registration = None + + if user.is_authenticated: + # Assuming user's licence_id is stored in the user profile (e.g., request.user.licence_id) + user_licence_id = user.licence_id + player_register_check = self.player_register_check(user_licence_id) + registered_user = None + if user_licence_id is not None and player_register_check is None: + validator = LicenseValidator(user_licence_id) + stripped_license = validator.stripped_license + # Check if there is a PlayerRegistration for this user in this tournament + from tournaments.models import PlayerRegistration + registered_user = PlayerRegistration.objects.filter( + licence_id__startswith=stripped_license, + team_registration__tournament=self, + ).first() + + # If the user is registered, retrieve their team registration + if registered_user: + team_registration = registered_user.team_registration + + return team_registration + + def tournament_register_status_display(self, user): + # if user.is_authenticated: + # return f"confirmée" + # else: + # return "ouverte" + # + team_registration = None + if user and user.is_authenticated: + team_registration = self.tournament_user_team(user) + team_status = self.team_status(team_registration) + if team_status and team_registration: + if team_status is OnlineRegistrationStatus.ENDED_WITH_RESULTS and team_registration.get_points_earned(): + message = f"+{team_registration.get_points_earned()} pts" + return message, team_status.color(), team_status.text_color() + return team_status.status_localized(), team_status.color(), team_status.text_color() + if team_status: + return team_status.status_localized(), team_status.color(), team_status.text_color() + return None + + + + def team_status(self, team_registration): + if team_registration: + if team_registration.out_of_tournament(): + return OnlineRegistrationStatus.WALKOUT + elif team_registration.is_in_waiting_list() >= 0: + return OnlineRegistrationStatus.WAITING_LIST + elif self.end_date is not None or self.should_be_over(): + return self.get_online_registration_status() + elif self.supposedly_in_progress(): + return OnlineRegistrationStatus.USER_IN_PROGRESS + return OnlineRegistrationStatus.CONFIRMED + + if self.end_date is not None or self.should_be_over(): + return None + + if self.is_canceled() is True: + return OnlineRegistrationStatus.CANCELED + + if self.enable_online_registration is False: + return None + + return self.get_online_registration_status() + registration_status = None + if self.enable_online_registration == True: + registration_status = self.get_online_registration_status().status_localized() + if registration_status is not None: + return f"{registration_status}" + return None def name_and_event(self): event_name = None @@ -1055,35 +1118,35 @@ class Tournament(models.Model): return True def get_online_registration_status(self): - if self.supposedly_in_progress(): - return OnlineRegistrationStatus.ENDED - if self.closed_registration_date is not None: + if self.closed_registration_date is not None: + return OnlineRegistrationStatus.ENDED + if self.end_date is not None: + return OnlineRegistrationStatus.ENDED_WITH_RESULTS + if self.supposedly_in_progress(): + return OnlineRegistrationStatus.IN_PROGRESS + + now = timezone.now() + + if self.opening_registration_date is not None: + timezoned_datetime = timezone.localtime(self.opening_registration_date) + if now < timezoned_datetime: + return OnlineRegistrationStatus.NOT_STARTED + + if self.registration_date_limit is not None: + timezoned_datetime = timezone.localtime(self.registration_date_limit) + if now > timezoned_datetime: return OnlineRegistrationStatus.ENDED - if self.end_date is not None: - return OnlineRegistrationStatus.ENDED_WITH_RESULTS - - now = timezone.now() - - if self.opening_registration_date is not None: - timezoned_datetime = timezone.localtime(self.opening_registration_date) - if now < timezoned_datetime: - return OnlineRegistrationStatus.NOT_STARTED - - if self.registration_date_limit is not None: - timezoned_datetime = timezone.localtime(self.registration_date_limit) - if now > timezoned_datetime: - return OnlineRegistrationStatus.ENDED - - if self.team_count is not None: - # Get all team registrations excluding walk_outs - current_team_count = self.teamregistration_set.exclude(walk_out=True).count() - if current_team_count >= self.team_count: - if self.waiting_list_limit is not None: - waiting_list_count = current_team_count - self.team_count - if waiting_list_count >= self.waiting_list_limit: - return OnlineRegistrationStatus.WAITING_LIST_FULL - return OnlineRegistrationStatus.WAITING_LIST_POSSIBLE - return OnlineRegistrationStatus.OPEN + + if self.team_count is not None: + # Get all team registrations excluding walk_outs + current_team_count = self.teamregistration_set.exclude(walk_out=True).count() + if current_team_count >= self.team_count: + if self.waiting_list_limit is not None: + waiting_list_count = current_team_count - self.team_count + if waiting_list_count >= self.waiting_list_limit: + return OnlineRegistrationStatus.WAITING_LIST_FULL + return OnlineRegistrationStatus.WAITING_LIST_POSSIBLE + return OnlineRegistrationStatus.OPEN def is_unregistration_possible(self): # Check if tournament has started diff --git a/tournaments/static/tournaments/css/style.css b/tournaments/static/tournaments/css/style.css index 035357a..11f8dfd 100644 --- a/tournaments/static/tournaments/css/style.css +++ b/tournaments/static/tournaments/css/style.css @@ -200,6 +200,10 @@ tr { text-decoration: none; font-size: 12px; font-weight: 600; + height: inherit; /* or height: 100% */ + display: flex; + align-items: center; + justify-content: center; } @media (max-width: 80em) { @@ -260,6 +264,11 @@ tr { font-size: 1.2em; } +.medium { + font-family: "Montserrat-SemiBold"; + font-size: 0.8em; +} + @media screen and (max-width: 40em) { .large { font-size: 0.9em; @@ -589,6 +598,14 @@ h-margin { padding: 5px 0px; } +.table-row-6-colums-tournament { + display: grid; + grid-template-columns: 12% 1fr 10% 8% 12% 12%; + align-items: center; + padding: 8px 0px; + gap: 8px; /* Adds equal spacing between all grid items */ +} + .table-row-6-colums-club-tournament { display: grid; grid-template-columns: 100px 80px 100px 80px 1fr auto; @@ -675,9 +692,9 @@ h-margin { } .table-cell { - flex-grow: 1; - /* text-align: center; */ - /* padding: 5px; */ + align-items: center; + text-align: left; + height: 100%; } .table-cell-large { diff --git a/tournaments/templates/tournaments/tournament_row.html b/tournaments/templates/tournaments/tournament_row.html index 199c25f..5277a84 100644 --- a/tournaments/templates/tournaments/tournament_row.html +++ b/tournaments/templates/tournaments/tournament_row.html @@ -1,43 +1,36 @@ - -
-
-
{{ tournament.level }}
-
{{ tournament.category }}
- {% if tournament.age %} -
{{ tournament.age }}
- {% endif %} -
-
-
{{ tournament.event.club.name }}
- {% if tournament.name_and_event %} -
- {{ tournament.name_and_event }} -
- {% endif %} -
-
-
{{ tournament.event.club.computedShortTitle }}
- {% if tournament.event.name %} -
{{ tournament.event.name }}
- {% endif %} - {% if tournament.name %} -
{{ tournament.name }}
- {% endif %} -
- - {% if tournament.tournament_status_display %} -
- {{ tournament.tournament_status_display|linebreaksbr }} -
- {% endif %} -
-
{{ tournament.formatted_start_date }}
- {% if tournament.tournament_status_display %} -
{{ tournament.tournament_status_display|linebreaksbr }}
- {% endif %} -
-
-
- {% if not forloop.last %} -
- {% endif %} + +
+
+
{{ tournament.level }}
+
{{ tournament.category }}
+ {% if tournament.age %} +
{{ tournament.age }}
+ {% endif %} +
+
+
{{ tournament.event.club.name }}
+ {% if tournament.name_and_event %} +
{{ tournament.name_and_event }}
+ {% endif %} +
+
+
Équipes
+
{{ tournament.tournament_status_display }}
+
+
+
Durée
+
{{ tournament.day_duration }} j.
+
+
+
{{ tournament.formatted_start_date_short|linebreaksbr }}
+
+
+ {% if register_status %} +
{{ register_status.0|linebreaksbr }}
+ {% endif %} +
+
+
+{% if not forloop.last %} +
+{% endif %} diff --git a/tournaments/templates/tournaments/tournaments.html b/tournaments/templates/tournaments/tournaments.html index d55463b..93f458f 100644 --- a/tournaments/templates/tournaments/tournaments.html +++ b/tournaments/templates/tournaments/tournaments.html @@ -24,7 +24,7 @@ {% for tournament in live %} - {% include 'tournaments/tournament_row.html' %} + {% include 'tournaments/tournament_row.html' with tournament=tournament.tournament register_status=tournament.register_status %} {% endfor %} {% if live|length >= 10 %} @@ -44,7 +44,7 @@ {% for tournament in future %} - {% include 'tournaments/tournament_row.html' %} + {% include 'tournaments/tournament_row.html' with tournament=tournament.tournament register_status=tournament.register_status %} {% endfor %} {% if future|length >= 10 %} @@ -71,7 +71,7 @@ {% for tournament in ended %} - {% include 'tournaments/tournament_row.html' %} + {% include 'tournaments/tournament_row.html' with tournament=tournament.tournament register_status=tournament.register_status %} {% endfor %} {% if ended|length >= 10 %} diff --git a/tournaments/views.py b/tournaments/views.py index 5eefc8c..d657b26 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -112,6 +112,34 @@ def index(request): live = live_tournaments(club_id) finished = finished_tournaments(club_id) + tournaments_with_status = [] + for tournament in live: + status = tournament.tournament_register_status_display(request.user) + tournaments_with_status.append({ + 'tournament': tournament, + 'register_status': status + }) + live = tournaments_with_status + + tournaments_with_status = [] + for tournament in future: + status = tournament.tournament_register_status_display(request.user) + tournaments_with_status.append({ + 'tournament': tournament, + 'register_status': status + }) + future = tournaments_with_status + + tournaments_with_status = [] + for tournament in finished: + status = tournament.tournament_register_status_display(request.user) + tournaments_with_status.append({ + 'tournament': tournament, + 'register_status': status + }) + finished = tournaments_with_status + + club = None if club_id: club = get_object_or_404(Club, pk=club_id)