Skip to content

Commit 0082495

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/taxation
2 parents 6e4f24e + d943dc1 commit 0082495

188 files changed

Lines changed: 1109 additions & 625 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/linkcheck.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ jobs:
3838
--exclude "www.ter.sncf.com" \
3939
--exclude "www.fmnf.pt" \
4040
--exclude "www.linkedin.com" \
41+
--exclude "www.bdz.bg" \
42+
--exclude "www.superfast.com" \
43+
--exclude "www.bluestarferries.com" \
44+
--exclude "www.lner.co.uk" \
45+
--exclude "www.greateranglia.co.uk" \
46+
--exclude "www.crosscountrytrains.co.uk" \
4147
--exclude "www.trenitalia.fr"
4248
- uses: actions/checkout@v3
4349
if: failure()

archetypes/operator/index.de.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ operator: "{{ .File.ContentBaseName }}"
4242
-->
4343

4444
{{< fip-validity type="fip-coupon" status="valid" >}}
45-
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" subtitle="FIP 50 / FIP 75" >}}
4646
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4747

4848
<!--

archetypes/operator/index.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ operator: "{{ .File.ContentBaseName }}"
4242
-->
4343

4444
{{< fip-validity type="fip-coupon" status="valid" >}}
45-
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" subtitle="FIP 50 / FIP 75" >}}
4646
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4747

4848
<!--

archetypes/operator/index.fr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ operator: "{{ .File.ContentBaseName }}"
4242
-->
4343

4444
{{< fip-validity type="fip-coupon" status="valid" >}}
45-
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" subtitle="FIP 50 / FIP 75" >}}
4646
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4747

4848
<!--

assets/images/logos/kml.svg

Lines changed: 3 additions & 0 deletions
Loading

assets/js/highlightHeadline.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
function initHighlightHeadline() {
22
const headings = Array.from(
33
document.querySelectorAll(".o-single__highlight :is(h1, h2, h3)"),
4-
);
4+
).filter((heading) => !heading.closest("dialog"));
55
const windowPath = window.location.pathname;
66
if (headings.length === 0) {
77
return;

assets/js/taxationCalculator.js

Lines changed: 95 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,22 @@ function init() {
2323
const resetBtns = container.querySelectorAll("[data-taxation-reset]");
2424

2525
const ctx = { container, config, i18n, state };
26+
const mobileMq = window.matchMedia("(max-width: 992px)");
27+
28+
function scrollCalculatorToTopOnMobile() {
29+
if (!mobileMq.matches) return;
30+
const MOBILE_HEADER_OFFSET = 88;
31+
const targetTop = window.scrollY + container.getBoundingClientRect().top;
32+
window.scrollTo({
33+
top: Math.max(0, targetTop - MOBILE_HEADER_OFFSET),
34+
behavior: "smooth",
35+
});
36+
}
37+
38+
ctx.scrollCalculatorToTopOnMobile = scrollCalculatorToTopOnMobile;
2639

2740
function rerenderAll() {
41+
renderPersonLimitControlInput(ctx, saveState);
2842
operatorsWrapper.innerHTML = "";
2943
nationalWrapper.innerHTML = "";
3044
const otherWrapper = container.querySelector("[data-taxation-other]");
@@ -94,17 +108,72 @@ function init() {
94108
updateSummary(container, config, i18n, state);
95109
}
96110

111+
function onPersonLimitChange() {
112+
for (const op of config.operators) {
113+
const opState = state.operators[op.slug];
114+
if (!hasActiveState(opState)) continue;
115+
const row = operatorsWrapper.querySelector(
116+
'[data-taxation-row="' + op.slug + '"]',
117+
);
118+
if (!row) continue;
119+
updateRowState(
120+
row,
121+
opState,
122+
op.firstClass || 0,
123+
op.secondClass,
124+
state.personLimit,
125+
true,
126+
op.singlePersonOnly || false,
127+
);
128+
updateRowMultipliers(
129+
row,
130+
op.singlePersonOnly ? 1 : state.personLimit,
131+
i18n,
132+
);
133+
updateRowWarning(
134+
row,
135+
op.singleClassOnly || false,
136+
op.singlePersonOnly || false,
137+
state.personLimit,
138+
i18n,
139+
);
140+
}
141+
142+
for (const nat of config.national) {
143+
const natState = state.national[nat.key];
144+
if (!hasActiveState(natState)) continue;
145+
const row = nationalWrapper.querySelector(
146+
'[data-taxation-row="' + nat.key + '"]',
147+
);
148+
if (!row) continue;
149+
updateRowState(
150+
row,
151+
natState,
152+
nat.firstClass,
153+
nat.secondClass,
154+
state.personLimit,
155+
false,
156+
false,
157+
);
158+
}
159+
160+
runPlanning(ctx);
161+
updateSummary(container, config, i18n, state);
162+
}
163+
164+
ctx.onPersonLimitChange = onPersonLimitChange;
165+
97166
ctx.rerenderAll = rerenderAll;
98167
ctx.runOptimization = runOptimization;
99168

100-
renderPersonLimitControlInput(ctx, saveState);
101169
rerenderAll();
102170

103171
if (resetBtns.length > 0 && operatorsWrapper && nationalWrapper) {
104172
const resetCalculator = function () {
105173
state.operators = {};
106174
state.national = {};
107175
state.other = 0;
176+
state.personLimit = 1;
108177
state.planningAssignments = {};
109178
state.planningManualAssignments = {};
110179
state.planningMonthCount = 0;
@@ -130,35 +199,17 @@ function getI18n(container) {
130199
addOperator: container.dataset.i18nAddOperator,
131200
addNational: container.dataset.i18nAddNational,
132201
remove: container.dataset.i18nRemove,
133-
perField: container.dataset.i18nPerField,
134-
field: container.dataset.i18nField,
135-
fields: container.dataset.i18nFields,
136202
increase: container.dataset.i18nIncrease,
137203
decrease: container.dataset.i18nDecrease,
138-
sum: container.dataset.i18nSum,
139-
categoryInternational: container.dataset.i18nCategoryInternational,
140-
categoryNational: container.dataset.i18nCategoryNational,
141204
categoryOther: container.dataset.i18nCategoryOther,
142205
otherPlaceholder: container.dataset.i18nOtherPlaceholder,
143-
classMixedWarning: container.dataset.i18nClassMixedWarning,
144-
secondPersonHint: container.dataset.i18nSecondPersonHint,
145206
highlightImportant: container.dataset.i18nHighlightImportant,
146-
highlightTip: container.dataset.i18nHighlightTip,
147-
thresholdAbove: container.dataset.i18nThresholdAbove,
148-
thresholdBelow: container.dataset.i18nThresholdBelow,
149-
thresholdExcess: container.dataset.i18nThresholdExcess,
150-
disclaimer: container.dataset.i18nDisclaimer,
151-
personsRequired: container.dataset.i18nPersonsRequired,
152-
personLimit: container.dataset.i18nPersonLimit,
153207
noRelativesWarning: container.dataset.i18nNoRelativesWarning,
154-
reset: container.dataset.i18nReset,
155208
planning: container.dataset.i18nPlanning,
156209
optimize: container.dataset.i18nOptimize,
157-
manualMode: container.dataset.i18nManualMode,
158-
optimizationTitle: container.dataset.i18nOptimizationTitle,
210+
addMonth: container.dataset.i18nAddMonth,
159211
optimizationMonth: container.dataset.i18nOptimizationMonth,
160-
optimizationItems: container.dataset.i18nOptimizationItems,
161-
optimizationImpossible: container.dataset.i18nOptimizationImpossible,
212+
personLimit: container.dataset.i18nPersonLimit,
162213
unassigned: container.dataset.i18nUnassigned,
163214
person: container.dataset.i18nPerson,
164215
persons: container.dataset.i18nPersons,
@@ -736,6 +787,7 @@ function createSearchSelect(options) {
736787
list.className = "o-taxation-calculator__search-list";
737788
list.setAttribute("role", "listbox");
738789
list.setAttribute("aria-hidden", "true");
790+
list.inert = true;
739791

740792
const activeKeys = new Set();
741793

@@ -755,6 +807,7 @@ function createSearchSelect(options) {
755807
const btn = document.createElement("button");
756808
btn.type = "button";
757809
btn.className = "o-taxation-calculator__search-item-btn";
810+
btn.setAttribute("aria-label", item.label);
758811

759812
const addIcon = createIcon("add_circle");
760813
addIcon.classList.add("o-taxation-calculator__search-add-icon");
@@ -813,6 +866,7 @@ function createSearchSelect(options) {
813866
function openList() {
814867
const count = buildItems();
815868
if (count > 0) {
869+
list.inert = false;
816870
list.setAttribute("aria-hidden", "false");
817871
input.setAttribute("aria-expanded", "true");
818872
wrapper.classList.add("o-taxation-calculator__search-select--open");
@@ -821,6 +875,10 @@ function createSearchSelect(options) {
821875
}
822876

823877
function closeList() {
878+
if (list.contains(document.activeElement)) {
879+
input.focus({ preventScroll: true });
880+
}
881+
list.inert = true;
824882
list.setAttribute("aria-hidden", "true");
825883
input.setAttribute("aria-expanded", "false");
826884
wrapper.classList.remove("o-taxation-calculator__search-select--open");
@@ -998,6 +1056,7 @@ function renderOperators(ctx, wrapper) {
9981056
items: selectItems,
9991057
onSelect(item) {
10001058
addOperatorCard(ctx, wrapper, searchSelect, item.data);
1059+
ctx.scrollCalculatorToTopOnMobile();
10011060
},
10021061
});
10031062

@@ -1030,6 +1089,7 @@ function renderNational(ctx, wrapper) {
10301089
items: selectItems,
10311090
onSelect(item) {
10321091
addNationalCard(ctx, wrapper, searchSelect, item.data);
1092+
ctx.scrollCalculatorToTopOnMobile();
10331093
},
10341094
});
10351095

@@ -1138,18 +1198,6 @@ function updateSummary(container, config, i18n, state) {
11381198
summaryHint,
11391199
);
11401200

1141-
updateSummaryBlock(
1142-
container,
1143-
{
1144-
totalEl: container.querySelector("[data-taxation-bottom-total]"),
1145-
personsEl: container.querySelector("[data-taxation-bottom-persons]"),
1146-
thresholdEl: container.querySelector("[data-taxation-bottom-threshold]"),
1147-
},
1148-
total,
1149-
totalPersons,
1150-
summaryHint,
1151-
);
1152-
11531201
updateThresholdBlock(
11541202
container.querySelector("[data-taxation-mobile-threshold-detail]"),
11551203
summaryHint,
@@ -1185,6 +1233,20 @@ function runPlanning(ctx) {
11851233
}
11861234
}
11871235

1236+
function updateRowMultipliers(row, effectivePersonLimit, i18n) {
1237+
var multiplierEls = row.querySelectorAll(
1238+
".o-taxation-calculator__multiplier",
1239+
);
1240+
for (const multiplierEl of multiplierEls) {
1241+
if (effectivePersonLimit === 1) {
1242+
multiplierEl.textContent = "x 1 " + i18n.person;
1243+
} else {
1244+
multiplierEl.textContent =
1245+
"x " + effectivePersonLimit + " " + i18n.persons;
1246+
}
1247+
}
1248+
}
1249+
11881250
function updateSummaryBlock(container, els, total, totalPersons, summaryHint) {
11891251
if (!els.totalEl) return;
11901252

assets/js/taxationInputs.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export function renderPersonLimitControl(ctx, saveState) {
3333
decreaseBtn.type = "button";
3434
decreaseBtn.className = "o-taxation-calculator__btn";
3535
decreaseBtn.appendChild(createIcon("remove"));
36+
decreaseBtn.title = i18n.decrease;
37+
decreaseBtn.setAttribute("aria-label", i18n.decrease);
3638

3739
const value = document.createElement("span");
3840
value.className = "o-taxation-calculator__person-limit-value";
@@ -42,6 +44,8 @@ export function renderPersonLimitControl(ctx, saveState) {
4244
increaseBtn.type = "button";
4345
increaseBtn.className = "o-taxation-calculator__btn";
4446
increaseBtn.appendChild(createIcon("add"));
47+
increaseBtn.title = i18n.increase;
48+
increaseBtn.setAttribute("aria-label", i18n.increase);
4549

4650
function updateButtons() {
4751
decreaseBtn.disabled = state.personLimit <= 1;
@@ -58,15 +62,19 @@ export function renderPersonLimitControl(ctx, saveState) {
5862
decreaseBtn.addEventListener("click", function () {
5963
if (state.personLimit <= 1) return;
6064
state.personLimit -= 1;
61-
ctx.rerenderAll();
65+
if (typeof ctx.onPersonLimitChange === "function") {
66+
ctx.onPersonLimitChange();
67+
}
6268
saveState(state);
6369
updateButtons();
6470
});
6571

6672
increaseBtn.addEventListener("click", function () {
6773
if (state.personLimit >= MAX_PERSONS) return;
6874
state.personLimit += 1;
69-
ctx.rerenderAll();
75+
if (typeof ctx.onPersonLimitChange === "function") {
76+
ctx.onPersonLimitChange();
77+
}
7078
saveState(state);
7179
updateButtons();
7280
});

0 commit comments

Comments
 (0)