commit 15b29dd0653d4220058bbd40ac74588bbe13fecc
parent e28aec85191253aabf183b739794b0aee9491bec
Author: Katja (ctucx) <git@ctu.cx>
Date: Sun, 26 Jan 2025 20:26:27 +0100
parent e28aec85191253aabf183b739794b0aee9491bec
Author: Katja (ctucx) <git@ctu.cx>
Date: Sun, 26 Jan 2025 20:26:27 +0100
settingsView: add loyalty/discount card option
7 files changed, 80 insertions(+), 19 deletions(-)
diff --git a/src/app_functions.js b/src/app_functions.js @@ -4,7 +4,7 @@ import { go } from './router.js'; import { settings, subscribeSettings } from './settings.js'; import { showLoader, hideOverlay, showModal, showAlertModal } from './overlays.js'; import { languages } from './languages.js'; -import { getFrom, getTo } from './helpers.js'; +import { getFrom, getTo, loyaltyCardToString, loyaltyCardFromString } from './helpers.js'; import { formatDateTime } from './formatters.js'; import { getHafasClient, client } from './hafas_client'; import { trainsearchToHafas, hafasToTrainsearch } from './refresh_token'; @@ -41,6 +41,10 @@ const addJourneys = async data => { slug: data.slug, }; }); + + + if (typeof data.params.loyaltyCard === 'object') data.params.loyaltyCard = loyaltyCardToString(data.params.loyaltyCard); + const journeysOverviewEntry = { ...data, journeys: data.journeys.map(j => j.refreshToken), @@ -100,6 +104,9 @@ export const getJourney = async (refreshToken, profile) => { export const getMoreJourneys = async (slug, mode) => { const saved = await db.getJourneysOverview(slug); const params = { ...saved.params, ...journeySettings() }; + + if (typeof params.loyaltyCard === 'string') params.loyaltyCard = loyaltyCardFromString(params.loyaltyCard); + params[mode+'Than'] = saved[mode+'Ref']; let { departure, arrival, from, to, ...moreOpt } = params; const [newData, ...existingJourneys] = await Promise.all( @@ -111,9 +118,11 @@ export const getMoreJourneys = async (slug, mode) => { ...saved, ...newData, }; + for (const journey of newData.journeys) { journey.refreshToken = hafasToTrainsearch(journey.refreshToken); } + if (mode === 'earlier') { res.journeys = newData.journeys.concat(existingJourneys); res.indexOffset += newData.journeys.length;
diff --git a/src/dataStorage.js b/src/dataStorage.js @@ -57,6 +57,14 @@ class IDBStorage { } await transaction.objectStore('settings').put(settings, 'settings'); + case 4: + settings = await transaction.objectStore('settings').get('settings'); + + if (settings !== undefined && settings.loyaltyCard === undefined) { + settings.loyaltyCard = 'NONE'; + } + + await transaction.objectStore('settings').put(settings, 'settings'); } }, blocking: async () => {
diff --git a/src/helpers.js b/src/helpers.js @@ -1,18 +1,38 @@ -export const ElementById = (id) => document.getElementById(id); +const loyaltyCards = { + NONE: Symbol('no loyalty card'), + BAHNCARD: Symbol('Bahncard'), + VORTEILSCARD: Symbol('VorteilsCard'), + HALBTAXABO: Symbol('HalbtaxAbo'), + VOORDEELURENABO: Symbol('Voordeelurenabo'), + SHCARD: Symbol('SH-Card'), + GENERALABONNEMENT: Symbol('General-Abonnement'), +}; + +const loyaltyCardsReverse = { + 'Symbol(no loyalty card)': 'NONE', + 'Symbol(Bahncard)': 'BAHNCARD', + 'Symbol(VorteilsCard)': 'VORTEILSCARD', + 'Symbol(HalbtaxAbo)': 'HALBTAXABO', + 'Symbol(Voordeelurenabo)': 'VOORDEELURENABO', + 'Symbol(SH-Card)': 'SHCARD', + 'Symbol(General-Abonnement)': 'GENERALABONNEMENT', +}; -export const showElement = (element) => element.classList.remove('hidden'); -export const hideElement = (element) => element.classList.add('hidden'); -export const elementHidden = (element) => element.classList.contains('hidden'); +export const ElementById = id => document.getElementById(id); -export const unflipElement = (element) => element.classList.remove('flipped'); -export const flipElement = (element) => element.classList.add('flipped'); +export const showElement = element => element.classList.remove('hidden'); +export const hideElement = element => element.classList.add('hidden'); +export const elementHidden = element => element.classList.contains('hidden'); +export const unflipElement = element => element.classList.remove('flipped'); +export const flipElement = element => element.classList.add('flipped'); -export const padZeros = (str) => { + +export const padZeros = str => { return ('00' + str).slice(-2); }; -export const isValidDate = (date) => { +export const isValidDate = date => { const matches = /^(\d{4})[-\/](\d{2})[-\/](\d{2})$/.exec(date); if (matches == null) { return false; @@ -27,14 +47,14 @@ export const isValidDate = (date) => { composedDate.getFullYear() == y; }; -export const isEmptyObject = (obj) => { - for (const prop in obj) { - if (Object.hasOwn(obj, prop)) { - return false; - } - } +export const loyaltyCardFromString = string => { + const splitedString = string.split('-'); + if (splitedString[0] === 'NONE') return { type: loyaltyCards[splitedString[0]] }; + return { type: loyaltyCards[splitedString[0]], discount: splitedString[1], class: splitedString[2] }; +}; - return true; +export const loyaltyCardToString = loyaltyCard => { + return `${loyaltyCardsReverse[loyaltyCard.type.toString()]}-${loyaltyCard.discount}-${loyaltyCard.class}`; } export const getFrom = journeys => {
diff --git a/src/languages.js b/src/languages.js @@ -65,6 +65,9 @@ export const languages = { 'show-prices': 'Preise anzeigen', 'titleSetDateTimeNow': 'Setze Uhrzeit & Datum auf jetzt', 'titleBikeFriendly': 'Fahrradmitnahme möglich', + 'loyaltyCard': 'Ermäßigungskarte', + 'loyaltyCardNone': 'keine Ermäßigungskarte', + 'class': 'Klasse', }, 'nl': { @@ -204,5 +207,8 @@ export const languages = { 'combineDateTime': 'Use combined DateTime-input', 'titleSetDateTimeNow': 'Set Date & Time to now', 'titleBikeFriendly': 'Bicycle transport possible', + 'loyaltyCard': 'Discount Card', + 'loyaltyCardNone': 'No discount card', + 'class': 'Class', } };
diff --git a/src/searchView.js b/src/searchView.js @@ -1,5 +1,5 @@ import { html, nothing, render } from 'lit-html'; -import { ElementById, hideElement, showElement, elementHidden, flipElement, unflipElement, padZeros, isValidDate, isEmptyObject } from './helpers.js'; +import { ElementById, hideElement, showElement, elementHidden, flipElement, unflipElement, padZeros, isValidDate, loyaltyCardFromString } from './helpers.js'; import { db } from './dataStorage.js'; import { t, getJourneys, newJourneys, ds100Reverse } from './app_functions.js'; import { formatName, formatFromTo } from './formatters.js'; @@ -104,7 +104,7 @@ const searchTemplate = (journeysHistory) => html` <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 class="button icon-clock" title="${t('titleSetDateTimeNow')}" @click=${setDateTimeNow}></div> </div> <div class="row"> @@ -326,6 +326,7 @@ const submitForm = async (event) => { accessibility: settings.accessibility, bike: settings.bikeFriendly, products: settings.products, + loyaltyCard: loyaltyCardFromString(settings.loyaltyCard), }; if (via) params.via = via; @@ -476,7 +477,7 @@ const focusNextElement = (currentElementId) => { case 'to': hideSuggestions(currentElementId); - ElementById('go').click(); + ElementById('go').focus(); break; } };
diff --git a/src/settings.js b/src/settings.js @@ -23,6 +23,7 @@ const defaultSettings = { }, accessibility: 'none', bikeFriendly: false, + loyaltyCard: 'NONE', journeysViewMode: 'canvas', combineDateTime: false, showPrices: true,
diff --git a/src/settingsView.js b/src/settingsView.js @@ -35,6 +35,19 @@ const settingsTemplate = () => html` </select> </div> + <div class="row" id="loyaltyCardElement"> + <label for="loyaltyCard">${t('loyaltyCard')}:</label> + <select id="loyaltyCard"> + <option value="NONE" ?selected=${settings.loyaltyCard === 'NONE'}>${t('loyaltyCardNone')}</option> + <option value="BAHNCARD-25-2" ?selected=${settings.loyaltyCard === 'BAHNCARD-25-2'}>BahnCard 25, 2. ${t("class")}</option> + <option value="BAHNCARD-25-1" ?selected=${settings.loyaltyCard === 'BAHNCARD-25-1'}>BahnCard 25, 1. ${t("class")}</option> + <option value="BAHNCARD-50-2" ?selected=${settings.loyaltyCard === 'BAHNCARD-50-2'}>BahnCard 50, 2. ${t("class")}</option> + <option value="BAHNCARD-50-1" ?selected=${settings.loyaltyCard === 'BAHNCARD-50-1'}>BahnCard 50, 1. ${t("class")}</option> + <option value="BAHNCARD-100-2" ?selected=${settings.loyaltyCard === 'BAHNCARD-100-2'}>BahnCard 100, 2. ${t("class")}</option> + <option value="BAHNCARD-100-1" ?selected=${settings.loyaltyCard === 'BAHNCARD-100-1'}>BahnCard 100, 1. ${t("class")}</option> + </select> + </div> + <div class="column"> <span>${t('options')}:</span> <label id="showPricesElement"><input type="checkbox" id="showPrices" ?checked=${settings.showPrices}> ${t('show-prices')} (${t("experimental")})<br></label> @@ -53,10 +66,12 @@ const profileChangeHandler = (profile) => { switch (profile) { case 'db': showElement(ElementById('showPricesElement')) + showElement(ElementById('loyaltyCardElement')) break; default: hideElement(ElementById('showPricesElement')) + hideElement(ElementById('loyaltyCardElement')) break; }; }; @@ -75,6 +90,7 @@ const saveSettings = async () => { settings.showPrices = ElementById('showPrices').checked; settings.language = ElementById('language').value; settings.profile = ElementById('profile').value; + settings.loyaltyCard = ElementById('loyaltyCard').value; return settings; });