mirror of https://github.com/snachodog/mybuddy.git
Add feeding method history (#774)
* add feeding method history * Make it a specialized breastfeeding card instead. * Minor improvements: - don't print days for an empty card. - make the width of the bar for each day proportional to that day's total feeding time. * Don't make bar width proportional to feeding time, actually, it's kinda ugly. --------- Co-authored-by: ag <ag@ag.com> Co-authored-by: Christopher C. Wells <git-2022@chris-wells.net>
This commit is contained in:
parent
25d3c9f58c
commit
ab5bb66c8f
|
@ -73,6 +73,10 @@
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
height: $progress-height * 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-sleep {
|
.card-sleep {
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{% extends 'cards/base.html' %}
|
||||||
|
{% load duration i18n %}
|
||||||
|
{% block header %}
|
||||||
|
<a href="{% url "core:feeding-list" %}">{% trans "Breastfeeding" %}</a>
|
||||||
|
{% endblock %}
|
||||||
|
{% block title %}
|
||||||
|
{% if total == 0 %}
|
||||||
|
{% trans "None" %}
|
||||||
|
{% else %}
|
||||||
|
{% trans "Past Week" %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% for key, info in stats.items %}
|
||||||
|
{% if info.left_count > 0 or info.right_count > 0 %}
|
||||||
|
<div class="progress mt-3" role="progressbar">
|
||||||
|
<div class="progress-bar bg-primary lead"
|
||||||
|
style="width: {{ info.left_pct|safe }}%">{{ info.left_count }} {% trans "left" %}</div>
|
||||||
|
<div class="progress-bar bg-secondary lead"
|
||||||
|
style="width: {{ info.right_pct|safe }}%">{{ info.right_count }} {% trans "right" %}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center text-light small">
|
||||||
|
{% if key == 0 %}
|
||||||
|
{% trans "today" %}
|
||||||
|
{% elif key == 1 %}
|
||||||
|
{% trans "yesterday" %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktrans with days_ago=key %}{{ days_ago }} days ago{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
|
{% if info.count > 0 %}
|
||||||
|
({{ info.count }} {% trans "feedings in" %} {{ info.duration|duration_string:'m' }})
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -26,6 +26,7 @@
|
||||||
<div class="col-sm-6 col-lg-4">{% card_sleep_naps_day object %}</div>
|
<div class="col-sm-6 col-lg-4">{% card_sleep_naps_day object %}</div>
|
||||||
<div class="col-sm-6 col-lg-4">{% card_tummytime_day object %}</div>
|
<div class="col-sm-6 col-lg-4">{% card_tummytime_day object %}</div>
|
||||||
<div class="col-sm-6 col-lg-4">{% card_diaperchange_types object %}</div>
|
<div class="col-sm-6 col-lg-4">{% card_diaperchange_types object %}</div>
|
||||||
|
<div class="col-sm-6 col-lg-4">{% card_breastfeeding object %}</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
|
|
|
@ -5,7 +5,8 @@ from django.db.models.functions import TruncDate
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from datetime import date, datetime, time
|
from datetime import date, datetime, time, timedelta
|
||||||
|
import collections
|
||||||
|
|
||||||
from core import models
|
from core import models
|
||||||
|
|
||||||
|
@ -107,6 +108,77 @@ def card_diaperchange_types(context, child, date=None):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register.inclusion_tag("cards/breastfeeding.html", takes_context=True)
|
||||||
|
def card_breastfeeding(context, child, date=None):
|
||||||
|
"""
|
||||||
|
Creates a break down of breasts used for breastfeeding, for the past
|
||||||
|
seven days.
|
||||||
|
:param child: an instance of the Child model.
|
||||||
|
:param date: a Date object for the day to filter.
|
||||||
|
:returns: a dictionary with the statistics.
|
||||||
|
"""
|
||||||
|
if date:
|
||||||
|
time = timezone.datetime.combine(date, timezone.localtime().min.time())
|
||||||
|
time = timezone.make_aware(time)
|
||||||
|
else:
|
||||||
|
time = timezone.localtime()
|
||||||
|
|
||||||
|
max_date = (time + timezone.timedelta(days=1)).replace(hour=0, minute=0, second=0)
|
||||||
|
min_date = (max_date - timezone.timedelta(days=7)).replace(
|
||||||
|
hour=0, minute=0, second=0
|
||||||
|
)
|
||||||
|
|
||||||
|
instances = (
|
||||||
|
models.Feeding.objects.filter(child=child)
|
||||||
|
.filter(start__gt=min_date)
|
||||||
|
.filter(start__lt=max_date)
|
||||||
|
.filter(method__in=("left breast", "right breast", "both breasts"))
|
||||||
|
.order_by("-start")
|
||||||
|
)
|
||||||
|
|
||||||
|
empty = len(instances) == 0
|
||||||
|
|
||||||
|
# Create a `stats` dictionary, keyed by day for the past 7 days.
|
||||||
|
stats = {}
|
||||||
|
for x in range(7):
|
||||||
|
stats[x] = {}
|
||||||
|
|
||||||
|
# Group feedings per day.
|
||||||
|
per_day = collections.defaultdict(list)
|
||||||
|
for instance in instances:
|
||||||
|
key = (max_date - instance.start).days
|
||||||
|
per_day[key].append(instance)
|
||||||
|
|
||||||
|
# Go through each day, set the stats dictionary for that day.
|
||||||
|
for key, day_instances in per_day.items():
|
||||||
|
left_count = 0
|
||||||
|
right_count = 0
|
||||||
|
for instance in day_instances:
|
||||||
|
if instance.method in ("left breast", "both breasts"):
|
||||||
|
left_count += 1
|
||||||
|
if instance.method in ("right breast", "both breasts"):
|
||||||
|
right_count += 1
|
||||||
|
|
||||||
|
stats[key] = {
|
||||||
|
"count": len(day_instances),
|
||||||
|
"duration": sum(
|
||||||
|
(instance.duration for instance in day_instances), start=timedelta()
|
||||||
|
),
|
||||||
|
"left_count": left_count,
|
||||||
|
"right_count": right_count,
|
||||||
|
"left_pct": 100 * left_count // (left_count + right_count),
|
||||||
|
"right_pct": 100 * right_count // (left_count + right_count),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"type": "feeding",
|
||||||
|
"stats": stats,
|
||||||
|
"total": len(instances),
|
||||||
|
"empty": empty,
|
||||||
|
"hide_empty": _hide_empty(context),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag("cards/feeding_recent.html", takes_context=True)
|
@register.inclusion_tag("cards/feeding_recent.html", takes_context=True)
|
||||||
def card_feeding_recent(context, child, end_date=None):
|
def card_feeding_recent(context, child, end_date=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -12145,6 +12145,10 @@ textarea.form-control-lg {
|
||||||
.card-pumping .card-body .last-feeding-method {
|
.card-pumping .card-body .last-feeding-method {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
|
.card-feeding .progress,
|
||||||
|
.card-pumping .progress {
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.card-sleep {
|
.card-sleep {
|
||||||
border-color: #ff8f00;
|
border-color: #ff8f00;
|
Binary file not shown.
|
@ -12145,6 +12145,10 @@ textarea.form-control-lg {
|
||||||
.card-pumping .card-body .last-feeding-method {
|
.card-pumping .card-body .last-feeding-method {
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
|
.card-feeding .progress,
|
||||||
|
.card-pumping .progress {
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.card-sleep {
|
.card-sleep {
|
||||||
border-color: #ff8f00;
|
border-color: #ff8f00;
|
||||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue