125 lines
5.8 KiB
HTML
125 lines
5.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Flight {{ flight.id }} — Boarding Pass{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
{% if flight.track_coordinates %}
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
{% endif %}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<a href="{{ url_for('review.list_flights') }}" class="back-link">← All flights</a>
|
|
|
|
<div class="detail-header">
|
|
<h1>{{ flight.from_iata or '?' }} → {{ flight.to_iata or '?' }}
|
|
<span class="badge badge-{{ flight.status }}">{{ flight.status.replace('_', ' ') }}</span>
|
|
</h1>
|
|
<p class="muted">Flight #{{ flight.id }} · created {{ flight.created_at }}</p>
|
|
</div>
|
|
|
|
{% if flight.error_message %}
|
|
<div class="alert alert-danger">{{ flight.error_message }}</div>
|
|
{% endif %}
|
|
{% if flight.parse_warnings %}
|
|
<div class="alert alert-warning">
|
|
<strong>Parse warnings:</strong>
|
|
<ul>{% for w in flight.parse_warnings %}<li>{{ w }}</li>{% endfor %}</ul>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="detail-grid">
|
|
<div class="card">
|
|
<h2>Details</h2>
|
|
<form method="post" action="{{ url_for('review.edit', flight_id=flight.id) }}" class="edit-form">
|
|
<label>Passenger name <input name="passenger_name" value="{{ flight.passenger_name or '' }}"></label>
|
|
<label>PNR <input name="pnr" value="{{ flight.pnr or '' }}"></label>
|
|
<div class="field-row">
|
|
<label>From (IATA) <input name="from_iata" value="{{ flight.from_iata or '' }}" maxlength="3"></label>
|
|
<label>To (IATA) <input name="to_iata" value="{{ flight.to_iata or '' }}" maxlength="3"></label>
|
|
</div>
|
|
<div class="field-row">
|
|
<label>Carrier (IATA) <input name="operating_carrier_iata" value="{{ flight.operating_carrier_iata or '' }}" maxlength="3"></label>
|
|
<label>Flight number <input name="flight_number" value="{{ flight.flight_number or '' }}"></label>
|
|
</div>
|
|
<div class="field-row">
|
|
<label>Flight date <input type="date" name="flight_date" value="{{ flight.flight_date or '' }}"></label>
|
|
<label>Seat <input name="seat" value="{{ flight.seat or '' }}"></label>
|
|
</div>
|
|
<label>Compartment <input name="compartment" value="{{ flight.compartment or '' }}" maxlength="1"></label>
|
|
<button type="submit" class="btn btn-secondary">Save changes</button>
|
|
</form>
|
|
|
|
<dl class="meta-list">
|
|
<dt>ICAO route</dt><dd>{{ flight.from_icao or '—' }} → {{ flight.to_icao or '—' }}</dd>
|
|
<dt>Carrier ICAO</dt><dd>{{ flight.operating_carrier_icao or '—' }}</dd>
|
|
<dt>Process after</dt><dd>{{ flight.process_after or '—' }}</dd>
|
|
<dt>Fetch attempts</dt><dd>{{ flight.fetch_attempts }}</dd>
|
|
{% if flight.flightaware_url %}
|
|
<dt>FlightAware</dt><dd><a href="{{ flight.flightaware_url }}" target="_blank" rel="noopener">{{ flight.flightaware_url }}</a></dd>
|
|
{% endif %}
|
|
{% if flight.track_point_count %}
|
|
<dt>Track points</dt><dd>{{ flight.track_point_count }}</dd>
|
|
{% endif %}
|
|
{% if flight.gate_departure_scheduled or flight.gate_departure_actual %}
|
|
<dt>Gate departure</dt><dd>sched {{ flight.gate_departure_scheduled or '—' }} / actual {{ flight.gate_departure_actual or '—' }}</dd>
|
|
{% endif %}
|
|
{% if flight.gate_arrival_scheduled or flight.gate_arrival_actual %}
|
|
<dt>Gate arrival</dt><dd>sched {{ flight.gate_arrival_scheduled or '—' }} / actual {{ flight.gate_arrival_actual or '—' }}</dd>
|
|
{% endif %}
|
|
{% if flight.takeoff_actual %}
|
|
<dt>Takeoff (actual)</dt><dd>{{ flight.takeoff_actual }}</dd>
|
|
{% endif %}
|
|
{% if flight.landing_actual %}
|
|
<dt>Landing (actual)</dt><dd>{{ flight.landing_actual }}</dd>
|
|
{% endif %}
|
|
{% if flight.departure_utc_offset or flight.arrival_utc_offset %}
|
|
<dt>Airport UTC offsets</dt><dd>{{ flight.departure_utc_offset or '—' }} → {{ flight.arrival_utc_offset or '—' }}</dd>
|
|
{% endif %}
|
|
{% if flight.schedule_error %}
|
|
<dt>Schedule lookup</dt><dd class="muted">{{ flight.schedule_error }}</dd>
|
|
{% endif %}
|
|
{% if flight.airtrail_flight_id %}
|
|
<dt>AirTrail flight</dt><dd>{{ flight.airtrail_flight_id }}</dd>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Photo</h2>
|
|
<a href="{{ url_for('uploaded_file', name=flight.image_path) }}" target="_blank" rel="noopener">
|
|
<img src="{{ url_for('uploaded_file', name=flight.image_path) }}" alt="Boarding pass photo" class="bp-photo">
|
|
</a>
|
|
{% if flight.raw_bcbp %}
|
|
<details class="raw-bcbp">
|
|
<summary>Raw BCBP data</summary>
|
|
<pre>{{ flight.raw_bcbp }}</pre>
|
|
</details>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if flight.track_coordinates %}
|
|
<div class="card map-card">
|
|
<h2>Flight track</h2>
|
|
<div id="track-map" data-track='{{ flight.track_coordinates | tojson }}'></div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="action-bar">
|
|
<form method="post" action="{{ url_for('review.requery', flight_id=flight.id) }}">
|
|
<button type="submit" class="btn btn-secondary">Re-query FlightAware</button>
|
|
</form>
|
|
<form method="post" action="{{ url_for('review.approve', flight_id=flight.id, token=approve_token) }}">
|
|
<button type="submit" class="btn btn-success" {% if flight.status not in ('pending_review', 'track_unavailable') %}disabled{% endif %}>Approve</button>
|
|
</form>
|
|
<form method="post" action="{{ url_for('review.reject', flight_id=flight.id, token=reject_token) }}">
|
|
<button type="submit" class="btn btn-danger" {% if flight.status in ('approved', 'rejected') %}disabled{% endif %}>Reject</button>
|
|
</form>
|
|
</div>
|
|
{% if flight.status not in ('pending_review', 'track_unavailable', 'approved', 'rejected') %}
|
|
<p class="muted">Approve is unavailable until FlightAware has been checked for this flight
|
|
(happens automatically the day after the flight, or click Re-query to check now).</p>
|
|
{% endif %}
|
|
{% endblock %}
|