Skip to content

Commit e67bafd

Browse files
feat: add issuer specific fip validity to operator pages (#684)
For each FIP issues a file called `validity.yaml` can be added to the corresponding operator directory, including information which how many coupons for which operator are issued. For example, let's have a look the at `validity.yaml` for FIP issuer DB: ```yml _anchors: coupon-4fields: &coupon-4fields status: valid text: de: "1 Freifahrtschein mit jeweils 4 Feldern pro Jahr. Jedes Feld ist zwei Tage gültig." en: "1 coupon with 4 fields each per year. Each field is valid for two days." fr: "1 coupon avec 4 champs chacun par an. Chaque champ est valable deux jours." coupon-not-available: &coupon-not-available status: invalid text: de: "Nicht verfügbar" en: "Not available" fr: "Non disponible" reduced-50: &reduced-50 status: valid text: de: "50 % Rabatt" en: "50 % discount" fr: "50 % de réduction" pkp: fip-coupon: *coupon-4fields fip-coupon-relatives: *coupon-4fields fip-reduced-ticket: *reduced-50 zssk: fip-coupon: *coupon-4fields fip-coupon-relatives: *coupon-not-available fip-reduced-ticket: *reduced-50 ``` Resolves #446 TODO: - [x] Add to archetype - [x] Transform all shortcodes - [x] Add Params from RDG - [x] Add Params from Discord (https://discord.com/channels/1250522473188032512/1451295200743002163/1451295200743002163) - [x] Obtain information from: https://discord.com/channels/1250522473188032512/1433782574806728804/1470447474345775198 - [x] Replace `__info-button` with internal button - [x] Handle Euskotren FIP Ticket - [x] Stena line two fields - [x] Remove own operator from table - [x] Unify DB text - [x] Merge relatives and active employee coupon section in one table and separate retirees --------- Co-authored-by: Robert Schuster <77234379+therobrob@users.noreply.github.com> Co-authored-by: Robert Schuster <robert.r.schuster@deutschebahn.com>
1 parent 947ae1a commit e67bafd

115 files changed

Lines changed: 2912 additions & 283 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.

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ repos:
2323
- id: check-xml
2424
exclude: "^layouts/_default/rss.xml$"
2525
- id: check-yaml
26+
exclude: "validity.yaml$"
2627
- id: debug-statements
2728
- id: destroyed-symlinks
2829
- id: end-of-file-fixer

AGENTS.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818

1919
### Translations
2020

21-
| Deutsch | Englisch | Französisch |
22-
| ---------------------------- | ------------------------- | ----------------------------------- |
23-
| FIP Freifahrtschein | FIP Coupon | Coupon FIP |
24-
| FIP Globalpreis | FIP Global Fare | Tarif Global FIP |
25-
| FIP 50 Ticket | FIP 50 Ticket | Billet FIP 50 |
26-
| FIP Ausweis | FIP Card | Carte FIP |
27-
| <operator> Ticketschalter | <operator> Ticket Office | Guichet <operator> |
28-
| <operator> Website | <operator> Website | Site Web <operator> |
29-
| <operator> Telefon | <operator> Telephone | Téléphone <operator> |
30-
| <operator> Fahrkartenautomat | <operator> Ticket Machine | Distributeurs de billets <operator> |
31-
| Grenzpunkt | Border Point | Point frontière |
32-
| FIP Rabatt / FIP Ermäßigung | FIP Discount | Remise FIP / Réduction FIP |
33-
| FIP Freifahrt Angehörige | FIP Coupon for relatives | Coupon FIP pour les ayants droit |
34-
| SBB | SBB | CFF |
21+
| Deutsch | Englisch | Französisch |
22+
| ---------------------------------- | ------------------------- | ----------------------------------- |
23+
| FIP Freifahrtschein | FIP Coupon | Coupon FIP |
24+
| FIP Globalpreis | FIP Global Fare | Tarif Global FIP |
25+
| FIP 50 Ticket | FIP 50 Ticket | Billet FIP 50 |
26+
| FIP Ausweis | FIP Card | Carte FIP |
27+
| <operator> Ticketschalter | <operator> Ticket Office | Guichet <operator> |
28+
| <operator> Website | <operator> Website | Site Web <operator> |
29+
| <operator> Telefon | <operator> Telephone | Téléphone <operator> |
30+
| <operator> Fahrkartenautomat | <operator> Ticket Machine | Distributeurs de billets <operator> |
31+
| Grenzpunkt | Border Point | Point frontière |
32+
| FIP Rabatt / FIP Ermäßigung | FIP Discount | Remise FIP / Réduction FIP |
33+
| FIP Freifahrtschein für Angehörige | FIP Coupon for relatives | Coupon FIP pour les ayants droit |
34+
| SBB | SBB | CFF |
3535

3636
#### Headlines
3737

archetypes/operator/index.de.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ operator: "{{ .File.ContentBaseName }}"
3333
Die Ticketkategorien können je nach Betreiber abweichen.
3434
-->
3535

36-
FIP Freifahrtschein: <✅/⛔> \
37-
FIP Freifahrt Angehörige: <✅/⛔> \
38-
FIP 50 Tickets: <✅/⛔> \
39-
FIP Globalpreis: <✅/⛔>
36+
<!--
37+
Verwende die folgenden Shortcodes, um die FIP-Gültigkeit anzuzeigen. Die folgenden Parameter können übergeben werden:
38+
- `type`: fip-coupon, fip-reduced-ticket, fip-global-fare, additional
39+
- `status`: valid, invalid, unknown
40+
- `text`: Optionaler benutzerdefinierter Text zur Anzeige
41+
- `disable_dialog`: true/false (Standard: false) - Auf true setzen, um den Dialog zu deaktivieren
42+
-->
43+
44+
{{< fip-validity type="fip-coupon" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
46+
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4047

4148
<!--
4249
Wo gelten FIP 50 Tickets/FIP Freifahrtscheine und gibt es Einschränkungen? Welches Ticket wird bei Einreise benötigt (z. B. durchgehendes FIP 50 Ticket oder FIP Freifahrtscheine beider Länder)

archetypes/operator/index.en.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ operator: "{{ .File.ContentBaseName }}"
3333
The ticket categories may vary depending on the operator.
3434
-->
3535

36-
FIP Coupon: <✅/⛔> \
37-
FIP Coupon for relatives: <✅/⛔> \
38-
FIP 50 Tickets: <✅/⛔> \
39-
FIP Global Fare: <✅/⛔>
36+
<!--
37+
Use the following shortcodes to display FIP validity. The following parameters can be passed:
38+
- `type`: fip-coupon, fip-reduced-ticket, fip-global-fare, additional
39+
- `status`: valid, invalid, unknown
40+
- `text`: Optional custom text to display
41+
- `disable_dialog`: true/false (default: false) - Set to true to disable the dialog
42+
-->
43+
44+
{{< fip-validity type="fip-coupon" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
46+
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4047

4148
<!--
4249
Where are FIP 50 Tickets/FIP Coupons valid and are there any restrictions? Which ticket is required for entry (e.g., continuous FIP 50 ticket or FIP Coupons of both countries)?

archetypes/operator/index.fr.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ operator: "{{ .File.ContentBaseName }}"
3333
Les catégories de billets peuvent varier selon l’opérateur.
3434
-->
3535

36-
Coupon FIP : <✅/⛔> \
37-
Coupon FIP pour les ayants droit : <✅/⛔> \
38-
Billets FIP 50 : <✅/⛔> \
39-
Tarif Global FIP : <✅/⛔>
36+
<!--
37+
Utilisez les shortcodes suivants pour afficher la validité FIP. Les paramètres suivants peuvent être transmis :
38+
- `type` : fip-coupon, fip-reduced-ticket, fip-global-fare, additional
39+
- `status` : valid, invalid, unknown
40+
- `text` : Texte personnalisé optionnel à afficher
41+
- `disable_dialog` : true/false (par défaut : false) - Définir sur true pour désactiver la boîte de dialogue
42+
-->
43+
44+
{{< fip-validity type="fip-coupon" status="valid" >}}
45+
{{< fip-validity type="fip-reduced-ticket" status="valid" >}}
46+
{{< fip-validity type="fip-global-fare" status="valid" disable_dialog="true" >}}
4047

4148
<!--
4249
Où les Billets FIP 50 / Coupons FIP sont-ils valables et quelles sont les restrictions ? Quel billet est nécessaire pour le voyage (par ex. Billet FIP 50 continu ou Coupons FIP des deux pays) ?

assets/js/dropdown.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,20 @@ document.addEventListener("DOMContentLoaded", function () {
3030
registerEventListeners("language-switcher");
3131
registerEventListeners("navbar-country-selection");
3232
registerEventListeners("navbar-operator-selection");
33+
[
34+
"fip-validity-issuer",
35+
"fip-validity-dialog-fip-coupon",
36+
"fip-validity-dialog-fip-reduced-ticket",
37+
].forEach((id) => {
38+
if (document.querySelector(`#${id}-button`)) {
39+
registerEventListeners(id);
40+
}
41+
});
3342
});
43+
44+
export const closeDropdown = (id) => {
45+
const button = document.querySelector(`#${id}-button`);
46+
const dropdown = document.querySelector(`#${id}-dropdown`);
47+
button.setAttribute("aria-expanded", "false");
48+
dropdown.setAttribute("aria-hidden", "true");
49+
};

assets/js/fipValidityComparison.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { closeDropdown } from "./dropdown.js";
2+
3+
const ISSUER_KEY = "fipguide-issuer";
4+
5+
document.addEventListener("DOMContentLoaded", function () {
6+
const restoreFns = [];
7+
8+
document
9+
.querySelectorAll("[data-fip-validity-button]")
10+
.forEach(function (button) {
11+
const dropdownId = button.id.replace(/-button$/, "");
12+
const scope = button.closest("dialog") || document;
13+
const label = button.querySelector("[data-fip-validity-label]");
14+
const logoSlot = button.querySelector("[data-fip-validity-logo]");
15+
const options = scope.querySelectorAll("[data-fip-option]");
16+
const wrappers = scope.querySelectorAll("[data-fip-issuer]");
17+
const selectFirstMessages = scope.querySelectorAll(
18+
"[data-fip-select-first]",
19+
);
20+
21+
function showIssuer(slug) {
22+
wrappers.forEach(function (wrapper) {
23+
if (wrapper.dataset.fipIssuer === slug) {
24+
wrapper.removeAttribute("hidden");
25+
} else {
26+
wrapper.setAttribute("hidden", "");
27+
}
28+
});
29+
selectFirstMessages.forEach(function (msg) {
30+
msg.setAttribute("hidden", "");
31+
});
32+
}
33+
34+
function selectOption(slug, text, { sync = true } = {}) {
35+
options.forEach(function (option) {
36+
option.setAttribute(
37+
"aria-selected",
38+
option.dataset.fipOption === slug ? "true" : "false",
39+
);
40+
});
41+
label.textContent = text;
42+
const operatorLogo = scope
43+
.querySelector(`[data-fip-option="${slug}"]`)
44+
?.querySelector("img");
45+
logoSlot.innerHTML = "";
46+
if (operatorLogo) {
47+
logoSlot.appendChild(operatorLogo.cloneNode());
48+
}
49+
showIssuer(slug);
50+
closeDropdown(dropdownId);
51+
localStorage.setItem(ISSUER_KEY, slug);
52+
if (sync) {
53+
restoreFns.forEach(function (fn) {
54+
if (fn !== restore) fn();
55+
});
56+
}
57+
}
58+
59+
options.forEach(function (option) {
60+
option.addEventListener("click", function () {
61+
selectOption(option.dataset.fipOption, option.textContent.trim());
62+
});
63+
});
64+
65+
function restore() {
66+
const savedSlug = localStorage.getItem(ISSUER_KEY);
67+
if (savedSlug) {
68+
const savedOption = scope.querySelector(
69+
`[data-fip-option="${savedSlug}"]`,
70+
);
71+
if (savedOption) {
72+
selectOption(savedSlug, savedOption.textContent.trim(), {
73+
sync: false,
74+
});
75+
return;
76+
}
77+
}
78+
}
79+
80+
restoreFns.push(restore);
81+
});
82+
83+
restoreFns.forEach((fn) => {
84+
fn();
85+
});
86+
});

assets/js/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ import "./search.js";
1010
import "./interactiveMap.js";
1111
import "./expander.js";
1212
import "./dialog.js";
13+
import "./fipValidityComparison.js";

assets/sass/_variables.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ $tag-colors-dark: (
2828
info: #d1d1d1,
2929
);
3030

31+
$fip-validity-colors: (
32+
valid: map-get($tag-colors, success),
33+
invalid: map-get($tag-colors, error),
34+
unknown: map-get($tag-colors, info),
35+
);
36+
37+
$fip-validity-colors-dark: (
38+
valid: map-get($tag-colors-dark, success),
39+
invalid: map-get($tag-colors-dark, error),
40+
unknown: map-get($tag-colors-dark, info),
41+
);
42+
3143
$highlight-colors: (
3244
tip: #116278,
3345
inofficial: #42454a,
@@ -60,6 +72,10 @@ html {
6072
--color-success: #096640;
6173
--color-error: #ad1731;
6274

75+
@each $name, $color in $fip-validity-colors {
76+
--fip-validity-#{$name}: #{$color};
77+
}
78+
6379
@each $name, $color in $tag-colors {
6480
--tag-#{$name}-bg: #{mix(white, $color, 90%)};
6581
--tag-#{$name}-color: #{$color};
@@ -78,6 +94,7 @@ html {
7894
--box-shadow: 0 0.4rem 1rem rgba(0, 0, 0, 0.25);
7995
--box-shadow-light: 0.4rem 0.4rem 0.4rem rgba(0, 0, 0, 0.1);
8096
--border: 0.1rem solid transparent;
97+
--border-visible: 0.1rem solid #d0d0d0;
8198
--pagefind-ui-font: roboto, Arial, Helvetica, sans-serif;
8299
--outline-focus-indicator: #257fa8;
83100

@@ -101,6 +118,10 @@ html[data-theme="dark"] {
101118
--color-success: #2ea44f;
102119
--color-error: #f85149;
103120

121+
@each $name, $color in $fip-validity-colors-dark {
122+
--fip-validity-#{$name}: #{$color};
123+
}
124+
104125
@each $name, $color in $tag-colors-dark {
105126
--tag-#{$name}-bg: #{mix(black, $color, 65%)};
106127
--tag-#{$name}-color: #{$color};
@@ -116,6 +137,7 @@ html[data-theme="dark"] {
116137
--box-shadow-light: 0.4rem 0.4rem 0.4rem rgba(0, 0, 0, 0.3);
117138
--pagefind-ui-background: var(--bg-default);
118139
--border: 0.1rem solid #3d444d;
140+
--border-visible: 0.1rem solid #3d444d;
119141
--outline-focus-indicator: #2e9acb;
120142
}
121143
}

assets/sass/button.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,9 @@
3232
&__internal {
3333
border: none;
3434
}
35+
36+
&:disabled {
37+
cursor: not-allowed;
38+
pointer-events: none;
39+
}
3540
}

0 commit comments

Comments
 (0)