refactor: extract stats and cycling panels to Twig macros
Move stats computation and both panel HTML divs out of trip.html.twig
into dedicated macros/stats.html.twig and macros/cycling.html.twig.
trip.html.twig imports both at the top of {% block content %} and
calls them via stats_m.stats_panel() and cycling_m.cycling_panel().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
{% macro cycling_panel() %}
|
||||
<div id="trip-cycling-block" class="trip-cycling-block">
|
||||
<div class="trip-panel-inner">
|
||||
<div class="trip-cycling-header">
|
||||
<span class="trip-cycling-icon">🚴</span>
|
||||
<span class="trip-cycling-title">Cycling Stats</span>
|
||||
</div>
|
||||
<div class="trip-cycling-grid">
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-distance">—</span>
|
||||
<span class="stat-label">km distance</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-ele-gain">—</span>
|
||||
<span class="stat-label">m ↑ gain</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-ele-loss">—</span>
|
||||
<span class="stat-label">m ↓ loss</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-highest">—</span>
|
||||
<span class="stat-label">m highest</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-lowest">—</span>
|
||||
<span class="stat-label">m lowest</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-moving-time">—</span>
|
||||
<span class="stat-label">moving time</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="cyc-avg-speed">—</span>
|
||||
<span class="stat-label">km/h avg speed</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="trip-panel-close" data-toggle="trip-cycling-toggle">↑ Close cycling</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,93 @@
|
||||
{% macro stats_panel(journal_entries, page, journal_count, has_gpx) %}
|
||||
{% set days_on_road = 0 %}
|
||||
{% if page.header.date_end is not empty %}
|
||||
{% set start_ts = page.header.date_start|date('U') %}
|
||||
{% set end_ts = page.header.date_end|date('U') %}
|
||||
{% set days_on_road = ((end_ts - start_ts) / 86400)|round(0, 'ceil') %}
|
||||
{% else %}
|
||||
{% set first_ts = null %}
|
||||
{% for entry in journal_entries %}
|
||||
{% set ts = entry.date|date('U') %}
|
||||
{% if first_ts is null or ts < first_ts %}{% set first_ts = ts %}{% endif %}
|
||||
{% endfor %}
|
||||
{% if first_ts is not null %}
|
||||
{% set diff_seconds = "now"|date('U') - first_ts %}
|
||||
{% set days_raw = (diff_seconds / 86400)|round(0, 'floor') %}
|
||||
{% set days_on_road = days_raw < 1 ? 1 : days_raw %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% set seen_lower = [] %}
|
||||
{% set country_display = [] %}
|
||||
{% for entry in journal_entries %}
|
||||
{% if entry.header.location_country is not empty %}
|
||||
{% set lower = entry.header.location_country|trim|lower %}
|
||||
{% if lower not in seen_lower %}
|
||||
{% set seen_lower = seen_lower|merge([lower]) %}
|
||||
{% set country_display = country_display|merge([entry.header.location_country|trim]) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% set seen_city_lower = [] %}
|
||||
{% set city_display = [] %}
|
||||
{% for entry in journal_entries %}
|
||||
{% if entry.header.location_city is not empty %}
|
||||
{% set lower = entry.header.location_city|trim|lower %}
|
||||
{% if lower not in seen_city_lower %}
|
||||
{% set seen_city_lower = seen_city_lower|merge([lower]) %}
|
||||
{% set city_display = city_display|merge([entry.header.location_city|trim]) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% set temp_min = null %}
|
||||
{% set temp_max = null %}
|
||||
{% for entry in journal_entries %}
|
||||
{% if entry.header.weather_temp_c is defined and entry.header.weather_temp_c is not empty %}
|
||||
{% set t = entry.header.weather_temp_c %}
|
||||
{% if temp_min is null or t < temp_min %}{% set temp_min = t %}{% endif %}
|
||||
{% if temp_max is null or t > temp_max %}{% set temp_max = t %}{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div id="trip-stats-block" class="trip-stats-block">
|
||||
<div class="trip-panel-inner">
|
||||
<div class="trip-stats-grid">
|
||||
<div class="stat-block">
|
||||
<span class="stat-value">{{ days_on_road }}</span>
|
||||
<span class="stat-label">{{ days_on_road == 1 ? 'day' : 'days' }} on the road</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value">{{ journal_count }}</span>
|
||||
<span class="stat-label">{{ journal_count == 1 ? 'entry' : 'entries' }} posted</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value">{{ country_display|length }}</span>
|
||||
<span class="stat-label">{{ country_display|length == 1 ? 'country' : 'countries' }} visited</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value">{{ city_display|length }}</span>
|
||||
<span class="stat-label">{{ city_display|length == 1 ? 'city' : 'cities' }} visited</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
<span class="stat-value" id="stat-distance">—</span>
|
||||
<span class="stat-label">{{ has_gpx ? '🚴 km cycled' : '🧭 km roamed' }}</span>
|
||||
</div>
|
||||
<div class="stat-block">
|
||||
{% if temp_min is not null %}
|
||||
<span class="stat-value">{{ temp_min == temp_max ? temp_min : temp_min ~ ' → ' ~ temp_max }}</span>
|
||||
{% else %}
|
||||
<span class="stat-value">—</span>
|
||||
{% endif %}
|
||||
<span class="stat-label">°C range</span>
|
||||
</div>
|
||||
</div>
|
||||
{% if country_display|length > 0 %}
|
||||
<p class="trip-stats-countries">{{ country_display|join(' · ') }}</p>
|
||||
{% endif %}
|
||||
<p class="trip-stats-note">{{ has_gpx ? 'Distance based on GPS track data.' : 'Distance is approximate — straight lines between entry locations.' }}</p>
|
||||
<button class="trip-panel-close" data-toggle="trip-stats-toggle">↑ Close stats</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
Reference in New Issue
Block a user