paddington-eurostar/templates/index.html
Edward Betts 4194e8fa64 Improve return date UX on search form
Disable the return date input until Return journey type is selected.
Clicking anywhere in the return date group auto-selects Return and
enables the field. The return date min is kept in sync with the
outbound date, bumping the value forward if it would otherwise fall
before the outbound date.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:42:39 +01:00

160 lines
5.6 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div class="card">
<h2>Plan your journey</h2>
<form method="get" action="{{ url_for('search') }}" id="search-form">
<div class="form-group-lg">
<label for="station_crs" class="field-label">Departure point</label>
<select id="station_crs" name="station_crs" class="form-control">
{% for name, crs in stations %}
<option value="{{ crs }}" {% if crs == 'BRI' %}selected{% endif %}>{{ name }} ({{ crs }})</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<span class="field-label">Journey type</span>
<div class="destination-grid" role="radiogroup" aria-label="Journey type">
<div class="destination-option">
<input type='radio' id="journey-outbound" name="journey_type" value="outbound" checked>
<label for="journey-outbound">
<strong>Out</strong>
<span>UK to Europe</span>
</label>
</div>
<div class="destination-option">
<input type='radio' id="journey-inbound" name="journey_type" value="inbound">
<label for="journey-inbound">
<strong>Back</strong>
<span>Europe to UK</span>
</label>
</div>
<div class="destination-option">
<input type='radio' id="journey-return" name="journey_type" value="return">
<label for="journey-return">
<strong>Return</strong>
<span>Out and back</span>
</label>
</div>
</div>
</div>
<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-option">
<input
type="radio"
id="destination-{{ slug }}"
name="destination"
value="{{ slug }}"
{% if loop.first %}checked{% endif %}
required>
<label for="destination-{{ slug }}">
<strong>{{ city }}</strong>
<span>{{ name }}</span>
</label>
</div>
{% endfor %}
</div>
</div>
<div class="form-group-lg">
<label for="travel_date" class="field-label">
Outbound / single date
</label>
<input type="date" id="travel_date" name="travel_date" required
min="{{ today }}" value="{{ today }}"
class="form-control">
</div>
<div class="form-group-lg" id="return-date-group">
<label for="return_date" class="field-label">
Return date
</label>
<input type="date" id="return_date" name="return_date"
min="{{ today }}" value="{{ default_return_date }}"
class="form-control" disabled>
</div>
<div class="form-group">
<label for="min_connection" class="field-label">
Minimum connection time (Paddington &rarr; St&nbsp;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 &rarr; St&nbsp;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>
<button type="submit" class="btn-primary">
Search journeys
</button>
</form>
<script>
(function() {
var form = document.getElementById('search-form');
var travelDate = document.getElementById('travel_date');
var returnDate = document.getElementById('return_date');
var returnRadio = document.getElementById('journey-return');
var journeyRadios = document.querySelectorAll('input[name="journey_type"]');
var returnDateName = returnDate.name;
function currentJourneyType() {
var checked = document.querySelector('input[name="journey_type"]:checked');
return checked ? checked.value : 'outbound';
}
function syncReturnDate() {
var isReturn = currentJourneyType() === 'return';
returnDate.name = isReturn ? returnDateName : '';
returnDate.disabled = !isReturn;
}
function updateReturnMin() {
if (travelDate.value) {
returnDate.min = travelDate.value;
if (returnDate.value < travelDate.value) {
returnDate.value = travelDate.value;
}
}
}
// Clicking anywhere in the return date group (including label/disabled input)
// activates return journey type and enables the field
document.getElementById('return-date-group').addEventListener('click', function() {
if (returnDate.disabled) {
returnRadio.checked = true;
syncReturnDate();
returnDate.focus();
}
});
travelDate.addEventListener('change', updateReturnMin);
journeyRadios.forEach(function(radio) {
radio.addEventListener('change', syncReturnDate);
});
form.addEventListener('submit', syncReturnDate);
updateReturnMin();
syncReturnDate();
})();
</script>
</div>
{% endblock %}