Redesign trip stats page with collapsible sections
Use Bootstrap cards and collapsible sections to make the long lists of airlines, airports, and stations easier to read. Items are now displayed as badges and hidden by default. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
523dc78b35
commit
905c9c330d
1 changed files with 96 additions and 108 deletions
|
|
@ -6,128 +6,116 @@
|
||||||
|
|
||||||
{% block title %}{{ heading }} - Edward Betts{% endblock %}
|
{% block title %}{{ heading }} - Edward Betts{% endblock %}
|
||||||
|
|
||||||
|
{% macro stat_list(id, label, counter, show_top=5) %}
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>{{ label }}:</strong> {{ counter | count }}
|
||||||
|
{% if counter | count > 0 %}
|
||||||
|
<a class="btn btn-sm btn-outline-secondary ms-2" data-bs-toggle="collapse" href="#{{ id }}" role="button" aria-expanded="false">
|
||||||
|
show/hide
|
||||||
|
</a>
|
||||||
|
<div class="collapse mt-2" id="{{ id }}">
|
||||||
|
<div class="d-flex flex-wrap gap-1">
|
||||||
|
{% for item, count in counter.most_common() %}
|
||||||
|
<span class="badge text-bg-secondary">{{ item }} <span class="badge text-bg-light text-dark">{{ count }}</span></span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h1>Trip statistics</h1>
|
<h1>Trip statistics</h1>
|
||||||
|
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header"><strong>Overall Summary</strong></div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
<div>Trips: {{ count }}</div>
|
<div>Trips: {{ count }}</div>
|
||||||
<div>Conferences: {{ conferences }}</div>
|
<div>Conferences: {{ conferences }}</div>
|
||||||
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
||||||
|
|
||||||
{% for transport_type, distance in distances_by_transport_type %}
|
{% for transport_type, distance in distances_by_transport_type %}
|
||||||
<div>
|
<div class="ms-3">{{ transport_type | title }}: {{ format_distance(distance) }}</div>
|
||||||
{{ transport_type | title }}
|
|
||||||
distance: {{format_distance(distance) }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div>
|
|
||||||
Flight segments: {{ overall_stats.flight_count }}
|
|
||||||
{% if overall_stats.airlines %}
|
|
||||||
({{ overall_stats.airlines | count }} airlines)
|
|
||||||
[ by airline:
|
|
||||||
{% for airline, count in overall_stats.airlines.most_common() %}
|
|
||||||
{{ airline }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% if overall_stats.airports %}
|
<div class="col-md-6">
|
||||||
<div>
|
<div>Flight segments: {{ overall_stats.flight_count }}</div>
|
||||||
Airports used: {{ overall_stats.airports | count }}
|
|
||||||
[ by airport:
|
|
||||||
{% for airport, count in overall_stats.airports.most_common() %}
|
|
||||||
{{ airport }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div>Train segments: {{ overall_stats.train_count }}</div>
|
<div>Train segments: {{ overall_stats.train_count }}</div>
|
||||||
{% if overall_stats.stations %}
|
|
||||||
<div>
|
|
||||||
Stations used: {{ overall_stats.stations | count }}
|
|
||||||
[ by station:
|
|
||||||
{% for station, count in overall_stats.stations.most_common() %}
|
|
||||||
{{ station }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{{ stat_list("overall-airlines", "Airlines", overall_stats.airlines) }}
|
||||||
|
{{ stat_list("overall-airports", "Airports", overall_stats.airports) }}
|
||||||
|
{{ stat_list("overall-stations", "Stations", overall_stats.stations) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% for year, year_stats in yearly_stats | dictsort(reverse=True) %}
|
{% for year, year_stats in yearly_stats | dictsort(reverse=True) %}
|
||||||
{% set countries = year_stats.countries | default([]) | sort(attribute="name") %}
|
{% set countries = year_stats.countries | default([]) | sort(attribute="name") %}
|
||||||
{% set new_countries = year_stats.new_countries | default([]) %}
|
{% set new_countries = year_stats.new_countries | default([]) %}
|
||||||
<h4>{{ year }}</h4>
|
|
||||||
<div>Trips in {{ year }}: {{ year_stats.count }}</div>
|
<div class="card mb-3">
|
||||||
<div>Conferences in {{ year }}: {{ year_stats.conferences }}</div>
|
<div class="card-header">
|
||||||
<div>{{ countries | count }} countries visited in {{ year }}:
|
<strong>{{ year }}</strong>
|
||||||
{% if new_countries %}
|
<span class="text-muted ms-2">{{ year_stats.count }} trips</span>
|
||||||
({{ new_countries | count }} new)
|
</div>
|
||||||
{% endif %}
|
<div class="card-body">
|
||||||
{% for c in countries %}
|
<div class="row mb-2">
|
||||||
<span class="d-inline-block border border-2 p-1 m-1">
|
<div class="col-md-6">
|
||||||
{{ c.flag }} {{ c.name }} ({{ c.alpha_2 }})
|
<div>Trips: {{ year_stats.count }}</div>
|
||||||
{% if c in new_countries %}
|
<div>Conferences: {{ year_stats.conferences }}</div>
|
||||||
<span class="badge text-bg-info">new</span>
|
<div>Distance: {{ format_distance(year_stats.total_distance or 0) }}</div>
|
||||||
{% endif %}
|
{% if year_stats.distances_by_transport_type %}
|
||||||
</span>
|
{% for transport_type, distance in year_stats.distances_by_transport_type.items() %}
|
||||||
|
<div class="ms-3">{{ transport_type | title }}: {{ format_distance(distance) }}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Flight segments in {{ year }}: {{ year_stats.flight_count or 0 }}
|
|
||||||
{% if year_stats.airlines %}
|
|
||||||
({{ year_stats.airlines | count }} airlines)
|
|
||||||
[ by airline:
|
|
||||||
{% for airline, count in year_stats.airlines.most_common() %}
|
|
||||||
{{ airline }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if year_stats.airports %}
|
<div class="col-md-6">
|
||||||
<div>
|
<div>Flight segments: {{ year_stats.flight_count or 0 }}</div>
|
||||||
Airports used in {{ year }}: {{ year_stats.airports | count }}
|
<div>Train segments: {{ year_stats.train_count or 0 }}</div>
|
||||||
[ by airport:
|
|
||||||
{% for airport, count in year_stats.airports.most_common() %}
|
|
||||||
{{ airport }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if year_stats.co2_kg %}
|
{% if year_stats.co2_kg %}
|
||||||
<div>Total CO₂:
|
<div>CO₂:
|
||||||
{% if year_stats.co2_kg >= 1000 %}
|
{% if year_stats.co2_kg >= 1000 %}
|
||||||
{{ "{:,.2f}".format(year_stats.co2_kg / 1000.0) }} tonnes
|
{{ "{:,.2f}".format(year_stats.co2_kg / 1000.0) }} tonnes
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ "{:,.0f}".format(year_stats.co2_kg) }} kg
|
{{ "{:,.0f}".format(year_stats.co2_kg) }} kg
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if year_stats.co2_by_transport_type %}
|
|
||||||
{% for transport_type, co2_kg in year_stats.co2_by_transport_type.items() %}
|
|
||||||
<div style="margin-left: 20px;">
|
|
||||||
{{ transport_type | title }} CO₂:
|
|
||||||
{% if co2_kg >= 1000 %}
|
|
||||||
{{ "{:,.2f}".format(co2_kg / 1000.0) }} tonnes
|
|
||||||
{% else %}
|
|
||||||
{{ "{:,.0f}".format(co2_kg) }} kg
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>Countries:</strong> {{ countries | count }}
|
||||||
|
{% if new_countries %}({{ new_countries | count }} new){% endif %}
|
||||||
|
<div class="d-flex flex-wrap gap-1 mt-1">
|
||||||
|
{% for c in countries %}
|
||||||
|
<span class="badge text-bg-light text-dark border">
|
||||||
|
{{ c.flag }} {{ c.name }}
|
||||||
|
{% if c in new_countries %}
|
||||||
|
<span class="badge text-bg-info">new</span>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if year_stats.airlines %}
|
||||||
|
{{ stat_list("airlines-" ~ year, "Airlines", year_stats.airlines) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if year_stats.airports %}
|
||||||
|
{{ stat_list("airports-" ~ year, "Airports", year_stats.airports) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>Trains segments in {{ year }}: {{ year_stats.train_count or 0 }}</div>
|
|
||||||
{% if year_stats.stations %}
|
{% if year_stats.stations %}
|
||||||
<div>
|
{{ stat_list("stations-" ~ year, "Stations", year_stats.stations) }}
|
||||||
Stations used in {{ year }}: {{ year_stats.stations | count }}
|
|
||||||
[ by station:
|
|
||||||
{% for station, count in year_stats.stations.most_common() %}
|
|
||||||
{{ station }}: {{ count }}{% if not loop.last %},{% endif %}
|
|
||||||
{% endfor %} ]
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>Total distance in {{ year}}: {{ format_distance(year_stats.total_distance or 0) }}</div>
|
|
||||||
{% if year_stats.distances_by_transport_type %}
|
|
||||||
{% for transport_type, distance in year_stats.distances_by_transport_type.items() %}
|
|
||||||
<div>
|
|
||||||
{{ transport_type | title }}
|
|
||||||
distance: {{format_distance(distance) }}
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</div>
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue