@mundogamernetwork/shared-ui 1.1.7 → 1.1.14
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/components/checkout/MgCartSummary.vue +3 -0
- package/components/checkout/MgCheckoutSidebar.vue +21 -38
- package/components/checkout/MgCouponInput.vue +21 -1
- package/components/checkout/MgGuestEmailForm.vue +0 -2
- package/components/checkout/MgPaymentMethodSelector.vue +31 -29
- package/components/checkout/MgPixQRCode.vue +0 -2
- package/composables/usePaymentMethods.ts +31 -44
- package/package.json +1 -1
|
@@ -32,6 +32,8 @@ const props = defineProps<{
|
|
|
32
32
|
autoWire?: boolean;
|
|
33
33
|
/** Show coupon input section */
|
|
34
34
|
showCoupon?: boolean;
|
|
35
|
+
/** Coupons unavailable for this flow (e.g. subscriptions) — shows disabled + notice */
|
|
36
|
+
couponUnavailable?: boolean;
|
|
35
37
|
}>();
|
|
36
38
|
|
|
37
39
|
const emit = defineEmits<{
|
|
@@ -101,6 +103,7 @@ const showCoupon = computed(() => props.showCoupon !== false);
|
|
|
101
103
|
:error="couponError"
|
|
102
104
|
:disabled="disabled"
|
|
103
105
|
:auto-wire="autoWire"
|
|
106
|
+
:unavailable="couponUnavailable || (autoWire && checkout?.hasPlanInCart?.value)"
|
|
104
107
|
@apply-coupon="(code) => emit('apply-coupon', code)"
|
|
105
108
|
@remove-coupon="emit('remove-coupon')"
|
|
106
109
|
/>
|
|
@@ -6,7 +6,6 @@ import MgCartItemList from "./MgCartItemList.vue";
|
|
|
6
6
|
import MgCartSummary from "./MgCartSummary.vue";
|
|
7
7
|
import MgPaymentMethodSelector from "./MgPaymentMethodSelector.vue";
|
|
8
8
|
import MgGuestEmailForm from "./MgGuestEmailForm.vue";
|
|
9
|
-
import MgPixQRCode from "./MgPixQRCode.vue";
|
|
10
9
|
|
|
11
10
|
const props = defineProps<{
|
|
12
11
|
checkout?: MgCheckoutInstance;
|
|
@@ -24,7 +23,7 @@ const emit = defineEmits<{
|
|
|
24
23
|
}>();
|
|
25
24
|
|
|
26
25
|
// Use injected checkout or prop
|
|
27
|
-
const co = props.checkout ?? injectMgCheckout()
|
|
26
|
+
const co = (props.checkout ?? injectMgCheckout())!;
|
|
28
27
|
if (!co) {
|
|
29
28
|
throw new Error("MgCheckoutSidebar: No checkout instance provided. Use provideMgCheckout() or pass checkout prop.");
|
|
30
29
|
}
|
|
@@ -33,11 +32,10 @@ onMounted(() => {
|
|
|
33
32
|
co.fetchCart();
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
35
|
+
function handleCheckout() {
|
|
36
|
+
// handlePurchase validates (email/gateway/terms) then opens the confirm modal;
|
|
37
|
+
// startValidation performs the actual submit. Consumers can also call directly.
|
|
38
|
+
co.handlePurchase();
|
|
41
39
|
}
|
|
42
40
|
</script>
|
|
43
41
|
|
|
@@ -49,28 +47,29 @@ async function handleCheckout() {
|
|
|
49
47
|
{{ $t?.("checkout.sidebar.cart") ?? "Your Cart" }}
|
|
50
48
|
</h3>
|
|
51
49
|
<MgCartItemList
|
|
52
|
-
:items="co.
|
|
50
|
+
:items="co.orderCart.value"
|
|
53
51
|
:loading="co.cartLoading.value"
|
|
54
52
|
:editable="editable ?? true"
|
|
55
53
|
:currency-symbol="currencySymbol"
|
|
56
54
|
@add-item="(id, type) => co.addItem(id, type)"
|
|
57
55
|
@remove-item="(id, type) => co.removeItem(id, type)"
|
|
58
|
-
@clear-all="co.
|
|
56
|
+
@clear-all="co.clearCartItems()"
|
|
59
57
|
/>
|
|
60
58
|
</div>
|
|
61
59
|
|
|
62
|
-
<!-- Cart Summary -->
|
|
60
|
+
<!-- Cart Summary (coupon auto-disabled when a plan is in cart) -->
|
|
63
61
|
<div v-if="co.hasItems.value" class="mg-checkout-sidebar__section">
|
|
64
62
|
<MgCartSummary
|
|
65
|
-
:total="co.
|
|
66
|
-
:original-total="co.
|
|
67
|
-
:has-discount="co.
|
|
63
|
+
:formatted-total="String(co.orderCartTotal.value)"
|
|
64
|
+
:formatted-original-total="String(co.orderCartDiscount.value)"
|
|
65
|
+
:has-discount="co.hasDiscountFlag.value"
|
|
68
66
|
:currency-symbol="currencySymbol"
|
|
69
67
|
:coupon-info="co.couponInfo.value"
|
|
70
68
|
:coupon-loading="co.couponLoading.value"
|
|
71
69
|
:coupon-error="co.couponError.value"
|
|
72
|
-
:
|
|
73
|
-
|
|
70
|
+
:coupon-unavailable="co.hasPlanInCart.value"
|
|
71
|
+
:disabled="co.loading.value"
|
|
72
|
+
@apply-coupon="(code: string) => co.applyCoupon(code)"
|
|
74
73
|
@remove-coupon="co.removeCoupon()"
|
|
75
74
|
/>
|
|
76
75
|
</div>
|
|
@@ -78,9 +77,9 @@ async function handleCheckout() {
|
|
|
78
77
|
<!-- Guest Email -->
|
|
79
78
|
<div v-if="co.hasItems.value" class="mg-checkout-sidebar__section">
|
|
80
79
|
<MgGuestEmailForm
|
|
81
|
-
v-model="co.
|
|
80
|
+
v-model="co.offlineEmail.value"
|
|
82
81
|
:error="co.emailError.value"
|
|
83
|
-
:is-authenticated="isAuthenticated"
|
|
82
|
+
:is-authenticated="isAuthenticated ?? co.signedIn.value"
|
|
84
83
|
/>
|
|
85
84
|
</div>
|
|
86
85
|
|
|
@@ -90,29 +89,15 @@ async function handleCheckout() {
|
|
|
90
89
|
{{ $t?.("checkout.sidebar.payment") ?? "Payment Method" }}
|
|
91
90
|
</h3>
|
|
92
91
|
<MgPaymentMethodSelector
|
|
93
|
-
v-model="co.
|
|
94
|
-
:http-service="(co as any).paymentMethods.methods.value.length ? undefined : undefined"
|
|
92
|
+
v-model="co.selectedPaymentGateway.value"
|
|
95
93
|
:context="paymentContext ?? 'checkout'"
|
|
96
94
|
/>
|
|
97
95
|
</div>
|
|
98
96
|
|
|
99
|
-
<!-- Pix QR Code (shown after checkout if Pix) -->
|
|
100
|
-
<div v-if="co.checkoutResponse.value?.payment_type === 'pix'" class="mg-checkout-sidebar__section">
|
|
101
|
-
<MgPixQRCode
|
|
102
|
-
:qr-code="co.checkoutResponse.value.pix_data!.qr_code"
|
|
103
|
-
:qr-code-base64="co.checkoutResponse.value.pix_data!.qr_code_base64"
|
|
104
|
-
:expires-at="co.checkoutResponse.value.pix_data!.expires_at"
|
|
105
|
-
@paid="emit('checkout-complete', co.checkoutResponse.value)"
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
97
|
<!-- Terms & Checkout Button -->
|
|
110
|
-
<div v-if="co.hasItems.value
|
|
98
|
+
<div v-if="co.hasItems.value" class="mg-checkout-sidebar__section mg-checkout-sidebar__actions">
|
|
111
99
|
<label class="terms-check">
|
|
112
|
-
<input
|
|
113
|
-
type="checkbox"
|
|
114
|
-
v-model="co.termsAccepted.value"
|
|
115
|
-
/>
|
|
100
|
+
<input type="checkbox" v-model="co.termUseAccepted.value" />
|
|
116
101
|
<span>
|
|
117
102
|
{{ $t?.("checkout.terms.accept") ?? "I accept the" }}
|
|
118
103
|
<a v-if="termsUrl" :href="termsUrl" target="_blank" class="terms-link">
|
|
@@ -124,10 +109,10 @@ async function handleCheckout() {
|
|
|
124
109
|
|
|
125
110
|
<button
|
|
126
111
|
class="checkout-btn"
|
|
127
|
-
:disabled="!co.hasItems.value || !co.
|
|
112
|
+
:disabled="!co.hasItems.value || !co.termUseAccepted.value || co.loading.value"
|
|
128
113
|
@click="handleCheckout"
|
|
129
114
|
>
|
|
130
|
-
<span v-if="co.
|
|
115
|
+
<span v-if="co.loading.value" class="spinner"></span>
|
|
131
116
|
<template v-else>
|
|
132
117
|
{{ $t?.("checkout.sidebar.buy") ?? "Complete Purchase" }}
|
|
133
118
|
</template>
|
|
@@ -154,7 +139,6 @@ async function handleCheckout() {
|
|
|
154
139
|
padding: 16px;
|
|
155
140
|
background: var(--body-bg-card, #fff);
|
|
156
141
|
border: 1px solid var(--inactive, #f3f4f6);
|
|
157
|
-
border-radius: 8px;
|
|
158
142
|
}
|
|
159
143
|
|
|
160
144
|
&__actions {
|
|
@@ -198,7 +182,6 @@ async function handleCheckout() {
|
|
|
198
182
|
width: 100%;
|
|
199
183
|
height: 48px;
|
|
200
184
|
border: none;
|
|
201
|
-
border-radius: 8px;
|
|
202
185
|
background: #4f46e5;
|
|
203
186
|
color: #fff;
|
|
204
187
|
font-size: 15px;
|
|
@@ -18,6 +18,14 @@ const props = defineProps<{
|
|
|
18
18
|
disabled?: boolean;
|
|
19
19
|
/** If true, the component manages its own state via injectMgCheckout */
|
|
20
20
|
autoWire?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When true, coupons are not available for this flow (e.g. subscriptions —
|
|
23
|
+
* the backend does not apply coupon discounts to plans yet). Shows the input
|
|
24
|
+
* disabled with an informational notice instead of accepting a code.
|
|
25
|
+
*/
|
|
26
|
+
unavailable?: boolean;
|
|
27
|
+
/** Override the default "coupons unavailable" notice text. */
|
|
28
|
+
unavailableText?: string;
|
|
21
29
|
}>();
|
|
22
30
|
|
|
23
31
|
const emit = defineEmits<{
|
|
@@ -41,7 +49,7 @@ const isLoading = computed(() =>
|
|
|
41
49
|
const couponError = computed(() =>
|
|
42
50
|
props.autoWire ? checkout?.couponError.value : (props.error ?? _localError.value)
|
|
43
51
|
);
|
|
44
|
-
const isDisabled = computed(() => props.disabled || isLoading.value);
|
|
52
|
+
const isDisabled = computed(() => props.disabled || props.unavailable || isLoading.value);
|
|
45
53
|
|
|
46
54
|
async function handleApply() {
|
|
47
55
|
const code = couponInput.value.trim().toUpperCase();
|
|
@@ -112,6 +120,11 @@ watch(
|
|
|
112
120
|
</button>
|
|
113
121
|
</div>
|
|
114
122
|
|
|
123
|
+
<!-- Unavailable notice (e.g. subscriptions: backend doesn't apply coupons yet) -->
|
|
124
|
+
<p v-if="unavailable" class="mg-coupon__notice">
|
|
125
|
+
{{ unavailableText ?? $t?.('checkout.coupon.unavailable_subscription') ?? 'Coupons are not available for subscriptions yet.' }}
|
|
126
|
+
</p>
|
|
127
|
+
|
|
115
128
|
<p v-if="couponError" class="mg-coupon__error">{{ couponError }}</p>
|
|
116
129
|
</div>
|
|
117
130
|
</template>
|
|
@@ -196,6 +209,13 @@ watch(
|
|
|
196
209
|
margin-top: 4px;
|
|
197
210
|
}
|
|
198
211
|
|
|
212
|
+
&__notice {
|
|
213
|
+
color: var(--secondary-info-fg, #9ca3af);
|
|
214
|
+
font-size: 12px;
|
|
215
|
+
margin-top: 6px;
|
|
216
|
+
font-style: italic;
|
|
217
|
+
}
|
|
218
|
+
|
|
199
219
|
&__spinner {
|
|
200
220
|
display: inline-block;
|
|
201
221
|
width: 14px;
|
|
@@ -41,7 +41,6 @@ function handleInput(e: Event) {
|
|
|
41
41
|
width: 100%;
|
|
42
42
|
padding: 16px;
|
|
43
43
|
border: 1px solid #f59e0b;
|
|
44
|
-
border-radius: 8px;
|
|
45
44
|
background: rgba(245, 158, 11, 0.05);
|
|
46
45
|
|
|
47
46
|
&__info {
|
|
@@ -76,7 +75,6 @@ function handleInput(e: Event) {
|
|
|
76
75
|
width: 100%;
|
|
77
76
|
padding: 10px 12px;
|
|
78
77
|
border: 1px solid var(--inactive, #d1d5db);
|
|
79
|
-
border-radius: 6px;
|
|
80
78
|
font-size: 14px;
|
|
81
79
|
background: var(--body-bg-card, #fff);
|
|
82
80
|
color: var(--active, #111827);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { onMounted, watch } from "vue";
|
|
3
3
|
import { usePaymentMethods } from "../../composables/usePaymentMethods";
|
|
4
|
+
import MgPaymentMethods from "../ui/MgPaymentMethods.vue";
|
|
4
5
|
import type { AxiosInstance } from "axios";
|
|
5
6
|
|
|
6
7
|
const props = defineProps<{
|
|
7
|
-
|
|
8
|
+
// Optional now — gateways are fixed (PayPal/Stripe), no HTTP fetch needed.
|
|
9
|
+
httpService?: AxiosInstance;
|
|
8
10
|
context?: "checkout" | "subscription";
|
|
9
11
|
modelValue?: string;
|
|
12
|
+
theme?: string;
|
|
10
13
|
}>();
|
|
11
14
|
|
|
12
15
|
const emit = defineEmits<{
|
|
@@ -38,28 +41,31 @@ watch(selectedMethod, (val) => {
|
|
|
38
41
|
emit("update:modelValue", val);
|
|
39
42
|
});
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
// Resolve the canonical gateway key (paypal|stripe) from a method.
|
|
45
|
+
// `name` is translatable on the backend, so fall back to the canonical id
|
|
46
|
+
// (PayPal = 2, Stripe = 3) when the name doesn't match.
|
|
47
|
+
function gatewayKey(m: { id: number; name: string }): string {
|
|
48
|
+
const n = (m.name ?? "").trim().toLowerCase();
|
|
49
|
+
if (n === "paypal" || m.id === 2) return "paypal";
|
|
50
|
+
if (n === "stripe" || m.id === 3) return "stripe";
|
|
51
|
+
return n;
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
const logos: Record<string, string> = {
|
|
48
|
-
paypal: "/imgs/payments/paypal.svg",
|
|
49
|
-
stripe: "/imgs/payments/stripe.svg",
|
|
50
|
-
mercadopago: "/imgs/payments/pix.svg",
|
|
51
|
-
};
|
|
52
|
-
return logos[key] ?? "/imgs/payments/default.svg";
|
|
54
|
+
function select(m: { id: number; name: string }) {
|
|
55
|
+
selectedMethod.value = gatewayKey(m);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
// Canonical numeric ids consumed by <MgPaymentMethods> inline SVG logos.
|
|
59
|
+
function getMethodId(m: { id: number; name: string }): number {
|
|
60
|
+
const key = gatewayKey(m);
|
|
61
|
+
if (key === "paypal") return 2;
|
|
62
|
+
if (key === "stripe") return 3;
|
|
63
|
+
return m.id;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getLabel(m: { id: number; name: string }): string {
|
|
67
|
+
const labels: Record<string, string> = { paypal: "PayPal", stripe: "Stripe" };
|
|
68
|
+
return labels[gatewayKey(m)] ?? m.name;
|
|
63
69
|
}
|
|
64
70
|
</script>
|
|
65
71
|
|
|
@@ -79,15 +85,13 @@ function getLabel(name: string): string {
|
|
|
79
85
|
:key="method.id"
|
|
80
86
|
type="button"
|
|
81
87
|
class="mg-payment-method"
|
|
82
|
-
:class="{ 'mg-payment-method--active': selectedMethod === method
|
|
83
|
-
@click="select(method
|
|
88
|
+
:class="{ 'mg-payment-method--active': selectedMethod === gatewayKey(method) }"
|
|
89
|
+
@click="select(method)"
|
|
84
90
|
>
|
|
85
|
-
<
|
|
86
|
-
:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
/>
|
|
90
|
-
<span class="mg-payment-method__label">{{ getLabel(method.name) }}</span>
|
|
91
|
+
<span class="mg-payment-method__logo">
|
|
92
|
+
<MgPaymentMethods :method="getMethodId(method)" :theme="theme" />
|
|
93
|
+
</span>
|
|
94
|
+
<span class="mg-payment-method__label">{{ getLabel(method) }}</span>
|
|
91
95
|
</button>
|
|
92
96
|
</div>
|
|
93
97
|
</div>
|
|
@@ -119,7 +123,6 @@ function getLabel(name: string): string {
|
|
|
119
123
|
gap: 8px;
|
|
120
124
|
padding: 12px 16px;
|
|
121
125
|
border: 2px solid var(--inactive, #e5e7eb);
|
|
122
|
-
border-radius: 8px;
|
|
123
126
|
background: transparent;
|
|
124
127
|
cursor: pointer;
|
|
125
128
|
transition: all 0.2s ease;
|
|
@@ -151,7 +154,6 @@ function getLabel(name: string): string {
|
|
|
151
154
|
|
|
152
155
|
.skeleton-block {
|
|
153
156
|
background: var(--inactive, #e5e7eb);
|
|
154
|
-
border-radius: 8px;
|
|
155
157
|
animation: pulse 1.5s ease-in-out infinite;
|
|
156
158
|
}
|
|
157
159
|
|
|
@@ -143,7 +143,6 @@ onUnmounted(() => {
|
|
|
143
143
|
align-items: center;
|
|
144
144
|
padding: 24px;
|
|
145
145
|
border: 1px solid var(--inactive, #e5e7eb);
|
|
146
|
-
border-radius: 12px;
|
|
147
146
|
background: var(--body-bg-card, #fff);
|
|
148
147
|
|
|
149
148
|
&__header {
|
|
@@ -191,7 +190,6 @@ onUnmounted(() => {
|
|
|
191
190
|
gap: 8px;
|
|
192
191
|
padding: 10px 20px;
|
|
193
192
|
border: 1px solid #4f46e5;
|
|
194
|
-
border-radius: 8px;
|
|
195
193
|
background: transparent;
|
|
196
194
|
color: #4f46e5;
|
|
197
195
|
font-size: 14px;
|
|
@@ -6,56 +6,43 @@ export interface PaymentMethod {
|
|
|
6
6
|
name: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Payment gateways shown in the checkout UI.
|
|
11
|
+
*
|
|
12
|
+
* These are FIXED to PayPal + Stripe — the only gateways live across the
|
|
13
|
+
* ecosystem. We do NOT read the `payment_methods` table: that table holds
|
|
14
|
+
* generic legacy methods (Cash, Credit Card, Transfer, Bitcoin...) and has no
|
|
15
|
+
* notion of PayPal/Stripe.
|
|
16
|
+
*
|
|
17
|
+
* The actual gateway *account* (which api_credential to charge) is resolved by
|
|
18
|
+
* the backend at checkout time, honouring the existing active / default /
|
|
19
|
+
* production flags on `api_credentials`. That lets admins switch accounts
|
|
20
|
+
* without any frontend change. The frontend only sends
|
|
21
|
+
* `payment_gateway: 'paypal' | 'stripe'`.
|
|
22
|
+
*
|
|
23
|
+
* The numeric `id` here (PayPal = 2, Stripe = 3) is the convention used by
|
|
24
|
+
* <MgPaymentMethods> to pick which inline SVG logo to render. It is unrelated
|
|
25
|
+
* to the payment_methods table ids and to api ids (PayPal = 4, Stripe = 5).
|
|
26
|
+
*/
|
|
27
|
+
const GATEWAYS: PaymentMethod[] = [
|
|
28
|
+
{ id: 2, name: "paypal" },
|
|
29
|
+
{ id: 3, name: "stripe" },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
export function usePaymentMethods(_httpService?: AxiosInstance) {
|
|
33
|
+
const methods = ref<PaymentMethod[]>([...GATEWAYS]);
|
|
11
34
|
const selectedMethod = ref<string>("");
|
|
12
35
|
const loading = ref(false);
|
|
13
36
|
const error = ref<string | null>(null);
|
|
14
37
|
|
|
15
|
-
async
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
loading.value = true;
|
|
19
|
-
error.value = null;
|
|
20
|
-
try {
|
|
21
|
-
const endpoint =
|
|
22
|
-
context === "subscription"
|
|
23
|
-
? "/payment-methods/subscriptions"
|
|
24
|
-
: "/payment-methods";
|
|
25
|
-
const res = await httpService.get(endpoint);
|
|
26
|
-
methods.value = res.data?.data ?? [];
|
|
27
|
-
|
|
28
|
-
// Auto-select if only one method available
|
|
29
|
-
if (methods.value.length === 1) {
|
|
30
|
-
selectedMethod.value = methods.value[0].name.toLowerCase();
|
|
31
|
-
}
|
|
32
|
-
} catch (e: any) {
|
|
33
|
-
// Fallback: if endpoint doesn't exist yet (404), provide default methods
|
|
34
|
-
console.warn("[usePaymentMethods] Endpoint not available, using fallback:", e?.response?.status);
|
|
35
|
-
methods.value = [
|
|
36
|
-
{ id: 0, name: "paypal" },
|
|
37
|
-
{ id: 1, name: "Stripe" },
|
|
38
|
-
];
|
|
39
|
-
if (methods.value.length > 0 && !selectedMethod.value) {
|
|
40
|
-
selectedMethod.value = methods.value[0].name.toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
error.value = null;
|
|
43
|
-
} finally {
|
|
44
|
-
loading.value = false;
|
|
45
|
-
}
|
|
38
|
+
// No HTTP call. Kept async + the context arg for call-site compatibility.
|
|
39
|
+
async function fetchMethods(_context: "checkout" | "subscription" = "checkout") {
|
|
40
|
+
methods.value = [...GATEWAYS];
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const isStripe = computed(
|
|
53
|
-
() => selectedMethod.value.toLowerCase() === "stripe"
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const isPaypal = computed(
|
|
57
|
-
() => selectedMethod.value.toLowerCase() === "paypal"
|
|
58
|
-
);
|
|
43
|
+
const isStripe = computed(() => selectedMethod.value.toLowerCase() === "stripe");
|
|
44
|
+
const isPaypal = computed(() => selectedMethod.value.toLowerCase() === "paypal");
|
|
45
|
+
const isPix = computed(() => false); // Pix not enabled yet
|
|
59
46
|
|
|
60
47
|
function selectMethod(name: string) {
|
|
61
48
|
selectedMethod.value = name.toLowerCase();
|