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>Trips: {{ count }}</div>
|
|
||||||
<div>Conferences: {{ conferences }}</div>
|
|
||||||
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
|
||||||
|
|
||||||
{% for transport_type, distance in distances_by_transport_type %}
|
<div class="card mb-4">
|
||||||
<div>
|
<div class="card-header"><strong>Overall Summary</strong></div>
|
||||||
{{ transport_type | title }}
|
<div class="card-body">
|
||||||
distance: {{format_distance(distance) }}
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div>Trips: {{ count }}</div>
|
||||||
|
<div>Conferences: {{ conferences }}</div>
|
||||||
|
<div>Total distance: {{ format_distance(total_distance) }}</div>
|
||||||
|
{% for transport_type, distance in distances_by_transport_type %}
|
||||||
|
<div class="ms-3">{{ transport_type | title }}: {{ format_distance(distance) }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div>Flight segments: {{ overall_stats.flight_count }}</div>
|
||||||
|
<div>Train segments: {{ overall_stats.train_count }}</div>
|
||||||
|
</div>
|
||||||
|
</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>
|
||||||
{% 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>
|
|
||||||
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>
|
|
||||||
{% 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>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% 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)
|
|
||||||
{% endif %}
|
|
||||||
{% for c in countries %}
|
|
||||||
<span class="d-inline-block border border-2 p-1 m-1">
|
|
||||||
{{ c.flag }} {{ c.name }} ({{ c.alpha_2 }})
|
|
||||||
{% if c in new_countries %}
|
|
||||||
<span class="badge text-bg-info">new</span>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="card-body">
|
||||||
Flight segments in {{ year }}: {{ year_stats.flight_count or 0 }}
|
<div class="row mb-2">
|
||||||
{% if year_stats.airlines %}
|
<div class="col-md-6">
|
||||||
({{ year_stats.airlines | count }} airlines)
|
<div>Trips: {{ year_stats.count }}</div>
|
||||||
[ by airline:
|
<div>Conferences: {{ year_stats.conferences }}</div>
|
||||||
{% for airline, count in year_stats.airlines.most_common() %}
|
<div>Distance: {{ format_distance(year_stats.total_distance or 0) }}</div>
|
||||||
{{ airline }}: {{ count }}{% if not loop.last %},{% endif %}
|
{% if year_stats.distances_by_transport_type %}
|
||||||
{% endfor %} ]
|
{% for transport_type, distance in year_stats.distances_by_transport_type.items() %}
|
||||||
{% endif %}
|
<div class="ms-3">{{ transport_type | title }}: {{ format_distance(distance) }}</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
{% if year_stats.airports %}
|
|
||||||
<div>
|
|
||||||
Airports used in {{ year }}: {{ year_stats.airports | count }}
|
|
||||||
[ 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 %}
|
|
||||||
<div>Total CO₂:
|
|
||||||
{% if year_stats.co2_kg >= 1000 %}
|
|
||||||
{{ "{:,.2f}".format(year_stats.co2_kg / 1000.0) }} tonnes
|
|
||||||
{% else %}
|
|
||||||
{{ "{:,.0f}".format(year_stats.co2_kg) }} kg
|
|
||||||
{% endif %}
|
|
||||||
</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>
|
||||||
{% endfor %}
|
<div class="col-md-6">
|
||||||
{% endif %}
|
<div>Flight segments: {{ year_stats.flight_count or 0 }}</div>
|
||||||
{% endif %}
|
<div>Train segments: {{ year_stats.train_count or 0 }}</div>
|
||||||
<div>Trains segments in {{ year }}: {{ year_stats.train_count or 0 }}</div>
|
{% if year_stats.co2_kg %}
|
||||||
{% if year_stats.stations %}
|
<div>CO₂:
|
||||||
<div>
|
{% if year_stats.co2_kg >= 1000 %}
|
||||||
Stations used in {{ year }}: {{ year_stats.stations | count }}
|
{{ "{:,.2f}".format(year_stats.co2_kg / 1000.0) }} tonnes
|
||||||
[ by station:
|
{% else %}
|
||||||
{% for station, count in year_stats.stations.most_common() %}
|
{{ "{:,.0f}".format(year_stats.co2_kg) }} kg
|
||||||
{{ station }}: {{ count }}{% if not loop.last %},{% endif %}
|
{% endif %}
|
||||||
{% endfor %} ]
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
{% endif %}
|
</div>
|
||||||
<div>Total distance in {{ year}}: {{ format_distance(year_stats.total_distance or 0) }}</div>
|
</div>
|
||||||
{% if year_stats.distances_by_transport_type %}
|
|
||||||
{% for transport_type, distance in year_stats.distances_by_transport_type.items() %}
|
<div class="mb-2">
|
||||||
<div>
|
<strong>Countries:</strong> {{ countries | count }}
|
||||||
{{ transport_type | title }}
|
{% if new_countries %}({{ new_countries | count }} new){% endif %}
|
||||||
distance: {{format_distance(distance) }}
|
<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 %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if year_stats.airlines %}
|
||||||
|
{{ stat_list("airlines-" ~ year, "Airlines", year_stats.airlines) }}
|
||||||
|
{% endif %}
|
||||||
|
{% if year_stats.airports %}
|
||||||
|
{{ stat_list("airports-" ~ year, "Airports", year_stats.airports) }}
|
||||||
|
{% endif %}
|
||||||
|
{% if year_stats.stations %}
|
||||||
|
{{ stat_list("stations-" ~ year, "Stations", year_stats.stations) }}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</div>
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue