ctucx.git: trainsearch

web based trip-planner, fork of https://cyberchaos.dev/yuka/trainsearch

commit 0821372dd5452bdb458ffa0398c210f6fa9075e3
parent 09c294302b87b1e0bade0f49dab8f51b9e033a31
Author: Katja (ctucx) <git@ctu.cx>
Date: Sat, 25 Jan 2025 11:31:59 +0100

searchView.js: add option for combied DateTime-input
5 files changed, 56 insertions(+), 43 deletions(-)
M
src/languages.js
|
3
++-
M
src/searchView.js
|
80
+++++++++++++++++++++++++++++++++++++++++++------------------------------------
M
src/settings.js
|
1
+
M
src/settingsView.js
|
12
+++++++-----
M
static/style.css
|
3
++-
diff --git a/src/languages.js b/src/languages.js
@@ -198,6 +198,7 @@ export const languages = {
 		'show-prices':       'Show prices',
 		'price':             'Price',
 		'back':              'Back',
-		'reload':           'Refresh data',
+		'reload':            'Refresh data',
+		'combineDateTime':   'Use combined DateTime-input',
 	}
 };
diff --git a/src/searchView.js b/src/searchView.js
@@ -16,13 +16,14 @@ const suggestions = {
 	to: {},
 };
 
-let currDate   = new Date();
-let fromValue  = '';
-let viaValue   = '';
-let toValue    = '';
-let isArrival  = false;
-let dateValue  = currDate.getFullYear() + '-' + padZeros(currDate.getMonth()+1) + '-' + padZeros(currDate.getDate());;
-let timeValue  = padZeros(currDate.getHours()) + ':' + padZeros(currDate.getMinutes());
+let currDate      = new Date();
+let dateValue     = `${currDate.getFullYear()}-${padZeros(currDate.getMonth()+1)}-${padZeros(currDate.getDate())}`;
+let timeValue     = `${padZeros(currDate.getHours())}:${padZeros(currDate.getMinutes())}`;
+let dateTimeValue = `${dateValue}T${timeValue}`;
+let isArrival     = false;
+let fromValue     = '';
+let viaValue      = '';
+let toValue       = '';
 
 const productIcons = {
 	// DB

@@ -95,8 +96,9 @@ const searchTemplate = (journeysHistory) => html`
 					<label for="arrival">${t('arrival')}</label>
 				</div>
 
-				<input type="date" name="date" id="date" title="${t('date')}" value="${dateValue}" placeholder="${t('date')}" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" required>
-				<input type="time" name="time" id="time" title="${t('time')}" value="${timeValue}" placeholder="${t('time')}" pattern="[0-9]{2}:[0-9]{2}" required>
+				<input type="datetime-local" name="datetime" id="datetime" title="${t('date')} & ${t('time')}" value="${dateTimeValue}" class="${!settings.combineDateTime ? 'hidden' : ''}" required>
+				<input type="time"           name="time"     id="time"     title="${t('time')}"                value="${timeValue}"     class="${!settings.combineDateTime ? '' : 'hidden'}" required>
+				<input type="date"           name="date"     id="date"     title="${t('date')}"                value="${dateValue}"     class="${!settings.combineDateTime ? '' : 'hidden'}" required>
 			</div>
 
 			<div class="row">

@@ -173,7 +175,6 @@ export const searchView = async () => {
 	if (viaValue !== '') toggleVia('show');
 
 	ElementById('form').addEventListener("submit", search);
-
 	ElementById('from').focus();
 
 	for (const [product, enabled] of Object.entries(settings.products)) {

@@ -193,27 +194,32 @@ export const search = async (event) => {
 		return settings;
 	});
 
-	let responseData;
-	let timestamp = '';
-	let from = '';
-	let via  = '';
-	let to   = '';
 
-	currDate  = new Date();
-	fromValue = ElementById('from').value.trim();
-	viaValue  = ElementById('via').value.trim();
-	toValue   = ElementById('to').value.trim();
-	dateValue = ElementById('date').value.trim();
-	timeValue = ElementById('time').value.trim();
-	isArrival = ElementById('arrival').checked;
+	fromValue     = ElementById('from').value.trim();
+	viaValue      = ElementById('via').value.trim();
+	toValue       = ElementById('to').value.trim();
+	dateValue     = ElementById('date').value.trim();
+	timeValue     = ElementById('time').value.trim();
+	dateTimeValue = ElementById('datetime').value.trim();
+	isArrival     = ElementById('arrival').checked;
 
 
+	// check if From or To empty
 	if (fromValue === '' || toValue   === '') {
 		showAlertModal('At least From and To need to be filled!');
 		return false;
 	}
 
-	// date
+
+	// date and time
+	if (!settings.combineDateTime) {
+		dateTimeValue = `${dateValue}T${timeValue}`;
+	} else {
+		const splitedDateTimeValue = dateTimeValue.split('T');
+		dateValue = splitedDateTimeValue[0];
+		timeValue = splitedDateTimeValue[1];
+	};
+
 	if (dateValue !== '') {
 		if (!isValidDate(dateValue)) {
 			showAlertModal('Invalid date');

@@ -223,8 +229,6 @@ export const search = async (event) => {
 		dateValue = `${currDate.getFullYear()}-${padZeros(currDate.getMonth()+1)}-${padZeros(currDate.getDate())}`;
 	}
 
-
-	// time
 	if (timeValue !== '') {
 		if (!new RegExp('([0-1][0-9]|2[0-3]):([0-5][0-9])').test(timeValue)) {
 			showAlertModal('Invalid time');

@@ -234,12 +238,14 @@ export const search = async (event) => {
 		timeValue = `${padZeros(currDate.getHours())}:${padZeros(currDate.getMinutes())}`;
 	}
 
-	const split_date = dateValue.split('-');
-	const split_time = timeValue.split(':');
+	const splitedDate = dateValue.split('-');
+	const splitedTime = timeValue.split(':');
+	const timestamp   = Math.round(new Date(splitedDate[0], splitedDate[1]-1, splitedDate[2], splitedTime[0], splitedTime[1]).getTime()/1000);
 
-	timestamp = Math.round(new Date(split_date[0], split_date[1]-1, split_date[2], split_time[0], split_time[1]).getTime()/1000);
 
 	// from
+	let from = '';
+
 	if (Object.entries(suggestions.from).length !== 0) {
 		from = suggestions.from;
 	} else {

@@ -253,7 +259,10 @@ export const search = async (event) => {
 		from = data[0];
 	}
 
+
 	// via
+	let via  = '';
+
 	if (viaValue == '') {
 		via = null;
 	} else if (Object.entries(suggestions.via).length !== 0) {

@@ -269,7 +278,10 @@ export const search = async (event) => {
 		via = data[0];
 	}
 
+
 	// to
+	let to   = '';
+
 	if (Object.entries(suggestions.to).length !== 0) {
 		to = suggestions.to;
 	} else {

@@ -292,16 +304,13 @@ export const search = async (event) => {
 		products: settings.products,
 	};
 
-	if (via) params.via = via;
-
-	if (!isArrival) {
-		params.departure = timestamp * 1000;
-	} else {
-		params.arrival = timestamp * 1000;
-	}
+	if (via)        params.via       = via;
+	if (!isArrival) params.departure = timestamp * 1000;
+	else            params.arrival   = timestamp * 1000;
 
 	showLoader();
 
+	let responseData;
 	try {
 		responseData = await newJourneys(params);
 	} catch(e) {

@@ -312,7 +321,6 @@ export const search = async (event) => {
 	hideOverlay();
 
 	go(`/${responseData.slug}/${settings.journeysViewMode}`);
-	return false;
 };
 
 export const toggleHistory = () => {
diff --git a/src/settings.js b/src/settings.js
@@ -23,6 +23,7 @@ const defaultSettings = {
 	},
 	accessibility: 'none',
 	journeysViewMode: 'canvas',
+	combineDateTime: false,
 	showPrices: true,
 	showDS100: true,
 };
diff --git a/src/settingsView.js b/src/settingsView.js
@@ -38,7 +38,8 @@ const settingsTemplate = () => html`
 			<label>${t('options')}:</label>
 			<div>
 				<label><input type="checkbox" ?checked=${settings.showDS100} id="showDS100"> ${t('showds100')}</label><br>
-				<label><input type="checkbox" ?checked=${settings.showPrices} id="showPrices"> ${t('show-prices')} (${t("experimental")})</label>
+				<label><input type="checkbox" ?checked=${settings.showPrices} id="showPrices"> ${t('show-prices')} (${t("experimental")})</label><br>
+				<label><input type="checkbox" ?checked=${settings.combineDateTime} id="combineDateTime"> ${t('combineDateTime')}</label>
 			</div>
 		</div>
 

@@ -61,10 +62,11 @@ const rebuildCach = () => {
 
 const saveSettings = async () => {
 	await modifySettings(settings => {
-		settings.showDS100  = ElementById('showDS100').checked;
-		settings.showPrices = ElementById('showPrices').checked;
-		settings.language   = ElementById('language').value;
-		settings.profile    = ElementById('profile').value;
+		settings.combineDateTime = ElementById('combineDateTime').checked;
+		settings.showDS100       = ElementById('showDS100').checked;
+		settings.showPrices      = ElementById('showPrices').checked;
+		settings.language        = ElementById('language').value;
+		settings.profile         = ElementById('profile').value;
 
 		return settings;
 	});
diff --git a/static/style.css b/static/style.css
@@ -254,7 +254,7 @@ header {
 	form {
 		color: white;
 
-		#time, #date {
+		#time, #date, #datetime {
 			flex-grow: 1;
 		}
 

@@ -540,6 +540,7 @@ button,
 	margin: 4px;
 }
 
+input[type="datetime-local"],
 input[type="date"],
 input[type="time"],
 input[type="text"] {