ctucx.git: trainsearch

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

commit ca78a5d834f337208aaafa0f8b2bc476d45b3f27
parent ec1a5644cf2095b2ac02022ee74245364a946f6b
Author: Katja (ctucx) <git@ctu.cx>
Date: Sun, 26 Jan 2025 13:46:54 +0100

searchView.js: move viewState to object
1 file changed, 76 insertions(+), 72 deletions(-)
M
src/searchView.js
|
148
+++++++++++++++++++++++++++++++++++++++++--------------------------------------
diff --git a/src/searchView.js b/src/searchView.js
@@ -1,29 +1,34 @@
+import { html, nothing, render } from 'lit-html';
 import { ElementById, hideElement, showElement, elementHidden, flipElement, unflipElement, padZeros, isValidDate } from './helpers.js';
 import { db } from './dataStorage.js';
 import { t, getJourneys, newJourneys, ds100Reverse } from './app_functions.js';
 import { formatName, formatFromTo } from './formatters.js';
 import { modifySettings, settings } from './settings.js';
 import { go } from './router.js';
-import { html, nothing, render } from 'lit-html';
 import { showAlertModal, showSelectModal, showLoader, hideOverlay} from './overlays.js';
 import { showSettings } from './settingsView.js';
 import { client } from './hafas_client';
 
-let   numEnter    = 0;
-const suggestions = {
-	from: {},
-	via: {},
-	to: {},
+const viewState = {
+	currDate:      new Date(),
+	numEnter:      0,
+	isArrival:     false,
+	dateValue:     '',
+	timeValue:     '',
+	dateTimeValue: '',
+	fromValue:     '',
+	viaValue:      '',
+	toValue:       '',
+	suggestions:   {
+		from: {},
+		via: {},
+		to: {},
+	},
 };
 
-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       = '';
+viewState.dateValue     = `${viewState.currDate.getFullYear()}-${padZeros(viewState.currDate.getMonth()+1)}-${padZeros(viewState.currDate.getDate())}`;
+viewState.timeValue     = `${padZeros(viewState.currDate.getHours())}:${padZeros(viewState.currDate.getMinutes())}`;
+viewState.dateTimeValue = `${viewState.dateValue}T${viewState.timeValue}`;
 
 const productIcons = {
 	// DB

@@ -65,16 +70,16 @@ const iconFor = id => {
 const searchTemplate = (journeysHistory) => html`
 	<div class="searchView">
 		<h1 class="title center">TrainSearch</h1>
-		<form class="column" id="form">
+		<form class="column" id="form" @submit=${submitForm}>
 			<div class="row nowrap">
-				<input type="text" name="from" id="from" title="${t('from')}" placeholder="${t('from')}" value="${fromValue}" autocomplete="off"
+				<input type="text" name="from" id="from" title="${t('from')}" placeholder="${t('from')}" value="${viewState.fromValue}" autocomplete="off"
 					@focus=${focusHandler} @blur=${blurHandler} @keydown=${keydownHandler} @keyup=${keyupHandler} @input=${loadSuggestions} required>
 				<div class="button icon-arrow2" id="viaButton" title="${t('via')}" @click=${toggleVia}></div>
 			</div>
 			<div class="suggestions" id="fromSuggestions" @mouseover=${mouseOverHandler} @mouseout=${mouseOutHandler}></div>
 
 			<div class="row nowrap hidden" id="viaRow">
-				<input type="text" name="via" id="via" title="${t('via')}" placeholder="${t('via')}" value="${viaValue}" autocomplete="off"
+				<input type="text" name="via" id="via" title="${t('via')}" placeholder="${t('via')}" value="${viewState.viaValue}" autocomplete="off"
 					@focus=${focusHandler} @blur=${blurHandler} @keydown=${keydownHandler} @keyup=${keyupHandler} @input=${loadSuggestions}>
 				<div class="button icon-arrow2 invisible"></div>
 			</div>

@@ -82,7 +87,7 @@ const searchTemplate = (journeysHistory) => html`
 
 
 			<div class="row nowrap">
-				<input type="text" name="to" id="to" title="${t('to')}" placeholder="${t('to')}" value="${toValue}" autocomplete="off"
+				<input type="text" name="to" id="to" title="${t('to')}" placeholder="${t('to')}" value="${viewState.toValue}" autocomplete="off"
 					@focus=${focusHandler} @blur=${blurHandler} @keydown=${keydownHandler} @keyup=${keyupHandler} @input=${loadSuggestions} required>
 				<div class="button icon-swap" title="${t('swap')}" @click=${swapFromTo}></div>
 			</div>

@@ -90,15 +95,15 @@ const searchTemplate = (journeysHistory) => html`
 
 			<div class="row">
 				<div class="selector">
-					<input type="radio" id="departure" name="deparr" ?checked=${!isArrival}>
+					<input type="radio" id="departure" name="deparr" ?checked=${!viewState.isArrival}>
 					<label for="departure">${t('departure')}</label>
-					<input type="radio" id="arrival" name="deparr" ?checked=${isArrival}>
+					<input type="radio" id="arrival" name="deparr" ?checked=${viewState.isArrival}>
 					<label for="arrival">${t('arrival')}</label>
 				</div>
 
-				<input type="datetime-local" name="datetime" id="datetime" title="${t('date')} & ${t('time')}" value="${dateTimeValue}" class="${!settings.combineDateTime ? 'hidden' : nothing}" required>
-				<input type="time"           name="time"     id="time"     title="${t('time')}"                value="${timeValue}"     class="${!settings.combineDateTime ? nothing : 'hidden'}" required>
-				<input type="date"           name="date"     id="date"     title="${t('date')}"                value="${dateValue}"     class="${!settings.combineDateTime ? nothing : 'hidden'}" required>
+				<input type="datetime-local" name="datetime" id="datetime" title="${t('date')} & ${t('time')}" value="${viewState.dateTimeValue}" class="${!settings.combineDateTime ? 'hidden' : nothing}" required>
+				<input type="time"           name="time"     id="time"     title="${t('time')}"                value="${viewState.timeValue}"     class="${!settings.combineDateTime ? nothing : 'hidden'}" required>
+				<input type="date"           name="date"     id="date"     title="${t('date')}"                value="${viewState.dateValue}"     class="${!settings.combineDateTime ? nothing : 'hidden'}" required>
 				<div class="button icon-clock" title="${t('now')}" @click=${setDateTimeNow}></div>
 			</div>
 

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

@@ -196,17 +200,17 @@ const submitForm = async (event) => {
 	});
 
 
-	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;
+	viewState.fromValue     = ElementById('from').value.trim();
+	viewState.viaValue      = ElementById('via').value.trim();
+	viewState.toValue       = ElementById('to').value.trim();
+	viewState.dateValue     = ElementById('date').value.trim();
+	viewState.timeValue     = ElementById('time').value.trim();
+	viewState.dateTimeValue = ElementById('datetime').value.trim();
+	viewState.isArrival     = ElementById('arrival').checked;
 
 
 	// check if From or To empty
-	if (fromValue === '' || toValue   === '') {
+	if (viewState.fromValue === '' || viewState.toValue   === '') {
 		showAlertModal('At least From and To need to be filled!');
 		return false;
 	}

@@ -214,43 +218,43 @@ const submitForm = async (event) => {
 
 	// date and time
 	if (!settings.combineDateTime) {
-		dateTimeValue = `${dateValue}T${timeValue}`;
+		viewState.dateTimeValue = `${viewState.dateValue}T${viewState.timeValue}`;
 	} else {
-		const splitedDateTimeValue = dateTimeValue.split('T');
-		dateValue = splitedDateTimeValue[0];
-		timeValue = splitedDateTimeValue[1];
+		const splitedDateTimeValue = viewState.dateTimeValue.split('T');
+		viewState.dateValue = splitedDateTimeValue[0];
+		viewState.timeValue = splitedDateTimeValue[1];
 	};
 
-	if (dateValue !== '') {
-		if (!isValidDate(dateValue)) {
+	if (viewState.dateValue !== '') {
+		if (!isValidDate(viewState.dateValue)) {
 			showAlertModal('Invalid date');
 			return false;
 		}
 	} else {
-		dateValue = `${currDate.getFullYear()}-${padZeros(currDate.getMonth()+1)}-${padZeros(currDate.getDate())}`;
+		viewState.dateValue = `${viewState.currDate.getFullYear()}-${padZeros(viewState.currDate.getMonth()+1)}-${padZeros(viewState.currDate.getDate())}`;
 	}
 
-	if (timeValue !== '') {
-		if (!new RegExp('([0-1][0-9]|2[0-3]):([0-5][0-9])').test(timeValue)) {
+	if (viewState['timeValue'] !== '') {
+		if (!new RegExp('([0-1][0-9]|2[0-3]):([0-5][0-9])').test(viewState.timeValue)) {
 			showAlertModal('Invalid time');
 			return false;
 		}
 	} else {
-		timeValue = `${padZeros(currDate.getHours())}:${padZeros(currDate.getMinutes())}`;
+		viewState['timeValue'] = `${padZeros(viewState.currDate.getHours())}:${padZeros(viewState.currDate.getMinutes())}`;
 	}
 
-	const splitedDate = dateValue.split('-');
-	const splitedTime = timeValue.split(':');
+	const splitedDate = viewState.dateValue.split('-');
+	const splitedTime = viewState.timeValue.split(':');
 	const timestamp   = Math.round(new Date(splitedDate[0], splitedDate[1]-1, splitedDate[2], splitedTime[0], splitedTime[1]).getTime()/1000);
 
 
 	// from
 	let from = '';
 
-	if (Object.entries(suggestions.from).length !== 0) {
-		from = suggestions.from;
+	if (Object.entries(viewState.suggestions.from).length !== 0) {
+		from = viewState.suggestions.from;
 	} else {
-		const data = await client.locations(fromValue, {'results': 1});
+		const data = await client.locations(viewState.fromValue, {'results': 1});
 
 		if (!data[0]) {
 			showAlertModal('Invalid From');

@@ -264,12 +268,12 @@ const submitForm = async (event) => {
 	// via
 	let via  = '';
 
-	if (viaValue == '') {
+	if (viewState.viaValue == '') {
 		via = null;
-	} else if (Object.entries(suggestions.via).length !== 0) {
-		via = suggestions.via;
+	} else if (Object.entries(viewState.suggestions.via).length !== 0) {
+		via = viewState.suggestions.via;
 	} else {
-		const data = await client.locations(viaValue, {'results': 1});
+		const data = await client.locations(viewState.viaValue, {'results': 1});
 
 		if (!data[0]) {
 			showAlertModal('Invalid Via');

@@ -283,10 +287,10 @@ const submitForm = async (event) => {
 	// to
 	let to   = '';
 
-	if (Object.entries(suggestions.to).length !== 0) {
-		to = suggestions.to;
+	if (Object.entries(viewState.suggestions.to).length !== 0) {
+		to = viewState.suggestions.to;
 	} else {
-		const data = await client.locations(toValue, {'results': 1});
+		const data = await client.locations(viewState.toValue, {'results': 1});
 
 		if (!data[0]) {
 			showAlertModal('Invalid To');

@@ -305,9 +309,9 @@ const submitForm = 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 (!viewState.isArrival) params.departure = timestamp * 1000;
+	else                      params.arrival   = timestamp * 1000;
 
 	showLoader();
 

@@ -352,7 +356,7 @@ const toggleVia = ( mode ) => {
 }
 
 const swapFromTo = () => {
-	suggestions.from = [suggestions.to, suggestions.to = suggestions.from][0];
+	viewState.suggestions.from = [viewState.suggestions.to, viewState.suggestions.to = viewState.suggestions.from][0];
 
 	const from = ElementById('from');
 	const to   = ElementById('to');

@@ -375,13 +379,13 @@ const setFromHistory = async id => {
 };
 
 const setDateTimeNow = () => {
-	currDate                      = new Date();
-	dateValue                     = `${currDate.getFullYear()}-${padZeros(currDate.getMonth()+1)}-${padZeros(currDate.getDate())}`;
-	timeValue                     = `${padZeros(currDate.getHours())}:${padZeros(currDate.getMinutes())}`;
-	dateTimeValue                 = `${dateValue}T${timeValue}`;
-	ElementById('date').value     = dateValue;
-	ElementById('time').value     = timeValue;
-	ElementById('datetime').value = dateTimeValue;
+	viewState.currDate            = new Date();
+	viewState.dateValue           = `${viewState.currDate.getFullYear()}-${padZeros(viewState.currDate.getMonth()+1)}-${padZeros(viewState.currDate.getDate())}`;
+	viewState.timeValue           = `${padZeros(viewState.currDate.getHours())}:${padZeros(viewState.currDate.getMinutes())}`;
+	viewState.dateTimeValue       = `${viewState.dateValue}T${viewState.timeValue}`;
+	ElementById('date').value     = viewState.dateValue;
+	ElementById('time').value     = viewState.timeValue;
+	ElementById('datetime').value = viewState.dateTimeValue;
 };
 
 const readProductSelection = settings => {

@@ -395,7 +399,7 @@ const readProductSelection = settings => {
 };
 
 const showSuggestions = (id) => {
-	numEnter = 0;
+	viewState.numEnter = 0;
 	showElement(ElementById(`${id}Suggestions`));
 };
 

@@ -414,7 +418,7 @@ const loadSuggestions = async (event) => {
 	const elementId    = event.target.id;
 	const elementValue = event.target.value.trim();
 
-	suggestions[elementId] = {};
+	viewState.suggestions[elementId] = {};
 
 	if (elementValue === '') return;
 

@@ -458,8 +462,8 @@ const setSuggestion = (data, inputId, pointerType) => {
 		data = JSON.parse(decodeURI(data));
 	}
 
-	ElementById(inputId).value = formatName(data);
-	suggestions[inputId]       = data;
+	ElementById(inputId).value     = formatName(data);
+	viewState.suggestions[inputId] = data;
 
 	hideSuggestions(inputId);
 	if (pointerType !== '') focusNextElement(inputId);

@@ -478,8 +482,8 @@ const keyupHandler = (event) => {
 
 	if (event.key !== 'Enter') return true;
 
-	if (numEnter === 2 && eventElement.value === formatName(suggestions[eventElement.id])) {
-		numEnter = 0;
+	if (viewState.numEnter === 2 && eventElement.value === formatName(viewState.suggestions[eventElement.id])) {
+		viewState.numEnter = 0;
 		focusNextElement(eventElement.id);
 	}
 };

@@ -495,7 +499,7 @@ const keydownHandler = (event) => {
 	if (event.key === 'Enter') {
 		event.preventDefault();
 		selectedElement.click();
-		numEnter++;
+		viewState.numEnter++;
 		return true;
 	};