diff --git a/client/src/components/Settings/DisplaySettingsTab.test.tsx b/client/src/components/Settings/DisplaySettingsTab.test.tsx index 822c2261d..84621b6ec 100644 --- a/client/src/components/Settings/DisplaySettingsTab.test.tsx +++ b/client/src/components/Settings/DisplaySettingsTab.test.tsx @@ -1,5 +1,5 @@ // FE-COMP-DISPLAY-001 to FE-COMP-DISPLAY-027 -import { render, screen } from '../../../tests/helpers/render'; +import { render, screen, within } from '../../../tests/helpers/render'; import userEvent from '@testing-library/user-event'; import { http, HttpResponse } from 'msw'; import { server } from '../../../tests/helpers/msw/server'; @@ -127,11 +127,38 @@ describe('DisplaySettingsTab', () => { it('FE-COMP-DISPLAY-025: blur booking codes On button is active when blur_booking_codes is true', () => { seedStore(useSettingsStore, { settings: buildSettings({ blur_booking_codes: true }) }); render(); - const onButtons = screen.getAllByText(/^On$/i); - const blurOnBtn = onButtons[1].closest('button')!; + const block = screen.getByText(/blur booking codes/i).closest('div')!; + const blurOnBtn = within(block).getByText(/^On$/i).closest('button')!; expect(blurOnBtn.style.border).toContain('var(--text-primary)'); }); + it('FE-COMP-DISPLAY-030: shows Always show booking routes next to Booking route labels', () => { + render(); + const bookingLabels = screen.getByText(/booking route labels/i); + const alwaysShow = screen.getByText(/always show booking routes/i); + expect(alwaysShow).toBeInTheDocument(); + // Adjacent siblings within the Travel & Map section: alwaysShow's block + // immediately follows bookingLabels' block. + expect(bookingLabels.closest('div')!.nextElementSibling).toBe(alwaysShow.closest('div')); + }); + + it('FE-COMP-DISPLAY-031: always-show-routes Off button is active by default (unset)', () => { + render(); + const block = screen.getByText(/always show booking routes/i).closest('div')!; + const offBtn = within(block).getByText(/^Off$/i).closest('button')!; + expect(offBtn.style.border).toContain('var(--text-primary)'); + }); + + it('FE-COMP-DISPLAY-032: clicking On for always-show-routes calls updateSetting with map_always_show_routes true', async () => { + const user = userEvent.setup(); + const updateSetting = vi.fn().mockResolvedValue(undefined); + seedStore(useSettingsStore, { settings: buildSettings(), updateSetting }); + render(); + const block = screen.getByText(/always show booking routes/i).closest('div')!; + await user.click(within(block).getByText(/^On$/i)); + expect(updateSetting).toHaveBeenCalledWith('map_always_show_routes', true); + }); + it('FE-COMP-DISPLAY-026: updateSetting failure shows toast error', async () => { const user = userEvent.setup(); const updateSetting = vi.fn().mockRejectedValue(new Error('Server error')); diff --git a/client/src/components/Settings/DisplaySettingsTab.tsx b/client/src/components/Settings/DisplaySettingsTab.tsx index 3627beed9..5cb02a8f5 100644 --- a/client/src/components/Settings/DisplaySettingsTab.tsx +++ b/client/src/components/Settings/DisplaySettingsTab.tsx @@ -265,6 +265,37 @@ export default function DisplaySettingsTab(): React.ReactElement {

{t('settings.bookingLabelsHint')}

+ {/* Always show booking routes */} +
+ +
+ {[ + { value: true, label: t('settings.on') || 'On' }, + { value: false, label: t('settings.off') || 'Off' }, + ].map(opt => ( + + ))} +
+

{t('settings.alwaysShowRoutesHint')}

+
+ {/* Explore places on the map (POI category pill) */}
diff --git a/client/src/types.ts b/client/src/types.ts index edb95b9b6..c6eafc760 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -117,6 +117,7 @@ export interface Settings { blur_booking_codes?: boolean map_booking_labels?: boolean map_poi_pill_enabled?: boolean + map_always_show_routes?: boolean optimize_from_accommodation?: boolean map_provider?: 'leaflet' | 'mapbox-gl' | 'maplibre-gl' mapbox_access_token?: string diff --git a/shared/src/i18n/ar/settings.ts b/shared/src/i18n/ar/settings.ts index 21a90912e..abfab0f7a 100644 --- a/shared/src/i18n/ar/settings.ts +++ b/shared/src/i18n/ar/settings.ts @@ -477,6 +477,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'المورد', 'settings.pluginActivity.columns.when': 'الوقت', 'settings.pluginActivity.columns.status': 'النتيجة', + 'settings.alwaysShowRoutes': 'إظهار مسارات الحجوزات دائمًا', + 'settings.alwaysShowRoutesHint': 'يعرض تلقائيًا مسار كل رحلة طيران وقطار وحجز آخر على الخريطة، دون الحاجة إلى تفعيله لكل عنصر على حدة.', }; export default settings; diff --git a/shared/src/i18n/br/settings.ts b/shared/src/i18n/br/settings.ts index 94073e767..ad339d510 100644 --- a/shared/src/i18n/br/settings.ts +++ b/shared/src/i18n/br/settings.ts @@ -493,6 +493,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Recurso', 'settings.pluginActivity.columns.when': 'Quando', 'settings.pluginActivity.columns.status': 'Resultado', + 'settings.alwaysShowRoutes': 'Sempre mostrar rotas de reserva', + 'settings.alwaysShowRoutesHint': 'Mostra automaticamente no mapa a rota de cada voo, trem e outra reserva, sem precisar ativar item por item.', }; export default settings; diff --git a/shared/src/i18n/cs/settings.ts b/shared/src/i18n/cs/settings.ts index 891b29571..68c995b3a 100644 --- a/shared/src/i18n/cs/settings.ts +++ b/shared/src/i18n/cs/settings.ts @@ -485,6 +485,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Zdroj', 'settings.pluginActivity.columns.when': 'Kdy', 'settings.pluginActivity.columns.status': 'Výsledek', + 'settings.alwaysShowRoutes': 'Vždy zobrazovat trasy rezervací', + 'settings.alwaysShowRoutesHint': 'Automaticky zobrazí na mapě trasu každého letu, vlaku a jiné rezervace, aniž byste ji museli zapínat jednotlivě.', }; export default settings; diff --git a/shared/src/i18n/de/settings.ts b/shared/src/i18n/de/settings.ts index 36b94e295..26cd4de40 100644 --- a/shared/src/i18n/de/settings.ts +++ b/shared/src/i18n/de/settings.ts @@ -496,6 +496,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Ressource', 'settings.pluginActivity.columns.when': 'Zeitpunkt', 'settings.pluginActivity.columns.status': 'Ergebnis', + 'settings.alwaysShowRoutes': 'Buchungsrouten immer anzeigen', + 'settings.alwaysShowRoutesHint': 'Zeigt die Route für jeden Flug, jede Zugfahrt und jede andere Buchung automatisch auf der Karte an – ohne sie einzeln aktivieren zu müssen.', }; export default settings; diff --git a/shared/src/i18n/en/settings.ts b/shared/src/i18n/en/settings.ts index 424ae2930..97d3c559d 100644 --- a/shared/src/i18n/en/settings.ts +++ b/shared/src/i18n/en/settings.ts @@ -483,6 +483,8 @@ const settings: TranslationStrings = { 'settings.offline.banner.syncing': 'Syncing {count}…', 'settings.offline.banner.failed': 'Failed to sync: {count}', 'settings.offline.banner.conflicts': 'Conflicts: {count}', + 'settings.alwaysShowRoutes': 'Always show booking routes', + 'settings.alwaysShowRoutesHint': 'Automatically draw the route for every flight, train and other booking on the map — no need to switch it on per item.', }; export default settings; diff --git a/shared/src/i18n/es/settings.ts b/shared/src/i18n/es/settings.ts index 0f6c064e6..024f29060 100644 --- a/shared/src/i18n/es/settings.ts +++ b/shared/src/i18n/es/settings.ts @@ -494,6 +494,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Recurso', 'settings.pluginActivity.columns.when': 'Cuándo', 'settings.pluginActivity.columns.status': 'Resultado', + 'settings.alwaysShowRoutes': 'Mostrar siempre las rutas de reserva', + 'settings.alwaysShowRoutesHint': 'Muestra automáticamente en el mapa la ruta de cada vuelo, tren y otra reserva, sin necesidad de activarla una por una.', }; export default settings; diff --git a/shared/src/i18n/fr/settings.ts b/shared/src/i18n/fr/settings.ts index dc7b0daf4..1cd52226e 100644 --- a/shared/src/i18n/fr/settings.ts +++ b/shared/src/i18n/fr/settings.ts @@ -501,6 +501,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Ressource', 'settings.pluginActivity.columns.when': 'Quand', 'settings.pluginActivity.columns.status': 'Résultat', + 'settings.alwaysShowRoutes': 'Toujours afficher les itinéraires de réservation', + 'settings.alwaysShowRoutesHint': 'Affiche automatiquement sur la carte l\'itinéraire de chaque vol, trajet en train et autre réservation, sans avoir à l\'activer un par un.', }; export default settings; diff --git a/shared/src/i18n/gr/settings.ts b/shared/src/i18n/gr/settings.ts index 598f84cb8..ab7dfbec6 100644 --- a/shared/src/i18n/gr/settings.ts +++ b/shared/src/i18n/gr/settings.ts @@ -504,6 +504,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Πόρος', 'settings.pluginActivity.columns.when': 'Πότε', 'settings.pluginActivity.columns.status': 'Αποτέλεσμα', + 'settings.alwaysShowRoutes': 'Πάντα εμφάνιση διαδρομών κράτησης', + 'settings.alwaysShowRoutesHint': 'Εμφανίζει αυτόματα στον χάρτη τη διαδρομή κάθε πτήσης, τρένου και άλλης κράτησης, χωρίς να χρειάζεται να την ενεργοποιείτε μία προς μία.', }; export default settings; diff --git a/shared/src/i18n/hu/settings.ts b/shared/src/i18n/hu/settings.ts index e2520eec8..210d07fe2 100644 --- a/shared/src/i18n/hu/settings.ts +++ b/shared/src/i18n/hu/settings.ts @@ -494,6 +494,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Erőforrás', 'settings.pluginActivity.columns.when': 'Mikor', 'settings.pluginActivity.columns.status': 'Eredmény', + 'settings.alwaysShowRoutes': 'Mindig jelenjenek meg a foglalási útvonalak', + 'settings.alwaysShowRoutesHint': 'Automatikusan megjeleníti minden repülőjárat, vonat és egyéb foglalás útvonalát a térképen, nincs szükség egyenkénti bekapcsolásra.', }; export default settings; diff --git a/shared/src/i18n/id/settings.ts b/shared/src/i18n/id/settings.ts index 7594b7e45..1d4ab5c60 100644 --- a/shared/src/i18n/id/settings.ts +++ b/shared/src/i18n/id/settings.ts @@ -491,6 +491,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Sumber daya', 'settings.pluginActivity.columns.when': 'Waktu', 'settings.pluginActivity.columns.status': 'Hasil', + 'settings.alwaysShowRoutes': 'Selalu tampilkan rute pemesanan', + 'settings.alwaysShowRoutesHint': 'Menampilkan rute setiap penerbangan, kereta, dan pemesanan lainnya di peta secara otomatis, tanpa perlu mengaktifkannya satu per satu.', }; export default settings; diff --git a/shared/src/i18n/it/settings.ts b/shared/src/i18n/it/settings.ts index 9d0cc9044..ea552c9e7 100644 --- a/shared/src/i18n/it/settings.ts +++ b/shared/src/i18n/it/settings.ts @@ -493,6 +493,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Risorsa', 'settings.pluginActivity.columns.when': 'Quando', 'settings.pluginActivity.columns.status': 'Esito', + 'settings.alwaysShowRoutes': 'Mostra sempre i percorsi delle prenotazioni', + 'settings.alwaysShowRoutesHint': 'Mostra automaticamente sulla mappa il percorso di ogni volo, treno e altra prenotazione, senza doverlo attivare singolarmente.', }; export default settings; diff --git a/shared/src/i18n/ja/settings.ts b/shared/src/i18n/ja/settings.ts index ebaeffa4a..165533ba4 100644 --- a/shared/src/i18n/ja/settings.ts +++ b/shared/src/i18n/ja/settings.ts @@ -465,6 +465,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'リソース', 'settings.pluginActivity.columns.when': '日時', 'settings.pluginActivity.columns.status': '結果', + 'settings.alwaysShowRoutes': '予約ルートを常に表示', + 'settings.alwaysShowRoutesHint': 'フライトや電車などすべての予約のルートを、個別にオンにしなくても地図上に自動的に表示します。', }; export default settings; diff --git a/shared/src/i18n/ko/settings.ts b/shared/src/i18n/ko/settings.ts index 67c75a3f7..fa2e69d6a 100644 --- a/shared/src/i18n/ko/settings.ts +++ b/shared/src/i18n/ko/settings.ts @@ -481,6 +481,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': '리소스', 'settings.pluginActivity.columns.when': '시간', 'settings.pluginActivity.columns.status': '결과', + 'settings.alwaysShowRoutes': '예약 경로 항상 표시', + 'settings.alwaysShowRoutesHint': '항공편, 기차 등 모든 예약의 경로를 개별적으로 켤 필요 없이 지도에 자동으로 표시합니다.', }; export default settings; diff --git a/shared/src/i18n/nl/settings.ts b/shared/src/i18n/nl/settings.ts index 17c683acf..77b3036bd 100644 --- a/shared/src/i18n/nl/settings.ts +++ b/shared/src/i18n/nl/settings.ts @@ -494,6 +494,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Bron', 'settings.pluginActivity.columns.when': 'Wanneer', 'settings.pluginActivity.columns.status': 'Resultaat', + 'settings.alwaysShowRoutes': 'Boekingsroutes altijd tonen', + 'settings.alwaysShowRoutesHint': 'Toont automatisch de route van elke vlucht, trein en andere boeking op de kaart, zonder dat u dit per boeking hoeft in te schakelen.', }; export default settings; diff --git a/shared/src/i18n/pl/settings.ts b/shared/src/i18n/pl/settings.ts index 6b84af0ee..8f87c7098 100644 --- a/shared/src/i18n/pl/settings.ts +++ b/shared/src/i18n/pl/settings.ts @@ -493,6 +493,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Zasób', 'settings.pluginActivity.columns.when': 'Kiedy', 'settings.pluginActivity.columns.status': 'Wynik', + 'settings.alwaysShowRoutes': 'Zawsze pokazuj trasy rezerwacji', + 'settings.alwaysShowRoutesHint': 'Automatycznie pokazuje na mapie trasę każdego lotu, pociągu i innej rezerwacji, bez konieczności włączania jej pojedynczo.', }; export default settings; diff --git a/shared/src/i18n/ru/settings.ts b/shared/src/i18n/ru/settings.ts index 9d8821df1..48ae8ad2e 100644 --- a/shared/src/i18n/ru/settings.ts +++ b/shared/src/i18n/ru/settings.ts @@ -494,6 +494,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Ресурс', 'settings.pluginActivity.columns.when': 'Когда', 'settings.pluginActivity.columns.status': 'Результат', + 'settings.alwaysShowRoutes': 'Всегда показывать маршруты бронирований', + 'settings.alwaysShowRoutesHint': 'Автоматически показывает на карте маршрут для каждого рейса, поезда и другого бронирования — без необходимости включать это отдельно для каждого элемента.', }; export default settings; diff --git a/shared/src/i18n/sv/settings.ts b/shared/src/i18n/sv/settings.ts index b06a1020c..69dab8236 100644 --- a/shared/src/i18n/sv/settings.ts +++ b/shared/src/i18n/sv/settings.ts @@ -490,6 +490,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Resurs', 'settings.pluginActivity.columns.when': 'När', 'settings.pluginActivity.columns.status': 'Resultat', + 'settings.alwaysShowRoutes': 'Visa alltid bokningsrutter', + 'settings.alwaysShowRoutesHint': 'Visar automatiskt rutten för varje flyg, tåg och annan bokning på kartan, utan att du behöver aktivera det för varje bokning för sig.', }; export default settings; diff --git a/shared/src/i18n/tr/settings.ts b/shared/src/i18n/tr/settings.ts index 55715ba7e..c13087437 100644 --- a/shared/src/i18n/tr/settings.ts +++ b/shared/src/i18n/tr/settings.ts @@ -490,6 +490,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Kaynak', 'settings.pluginActivity.columns.when': 'Ne zaman', 'settings.pluginActivity.columns.status': 'Sonuç', + 'settings.alwaysShowRoutes': 'Rezervasyon rotalarını her zaman göster', + 'settings.alwaysShowRoutesHint': 'Haritada her uçuş, tren ve diğer rezervasyonun rotasını, tek tek açmaya gerek kalmadan otomatik olarak gösterir.', }; export default settings; diff --git a/shared/src/i18n/uk/settings.ts b/shared/src/i18n/uk/settings.ts index 64d019e8a..1c785b840 100644 --- a/shared/src/i18n/uk/settings.ts +++ b/shared/src/i18n/uk/settings.ts @@ -493,6 +493,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Ресурс', 'settings.pluginActivity.columns.when': 'Коли', 'settings.pluginActivity.columns.status': 'Результат', + 'settings.alwaysShowRoutes': 'Завжди показувати маршрути бронювань', + 'settings.alwaysShowRoutesHint': 'Автоматично показує на карті маршрут для кожного рейсу, поїзда та іншого бронювання — без потреби вмикати це окремо для кожного елемента.', }; export default settings; diff --git a/shared/src/i18n/vi/settings.ts b/shared/src/i18n/vi/settings.ts index 327cb3913..253fd4612 100644 --- a/shared/src/i18n/vi/settings.ts +++ b/shared/src/i18n/vi/settings.ts @@ -495,6 +495,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': 'Tài nguyên', 'settings.pluginActivity.columns.when': 'Thời điểm', 'settings.pluginActivity.columns.status': 'Kết quả', + 'settings.alwaysShowRoutes': 'Luôn hiển thị tuyến đường đặt chỗ', + 'settings.alwaysShowRoutesHint': 'Tự động hiển thị trên bản đồ tuyến đường của mỗi chuyến bay, tàu hỏa và đặt chỗ khác, không cần bật riêng từng mục.', }; export default settings; diff --git a/shared/src/i18n/zh-TW/settings.ts b/shared/src/i18n/zh-TW/settings.ts index 2cfa481bc..50ab41c7a 100644 --- a/shared/src/i18n/zh-TW/settings.ts +++ b/shared/src/i18n/zh-TW/settings.ts @@ -464,6 +464,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': '資源', 'settings.pluginActivity.columns.when': '時間', 'settings.pluginActivity.columns.status': '結果', + 'settings.alwaysShowRoutes': '一律顯示訂票路線', + 'settings.alwaysShowRoutesHint': '自動在地圖上顯示每個航班、火車及其他預訂的路線,不需要逐一手動開啟。', }; export default settings; diff --git a/shared/src/i18n/zh/settings.ts b/shared/src/i18n/zh/settings.ts index f792bd47d..1424efc47 100644 --- a/shared/src/i18n/zh/settings.ts +++ b/shared/src/i18n/zh/settings.ts @@ -460,6 +460,8 @@ const settings: TranslationStrings = { 'settings.pluginActivity.columns.resource': '资源', 'settings.pluginActivity.columns.when': '时间', 'settings.pluginActivity.columns.status': '结果', + 'settings.alwaysShowRoutes': '始终显示预订路线', + 'settings.alwaysShowRoutesHint': '自动在地图上显示每个航班、火车和其他预订的路线,无需逐个手动开启。', }; export default settings;