Update dashboard for gymnast.

This commit is contained in:
Gregory Trullemans 2024-05-10 20:53:02 +01:00
parent a10df7b3d2
commit cef1893333
5 changed files with 162 additions and 75 deletions

View File

@ -27,8 +27,8 @@
<h4 class=""><i class="text-primary fal fa-laugh-wink"></i> Hi {{ user.first_name }} !</h4> <h4 class=""><i class="text-primary fal fa-laugh-wink"></i> Hi {{ user.first_name }} !</h4>
</div> </div>
<div class="card-body text-justify pt-0"> <div class="card-body text-justify pt-0">
<p>Welcome to Jarvi v1.03 <span class="text-muted">(last update : 9 may 2024)</span>. You can find the user manual <a href="{% url 'help' %}" target="_blank">here (in french)</a>.</p> <p>Welcome to Jarvi v1.0.4 <span class="text-muted">(last update : 10 may 2024)</span>.</p>
<p>This application is here to help coaches to manage the gymnasts (evolution, evaluation, routines, scores, …). This tool is not perfect so feel free to make improvement proposals, bug reports, … by sending me an <a href="mailto:gregory@flyingacrobaticstrampoline.be?subject=Jarvis remarks">email</a>.</p> <p>This application is designed to assist coaches in managing gymnasts' progress, evaluations, routines, scores, and more. While this tool isn't flawless, please feel free to submit improvement suggestions, bug reports, or any feedback by sending an <a href="mailto:gregory@flyingacrobaticstrampoline.be?subject=Jarvis remarks">email</a>.</p>
</div> </div>
</div> </div>
</div> </div>
@ -130,13 +130,53 @@
<h4><i class="fal fa-exclamation-triangle text-danger"></i> Your last profile update</h4> <h4><i class="fal fa-exclamation-triangle text-danger"></i> Your last profile update</h4>
</div> </div>
<div class="card-body pt-0"> <div class="card-body pt-0">
<ol class="list-unstyled"> <ol class="list-unstyled mb-0">
<li>Wellbeing: <i>{{ wellbeing_last_update.0 |date:"j F Y" }}</i></li> <li>Wellbeing:
<li>Height/Weight: <i>{{ height_weight_last_update.0 |date:"j F Y" }}</i></li> {% if wellbeing_state %}
<li>Intensity: <i>{{ intensities_last_update.0 |date:"j F Y" }}</i></li> <span class="text-{{ wellbeing_state }}">
{% endif %}
{{ wellbeing_last_record_date.0 |date:"j F Y" }}
{% if wellbeing_state %}
</span>
{% endif %}
</li>
<li>Height/Weight:
{% if height_weight_state %}
<span class="text-{{ height_weight_state }}">
{% endif %}
{{ height_weight_last_record_date.0 |date:"j F Y" }}
{% if wellbeing_state %}
</span>
{% endif %}
</li>
<li>Intensity:
{% if intensity_state %}
<span class="text-{{ intensity_state }}">
{% endif %}
{{ intensities_last_record_date.0 |date:"j F Y" }}
{% if wellbeing_state %}
</span>
{% endif %}
</li>
<!-- <li>{{ points_last_update }}</li> --> <!-- <li>{{ points_last_update }}</li> -->
<li>Chrono: <i>{{ chronos_last_update.0 |date:"j F Y" }}</i></li> <li>Chrono:
<li>Learned Skill: <i>{{ known_skills_last_update.0 |date:"j F Y" }}</i></li> {% if chrono_state %}
<span class="text-{{ chrono_state }}">
{% endif %}
{{ chrono_last_record_date.0 |date:"j F Y" }}
{% if chrono_state %}
</span>
{% endif %}
</li>
<li>Learned Skill:
{% if known_skills_state %}
<span class="text-{{ known_skills_state }}">
{% endif %}
{{ known_skills_last_record_date.0 |date:"j F Y" }}
{% if known_skills_state %}
</span>
{% endif %}
</li>
</ol> </ol>
</div> </div>
{% endif %} {% endif %}

View File

@ -93,11 +93,31 @@ def next_birthdays(request, number_of_birthday):
return birthday_list return birthday_list
def gymnast_have_birthday(request):
"""
Renvoie la liste des gymnastes qui ont leur anniversaire aujourd'hui.
"""
today = pendulum.now().date()
return Gymnast.objects.filter(birthdate__day=today.day, birthdate__month=today.month).values_list("id")
# @lru_cache() # @lru_cache()
# def get_last_updated_gymnasts(expiration_date): # def get_last_updated_gymnasts(expiration_date):
# ... # ...
# TODO: véririer si c'est l'anniversaire de la personne qui est connectée.
# TODO: check if gymnast have point
# ---------------------------
# 1. récupérer tous les évènements passés
# 2. pour chaque event, vérifier que tous les gymnastes renseignés
# dans les participants ont des points associés.
# S'il n'y a pas de point, faire une alerte à l'utilisateur qui se connecte.
# TODO: Check if gymnast have update
# -----------------------------
# lister tous les gymnastes qui n'ont pas eu d'update depuis... 2 semaines ?
# peut-être le paramètre (en jour) devrait être stocké en DB.
# S'il n'y a pas d'update, faire une alerte à l'utilisateur qui se connecte.
@login_required @login_required
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def home(request): def home(request):
@ -106,9 +126,21 @@ def home(request):
""" """
today = timezone.now() # pendulum.now().date() today = timezone.now() # pendulum.now().date()
_, week_number = from_date_to_week_number(today) _, week_number = from_date_to_week_number(today)
event_list = Event.objects.filter(date_begin__gte=today).order_by("date_begin")[:10]
quote = Citation.objects.order_by("?").first() context = {
"week_number": week_number,
"quote": Citation.objects.order_by("?").first(),
"event_list": Event.objects.filter(date_begin__gte=today).order_by("date_begin")[:10],
"nb_active_gymnast": Gymnast.objects.filter(is_active=True).count(),
"nb_trainer": User.objects.filter(is_active=True, groups__name="trainer").count(),
"nb_event": Event.objects.all().count(),
"nb_skill": Skill.objects.all().count(),
"nb_routine": Routine.objects.all().count(),
"nb_score": Point.objects.all().count(),
"nb_club": Club.objects.all().count(),
"percentage_week": (week_number / 52) * 100,
"birthday_list": next_birthdays(request, 10),
}
is_trainer = request.user.groups.filter(name="trainer").exists() is_trainer = request.user.groups.filter(name="trainer").exists()
if is_trainer: if is_trainer:
@ -150,75 +182,86 @@ def home(request):
) )
.distinct() .distinct()
) )
wellbeing_last_update = None
height_weight_last_update = None context["is_trainer"] = is_trainer
intensities_last_update = None context["last_updated_gymnasts"] = last_updated_gymnasts
# points_last_update = None context["waiting_update_gymnast"] = waiting_update_gymnast
chronos_last_update = None
known_skills_last_update = None
else: else:
todate = pendulum.now().date()
birthday_list = gymnast_have_birthday(request)
gymnast = get_object_or_404(Gymnast, pk=request.user.gymnast.id) gymnast = get_object_or_404(Gymnast, pk=request.user.gymnast.id)
last_updated_gymnasts = None
waiting_update_gymnast = None # if birthday_list is not None and gymnast.id in birthday_list:
wellbeing_last_update = WellBeing.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first() # print("C'est l'anniversaire du gymnaste !")
height_weight_last_update = HeightWeight.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first() # else:
intensities_last_update = Intensity.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first() # print("Pas son annif…")
wellbeing_last_record_date = WellBeing.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
if todate.diff(wellbeing_last_record_date[0]).in_days() > 21:
wellbeing_state = "danger bold"
elif todate.diff(wellbeing_last_record_date[0]).in_days() > 14:
wellbeing_state = "danger"
elif todate.diff(wellbeing_last_record_date[0]).in_days() > 7:
wellbeing_state = "warning"
else:
wellbeing_state = None
height_weight_last_record_date = HeightWeight.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
if todate.diff(height_weight_last_record_date[0]).in_days() > 21:
height_weight_state = "danger bold"
elif todate.diff(height_weight_last_record_date[0]).in_days() > 14:
height_weight_state = "danger"
elif todate.diff(height_weight_last_record_date[0]).in_days() > 7:
height_weight_state = "warning"
else:
height_weight_state = None
intensities_last_record_date = Intensity.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
if todate.diff(intensities_last_record_date[0]).in_days() > 21:
intensity_state = "danger bold"
elif todate.diff(intensities_last_record_date[0]).in_days() > 14:
intensity_state = "danger"
elif todate.diff(intensities_last_record_date[0]).in_days() > 7:
intensity_state = "warning"
else:
intensity_state = None
# points_last_update = Gymnast.objects.all().order_by("-date")[:1] # points_last_update = Gymnast.objects.all().order_by("-date")[:1]
chronos_last_update = Chrono.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first() chrono_last_record_date = Chrono.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
known_skills_last_update = LearnedSkill.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first() if todate.diff(chrono_last_record_date[0]).in_days() > 21:
chrono_state = "danger bold"
elif todate.diff(chrono_last_record_date[0]).in_days() > 14:
chrono_state = "danger"
elif todate.diff(chrono_last_record_date[0]).in_days() > 7:
chrono_state = "warning"
else:
chrono_state = None
# TODO: véririer si c'est l'anniversaire de la personne qui est connectée. known_skills_last_record_date = LearnedSkill.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
if todate.diff(known_skills_last_record_date[0]).in_days() > 21:
known_skills_state = "danger bold"
elif todate.diff(known_skills_last_record_date[0]).in_days() > 14:
known_skills_state = "danger"
elif todate.diff(known_skills_last_record_date[0]).in_days() > 7:
known_skills_state = "warning"
else:
known_skills_state = None
nb_active_gymnast = Gymnast.objects.filter(is_active=True).count() context["wellbeing_last_record_date"] = wellbeing_last_record_date
nb_trainer = User.objects.filter(is_active=True, groups__name="trainer").count() context["wellbeing_state"] = wellbeing_state
nb_event = Event.objects.all().count() context["height_weight_last_record_date"] = height_weight_last_record_date
nb_skill = Skill.objects.all().count() context["height_weight_state"] = height_weight_state
nb_routine = Routine.objects.all().count() context["intensities_last_record_date"] = intensities_last_record_date
nb_score = Point.objects.all().count() context["intensity_state"] = intensity_state
nb_club = Club.objects.all().count()
percentage_week = (week_number / 52) * 100
birthday_list = next_birthdays(request, 10)
# # check if gymnast have point
# # ---------------------------
# # 1. récupérer tous les évènements passés
# # 2. pour chaque event, vérifier que tous les gymnastes renseignés
# # dans les participants ont des points associés.
# # S'il n'y a pas de point, faire une alerte à l'utilisateur qui se connecte.
# # Check if gymnast have update
# # -----------------------------
# # lister tous les gymnastes qui n'ont pas eu d'update depuis... 2 semaines ?
# # peut-être le paramètre (en jour) devrait être stocké en DB.
# # S'il n'y a pas d'update, faire une alerte à l'utilisateur qui se connecte.
context = {
"quote": quote,
"week_number": week_number,
"event_list": event_list,
"last_updated_gymnasts": last_updated_gymnasts,
"waiting_update_gymnast": waiting_update_gymnast,
"nb_active_gymnast": nb_active_gymnast,
"nb_trainer": nb_trainer,
"nb_event": nb_event,
"nb_skill": nb_skill,
"nb_routine": nb_routine,
"nb_score": nb_score,
"nb_club": nb_club,
"wellbeing_last_update": wellbeing_last_update,
"height_weight_last_update": height_weight_last_update,
"intensities_last_update": intensities_last_update,
# "points_last_update": points_last_update, # "points_last_update": points_last_update,
"chronos_last_update": chronos_last_update, context["chrono_last_record_date"] = chrono_last_record_date
"known_skills_last_update": known_skills_last_update, context["chrono_state"] = chrono_state
"percentage_week": percentage_week, context["known_skills_last_record_date"] = known_skills_last_record_date
"birthday_list": birthday_list, context["known_skills_state"] = known_skills_state
"is_trainer": is_trainer,
}
return render(request, "dashboard/dashboard.html", context) return render(request, "dashboard/dashboard.html", context)
# return render(request, "dashboard/dashboard.html", {})
@login_required @login_required

View File

@ -28,9 +28,9 @@
{% if request.user|has_group:"trainer" %} {% if request.user|has_group:"trainer" %}
<th style="width: 3%"></th> <th style="width: 3%"></th>
{% endif %} {% endif %}
<th class="header text-left" style="width: 27%">Name</th> <th class="header text-left" style="width: 30%">Name</th>
<th class="header text-left" style="width: 35%">Address</th> <th class="header text-left" style="width: 35%">Address</th>
<th class="header text-center" style="width: 10%">Zip</th> <th class="header text-center" style="width: 7%">Zip</th>
<th class="header text-center" style="width: 15%">City</th> <th class="header text-center" style="width: 15%">City</th>
</tr> </tr>
</thead> </thead>

View File

@ -41,7 +41,7 @@
</a></h3> </a></h3>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body mb-0">
{% if next_event_list %} {% if next_event_list %}
<table class="table tablesorter table-condensed table-striped" id="next_events"> <table class="table tablesorter table-condensed table-striped" id="next_events">
<thead> <thead>

View File

@ -95,6 +95,10 @@ textarea.form-control {
font-size: 12px; font-size: 12px;
} }
.bold {
font-weight: bold;
}
.progress-bar-primary { .progress-bar-primary {
background: #ba54f5; background: #ba54f5;
background-image: -webkit-linear-gradient(to bottom left, #ba54f5, #e14eca, #ba54f5); background-image: -webkit-linear-gradient(to bottom left, #ba54f5, #e14eca, #ba54f5);