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_morning_eurostars,
|
||||
)
|
||||
import cache
|
||||
import circle_line
|
||||
|
||||
RTT_PADDINGTON_URL = (
|
||||
"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):
|
||||
app.config.from_pyfile(_local)
|
||||
|
||||
import cache
|
||||
import circle_line
|
||||
|
||||
cache.CACHE_DIR = app.config["CACHE_DIR"] # 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()
|
||||
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 = {
|
||||
"paris": "Paris Gare du Nord",
|
||||
"brussels": "Brussels Midi",
|
||||
"lille": "Lille Europe",
|
||||
"amsterdam": "Amsterdam Centraal",
|
||||
"rotterdam": "Rotterdam Centraal",
|
||||
"cologne": "Cologne Hbf",
|
||||
option["slug"]: option["destination"] for option in DESTINATION_OPTIONS
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -88,7 +99,7 @@ def index() -> ResponseReturnValue:
|
|||
default_min, default_max = _get_defaults()
|
||||
return render_template(
|
||||
"index.html",
|
||||
destinations=DESTINATIONS,
|
||||
destination_options=DESTINATION_OPTIONS,
|
||||
today=today,
|
||||
stations=STATIONS,
|
||||
default_min_connection=default_min,
|
||||
|
|
|
|||
|
|
@ -95,6 +95,10 @@
|
|||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.destination-grid--eurostar {
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.destination-option {
|
||||
position: relative;
|
||||
}
|
||||
|
|
@ -110,7 +114,7 @@
|
|||
.destination-option label {
|
||||
display: block;
|
||||
min-height: 100%;
|
||||
padding: 0.95rem 1rem;
|
||||
padding: 0.8rem 0.85rem;
|
||||
border: 1px solid #cbd5e0;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
|
||||
|
|
@ -121,7 +125,7 @@
|
|||
.destination-option label strong {
|
||||
display: block;
|
||||
color: #0f172a;
|
||||
font-size: 1rem;
|
||||
font-size: 0.98rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
|
|
@ -184,6 +188,10 @@
|
|||
@media (max-width: 640px) {
|
||||
.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 */
|
||||
.results-table, .results-table tbody { display: block; }
|
||||
.results-table thead { display: none; }
|
||||
|
|
@ -233,6 +241,21 @@
|
|||
/* Form groups */
|
||||
.form-group { margin-bottom: 1.2rem; }
|
||||
.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; }
|
||||
|
||||
/* Buttons */
|
||||
|
|
|
|||
|
|
@ -99,13 +99,12 @@
|
|||
|
||||
<div class="form-group">
|
||||
<span class="field-label">Eurostar destination</span>
|
||||
<div class="destination-grid" role="radiogroup" aria-label="Eurostar destination">
|
||||
{% for slug, name in destinations.items() %}
|
||||
{% set city = name.replace(' Gare du Nord','').replace(' Centraal','').replace(' Midi','').replace(' Europe','') %}
|
||||
<div class="destination-grid destination-grid--eurostar" role="radiogroup" aria-label="Eurostar destination">
|
||||
{% for destination in destination_options %}
|
||||
<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>
|
||||
<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>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
@ -128,26 +127,28 @@
|
|||
<input type="hidden" id="return_date" name="">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="min_connection" class="field-label">
|
||||
Minimum connection time (Paddington → St Pancras)
|
||||
</label>
|
||||
<select id="min_connection" name="min_connection" class="form-control">
|
||||
{% for mins in valid_min_connections %}
|
||||
<option value="{{ mins }}" {% if mins == default_min_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="min_connection" class="field-label">
|
||||
Minimum connection time (Paddington → St Pancras)
|
||||
</label>
|
||||
<select id="min_connection" name="min_connection" class="form-control">
|
||||
{% for mins in valid_min_connections %}
|
||||
<option value="{{ mins }}" {% if mins == default_min_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group-lg">
|
||||
<label for="max_connection" class="field-label">
|
||||
Maximum connection time (Paddington → St Pancras)
|
||||
</label>
|
||||
<select id="max_connection" name="max_connection" class="form-control">
|
||||
{% for mins in valid_max_connections %}
|
||||
<option value="{{ mins }}" {% if mins == default_max_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-group">
|
||||
<label for="max_connection" class="field-label">
|
||||
Maximum connection time (Paddington → St Pancras)
|
||||
</label>
|
||||
<select id="max_connection" name="max_connection" class="form-control">
|
||||
{% for mins in valid_max_connections %}
|
||||
<option value="{{ mins }}" {% if mins == default_max_connection %}selected{% endif %}>{{ mins }} min</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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 "Bristol Temple Meads" in html
|
||||
assert 'name="station_crs"' in html
|
||||
assert html.count('type="radio"') == len(app_module.DESTINATIONS)
|
||||
assert "destination-rotterdam" in html
|
||||
assert html.count('name="destination"') == len(app_module.DESTINATIONS)
|
||||
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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue