From 36e45701417413847192bf54d614d77099d5af6c Mon Sep 17 00:00:00 2001 From: Stephan Kerkman Date: Thu, 28 May 2026 15:05:13 +0200 Subject: [PATCH] feat: month strip display, fix dashboard counter, styled month form - Add month_strip template tag rendering JFMAMJJASOND circles, active months dark green, inactive light grey - Replace raw number list in pruning_strip with visual month strip - Restyle pruning month checkboxes as clickable circles in plant form - Fix dashboard 'Need pruning' counter (broken filter chain always showed 0) Co-Authored-By: Claude Sonnet 4.6 --- plants/templates/plants/base.html | 11 ++++++++++- plants/templates/plants/dashboard.html | 2 +- .../templates/plants/partials/month_strip.html | 1 + .../templates/plants/partials/pruning_strip.html | 7 +++---- plants/templates/plants/plant_form.html | 6 +++--- plants/templatetags/__init__.py | 0 plants/templatetags/plant_extras.py | 16 ++++++++++++++++ plants/views/dashboard.py | 1 + 8 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 plants/templates/plants/partials/month_strip.html create mode 100644 plants/templatetags/__init__.py create mode 100644 plants/templatetags/plant_extras.py diff --git a/plants/templates/plants/base.html b/plants/templates/plants/base.html index 55013eb..4aac15e 100644 --- a/plants/templates/plants/base.html +++ b/plants/templates/plants/base.html @@ -13,7 +13,16 @@ .care-chip { display: inline-block; padding: .2rem .55rem; border-radius: 1rem; font-size: .8rem; margin: .15rem; } .pruning-strip { border-left: 4px solid #ffc107; background: #fff9c4; padding: .5rem .75rem; border-radius: 0 .375rem .375rem 0; } .pruning-strip.overdue { border-color: #dc3545; background: #fff5f5; } - .month-checkboxes .form-check { display: inline-flex; margin-right: .5rem; } + /* Month strip — display */ + .month-strip { display: flex; gap: 3px; } + .month-dot { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; font-size: 10px; font-weight: 700; letter-spacing: 0; background: #e9ecef; color: #adb5bd; } + .month-dot--on { background: #2d6a4f; color: #fff; } + /* Month toggle — form */ + .month-toggle-group { display: flex; flex-wrap: wrap; gap: 5px; } + .month-toggle { position: relative; } + .month-toggle input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; } + .month-toggle label { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; font-size: 13px; font-weight: 700; cursor: pointer; background: #e9ecef; color: #6c757d; transition: background .15s, color .15s; user-select: none; } + .month-toggle input:checked + label { background: #2d6a4f; color: #fff; } diff --git a/plants/templates/plants/dashboard.html b/plants/templates/plants/dashboard.html index f38a542..41dd125 100644 --- a/plants/templates/plants/dashboard.html +++ b/plants/templates/plants/dashboard.html @@ -19,7 +19,7 @@
- {{ overdue|length|add:due_this_month|length }} + {{ needs_pruning_count }}
Need pruning
diff --git a/plants/templates/plants/partials/month_strip.html b/plants/templates/plants/partials/month_strip.html new file mode 100644 index 0000000..bb8bb96 --- /dev/null +++ b/plants/templates/plants/partials/month_strip.html @@ -0,0 +1 @@ +
{% for m in months %}{{ m.letter }}{% endfor %}
diff --git a/plants/templates/plants/partials/pruning_strip.html b/plants/templates/plants/partials/pruning_strip.html index df5c0b7..9cd5885 100644 --- a/plants/templates/plants/partials/pruning_strip.html +++ b/plants/templates/plants/partials/pruning_strip.html @@ -1,15 +1,14 @@ +{% load plant_extras %}
✂️ Pruning {% if plant.pruning_months %} -
- Scheduled: {{ plant.pruning_months|join:", " }} -
+
{% month_strip plant.pruning_months %}
{% endif %} {% with plant.pruning_logs.first as last_log %} {% if last_log %} -
Last pruned: {{ last_log.pruned_on|date:"j M Y" }}
+
Last pruned: {{ last_log.pruned_on|date:"j M Y" }}
{% endif %} {% endwith %}
diff --git a/plants/templates/plants/plant_form.html b/plants/templates/plants/plant_form.html index 23cb235..9a6c9e0 100644 --- a/plants/templates/plants/plant_form.html +++ b/plants/templates/plants/plant_form.html @@ -42,11 +42,11 @@
-
+
{% for widget in form.pruning_months %} -
+
{{ widget.tag }} - +
{% endfor %}
diff --git a/plants/templatetags/__init__.py b/plants/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plants/templatetags/plant_extras.py b/plants/templatetags/plant_extras.py new file mode 100644 index 0000000..ff72063 --- /dev/null +++ b/plants/templatetags/plant_extras.py @@ -0,0 +1,16 @@ +from django import template + +register = template.Library() + +_LETTERS = list('JFMAMJJASOND') + + +@register.inclusion_tag('plants/partials/month_strip.html') +def month_strip(pruning_months): + months_set = set(pruning_months or []) + return { + 'months': [ + {'letter': _LETTERS[i], 'active': (i + 1) in months_set} + for i in range(12) + ] + } diff --git a/plants/views/dashboard.py b/plants/views/dashboard.py index 8d2bce2..23019e0 100644 --- a/plants/views/dashboard.py +++ b/plants/views/dashboard.py @@ -21,5 +21,6 @@ def dashboard(request): 'total_plants': len(all_plants), 'overdue': overdue, 'due_this_month': due_this_month, + 'needs_pruning_count': len(overdue) + len(due_this_month), 'today': today, })