@autobusal/routes-order 1.30.0 → 1.31.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 +40 -0
- package/Checkout/Sidebar/Sidebar.tsx +7 -2
- package/Step5/Summary/About/About.tsx +80 -64
- package/Step5/Summary/About/styles.ts +29 -0
- package/Step5/Summary/styles.ts +12 -5
- package/package.json +1 -1
- package/services.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.31.0
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **The checkout Order Summary stacks the legs vertically and numbers them**
|
|
8
|
+
— "Trip 1" above the outbound, "Trip 2" above the return.
|
|
9
|
+
|
|
10
|
+
They sat side by side from 768px up, which was written when the summary
|
|
11
|
+
spanned the page. It has lived in the checkout *sidebar* since 1.11.0 — a
|
|
12
|
+
narrow column — so two legs abreast left each about half the width a single
|
|
13
|
+
line like "Terminali Lindor Interurban dhe Nderkombetar i Autobusave (TEG)"
|
|
14
|
+
needs, and nothing said which was which. Vertical at every width now, in the
|
|
15
|
+
order they are travelled.
|
|
16
|
+
|
|
17
|
+
**The number is only rendered on a round trip.** A one-way has nothing to
|
|
18
|
+
enumerate, and a lone "Trip 1" would send the reader looking for a Trip 2
|
|
19
|
+
that was never bought. `Checkout/Sidebar` is the one component that knows
|
|
20
|
+
whether a second leg exists, so it is the one that decides — `About` just
|
|
21
|
+
takes an optional `number`.
|
|
22
|
+
|
|
23
|
+
"Trip" rather than "Segment": segment is airline jargon, and this is the
|
|
24
|
+
last screen before somebody pays for a bus ticket.
|
|
25
|
+
|
|
26
|
+
## 1.30.1
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **Step 3 could never list a single return leg.** `useGetReturns` spread the
|
|
31
|
+
search form straight into the query string, so the return date went over as
|
|
32
|
+
`_return` — the form's name for it, because `return` is a reserved word in
|
|
33
|
+
JS — while the API validates `return`. Every request answered
|
|
34
|
+
`422 The return field is required`, and "Select a Return Schedule" was empty
|
|
35
|
+
for every round trip ever searched. The order builder in the same file has
|
|
36
|
+
always done this mapping (`order.return = step1._return`); only this call
|
|
37
|
+
was missed.
|
|
38
|
+
|
|
39
|
+
Paired with an obtapi fix — `Routes\Search\Returns::find()` returned nothing
|
|
40
|
+
on its success path — so the step was broken twice over and neither failure
|
|
41
|
+
could be seen past the other.
|
|
42
|
+
|
|
3
43
|
## 1.30.0
|
|
4
44
|
|
|
5
45
|
### Added
|
|
@@ -53,9 +53,14 @@ const Sidebar = ({ step1, step2, step3, fare, addons, coupon, total, action, pen
|
|
|
53
53
|
{ t('routes_order.step5.summary.title') }
|
|
54
54
|
</SubTitle>
|
|
55
55
|
|
|
56
|
+
{ /* Edited: Ferjolt Ozuni - Date: 2026-08-06
|
|
57
|
+
Numbered only on a ROUND TRIP. This is the one place that knows
|
|
58
|
+
whether a second leg exists, so it is the one place that can
|
|
59
|
+
decide - a one-way labelled "Trip 1" would send the reader looking
|
|
60
|
+
for a Trip 2 that was never bought. */ }
|
|
56
61
|
<Information>
|
|
57
|
-
<About type="departure" step1={ step1 } data={ step2 } t={ t } />
|
|
58
|
-
<About type="return" step1={ step1 } data={ step3 } t={ t } />
|
|
62
|
+
<About type="departure" step1={ step1 } data={ step2 } number={ step3 ? 1 : undefined } t={ t } />
|
|
63
|
+
<About type="return" step1={ step1 } data={ step3 } number={ step3 ? 2 : undefined } t={ t } />
|
|
59
64
|
</Information>
|
|
60
65
|
|
|
61
66
|
{ /* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TFunction } from 'i18next';
|
|
2
2
|
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa';
|
|
3
3
|
import { FaCircleDot, FaLocationDot } from 'react-icons/fa6';
|
|
4
|
-
import { Container, ContainerIcon, Icon, Information, Title, Operator, Carrier, Logo, Leg, Point, PointIcon, PointCity, Country, PointMeta } from './styles';
|
|
4
|
+
import { Trip, TripLabel, Container, ContainerIcon, Icon, Information, Title, Operator, Carrier, Logo, Leg, Point, PointIcon, PointCity, Country, PointMeta } from './styles';
|
|
5
5
|
import { RoutesSearchForm } from '@autobusal/routes-search/types';
|
|
6
6
|
import { FoundData } from '@autobusal/providers/types/routes';
|
|
7
7
|
|
|
@@ -9,6 +9,16 @@ interface Props {
|
|
|
9
9
|
type: 'departure' | 'return'
|
|
10
10
|
step1: RoutesSearchForm
|
|
11
11
|
data?: FoundData
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Which leg of the journey this is, 1-based.
|
|
15
|
+
*
|
|
16
|
+
* Ferjolt Ozuni - Date: 2026-08-06
|
|
17
|
+
* Only passed on a ROUND TRIP - the caller is the one that knows whether
|
|
18
|
+
* there is a second leg, and a one-way has nothing to number.
|
|
19
|
+
*/
|
|
20
|
+
number?: number
|
|
21
|
+
|
|
12
22
|
t: TFunction<'public'>
|
|
13
23
|
}
|
|
14
24
|
|
|
@@ -26,7 +36,7 @@ interface Props {
|
|
|
26
36
|
* before someone pays, and "Thessaloniki, Greece" settles a doubt that
|
|
27
37
|
* "(GRC)" only half answers.
|
|
28
38
|
*/
|
|
29
|
-
const About = ({ type, step1, data, t }: Props): (JSX.Element | null) => {
|
|
39
|
+
const About = ({ type, step1, data, number, t }: Props): (JSX.Element | null) => {
|
|
30
40
|
if (!data) {
|
|
31
41
|
return null;
|
|
32
42
|
}
|
|
@@ -36,68 +46,74 @@ const About = ({ type, step1, data, t }: Props): (JSX.Element | null) => {
|
|
|
36
46
|
const date = type === 'departure' ? step1.departure : step1._return;
|
|
37
47
|
|
|
38
48
|
return (
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
49
|
+
<Trip>
|
|
50
|
+
{ number !== undefined && (
|
|
51
|
+
<TripLabel>{ t('routes_order.step5.summary.trip', { number }) }</TripLabel>
|
|
52
|
+
) }
|
|
53
|
+
|
|
54
|
+
<Container>
|
|
55
|
+
<ContainerIcon>
|
|
56
|
+
<Icon>{ icon }</Icon>
|
|
57
|
+
</ContainerIcon>
|
|
58
|
+
|
|
59
|
+
<Information>
|
|
60
|
+
<Title>{ data.name } ({ data.code })</Title>
|
|
61
|
+
|
|
62
|
+
{ /* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
63
|
+
Mark and name together, ranged right. The name used to sit
|
|
64
|
+
alone at the foot of the block, so the logo read as decoration
|
|
65
|
+
rather than as the operator being identified. */ }
|
|
66
|
+
<Carrier>
|
|
67
|
+
{ data.operator.logo_url && (
|
|
68
|
+
<Logo src={ data.operator.logo_url } alt={ data.operator.company } />
|
|
69
|
+
) }
|
|
70
|
+
|
|
71
|
+
<Operator>{ data.operator.company }</Operator>
|
|
72
|
+
</Carrier>
|
|
73
|
+
|
|
74
|
+
<Leg>
|
|
75
|
+
<Point>
|
|
76
|
+
<PointIcon><FaCircleDot /></PointIcon>
|
|
77
|
+
|
|
78
|
+
<PointCity>
|
|
79
|
+
{ data.locations.from.city.name }
|
|
80
|
+
{ data.locations.from.city.country?.name && (
|
|
81
|
+
<Country>, { data.locations.from.city.country.name }</Country>
|
|
82
|
+
) }
|
|
83
|
+
</PointCity>
|
|
84
|
+
|
|
85
|
+
{ /* the date and time are what a buyer double-checks before
|
|
86
|
+
paying, so they carry the weight here */ }
|
|
87
|
+
<PointMeta $strong>
|
|
88
|
+
{ t('routes_order.step5.summary.departs', {
|
|
89
|
+
date,
|
|
90
|
+
hour: data.locations.from.departure,
|
|
91
|
+
stop: data.locations.from.stop?.name
|
|
92
|
+
}) }
|
|
93
|
+
</PointMeta>
|
|
94
|
+
</Point>
|
|
95
|
+
|
|
96
|
+
<Point>
|
|
97
|
+
<PointIcon><FaLocationDot /></PointIcon>
|
|
98
|
+
|
|
99
|
+
<PointCity>
|
|
100
|
+
{ data.locations.to.city.name }
|
|
101
|
+
{ data.locations.to.city.country?.name && (
|
|
102
|
+
<Country>, { data.locations.to.city.country.name }</Country>
|
|
103
|
+
) }
|
|
104
|
+
</PointCity>
|
|
105
|
+
|
|
106
|
+
<PointMeta>
|
|
107
|
+
{ t('routes_order.step5.summary.arrives', {
|
|
108
|
+
hour: data.locations.to.arrival,
|
|
109
|
+
stop: data.locations.to.stop?.name
|
|
110
|
+
}) }
|
|
111
|
+
</PointMeta>
|
|
112
|
+
</Point>
|
|
113
|
+
</Leg>
|
|
114
|
+
</Information>
|
|
115
|
+
</Container>
|
|
116
|
+
</Trip>
|
|
101
117
|
);
|
|
102
118
|
};
|
|
103
119
|
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* One leg, with its number above it.
|
|
5
|
+
*
|
|
6
|
+
* Ferjolt Ozuni - Date: 2026-08-06
|
|
7
|
+
* This wrapper exists so the label can sit ACROSS the leg rather than beside
|
|
8
|
+
* the arrow: Container below is the icon-and-content row, and a heading
|
|
9
|
+
* placed inside it would indent into the content column and read as part of
|
|
10
|
+
* the route name.
|
|
11
|
+
*/
|
|
12
|
+
export const Trip = styled.div`
|
|
13
|
+
flex: 1;
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* "Trip 1", "Trip 2" - only rendered when there are two.
|
|
18
|
+
*
|
|
19
|
+
* Ferjolt Ozuni - Date: 2026-08-06
|
|
20
|
+
* A one-way booking has nothing to enumerate, and numbering a lone leg would
|
|
21
|
+
* invite the reader to go looking for the other one.
|
|
22
|
+
*/
|
|
23
|
+
export const TripLabel = styled.div`
|
|
24
|
+
margin-bottom: 8px;
|
|
25
|
+
color: ${ props => props.theme.font.faded };
|
|
26
|
+
font-size: ${ props => props.theme.size.xs };
|
|
27
|
+
font-weight: 700;
|
|
28
|
+
text-transform: uppercase;
|
|
29
|
+
letter-spacing: 0.06em;
|
|
30
|
+
`;
|
|
31
|
+
|
|
3
32
|
export const Container = styled.div`
|
|
4
33
|
flex: 1;
|
|
5
34
|
display: flex;
|
package/Step5/Summary/styles.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* The legs of the booking, stacked.
|
|
5
|
+
*
|
|
6
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-06
|
|
7
|
+
* They used to sit SIDE BY SIDE from 768px up. That was written when the
|
|
8
|
+
* summary spanned the page; it now lives in the checkout sidebar, a narrow
|
|
9
|
+
* column, where two legs abreast left each one about half the room a single
|
|
10
|
+
* line like "Terminali Lindor Interurban dhe Nderkombetar i Autobusave
|
|
11
|
+
* (TEG)" needs. Vertical at every width, so each leg gets the panel's full
|
|
12
|
+
* width and the two read in the order they are travelled.
|
|
13
|
+
*/
|
|
3
14
|
export const Information = styled.div`
|
|
4
15
|
display: flex;
|
|
5
16
|
flex-direction: column;
|
|
6
|
-
gap:
|
|
7
|
-
|
|
8
|
-
@media (min-width: 768px) {
|
|
9
|
-
flex-direction: row;
|
|
10
|
-
}
|
|
17
|
+
gap: 20px;
|
|
11
18
|
`;
|
package/package.json
CHANGED
package/services.ts
CHANGED
|
@@ -47,6 +47,18 @@ export const useGetAlternatives = (data: RoutesSearchForm, enabled: boolean): Us
|
|
|
47
47
|
})
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The return legs on offer for an already-chosen outbound.
|
|
52
|
+
*
|
|
53
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-05
|
|
54
|
+
* The return date goes over as `return`. The form calls it `_return`
|
|
55
|
+
* because `return` is a reserved word in JS, and spreading the form
|
|
56
|
+
* straight into the query string therefore sent a field the API does not
|
|
57
|
+
* know while omitting the one it validates - so this request answered 422
|
|
58
|
+
* "The return field is required" every single time, and step 3 could never
|
|
59
|
+
* list anything. The order builder below has always done this mapping
|
|
60
|
+
* (`order.return = step1._return`); only this call was missed.
|
|
61
|
+
*/
|
|
50
62
|
export const useGetReturns = (data: RoutesSearchForm, departure: FoundData): UseQueryResult<FoundData[]> => (
|
|
51
63
|
useQuery({
|
|
52
64
|
queryKey: ['search-routes-step3', { data }],
|
|
@@ -55,6 +67,7 @@ export const useGetReturns = (data: RoutesSearchForm, departure: FoundData): Use
|
|
|
55
67
|
.get('/api/routes/search/return', {
|
|
56
68
|
params: {
|
|
57
69
|
...data,
|
|
70
|
+
return: data._return,
|
|
58
71
|
operator_id: departure.operator.id
|
|
59
72
|
}
|
|
60
73
|
})
|