@autobusal/routes-order 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/RoutesOrder.tsx +27 -1
- package/Step1/Step1.tsx +11 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,37 @@
|
|
|
3
3
|
All notable changes to this package are documented here. This project follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/) and [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.7.0] - 2026-07-30
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **Per-pair `<title>`/description for `/bus-lines/:from/:to`.** Every
|
|
11
|
+
route-pair search page previously shared one static generic
|
|
12
|
+
title/description (`routes_order.title`/`meta.description`) regardless
|
|
13
|
+
of which cities were being searched - hundreds of near-duplicate-content
|
|
14
|
+
pages, invisible to search engines as distinct pages, even though
|
|
15
|
+
obtapi's `Route::linkPurchase()` and the sitemap already point directly
|
|
16
|
+
at specific pairs. Now resolves `:from`/`:to` against
|
|
17
|
+
`routes-search`'s own city list (same cached query `<RoutesSearch>`
|
|
18
|
+
already uses - no extra fetch) and renders real
|
|
19
|
+
`routes_order.title_pair`/`meta.description_pair` templates (all 15
|
|
20
|
+
languages) when both resolve, falling back to the generic copy for the
|
|
21
|
+
bare `/bus-lines` search form.
|
|
22
|
+
|
|
23
|
+
## [1.6.2] - 2026-07-30
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **The full 9-segment `/bus-lines/:from/:to/:departure/:_return/:type/:adults/:children/:babies`
|
|
28
|
+
URL only auto-searched if a `?type=submit` query param was also present**
|
|
29
|
+
(`Step1/Step1.tsx`) - set only when the in-app search form navigated here
|
|
30
|
+
itself. Every OTHER way of reaching this URL - obtapi's
|
|
31
|
+
`Route::linkPurchase()` (which generates exactly this path with no query
|
|
32
|
+
param), a shared link, a search engine crawling it - rendered nothing but
|
|
33
|
+
the empty search form despite the URL already carrying a complete search
|
|
34
|
+
spec. Now also auto-searches whenever `:departure` is present in the path,
|
|
35
|
+
which only the full 9-segment route ever populates.
|
|
36
|
+
|
|
6
37
|
## [1.6.1] - 2026-07-27
|
|
7
38
|
|
|
8
39
|
### Added
|
package/RoutesOrder.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
+
import { useParams } from 'react-router-dom';
|
|
2
3
|
import { TFunction } from 'i18next';
|
|
3
4
|
import { Meta } from '@autobusal/common';
|
|
5
|
+
import { useGetSuggestions } from '@autobusal/routes-search/services';
|
|
4
6
|
import Step1 from './Step1/Step1';
|
|
5
7
|
import Step2 from './Step2';
|
|
6
8
|
import Step3 from './Step3';
|
|
@@ -15,6 +17,30 @@ interface Props {
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
const RoutesOrder = ({ t }: Props): JSX.Element => {
|
|
20
|
+
const params = useParams();
|
|
21
|
+
|
|
22
|
+
// `/bus-lines/:from/:to[...]` shared one static title/description across
|
|
23
|
+
// every single from-to pair - hundreds of near-duplicate-content search
|
|
24
|
+
// pages, invisible to search engines as distinct content, even though
|
|
25
|
+
// obtapi's Route::linkPurchase() and the sitemap already point directly
|
|
26
|
+
// at specific pairs. `useGetSuggestions` (routes-search's own city
|
|
27
|
+
// autocomplete data) is reused here rather than a new fetch - Step1's
|
|
28
|
+
// own <RoutesSearch> below hits the same cached query, so this costs
|
|
29
|
+
// nothing extra. Falls back to the generic copy for the bare /bus-lines
|
|
30
|
+
// search form (no :from/:to params yet) or if a slug doesn't resolve.
|
|
31
|
+
const { data: cities } = useGetSuggestions();
|
|
32
|
+
|
|
33
|
+
const fromCity = cities.find(city => city.slug === params.from);
|
|
34
|
+
const toCity = cities.find(city => city.slug === params.to);
|
|
35
|
+
|
|
36
|
+
const title = fromCity && toCity
|
|
37
|
+
? t('routes_order.title_pair', { from: fromCity.name, to: toCity.name })
|
|
38
|
+
: t('routes_order.title');
|
|
39
|
+
|
|
40
|
+
const description = fromCity && toCity
|
|
41
|
+
? t('routes_order.meta.description_pair', { from: fromCity.name, to: toCity.name })
|
|
42
|
+
: t('routes_order.meta.description');
|
|
43
|
+
|
|
18
44
|
const [ redirected, setRedirected ] = useState<boolean>(false);
|
|
19
45
|
const [ current, setCurrent ] = useState<number>(1);
|
|
20
46
|
const [ step1, setStep1 ] = useState<RoutesSearchForm | undefined>(undefined);
|
|
@@ -70,7 +96,7 @@ const RoutesOrder = ({ t }: Props): JSX.Element => {
|
|
|
70
96
|
const showStep5 = current === 5 && step1 !== undefined && step2 !== undefined && step4 !== undefined;
|
|
71
97
|
|
|
72
98
|
return (
|
|
73
|
-
<Meta title={
|
|
99
|
+
<Meta title={ title } description={ description }>
|
|
74
100
|
{ showStep1 && (
|
|
75
101
|
<Step1
|
|
76
102
|
value={ step1 }
|
package/Step1/Step1.tsx
CHANGED
|
@@ -25,7 +25,17 @@ const Step1 = ({ value, redirected, t, onSave }: Props): JSX.Element => {
|
|
|
25
25
|
|
|
26
26
|
const prepared = prepare(value, params, searchParams, data.preferences.defaultLocations);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// Two ways this page ends up with a complete search spec:
|
|
29
|
+
// 1. `?type=submit` - set by the in-app search form (home/Main/Main.tsx)
|
|
30
|
+
// when it navigates here itself.
|
|
31
|
+
// 2. `:departure` present in the URL path - the full 9-segment route
|
|
32
|
+
// (/bus-lines/:from/:to/:departure/:_return/:type/:adults/:children/:babies)
|
|
33
|
+
// already carries a complete search spec with no query param needed.
|
|
34
|
+
// This is how obtapi's Route::linkPurchase() generates links, and how
|
|
35
|
+
// anyone (a search engine, a shared link) reaches this URL directly -
|
|
36
|
+
// previously only case 1 triggered a search, so every one of those
|
|
37
|
+
// deep links rendered nothing but the empty search form.
|
|
38
|
+
const isSubmitted = searchParams.get('type') === 'submit' || params.departure !== undefined;
|
|
29
39
|
|
|
30
40
|
useEffect(() => {
|
|
31
41
|
if (isSubmitted && !redirected) {
|