Refine homepage journey form layout
This commit is contained in:
parent
13c4341f3a
commit
ed8a5626a4
4 changed files with 74 additions and 38 deletions
31
app.py
31
app.py
|
|
@ -32,6 +32,8 @@ from trip_planner import (
|
||||||
find_unreachable_inbound_eurostars,
|
find_unreachable_inbound_eurostars,
|
||||||
find_unreachable_morning_eurostars,
|
find_unreachable_morning_eurostars,
|
||||||
)
|
)
|
||||||
|
import cache
|
||||||
|
import circle_line
|
||||||
|
|
||||||
RTT_PADDINGTON_URL = (
|
RTT_PADDINGTON_URL = (
|
||||||
"https://www.realtimetrains.co.uk/search/detailed/"
|
"https://www.realtimetrains.co.uk/search/detailed/"
|
||||||
|
|
@ -51,9 +53,6 @@ _local = os.path.join(os.path.dirname(__file__), "config", "local.py")
|
||||||
if os.path.exists(_local):
|
if os.path.exists(_local):
|
||||||
app.config.from_pyfile(_local)
|
app.config.from_pyfile(_local)
|
||||||
|
|
||||||
import cache
|
|
||||||
import circle_line
|
|
||||||
|
|
||||||
cache.CACHE_DIR = app.config["CACHE_DIR"] # type: ignore[attr-defined]
|
cache.CACHE_DIR = app.config["CACHE_DIR"] # type: ignore[attr-defined]
|
||||||
circle_line._TXC_XML = app.config["CIRCLE_LINE_XML"] # type: ignore[attr-defined]
|
circle_line._TXC_XML = app.config["CIRCLE_LINE_XML"] # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
|
@ -72,13 +71,25 @@ def _load_stations() -> list[tuple[str, str]]:
|
||||||
STATIONS = _load_stations()
|
STATIONS = _load_stations()
|
||||||
STATION_BY_CRS = {crs: name for name, crs in STATIONS}
|
STATION_BY_CRS = {crs: name for name, crs in STATIONS}
|
||||||
|
|
||||||
|
DESTINATION_OPTIONS = [
|
||||||
|
{"slug": "paris", "city": "Paris", "destination": "Paris Gare du Nord"},
|
||||||
|
{"slug": "brussels", "city": "Brussels", "destination": "Brussels Midi"},
|
||||||
|
{"slug": "lille", "city": "Lille", "destination": "Lille Europe"},
|
||||||
|
{
|
||||||
|
"slug": "amsterdam",
|
||||||
|
"city": "Amsterdam",
|
||||||
|
"destination": "Amsterdam Centraal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"slug": "rotterdam",
|
||||||
|
"city": "Rotterdam",
|
||||||
|
"destination": "Rotterdam Centraal",
|
||||||
|
},
|
||||||
|
{"slug": "cologne", "city": "Cologne Hbf", "destination": "Cologne Hbf"},
|
||||||
|
]
|
||||||
|
|
||||||
DESTINATIONS = {
|
DESTINATIONS = {
|
||||||
"paris": "Paris Gare du Nord",
|
option["slug"]: option["destination"] for option in DESTINATION_OPTIONS
|
||||||
"brussels": "Brussels Midi",
|
|
||||||
"lille": "Lille Europe",
|
|
||||||
"amsterdam": "Amsterdam Centraal",
|
|
||||||
"rotterdam": "Rotterdam Centraal",
|
|
||||||
"cologne": "Cologne Hbf",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -88,7 +99,7 @@ def index() -> ResponseReturnValue:
|
||||||
default_min, default_max = _get_defaults()
|
default_min, default_max = _get_defaults()
|
||||||
return render_template(
|
return render_template(
|
||||||
"index.html",
|
"index.html",
|
||||||
destinations=DESTINATIONS,
|
destination_options=DESTINATION_OPTIONS,
|
||||||
today=today,
|
today=today,
|
||||||
stations=STATIONS,
|
stations=STATIONS,
|
||||||
default_min_connection=default_min,
|
default_min_connection=default_min,
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,10 @@
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.destination-grid--eurostar {
|
||||||
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.destination-option {
|
.destination-option {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +114,7 @@
|
||||||
.destination-option label {
|
.destination-option label {
|
||||||
display: block;
|
display: block;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
padding: 0.95rem 1rem;
|
padding: 0.8rem 0.85rem;
|
||||||
border: 1px solid #cbd5e0;
|
border: 1px solid #cbd5e0;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
|
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
|
||||||
|
|
@ -121,7 +125,7 @@
|
||||||
.destination-option label strong {
|
.destination-option label strong {
|
||||||
display: block;
|
display: block;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 1rem;
|
font-size: 0.98rem;
|
||||||
margin-bottom: 0.2rem;
|
margin-bottom: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,6 +188,10 @@
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.card { padding: 1.25rem; }
|
.card { padding: 1.25rem; }
|
||||||
|
|
||||||
|
.destination-grid--eurostar {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert results table to a 2-column card layout per row */
|
/* Convert results table to a 2-column card layout per row */
|
||||||
.results-table, .results-table tbody { display: block; }
|
.results-table, .results-table tbody { display: block; }
|
||||||
.results-table thead { display: none; }
|
.results-table thead { display: none; }
|
||||||
|
|
@ -233,6 +241,21 @@
|
||||||
/* Form groups */
|
/* Form groups */
|
||||||
.form-group { margin-bottom: 1.2rem; }
|
.form-group { margin-bottom: 1.2rem; }
|
||||||
.form-group-lg { margin-bottom: 1.5rem; }
|
.form-group-lg { margin-bottom: 1.5rem; }
|
||||||
|
.form-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
.form-row .form-group,
|
||||||
|
.form-row .form-group-lg {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.form-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
#return-date-group:has(input:disabled) { cursor: pointer; }
|
#return-date-group:has(input:disabled) { cursor: pointer; }
|
||||||
|
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
|
|
|
||||||
|
|
@ -99,13 +99,12 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<span class="field-label">Eurostar destination</span>
|
<span class="field-label">Eurostar destination</span>
|
||||||
<div class="destination-grid" role="radiogroup" aria-label="Eurostar destination">
|
<div class="destination-grid destination-grid--eurostar" role="radiogroup" aria-label="Eurostar destination">
|
||||||
{% for slug, name in destinations.items() %}
|
{% for destination in destination_options %}
|
||||||
{% set city = name.replace(' Gare du Nord','').replace(' Centraal','').replace(' Midi','').replace(' Europe','') %}
|
|
||||||
<div class="destination-option">
|
<div class="destination-option">
|
||||||
<input type="radio" id="dest-{{ slug }}" name="destination" value="{{ slug }}"
|
<input type="radio" id="dest-{{ destination.slug }}" name="destination" value="{{ destination.slug }}"
|
||||||
{% if loop.first %}checked{% endif %} required>
|
{% if loop.first %}checked{% endif %} required>
|
||||||
<label for="dest-{{ slug }}"><strong>{{ city }}</strong><span>{{ name }}</span></label>
|
<label for="dest-{{ destination.slug }}"><strong>{{ destination.city }}</strong><span>{{ destination.destination }}</span></label>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -128,26 +127,28 @@
|
||||||
<input type="hidden" id="return_date" name="">
|
<input type="hidden" id="return_date" name="">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-row">
|
||||||
<label for="min_connection" class="field-label">
|
<div class="form-group">
|
||||||
Minimum connection time (Paddington → St Pancras)
|
<label for="min_connection" class="field-label">
|
||||||
</label>
|
Minimum connection time (Paddington → St Pancras)
|
||||||
<select id="min_connection" name="min_connection" class="form-control">
|
</label>
|
||||||
{% for mins in valid_min_connections %}
|
<select id="min_connection" name="min_connection" class="form-control">
|
||||||
<option value="{{ mins }}" {% if mins == default_min_connection %}selected{% endif %}>{{ mins }} min</option>
|
{% for mins in valid_min_connections %}
|
||||||
{% endfor %}
|
<option value="{{ mins }}" {% if mins == default_min_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||||
</select>
|
{% endfor %}
|
||||||
</div>
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group-lg">
|
<div class="form-group">
|
||||||
<label for="max_connection" class="field-label">
|
<label for="max_connection" class="field-label">
|
||||||
Maximum connection time (Paddington → St Pancras)
|
Maximum connection time (Paddington → St Pancras)
|
||||||
</label>
|
</label>
|
||||||
<select id="max_connection" name="max_connection" class="form-control">
|
<select id="max_connection" name="max_connection" class="form-control">
|
||||||
{% for mins in valid_max_connections %}
|
{% for mins in valid_max_connections %}
|
||||||
<option value="{{ mins }}" {% if mins == default_max_connection %}selected{% endif %}>{{ mins }} min</option>
|
<option value="{{ mins }}" {% if mins == default_max_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn-primary">Search journeys</button>
|
<button type="submit" class="btn-primary">Search journeys</button>
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,9 @@ def test_index_shows_station_dropdown_and_destination_radios() -> None:
|
||||||
assert "Departure point" in html
|
assert "Departure point" in html
|
||||||
assert "Bristol Temple Meads" in html
|
assert "Bristol Temple Meads" in html
|
||||||
assert 'name="station_crs"' in html
|
assert 'name="station_crs"' in html
|
||||||
assert html.count('type="radio"') == len(app_module.DESTINATIONS)
|
assert html.count('name="destination"') == len(app_module.DESTINATIONS)
|
||||||
assert "destination-rotterdam" in html
|
assert 'id="dest-rotterdam"' in html
|
||||||
|
assert "<strong>Cologne Hbf</strong><span>Cologne Hbf</span>" in html
|
||||||
|
|
||||||
|
|
||||||
def test_search_redirects_to_results_with_selected_params() -> None:
|
def test_search_redirects_to_results_with_selected_params() -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue