@autobusal/routes-order 1.31.0 → 1.31.1
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 +10 -0
- package/Checkout/Checkout.tsx +17 -2
- package/Checkout/Sidebar/Sidebar.tsx +12 -3
- package/Step5/Payments/Payments.tsx +24 -1
- package/Step5/utilities.ts +39 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.31.1
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **One payment method means one button.** The picker no longer renders when
|
|
8
|
+
there is nothing to pick, and the button reads "Pay Now" rather than "Make
|
|
9
|
+
Payment" - a heading over a single option the buyer had to press before
|
|
10
|
+
pressing the real one was a click that only ever had one answer, on the
|
|
11
|
+
last screen before paying.
|
|
12
|
+
|
|
3
13
|
## 1.31.0
|
|
4
14
|
|
|
5
15
|
### Changed
|
package/Checkout/Checkout.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import Addons from '../Step5/Addons/Addons';
|
|
|
15
15
|
import Billing from '../Step5/Billing/Billing';
|
|
16
16
|
import Payments from '../Step5/Payments/Payments';
|
|
17
17
|
import Sidebar from './Sidebar/Sidebar';
|
|
18
|
-
import { getTotal, convertCoupon } from '../Step5/utilities';
|
|
18
|
+
import { getTotal, convertCoupon, getAvailablePayments } from '../Step5/utilities';
|
|
19
19
|
import { Title, Actions, Results, Listing } from '../styles';
|
|
20
20
|
import { RoutesSearchForm } from '@autobusal/routes-search/types';
|
|
21
21
|
import { PersonData, BillingData } from '@autobusal/providers/types/persons';
|
|
@@ -24,7 +24,7 @@ import { CouponData } from '@autobusal/providers/types/orders';
|
|
|
24
24
|
import { TotalData } from '../types';
|
|
25
25
|
import { useUserStore } from '@autobusal/providers/stores/user';
|
|
26
26
|
import { useGetSettings } from '@autobusal/providers/services';
|
|
27
|
-
import { usePostOrder, useGetFlex } from '../services';
|
|
27
|
+
import { usePostOrder, useGetFlex, useGetPayments } from '../services';
|
|
28
28
|
import { addon as commerceAddon, beginCheckout, stash } from '@autobusal/providers/Setup/commerce';
|
|
29
29
|
import { item as commerceItem } from '../commerce';
|
|
30
30
|
|
|
@@ -74,6 +74,20 @@ const Checkout = ({ values, step1, step2, step3, isPartner, t, onStore, onBack }
|
|
|
74
74
|
const [ total, setTotal ] = useState<TotalData>(getTotal(step2, step3));
|
|
75
75
|
const [ action, setAction ] = useState<string | undefined>(undefined);
|
|
76
76
|
|
|
77
|
+
/*
|
|
78
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-07
|
|
79
|
+
*
|
|
80
|
+
* Whether there is a payment CHOICE to be made, which decides both whether
|
|
81
|
+
* the picker draws itself and what the button says.
|
|
82
|
+
*
|
|
83
|
+
* The same query the picker runs, under the same key, so react-query
|
|
84
|
+
* answers it from cache - this reads the answer, it does not fetch it a
|
|
85
|
+
* second time.
|
|
86
|
+
*/
|
|
87
|
+
const { data: paymentsData } = useGetPayments();
|
|
88
|
+
|
|
89
|
+
const singleMethod = getAvailablePayments(paymentsData, isPartner ?? false).length === 1;
|
|
90
|
+
|
|
77
91
|
const [ addonWhatsapp, setAddonWhatsapp ] = useState<boolean>(false);
|
|
78
92
|
const [ addonWhatsappNumber, setAddonWhatsappNumber ] = useState<string>('');
|
|
79
93
|
const [ addonTelegram, setAddonTelegram ] = useState<boolean>(false);
|
|
@@ -312,6 +326,7 @@ const Checkout = ({ values, step1, step2, step3, isPartner, t, onStore, onBack }
|
|
|
312
326
|
coupon={ coupon }
|
|
313
327
|
total={ grandTotal }
|
|
314
328
|
action={ action }
|
|
329
|
+
single={ singleMethod }
|
|
315
330
|
pending={ isPending }
|
|
316
331
|
t={ t }
|
|
317
332
|
onPay={ onPay }
|
|
@@ -26,6 +26,7 @@ interface Props {
|
|
|
26
26
|
coupon?: CouponData
|
|
27
27
|
total: TotalData
|
|
28
28
|
action?: string
|
|
29
|
+
single?: boolean
|
|
29
30
|
pending: boolean
|
|
30
31
|
t: TFunction<'common'>
|
|
31
32
|
onPay: () => void
|
|
@@ -45,7 +46,7 @@ interface Props {
|
|
|
45
46
|
* page and scrolled away while add-ons were being ticked - so the number
|
|
46
47
|
* changed out of sight of the person it was changing for.
|
|
47
48
|
*/
|
|
48
|
-
const Sidebar = ({ step1, step2, step3, fare, addons, coupon, total, action, pending, t, onPay, children, payments }: Props): JSX.Element => (
|
|
49
|
+
const Sidebar = ({ step1, step2, step3, fare, addons, coupon, total, action, single, pending, t, onPay, children, payments }: Props): JSX.Element => (
|
|
49
50
|
<Container>
|
|
50
51
|
<Panel className="box">
|
|
51
52
|
<SubTitle>
|
|
@@ -89,7 +90,13 @@ const Sidebar = ({ step1, step2, step3, fare, addons, coupon, total, action, pen
|
|
|
89
90
|
{ /* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
90
91
|
The label follows the chosen method, so the button says what it
|
|
91
92
|
is about to do - "Reserve" does not take money, and a button
|
|
92
|
-
reading "Make Payment" for it would be a lie.
|
|
93
|
+
reading "Make Payment" for it would be a lie.
|
|
94
|
+
|
|
95
|
+
Edited: Ferjolt Ozuni - Date: 2026-08-07
|
|
96
|
+
And when there is only one method, the picker above renders
|
|
97
|
+
nothing, so this is the whole payment step. "Make Payment" reads
|
|
98
|
+
as "proceed to the part where you pay"; with nothing left in
|
|
99
|
+
between, it should say what actually happens next. */ }
|
|
93
100
|
<Button
|
|
94
101
|
loading={ pending }
|
|
95
102
|
noMargin
|
|
@@ -98,7 +105,9 @@ const Sidebar = ({ step1, step2, step3, fare, addons, coupon, total, action, pen
|
|
|
98
105
|
<MdDone />
|
|
99
106
|
{ action === 'reserve'
|
|
100
107
|
? t('routes_order.step5.reserve')
|
|
101
|
-
:
|
|
108
|
+
: single
|
|
109
|
+
? t('routes_order.step5.pay_now')
|
|
110
|
+
: t('routes_order.step5.next') }
|
|
102
111
|
</>
|
|
103
112
|
) }
|
|
104
113
|
onClick={ onPay }
|
|
@@ -7,6 +7,7 @@ import { Inline } from '@autobusal/common';
|
|
|
7
7
|
import { SubTitle } from '../../styles';
|
|
8
8
|
import { Container, ContainerPayments, ButtonPayment } from './styles';
|
|
9
9
|
import { useGetPayments } from '../../services';
|
|
10
|
+
import { getAvailablePayments } from '../utilities';
|
|
10
11
|
|
|
11
12
|
interface Props {
|
|
12
13
|
selected: string
|
|
@@ -15,9 +16,11 @@ interface Props {
|
|
|
15
16
|
onChange: (action: string) => void
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const Payments = ({ selected, isPartner, t, onChange }: Props): JSX.Element => {
|
|
19
|
+
const Payments = ({ selected, isPartner, t, onChange }: Props): JSX.Element | null => {
|
|
19
20
|
const { data, isLoading, isSuccess } = useGetPayments();
|
|
20
21
|
|
|
22
|
+
const available = getAvailablePayments(data, isPartner);
|
|
23
|
+
|
|
21
24
|
useEffect(() => {
|
|
22
25
|
if (isSuccess) {
|
|
23
26
|
const found = Object.keys(data).find(item => {
|
|
@@ -37,6 +40,26 @@ const Payments = ({ selected, isPartner, t, onChange }: Props): JSX.Element => {
|
|
|
37
40
|
);
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/*
|
|
44
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-07
|
|
45
|
+
*
|
|
46
|
+
* One method is not a choice, so there is nothing to draw.
|
|
47
|
+
*
|
|
48
|
+
* A heading reading "Payment Method" over a single button the buyer must
|
|
49
|
+
* press before pressing the real one is a step that only ever has one
|
|
50
|
+
* answer - and it is the last screen before paying, which is the worst
|
|
51
|
+
* place to spend a click. The effect above has already selected it, so the
|
|
52
|
+
* button beside this can simply say "Pay Now".
|
|
53
|
+
*
|
|
54
|
+
* Rendering nothing rather than hiding with CSS: the picker is a control,
|
|
55
|
+
* and a control nobody can act on should not be in the page at all - it
|
|
56
|
+
* would still be reachable by keyboard and still announced by a screen
|
|
57
|
+
* reader as a thing to decide.
|
|
58
|
+
*/
|
|
59
|
+
if (available.length <= 1) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
40
63
|
return (
|
|
41
64
|
<>
|
|
42
65
|
<Container>
|
package/Step5/utilities.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FoundData } from '@autobusal/providers/types/routes';
|
|
2
2
|
import { CouponData } from '@autobusal/providers/types/orders';
|
|
3
|
-
import { TotalData } from '../types';
|
|
3
|
+
import { ActionData, TotalData } from '../types';
|
|
4
4
|
|
|
5
5
|
export const getTotal = (step2: FoundData, step3?: FoundData): TotalData => {
|
|
6
6
|
// we get the currency
|
|
@@ -21,4 +21,41 @@ export const convertCoupon = (data: CouponData): TotalData => {
|
|
|
21
21
|
display: data.total,
|
|
22
22
|
value: Number(currency[0])
|
|
23
23
|
};
|
|
24
|
-
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The payment methods actually offered on this checkout, in the order the
|
|
28
|
+
* picker shows them.
|
|
29
|
+
*
|
|
30
|
+
* Ferjolt Ozuni - Date: 2026-08-07
|
|
31
|
+
*
|
|
32
|
+
* Pulled out of Payments because two places need the same answer and they
|
|
33
|
+
* must not disagree: the picker decides what to draw, and the button decides
|
|
34
|
+
* whether it is asking the buyer to choose ("Make Payment", after picking a
|
|
35
|
+
* method) or simply to pay ("Pay Now", when there is nothing to pick). A
|
|
36
|
+
* second copy of these conditions would eventually drift and produce a
|
|
37
|
+
* button offering a choice that is not on screen.
|
|
38
|
+
*
|
|
39
|
+
* The conditions themselves are unchanged, including their oddities: `cash`
|
|
40
|
+
* rides on the `funds` flag rather than one of its own, and a partner is
|
|
41
|
+
* offered every card gateway regardless of what the label enabled. Both were
|
|
42
|
+
* already true; this is a move, not a rewrite.
|
|
43
|
+
*/
|
|
44
|
+
export const getAvailablePayments = (data?: ActionData, isPartner = false): string[] => {
|
|
45
|
+
if (!data) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const available: string[] = [];
|
|
50
|
+
|
|
51
|
+
if (data.reserve && !isPartner) { available.push('reserve'); }
|
|
52
|
+
if (data.funds && !isPartner) { available.push('funds', 'cash'); }
|
|
53
|
+
|
|
54
|
+
if (data.bkt || isPartner) { available.push('bkt'); }
|
|
55
|
+
if (data.stripe || isPartner) { available.push('stripe'); }
|
|
56
|
+
if (data.mollie || isPartner) { available.push('mollie'); }
|
|
57
|
+
if (data.raiffeisen || isPartner) { available.push('raiffeisen'); }
|
|
58
|
+
if (data.nexi || isPartner) { available.push('nexi'); }
|
|
59
|
+
|
|
60
|
+
return available;
|
|
61
|
+
};
|