@12-apps/payments-frontend 3.39.0 → 3.41.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/package.json +2 -2
- package/src/activation/use-redirect-activation.ts +22 -1
- package/src/components/PaymentProviderSettings.tsx +13 -0
- package/src/components/checkout/list/bank-apps.ts +113 -0
- package/src/components/checkout/list/bank-en-US.ts +26 -0
- package/src/components/checkout/list/bank-logos.tsx +35 -0
- package/src/components/checkout/list/bank-pt-BR.ts +26 -0
- package/src/components/checkout/list/choice.ts +8 -3
- package/src/components/checkout/list/context.tsx +27 -3
- package/src/components/checkout/list/list-face.tsx +55 -15
- package/src/components/checkout/list/list-memory.ts +96 -0
- package/src/components/checkout/list/list-pix.tsx +151 -15
- package/src/components/checkout/list/payment-list-step.tsx +1 -0
- package/src/components/checkout/list/pix-banks.tsx +178 -0
- package/src/components/checkout/list/types.ts +91 -0
- package/src/components/checkout/list/use-list-state.ts +6 -3
- package/src/components/checkout/pix-after-copy.tsx +8 -2
- package/src/components/checkout/pix-parts.tsx +56 -0
- package/src/components/checkout/pix-view.tsx +2 -0
- package/src/components/settings-live.ts +66 -0
- package/src/flows/create-payments-settings.tsx +6 -2
- package/src/index.ts +2 -2
- package/src/locales.ts +12 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.41.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Browser half of the vendor-agnostic payments platform: plug-and-play MUI components for the per-provider settings page (credential form from each provider's schema, masked hints, verify/enable) and the checkout page (PIX QR + polling, card tokenization, hosted-checkout redirect), plus the headless hooks and fetch clients they build on. Talks only to the host's payments HTTP surface — never to a provider directly. Microfrontend-ready: no app coupling, host injects theme and auth.",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"storybook:build": "storybook build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@12-apps/payments-backend": "^4.
|
|
26
|
+
"@12-apps/payments-backend": "^4.31.0",
|
|
27
27
|
"react-qr-code": "^2.2.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -53,7 +53,10 @@ import { clearReturnedSettlement, takeReturnedSettlement } from './returned-sett
|
|
|
53
53
|
* things that clear it are settlement and an explicit "give up".
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* How often to ask the provider whether the payment landed — the recorded
|
|
58
|
+
* third-party-wait exception, see {@link usePollTimer}.
|
|
59
|
+
*/
|
|
57
60
|
const DEFAULT_POLL_MS = 4000;
|
|
58
61
|
|
|
59
62
|
/** Give up asking after this long, rather than polling a tab forever. */
|
|
@@ -126,6 +129,24 @@ interface ActivationCallbacks {
|
|
|
126
129
|
/**
|
|
127
130
|
* Ask the provider every few seconds, and stop asking eventually.
|
|
128
131
|
*
|
|
132
|
+
* ## A deliberate poll: the recorded exception to "hear, do not poll" (FUT-2433)
|
|
133
|
+
*
|
|
134
|
+
* Every other wait in this package hears the host's channel and keeps no timer
|
|
135
|
+
* while it is live. This one cannot, and it is the one exception class the
|
|
136
|
+
* origin host records: a timer-driven read of a THIRD PARTY's state that no
|
|
137
|
+
* webhook or publisher of the host's reaches yet, bounded in time, and named.
|
|
138
|
+
* Each tick is not a read of the host's own rows — `verify-charge` asks the
|
|
139
|
+
* PROVIDER whether the activation charge was paid, and while nobody has asked,
|
|
140
|
+
* nothing server-side has moved that a hint could carry. The activation webhook
|
|
141
|
+
* that would settle it is not guaranteed to arrive (a tunnel, a preview box), so
|
|
142
|
+
* the wait is the confirmation. It runs only while the owner is paying on the
|
|
143
|
+
* provider's page and gives up at `pollTimeoutMs` (ten minutes by default).
|
|
144
|
+
*
|
|
145
|
+
* Where it is recorded: the origin host's realtime doc ("Allowed exceptions")
|
|
146
|
+
* and the decision record that superseded its 0071 with it. If activation
|
|
147
|
+
* ever becomes webhook-only, this relaxes to the channel exactly as the
|
|
148
|
+
* checkout's waits did (FUT-649) and the exception goes away.
|
|
149
|
+
*
|
|
129
150
|
* The give-up is a `failed` state carrying the host's own sentence, because the
|
|
130
151
|
* wording is load-bearing: the charge is STILL valid, and an owner who has
|
|
131
152
|
* genuinely paid must not be told they did not pay in time.
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
type ProviderChangeHandler,
|
|
22
22
|
} from './settings-state';
|
|
23
23
|
import { openSection, SetupGuideSection } from './SetupGuideSection';
|
|
24
|
+
import { useSettingsLive, type PaymentsSettingsLiveSignal } from './settings-live';
|
|
24
25
|
import type { PaymentsSettingsCopy } from './settings-copy';
|
|
25
26
|
import { PaymentsSettingsCopyProvider } from './settings-copy-context';
|
|
26
27
|
|
|
@@ -102,6 +103,16 @@ export interface PaymentProviderSettingsProps {
|
|
|
102
103
|
* its history ({@link ProviderChangeHandler}).
|
|
103
104
|
*/
|
|
104
105
|
onProviderChange?: ProviderChangeHandler;
|
|
106
|
+
/**
|
|
107
|
+
* The host's realtime channel for this store's payment settings (FUT-648).
|
|
108
|
+
*
|
|
109
|
+
* A hint re-reads the view, and so does every (re)connect: an OAuth grant
|
|
110
|
+
* completed in another tab, a colleague's save, a webhook settling the
|
|
111
|
+
* activation charge all reach this screen without a reload. Omit it and the
|
|
112
|
+
* screen reads on mount and after its own actions, exactly as before — it
|
|
113
|
+
* keeps no timer either way. See {@link PaymentsSettingsLiveSignal}.
|
|
114
|
+
*/
|
|
115
|
+
live?: PaymentsSettingsLiveSignal;
|
|
105
116
|
/**
|
|
106
117
|
* The activation step, rendered under the connection card.
|
|
107
118
|
*
|
|
@@ -299,8 +310,10 @@ export function PaymentProviderSettings({
|
|
|
299
310
|
selectedProvider,
|
|
300
311
|
onProviderChange,
|
|
301
312
|
renderVerification,
|
|
313
|
+
live,
|
|
302
314
|
}: PaymentProviderSettingsProps) {
|
|
303
315
|
const { view, error, reload } = useSettingsState(client);
|
|
316
|
+
useSettingsLive(live, () => void reload());
|
|
304
317
|
const { selected, setSelected } = useSelectedProvider(
|
|
305
318
|
initialProvider,
|
|
306
319
|
selectedProvider,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opening the buyer's bank app from the Pix face (FUT-3612).
|
|
3
|
+
*
|
|
4
|
+
* There is no standard Pix link that pays a copia-e-cola code, so this only
|
|
5
|
+
* OPENS the app; the buyer pastes the code the button already copied. Android
|
|
6
|
+
* opens an app through an `intent:` URL naming its package; iOS only through a
|
|
7
|
+
* URL scheme the bank's app registers. Neither tells the page whether it
|
|
8
|
+
* worked, so {@link openBankApp} watches the page: an app that opened takes
|
|
9
|
+
* the screen within a moment, and a page still visible after
|
|
10
|
+
* {@link OPEN_WAIT_MS} is a bank that did not open — not installed, or a link
|
|
11
|
+
* this phone does not know.
|
|
12
|
+
*/
|
|
13
|
+
import type { PixBankId } from "./types";
|
|
14
|
+
|
|
15
|
+
/** How long a page may stay visible before the bank counts as not opened. */
|
|
16
|
+
const OPEN_WAIT_MS = 1500;
|
|
17
|
+
|
|
18
|
+
interface BankApp {
|
|
19
|
+
/** The Play Store package of the bank's personal app — each one checked on its Play listing (2026-10-16). */
|
|
20
|
+
android: string;
|
|
21
|
+
/**
|
|
22
|
+
* The URL scheme its app answers on iOS (without "://"). Only Nubank's
|
|
23
|
+
* (`nuapp`) is documented — in Nubank's own deep links. The other five
|
|
24
|
+
* publish no scheme we could find: theirs are the likeliest name, and a
|
|
25
|
+
* phone that does not know one is a bank that "did not open", which the face
|
|
26
|
+
* says (owner, 2026-10-16: Android and iOS, and say so when it does not open).
|
|
27
|
+
*/
|
|
28
|
+
ios: string;
|
|
29
|
+
/** A scheme Android opens the app with, when one is known; else the app's launcher, by package. */
|
|
30
|
+
scheme?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The six, in the prototype's order. */
|
|
34
|
+
export const PIX_BANKS: readonly PixBankId[] = ["nubank", "itau", "bradesco", "bb", "caixa", "santander"];
|
|
35
|
+
|
|
36
|
+
const APPS: Record<PixBankId, BankApp> = {
|
|
37
|
+
nubank: { android: "com.nu.production", ios: "nuapp", scheme: "nuapp" },
|
|
38
|
+
itau: { android: "com.itau", ios: "itau" },
|
|
39
|
+
bradesco: { android: "com.bradesco", ios: "bradesco" },
|
|
40
|
+
bb: { android: "br.com.bb.android", ios: "bbapp" },
|
|
41
|
+
caixa: { android: "br.gov.caixa.CAIXA", ios: "caixa" },
|
|
42
|
+
santander: { android: "com.santander.app", ios: "santanderpf" },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type PhoneOs = "android" | "ios";
|
|
46
|
+
|
|
47
|
+
/** The phone this page runs on, or `null` for a computer (or no browser at all). */
|
|
48
|
+
export function phoneOs(nav: Pick<Navigator, "userAgent" | "maxTouchPoints"> | undefined = typeof navigator === "undefined" ? undefined : navigator): PhoneOs | null {
|
|
49
|
+
if (!nav) return null;
|
|
50
|
+
const ua = nav.userAgent;
|
|
51
|
+
if (/Android/i.test(ua)) return "android";
|
|
52
|
+
if (/iPhone|iPad|iPod/i.test(ua)) return "ios";
|
|
53
|
+
// iPadOS asks for the desktop site: a "Macintosh" with a touch screen.
|
|
54
|
+
if (/Macintosh/i.test(ua) && nav.maxTouchPoints > 1) return "ios";
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The phone the host's bank flow runs on: its own word when it gave one
|
|
60
|
+
* (`phone`), else the browser's. `null` ⇒ a computer: no banks.
|
|
61
|
+
*/
|
|
62
|
+
export function bankFlowOs(phone: boolean | undefined): PhoneOs | null {
|
|
63
|
+
if (phone === false) return null;
|
|
64
|
+
if (phone === true) return phoneOs() ?? "android";
|
|
65
|
+
return phoneOs();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The URL that opens `bank`'s app on `os`. Android: an `intent:` URL naming the
|
|
70
|
+
* package — through the app's scheme when one is known, else its launcher; a
|
|
71
|
+
* phone without the app gets the bank's Play Store page from the browser.
|
|
72
|
+
*/
|
|
73
|
+
export function bankAppUrl(bank: PixBankId, os: PhoneOs): string {
|
|
74
|
+
const app = APPS[bank];
|
|
75
|
+
if (os === "ios") return `${app.ios}://`;
|
|
76
|
+
if (app.scheme) return `intent://#Intent;scheme=${app.scheme};package=${app.android};end`;
|
|
77
|
+
return `intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=${app.android};end`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Open `bank`'s app, and say whether it opened: `true` when the page lost the
|
|
82
|
+
* screen (hidden, or left) within {@link OPEN_WAIT_MS}.
|
|
83
|
+
*/
|
|
84
|
+
export function openBankApp(
|
|
85
|
+
bank: PixBankId,
|
|
86
|
+
os: PhoneOs,
|
|
87
|
+
env: { win: Window; doc: Document; waitMs?: number } = { win: window, doc: document },
|
|
88
|
+
): Promise<boolean> {
|
|
89
|
+
const { win, doc } = env;
|
|
90
|
+
return new Promise((resolve) => {
|
|
91
|
+
let left = false;
|
|
92
|
+
const onVisibility = (): void => {
|
|
93
|
+
if (doc.visibilityState === "hidden") left = true;
|
|
94
|
+
};
|
|
95
|
+
const onLeave = (): void => {
|
|
96
|
+
left = true;
|
|
97
|
+
};
|
|
98
|
+
doc.addEventListener("visibilitychange", onVisibility);
|
|
99
|
+
win.addEventListener("pagehide", onLeave);
|
|
100
|
+
win.addEventListener("blur", onLeave);
|
|
101
|
+
win.setTimeout(() => {
|
|
102
|
+
doc.removeEventListener("visibilitychange", onVisibility);
|
|
103
|
+
win.removeEventListener("pagehide", onLeave);
|
|
104
|
+
win.removeEventListener("blur", onLeave);
|
|
105
|
+
resolve(left);
|
|
106
|
+
}, env.waitMs ?? OPEN_WAIT_MS);
|
|
107
|
+
try {
|
|
108
|
+
win.location.href = bankAppUrl(bank, os);
|
|
109
|
+
} catch {
|
|
110
|
+
// A scheme the browser refuses outright is a bank that did not open.
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PixBankCopy } from "./types";
|
|
2
|
+
|
|
3
|
+
/** The Pix-to-bank flow's words, en-US (FUT-3612). */
|
|
4
|
+
export const EN_US_PIX_BANK_COPY: PixBankCopy = {
|
|
5
|
+
names: {
|
|
6
|
+
nubank: { name: "Nubank", the: "" },
|
|
7
|
+
itau: { name: "Itaú", the: "" },
|
|
8
|
+
bradesco: { name: "Bradesco", the: "" },
|
|
9
|
+
bb: { name: "Banco do Brasil", the: "" },
|
|
10
|
+
caixa: { name: "Caixa", the: "" },
|
|
11
|
+
santander: { name: "Santander", the: "" },
|
|
12
|
+
},
|
|
13
|
+
generateAndCopy: "Create and copy the Pix",
|
|
14
|
+
generateCopyAndOpen: (bank) => `Create, copy and open ${bank.name}`,
|
|
15
|
+
copyAndOpen: (bank) => `Copy and open ${bank.name}`,
|
|
16
|
+
openOther: "Open another bank",
|
|
17
|
+
listTitle: "Open your bank and paste in Pix copia e cola",
|
|
18
|
+
open: (bank) => `Open ${bank.name}`,
|
|
19
|
+
opening: (bank) => `Opening **${bank.name}**…`,
|
|
20
|
+
other: "Another bank",
|
|
21
|
+
notOpened: (bank) => `We couldn't open ${bank.name}. Is the app installed on this phone?`,
|
|
22
|
+
retry: "Try again",
|
|
23
|
+
copied: "Pix code copied",
|
|
24
|
+
copiedPick: "Pix code copied. Choose your bank.",
|
|
25
|
+
copiedOpening: (bank) => `Pix code copied. Opening ${bank.name}…`,
|
|
26
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Box } from "@mui/material";
|
|
2
|
+
import type { JSX } from "react";
|
|
3
|
+
|
|
4
|
+
import type { PixBankId } from "./types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The six banks' own marks (FUT-3612, owner 2026-10-15: "coloca as logos dos
|
|
8
|
+
* bancos"), drawn at 32px beside each name so a buyer finds their bank by its
|
|
9
|
+
* mark. Inline as data URIs — no remote asset (ADR 0074's sibling rule, §5.1
|
|
10
|
+
* item 5) — and only to identify the bank. Sources: Nubank and Itaú from
|
|
11
|
+
* Wikimedia Commons (PD-textlogo, trademarked); Bradesco, Banco do Brasil,
|
|
12
|
+
* Caixa and Santander from the Bancos-em-SVG collection (the banks' symbols).
|
|
13
|
+
* Each is the bank's trademark.
|
|
14
|
+
*/
|
|
15
|
+
const LOGOS: Record<PixBankId, string> = {
|
|
16
|
+
nubank: "data:image/svg+xml;base64,PHN2ZyB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIiB2aWV3Qm94PSIwIDAgMjYzLjg0MjA3IDE0NS41NjczNyIgdmVyc2lvbj0iMS4xIiBpZD0ic3ZnNiIgc29kaXBvZGk6ZG9jbmFtZT0iTnViYW5rIGxvZ28gMjAyMS5zdmciIHdpZHRoPSIyNjMuODQyMDciIGhlaWdodD0iMTQ1LjU2NzM3IiBpbmtzY2FwZTpleHBvcnQtZmlsZW5hbWU9IkM6XFVzZXJzXGFsZXhcc2l0ZXNcbnViYW5rLWxvZ28tMC5wbmciIGlua3NjYXBlOmV4cG9ydC14ZHBpPSI1NjEuNzM3MTIiIGlua3NjYXBlOmV4cG9ydC15ZHBpPSI1NjEuNzM3MTIiIGlua3NjYXBlOnZlcnNpb249IjEuMC4yIChlODZjODcwODc5LCAyMDIxLTAxLTE1LCBjdXN0b20pIj4gPG1ldGFkYXRhIGlkPSJtZXRhZGF0YTEyIj4gPHJkZjpSREY+IDxjYzpXb3JrIHJkZjphYm91dD0iIj4gPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+IDxkYzp0eXBlIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+IDxkYzp0aXRsZT48L2RjOnRpdGxlPiA8L2NjOldvcms+IDwvcmRmOlJERj4gPC9tZXRhZGF0YT4gPGRlZnMgaWQ9ImRlZnMxMCIgLz4gPHNvZGlwb2RpOm5hbWVkdmlldyBwYWdlY29sb3I9IiNmZmZmZmYiIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiBib3JkZXJvcGFjaXR5PSIxIiBvYmplY3R0b2xlcmFuY2U9IjEwIiBncmlkdG9sZXJhbmNlPSIxMCIgZ3VpZGV0b2xlcmFuY2U9IjEwIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxMzY2IiBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI3MDUiIGlkPSJuYW1lZHZpZXc4IiBzaG93Z3JpZD0iZmFsc2UiIGlua3NjYXBlOnpvb209IjAuMjE0NTk3NTkiIGlua3NjYXBlOmN4PSIyMDguODkzNiIgaW5rc2NhcGU6Y3k9IjEyOC41MTMxNSIgaW5rc2NhcGU6d2luZG93LXg9Ii04IiBpbmtzY2FwZTp3aW5kb3cteT0iLTgiIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzYiIGlua3NjYXBlOmRvY3VtZW50LXJvdGF0aW9uPSIwIiBmaXQtbWFyZ2luLXRvcD0iMCIgZml0LW1hcmdpbi1sZWZ0PSIwIiBmaXQtbWFyZ2luLXJpZ2h0PSIwIiBmaXQtbWFyZ2luLWJvdHRvbT0iMCIgLz4gPHBhdGggZD0iTSA0Ny42Mjc1OTgsMTMuODg1NjUgQyA1NS45NzA5MTgsNS4xMjAyMiA2Ny4wMzgxODgsMCA4MC4wNDAxNTgsMCBjIDI1LjMyOTMwMiwwIDQyLjEyMjg2MiwxOC40OTM2MSA0NS4zMzU4MTIsNDYuMTk4MzEgMS4wNDE3Myw4Ljk5NzAyIDEuMDMyMTcsMjEuNjgxNDYgMS4wMjE3MiwzNi4zNzMzOCAtMC4wMDIsMS41MDY2MiAtMC4wMDIsMy4wMzQ2NCAtMC4wMDIsNC41ODE3NSB2IDU1LjAzODM5IEggOTEuNTYzMDY4IHYgLTQwLjcwODEyIGMgMCwwIC0wLjA3MSwtMzQuODQwMzYgLTAuMjgzODYsLTQxLjM1MTggLTAuOTM0ODIsLTI4LjM1OTQ1IC0xNy43MjM4MywtNDYuMTc5MTEgLTQzLjY1NDk3LC00Ni4xOTgyNiAtNy44MjM2LDguMjY1NzcgLTEyLjAxNTU5LDE4LjM3MjEgLTEyLjYzMzgxLDMzLjgyNDk4IC0wLjA4NSwyLjE1NTMxIC0wLjA2MzYsOS43OTQ5MSAtMC4wMzU0LDE5Ljg2MzY3IDAuMDE0Niw1LjIxNjggMC4wMzEsMTEuMDg1OTIgMC4wMzU0LDE3LjE4MjA0IDAuMDI1OCwyNi41MzM4OCAwLDU3LjM5MzQxIDAsNTcuMzkzNDEgSCAwLjE1NzcwMTQ1IFYgNzkuNTQ4NDIgYyAwLC0yLjE0NjY4IC0wLjAzOTE1LC00LjMxMTU1IC0wLjA3ODM5LC02LjQ4NTA2IC0wLjA3ODk5OTk5NzEsLTQuMzcyMDUgLTAuMTU4NjI2LC04Ljc3Nzc1IDAuMDc4MzksLTEzLjE0MDI1IEMgMC41NTEyNTI0NSw1Mi42NTA2MiAxLjgwOTMyMjUsNDUuNTAxNCA1LjIwMjg2ODUsMzguODU5OTUgMTIuOTcwNjU4LDIzLjY0NDgxIDI4Ljg4Njg4OCwxMy44NDgzNSA0NS44NTQ4NDgsMTMuODQ4MzUgYyAwLjU5Mjc0LDAgMS4xODU5MywwLjAxMzcgMS43NzI3NSwwLjAzNjQgeiIgY2xhc3M9IlBhdGgteHJ0a3BkLTAgZXFmWWlSIiBpZD0icGF0aDIiIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiIHN0eWxlPSJmaWxsOiM4MjBhZDE7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlLXdpZHRoOjQuNTQ5IiBpbmtzY2FwZTpleHBvcnQtZmlsZW5hbWU9IkM6XFVzZXJzXGFsZXhcc2l0ZXNcbnViYW5rLWxvZ28tNS5wbmciIGlua3NjYXBlOmV4cG9ydC14ZHBpPSIxMzIuNzY1MzgiIGlua3NjYXBlOmV4cG9ydC15ZHBpPSIxMzIuNzY1MzgiIC8+IDxwYXRoIGQ9Im0gMjYzLjY4NDMzLDg1LjY0NDk5IGMgMC4yMzcsLTQuMzYyNDkgMC4xNTczOSwtOC43Njg2NiAwLjA3ODcsLTEzLjE0MDI1IC0wLjAzOTYsLTIuMTczNTEgLTAuMDc4NywtNC4zMzgzOCAtMC4wNzg3LC02LjQ4NTA1IFYgMy4zNzAyMiBoIC0zNC44MzIxOCBjIDAsMCAtMC4wMjYsMzAuODU5NTMgMCw1Ny4zOTMwOSAwLjAwNCw2LjA5NjEyIDAuMDIwNSwxMS45NjQ3OSAwLjAzNSwxNy4xODE1OSAwLjAyODIsMTAuMDY5MjEgMC4wNDk2LDE3LjcwODgxIC0wLjAzNSwxOS44NjQxMyAtMC42MTgyMSwxNS40NTM0MiAtNC44MTA1NiwyNS41NTk0OCAtMTIuNjMzOTQsMzMuODI1NDggLTI1LjkzMDY5LC0wLjAxODIgLTQyLjcxOTIzLC0xNy44MzkzOCAtNDMuNjU0NTEsLTQ2LjE5ODMyIC0wLjIxMjksLTYuNTExNDQgLTAuMzAyOTcsLTIyLjY2OTk1IC0wLjMwMjk3LC00MS4zODQ1MSBWIDMuMzQzNjEgbCAtMzQuODA2NjksMC4wMzE4IHYgNTUuMDM4NTIgYyAwLDEuNTQ3MTIgLTAuMDAyLDMuMDc0NjggLTAuMDAyLDQuNTgxNzYgLTAuMDExLDE0LjY5MTkxIC0wLjAyLDI3LjM3NTkgMS4wMjE3LDM2LjM3MzM4IDMuMjA2MTUsMjcuNzA0NzkgMTkuOTk5Nyw0Ni4xOTgzIDQ1LjMyOSw0Ni4xOTgzIDEzLjAwMjQyLDAgMjQuMDY5NjksLTUuMTIwMzUgMzIuNDEzMDEsLTEzLjg4NTgyIDAuNTg2MzcsMC4wMjI3IDEuMTc5MTEsMC4wMzY0IDEuNzcxODQsMC4wMzY0IDE2Ljk2Nzc4LDAgMzIuODg0MjksLTkuNzk2MjggNDAuNjUyMTcsLTI1LjAxMTMzIDMuMzkzNTUsLTYuNjQyIDQuNjUxMzUsLTEzLjc5MDc2IDUuMDQ0ODQsLTIxLjA2MzI1IHoiIGNsYXNzPSJQYXRoLXhydGtwZC0wIGVxZllpUiIgaWQ9InBhdGg0IiBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIiBzdHlsZT0iZmlsbDojODIwYWQxO2ZpbGwtb3BhY2l0eToxO3N0cm9rZS13aWR0aDo0LjU0OSIgaW5rc2NhcGU6ZXhwb3J0LWZpbGVuYW1lPSJDOlxVc2Vyc1xhbGV4XHNpdGVzXG51YmFuay1sb2dvLTUucG5nIiBpbmtzY2FwZTpleHBvcnQteGRwaT0iMTMyLjc2NTM4IiBpbmtzY2FwZTpleHBvcnQteWRwaT0iMTMyLjc2NTM4IiAvPiA8cGF0aCBkPSJtIDExOC41ODczMSw3OTQuNjAwOTMgYyAxNC4xNTg0NiwtMTQuOTQ0NjQgMzIuOTM5NDIsLTIzLjY3NDM1IDU1LjAwMzc4LC0yMy42NzQzNSA0Mi45ODMzMSwwIDcxLjQ4MTY1LDMxLjUzMDY1IDc2LjkzNDAxLDc4Ljc2NTY1IDEuNzY3NzcsMTUuMzM5NSAxLjc1MTYsMzYuOTY1OCAxLjczMzg5LDYyLjAxNDcgMCwyLjU2ODggMCw1LjE3MzkgMCw3LjgxMTcgdiA5My44Mzc0NyBoIC01OS4xMTA0NCB2IC02OS40MDUxNyBjIDAsMCAtMC4xMjA1NSwtNTkuNDAwOSAtMC40ODE4NiwtNzAuNTAyNiAtMS41ODYxOCwtNDguMzUxNCAtMzAuMDc2NzgsLTc4LjczMyAtNzQuMDgxNjksLTc4Ljc2NTYgLTEzLjI3NjQyLDE0LjA5MjcgLTIwLjM5MDM3MiwzMS4zMjM0IC0yMS40Mzk0MDIsNTcuNjY5OCAtMC4xNDQxMiwzLjY3NDcgLTAuMTA3OTEsMTYuNjk5OCAtMC4wNjA2LDMzLjg2NjUgMC4wMjQ4LDguODk0NCAwLjA1MzMsMTguOTAwOSAwLjA2MDYsMjkuMjk0NSAwLjA0NSw0NS4yMzg5IDAsOTcuODUyNjcgMCw5Ny44NTI2NyBIIDM4LjAzNTA2OCBWIDkwNi41NTI0MyBjIDAsLTMuNjU5OSAtMC4wNjcsLTcuMzUwOSAtMC4xMzMsLTExLjA1NjcgLTAuMTMzOTMsLTcuNDU0MSAtMC4yNjkwMywtMTQuOTY1NiAwLjEzMywtMjIuNDAzNCAwLjY2ODAzLC0xMi4zOTkyIDIuODAyOTMsLTI0LjU4ODMgOC41NjE4LC0zNS45MTE1IDEzLjE4MTYzLC0yNS45NDExIDQwLjE5MTM0LC00Mi42NDM1IDY4Ljk4NTcyMiwtNDIuNjQzNSAxLjAwNTc3LDAgMi4wMTI0NCwwLjAyMyAzLjAwODIxLDAuMDYyIHoiIGNsYXNzPSJQYXRoLXhydGtwZC0wIGVxZllpUiIgaWQ9InBhdGgyLTYiIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiIHN0eWxlPSJmaWxsOiNmZmZmZmY7c3Ryb2tlLXdpZHRoOjcuNzM3NjgiIGlua3NjYXBlOmV4cG9ydC1maWxlbmFtZT0iQzpcVXNlcnNcYWxleFxzaXRlc1xudWJhbmstbG9nby00LnBuZyIgaW5rc2NhcGU6ZXhwb3J0LXhkcGk9IjkyLjYxODA5NSIgaW5rc2NhcGU6ZXhwb3J0LXlkcGk9IjkyLjYxODA5NSIgLz4gPHBhdGggZD0ibSA0ODUuMjMyMTcsOTE2Ljk0NjgzIGMgMC40MDIyMSwtNy40Mzc5IDAuMjY3MTQsLTE0Ljk1MDEgMC4xMzM2LC0yMi40MDM1IC0wLjA2NzIsLTMuNzA1NyAtMC4xMzM2LC03LjM5NjcgLTAuMTMzNiwtMTEuMDU2NyB2IC0xMDYuODE0IGggLTU5LjEwOTYyIGMgMCwwIC0wLjA0NDMsNTIuNjEzOSAwLDk3Ljg1MjIgMC4wMSwxMC4zOTM2IDAuMDM0NiwyMC4zOTkzIDAuMDU5MywyOS4yOTM3IDAuMDQ3OCwxNy4xNjc1IDAuMDg0MSwzMC4xOTI2IC0wLjA1OTMsMzMuODY3MyAtMS4wNDkxMSwyNi4zNDczIC04LjE2MzQzLDQzLjU3NzYgLTIxLjQzOTU5LDU3LjY3MDcgLTQ0LjAwMzk4LC0wLjAzMSAtNzIuNDkzODUsLTMwLjQxNTMgLTc0LjA4MTA1LC03OC43NjU3IC0wLjM2MTI1LC0xMS4xMDE3IC0wLjUxNDE4LC0zOC42NTExIC0wLjUxNDE4LC03MC41NTg0IHYgLTY5LjQwNTE2IGwgLTU5LjA2NjM1LDAuMDU0MSB2IDkzLjgzNzg2IGMgMCwyLjYzNzcgMCw1LjI0MjEgMCw3LjgxMTYgLTAuMDE5MiwyNS4wNDkgLTAuMDMzLDQ2LjY3NDUgMS43MzM4Nyw2Mi4wMTQ3IDUuNDQwNzEsNDcuMjM1MiAzMy45MzkwNSw3OC43NjU2NyA3Ni45MjI1NSw3OC43NjU2NyAyMi4wNjUwMSwwIDQwLjg0NTg3LC04LjcyOTkgNTUuMDA0MzYsLTIzLjY3NDU3IDAuOTk1MDgsMC4wMzkgMi4wMDA5NCwwLjA2MiAzLjAwNjc5LDAuMDYyIDI4Ljc5NDA4LDAgNTUuODA0MTIsLTE2LjcwMjEgNjguOTg2MDUsLTQyLjY0MyA1Ljc1ODg5LC0xMS4zMjQzIDcuODkzMjgsLTIzLjUxMjUgOC41NjEwNSwtMzUuOTExNyB6IiBjbGFzcz0iUGF0aC14cnRrcGQtMCBlcWZZaVIiIGlkPSJwYXRoNC01IiBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIiBzdHlsZT0iZmlsbDojZmZmZmZmO3N0cm9rZS13aWR0aDo3LjczNzY4IiBpbmtzY2FwZTpleHBvcnQtZmlsZW5hbWU9IkM6XFVzZXJzXGFsZXhcc2l0ZXNcbnViYW5rLWxvZ28tNC5wbmciIGlua3NjYXBlOmV4cG9ydC14ZHBpPSI5Mi42MTgwOTUiIGlua3NjYXBlOmV4cG9ydC15ZHBpPSI5Mi42MTgwOTUiIC8+IDwvc3ZnPg==",
|
|
17
|
+
itau: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MDAiIGhlaWdodD0iNTAwIiB2aWV3Qm94PSIwIDAgNTAwIDUwMCI+PHBhdGggZD0iTTIxOC42NzYgMTAuNTc0Yy0xMy43OTcuMzI4LTIzLjkxOC44MTMtNDIuNDczIDEuOTU3LTguNTgyLjUxMi0xNy45NSAxLjI2Ni0yNC41NDcgMS45MjYtMS42NTYuMTgtNS4xMi41MTItNy42OC43NTQtMTAuNzUzIDEuMDU1LTI2LjcxOCAzLjA3LTMzLjQzMyA0LjIxNS0xLjQxOC4yNDItMy40OTYuNTc0LTQuNjY4Ljc1NC0xLjE0NS4xNTItMy4xOTUuNTExLTQuNTIuNzU0LTEuMzI0LjI0Mi0zLjU1NC42NjQtNC45NjguOTAyLTQuOTczLjg0NC0xMy40MzQgMi41NjItMTguMjIzIDMuNzA3LTEuMzI4LjMzMi0zLjcwNy45MDItNS4yNzMgMS4yNjYtMS41NjcuMzU5LTIuOTguNjkxLTMuMTYuNzIyLTguODI5IDIuMTA2LTE3LjU5NCA2LjM1Ni0yNC4zNCAxMS44NjdDMzguODI0IDQ0LjczIDMyLjk1MyA1My4zNDQgMzAgNjEuODk4Yy0uNDggMS4zMjUtLjk2NSAyLjY4LTEuMTEzIDMuMDEyLS41MTIgMS4xNDUtMi43NDIgMTAuNzgxLTQuMzQgMTguNjc2LS4yMzggMS4zMjQtLjY2IDMuMjgxLS45MDIgNC4zNjctLjI0MyAxLjA4Mi0uNTcgMi45OC0uNzgyIDQuMjE1LS4xODMgMS4yMzQtLjQyMiAyLjc0Mi0uNTc0IDMuMzEyLS40NTMgMS43Mi0yLjI4OSAxMy40NjUtMy40NjUgMjEuOTg5LTEuMTQ0IDguMjU0LTEuODk4IDE0LjI1LTIuNTU4IDIwLjMzMi0uMzMyIDIuOTgtLjY2NCA1LjkwMi0uNzIzIDYuNDc2LS4wOS41Ny0uMzYzIDMuNDkzLS42MzMgNi40NzctLjI0MiAyLjk4LS42MDEgNi42MjUtLjc4NSA4LjEzMy0uNjMzIDUuNTM5LTIuMiAyOS42NjgtMi45OCA0Ni42ODctLjYwMiAxMi42MTctLjk5MyAzOS42MzctLjc4MiA1NC4zNjcuMjExIDE4LjM3Mi42NiAzNC43OSAxLjA4MiA0MC41MTIuMTUzIDIuMzE3LjQ1MyA3LjIuNjMzIDEwLjg0NC4xOCAzLjY0NC40MjIgOC4zMTIuNTc0IDEwLjM5LjY5MiAxMC40MjIgMS4yMzUgMTcuMjU4IDEuNTA0IDE5LjQyNi4xNTMgMS4zMjguNTEyIDQuODUyLjc1NCA3LjgwMS4yNDIgMi45NTMuNjAyIDYuNDc3Ljc1NCA3LjgzMi4xOCAxLjM1Ni41MTIgNC4yNzcuNzUgNi41MDguNzU0IDcuMTM3IDEuMzI4IDExLjgwNSAxLjgwOSAxNC45MS4yNDIgMS42NTYuNjY0IDQuNDg4LjkwMiA2LjMyNC44NzUgNi42MjUgMS44OTggMTMuMDcgMy4wMTIgMTguOTc3LjI0MiAxLjMyNC42MzMgMy41NTUuOTA2IDQuOTY5LjUxMiAzLjAxMSAxLjY4NyA5LjAwNyAyLjUzMSAxMi44IDIuODkgMTMuMjg2IDQuMTU2IDE3LjI1OCA3LjU1OSAyMy43OTcuOTMzIDEuODA1IDIuMTM3IDMuOTE0IDIuNjggNC42NjguNTExLjc1NCAxLjI2NSAxLjgzNiAxLjY1NiAyLjQxIDEuNzE4IDIuNTU5IDYuNjI5IDcuNTU5IDkuMzQgOS40ODkuNDQ5LjMyOCAxLjMyNC45NiAxLjg5NCAxLjQxNC42MDYuNDggMS4xNzYuODQzIDEuMzI4Ljg0My4xMjEgMCAuNDIyLjIxMS42Ni40NTQgMS4xNzYgMS4xNDQgOS40NjEgNS4wOSAxMy4wMTIgNi4xNDQuNjY0LjIxMSAxLjQ3Ny40OCAxLjgwOS42MzMuNzg1LjM2IDUuMjEgMS40NzMgMTAuNTQzIDIuNjggMi4zMi41NDMgNC42OTkgMS4xMTMgNS4yNyAxLjI2NSAxLjM4Ni4zNiAxMC4xMiAyLjEwNiAxNi43MTggMy4zMTMgMy43OTMuNjkxIDExLjE3NiAxLjg2NyAxNS44MTIgMi41MzEgMS43NDcuMjM4IDMuOTc3LjU3IDQuOTcuNzUgMy42NDQuNjMzIDE4LjcwNiAyLjM4MyAyOC4xNjMgMy4yODUgMy40MDMuMzMyIDcuNTkuNzIzIDkuMzM2LjkwMiAyLjgzMi4zMDEgNS43MjMuNTQzIDE5LjU3OCAxLjUzNiAyLjA3OC4xNTIgNi44MDkuNDIyIDEwLjU0My42MDUgMy43MzUuMTggOC45NDYuNDUgMTEuNTk4LjYwMiAyMS40NDUgMS4yMzQgODIuNzcgMS4yMzQgMTAzLjkxNCAwIDIuNjUyLS4xOCA3Ljg2My0uNDIyIDExLjU5OC0uNjAyIDYuNDE0LS4zIDguNzY1LS40NTMgMTguODI0LTEuMjA3IDEyLjg5LS45OTIgMzEuODQtMi44MzIgMzguMjU0LTMuNzM0IDEuODM2LS4yNyA1LS42OTIgNy4wNzgtLjk2NSA3LjY4LS45OTIgMTguMjIzLTIuNTkgMjQuMjQ2LTMuNzAzIDYuNTk4LTEuMjA3IDE1LjMzMi0yLjk1MyAxNi43MTktMy4zMTMuNTctLjE1MiAyLjk0OS0uNzIyIDUuMjctMS4yNjUgNS4yMS0xLjE3NiA5LjczLTIuMzIgMTAuNTQyLTIuNjhhMTc0LjggMTc0LjggMCAwIDEgMy4wMTItMS4wNTVjMi40NjktLjgxMiAxMC42NjQtNC42OTkgMTEuMzU1LTUuMzYzLjIxMS0uMjExLjgxMy0uNjYgMS4zMjUtLjk2NSAyLjM1MS0xLjQ3MyAzLjQzMy0yLjMxNiA1LjU3NC00LjI0NiAyLjQxLTIuMiA1Ljc1NC01LjgxMiA2LjU2Ni03LjA0Ny4yNy0uNDIyLjk5My0xLjQ0NSAxLjU5NC0yLjI1OC42MzMtLjg0MyAxLjE0NS0xLjU5NyAxLjE0NS0xLjcxOCAwLS4xMjIuNDg0LS45NjUgMS4wNTQtMS44NjguNTc1LS45MDIgMS4yNjYtMi4yMyAxLjU0LTIuOTUzLjMtLjY5MS42LTEuNDQ1LjcyMi0xLjU5My41Ny0uNzU0IDIuNjgtNi43NSAzLjU4Mi0xMC4xNTMgMS40MTgtNS4yNyA0LjA2Ni0xNy43MSA1LjAzMS0yMy41ODYuMjQyLTEuNTA0LjUxMi0yLjkxOC42MDItMy4xNi4yNzMtLjY2NCAxLjkzLTEwLjk5NiAzLjQzMy0yMS41MzUuMzMyLTIuMzIuNjY0LTQuNjQuNzU0LTUuMTIxLjI0My0xLjM4NyAxLjMyNS0xMC42MzMgMS44MDktMTUuNTEyLjIzOC0yLjQxLjU3LTUuMTgzLjc1LTYuMTc2LjE4NC0uOTk2LjUxMi00LjI0Ni43NTQtNy4yMy4yNDItMi45OC41NzQtNi42NTYuNzIzLTguMTMzLjE4LTEuNTA0LjQ1My00LjkzNy42MzItNy42OC4xOC0yLjc0Mi40NTMtNi4xMTMuNjAyLTcuNTMuMTgzLTEuNDE1LjUxMi02LjYyNi43NTQtMTEuNTk1LjI3My00Ljk3Mi41NzQtMTEuMDg2Ljc1NC0xMy41NTQgMS4zNTUtMjEuODk5IDEuMzU1LTc5LjM2OCAwLTEwMS45NTctLjE1My0yLjU2My0uNDIyLTcuNTktLjYwMi0xMS4xNDUtLjE4My0zLjU1NS0uNDUzLTguMjU0LS42MDUtMTAuMzk0LS4xOC0yLjE2OC0uNTctNy41LS45MDMtMTEuODk1LS4zMzItNC4zOTgtLjY2NC04LjUyNy0uNzU0LTkuMTg3LS4wOS0uNjY1LS4zNTktMy41ODYtLjYwMS02LjQ3Ny0uMjQyLTIuODktLjUxMi01LjYwMi0uNjAyLTYuMDIzLS4wOS0uNDIyLS40MjItMy4xOTYtLjc1NC02LjE3Ni0uNzgtNy4yLTEuNzQ2LTE1LjE0OS0xLjk1Ny0xNi4wODItLjA5LS40MjItLjQyMi0yLjgzMi0uNzU0LTUuMzA1LTEuNDc2LTExLjI2Mi00LjIxNC0yNi45NTctNi41NjYtMzcuNjQ4LS4zMzItMS41MDgtLjg3MS0zLjk0Ni0xLjIwMy01LjQyMi0uODQ0LTMuODU2LTEuODQtNy43NDItMi4xNjgtOC40MzQtLjE1Mi0uMzMyLS40MjItMS4xNDQtLjYzMy0xLjgwOC0uNjY0LTIuMjI3LTQuMDA4LTkuNjY4LTQuODUxLTEwLjg0NC0uMTIyLS4xOC0xLjA4Mi0xLjU5NC0yLjExLTMuMTYtMi4xMzctMy4yMjMtNy42MTctOC45NDYtMTAuOTAyLTExLjM1Ni02LjUwNC00Ljc4OS0xMy43MzUtOC4wNDMtMjMuMDctMTAuMzMyYTQ0MC45MzIgNDQwLjkzMiAwIDAgMS00LjgyLTEuMjA3Yy0xLjExNC0uMzI4LTMuMzQ1LS44MTItOC4xMzQtMS44MDVhMzk2LjMxNyAzOTYuMzE3IDAgMCAxLTQuMDY2LS44NzVjLTUuODEzLTEuNDE0LTI0LjczLTQuNDg4LTM3LjA0Ny02LjA1NC0yLjQ3My0uMzAxLTQuOTEtLjYzMy01LjQyMi0uNzUtLjkwNi0uMTg0LTUuMjczLS42MzMtMTQuMTU2LTEuNTA4LTIuNDczLS4yNDItNS44NzUtLjYwMi03LjUzMS0uNzU0LTEuNjU2LS4xOC00LjY0LS40NS02LjYyNS0uNjMzLTEuOTg5LS4xNDgtNS4yNDItLjQyMi03LjIzLS41Ny02Ljc0Ny0uNTc0LTI1LjQ4MS0xLjY1Ni0zNS44NDQtMi4xMS0yMC4wMzItLjg3NC01Ny4wMi0xLjE0NC03OS45Ny0uNTdaTTg1Ljk2NSAyMTQuMDk4Yy4xOC4xNDggMS4wNTUuNDIyIDEuOTI2LjYzMiAxLjYyOS4zOTEgMy45MTggMS40NDYgNS42MzIgMi41OSAxLjM1Ni45MDMgNC41NTEgNC4zMzYgNS4xOCA1LjU0My4zMDUuNjAyLjYzMyAxLjE0NS43MjMgMS4yMzUuMDk0LjA5LjM2My42OTEuNjA1IDEuMzU1LjIxMS42Ni40OCAxLjM1Ni42MzMgMS41MDQuMzkuNTc0Ljg0NCA0LjE1Ni44NDQgNi44MDkgMCAyLjU5LS4zOTUgNS42MzItLjkwNiA2Ljc0Ni0xLjYyNSAzLjczNC0yLjQxIDQuOTY4LTQuNDU3IDcuMTQtMS44OTkgMS45NTctMi42OCAyLjU1OS01LjI3IDMuODI1LTIuMTEgMS4wNTQtMy42MTcgMS41OTctNC44MiAxLjcxNC0uOTY1LjEyMS0xLjgwOS4zMzItMS44OTkuNDU0LS4yMS4zNjMtNi43NDYuMzYzLTYuNzQ2IDAgMC0uMTIyLS43NTQtLjMzMy0xLjcxOS0uNDU0LS45MzMtLjExNy0yLjEwNS0uMzktMi42MTctLjYwMWEzMC45OTggMzAuOTk4IDAgMCAwLTEuOTg4LS44MTNjLS41NzQtLjIxLTEuMTE3LS40NTMtMS4yMDctLjU0My0uMDktLjEyLS41NDMtLjM5LTEuMDU1LS42MzItMS43NDYtLjg3Mi01LjM2LTQuODgtNi40MTQtNy4wNzktLjU3NC0xLjE3NS0xLjExMy0yLjMyLTEuMjY1LTIuNTU4LTEuMDI0LTIuMDUtMS4yMDQtMTEuMzg3LS4yNDMtMTMuNTU1LjI3NC0uNTc0LjY2NC0xLjUzNS44NzUtMi4xMS4yMTEtLjU3LjQ1My0xLjExMy41NDMtMS4yMDIuMDktLjA5LjQ1LS42OTYuNzgyLTEuMzU2LjU3NC0xLjExNyA0LjE1Ni00Ljk3MiA0LjY2OC00Ljk3Mi4xMiAwIC4zOTQtLjIxMS42MDUtLjQ4LjU3LS42MzQgMy40OTItMi4wNDggNS4yNy0yLjUuODQzLS4yMTIgMS43NzctLjUxMyAyLjEwOS0uNjY1LjMzMi0uMTQ4IDEuMTQ0LS4zIDEuODA1LS4zOSAxLjc3Ny0uMTggOC4wMTUuMDkgOC40MDYuMzYzWm0zMjguMTkxIDIwLjk5MnYxNS4yMWgtNTguNDMzdi0yMC4zNTlsMy4yNTQtLjUxNWM3LjE5OS0xLjExMyAxMS42ODctMS44NjcgMTEuOTU3LTIuMDQ3LjE4LS4xMjEgMS42NTYtLjM2IDMuMzEyLS41NyAxLjY1Ni0uMjExIDMuMTY0LS40ODUgMy4zMTMtLjYwNi4xODMtLjExNyAxLjU5Ny0uMzkgMy4xNjQtLjYwMSAxLjU2Ni0uMTggMy42MTMtLjU0MyA0LjUyLS43ODIuOTAyLS4yMSAyLjgtLjU0MyA0LjIxNC0uNzIyIDEuNDE4LS4xODQgMi44MzItLjQ1MyAzLjE2NC0uNTc1LjMzMi0uMTQ4IDEuODM2LS40MjEgMy4zMTMtLjYzMiAxLjUwNy0uMTggMy4xOTEtLjQ1IDMuNzY1LS42MzMuNTctLjE0OSAyLjc0Mi0uNTcgNC44Mi0uOTAzIDIuMDc5LS4zMzIgNC43OS0uNzggNi4wMjQtLjk5MiAxLjIzNC0uMjQyIDIuNTU5LS40MjIgMi45NS0uNDUzbC42NjMtLjAzMVptLTI0OS4zOTggMTMuNDMzdjE4LjA0M2gzMC4xMnYyNi44MDlIMTY0LjczbC4xMTggMjcuOTIyYy4wOTMgMzAuMDkuMDMgMjguNjEzIDEuNjYgMzIuMzE2IDEuMjM0IDIuODY0IDQuNzI2IDUuNzg1IDcuNzM4IDYuNTA4LjUxMi4xMjEgMS4wODYuMzYgMS4zMjguNTQzLjU3LjQ1IDEyLjc3LjQ1IDEzLjMxMy0uMDMxLjIzOC0uMTggMS4zMjQtLjQyMiAyLjQ2OC0uNTQzbDIuMDItLjIxMXYyNi40MThsLS44MTYuMzZjLS43NS4zMzEtNC4yMTUuODc0LTguOTczIDEuNDQ1LTYuNzc3Ljc4NS0xOS4xMjkuODc1LTE5Ljg1Mi4xMi0uMTgtLjE0OC0uNjYtLjI2OS0xLjExMy0uMjY5LTEuMTc2IDAtNi4wNTUtLjkwNi02LjQxOC0xLjE3Ni0uMTgtLjEyLS45OTItLjQyMi0xLjgzNi0uNjAxLS44MTItLjIxMS0xLjYyNS0uNDg1LTEuODA4LS42MDItLjE0OS0uMTUyLS44NC0uNDIyLTEuNTA0LS42MzMtLjY2NC0uMjEtMS4yNjYtLjQ4NC0xLjM1Ni0uNTc0LS4wOS0uMDktLjYzMy0uNDIyLTEuMjA3LS43NTQtMi41LTEuMzI0LTMuMjUtMS44MDQtNC41NzgtMi45MjItLjc4MS0uNjMyLTEuNTA0LTEuMTcxLTEuNjU2LTEuMTcxLS4zMDEtLjAzMi0yLjU5LTIuNTMyLTQuMzk1LTQuODItMS4zODYtMS43NzgtMy40MzctNS4xOC00LjEyOS02LjkzLS4yNDItLjU3LS41MTEtMS4xMTQtLjYwMS0xLjIwNC0uMTIxLS4wOS0uNDIyLTEuMDIzLS43MjMtMi4xMDktLjI3My0xLjA4Mi0uNjMzLTIuMjI3LS43ODUtMi41NTktLjE0OC0uMzMyLS41MTItMS42ODctLjc1LTMuMDExYTE0NC4yODYgMTQ0LjI4NiAwIDAgMC0uODE2LTMuNzY2Yy0uMjExLS45MDItLjM2LTExLjUwOC0uNDUtMzEuNTY2bC0uMTItMzAuMThoLTE3LjQ0MnYtMjYuODA5aDE3LjQ3M3YtMzAuMzYzbDIuMDQ2LS4yMWMxLjExNC0uMTE4IDIuMTY4LS4zMjkgMi4zMi0uNDUuMTgtLjEyMSAxLjY1Ny0uMzkgMy4zMTMtLjYwMiAxLjY1Ni0uMjEgMy4xNjQtLjUxNSAzLjMxMy0uNjMyLjE4LS4xMjEgMi4wNzgtLjQ1NCA0LjIxOC0uNzIzIDIuMTY4LS4zMDUgNC4wNjctLjYzMyA0LjIxNS0uNzU0LjE4LS4xMjEgMS4xNzYtLjMzMiAyLjI1OC0uNDIyYTQ5LjcxOSA0OS43MTkgMCAwIDAgNC4yMTktLjY5MWMzLjIyMy0uNjY0IDguODU1LTEuNTQgOS4xMjUtMS4zODcuMTIxLjA1OS4yMSA4LjI1NC4yMSAxOC4xOTFabTk5Ljg1MSAxNS4xOGM0LjIxNS4yNDIgOC45NzcuNzg1IDkuMzM2IDEuMDU1LjE4LjEyLjkwMy4zMzIgMS42NTcuNDIyIDEuNzE4LjI3MyA1LjkwNiAxLjUwNyA4LjQzMyAyLjUzIDIuMTEuODQ1IDYuODA5IDMuMTkyIDcuNTMxIDMuNzk4LjI0My4xOC43ODIuNTM5IDEuMjA0LjcyMi40MjEuMjExIDEuNzUgMS4yNjIgMi45MjEgMi4yOSAxLjE3NiAxLjA1NCAyLjI2MiAxLjk1NyAyLjQxIDIuMDE1LjQ1NC4yMTEgNS44MTMgNi43MTkgNS44MTMgNy4wNzggMCAuMDkuMjc0LjU3NS42MDYgMS4wMjQuNjMyLjkwNiAzLjMxMiA2LjExNyAzLjMxMiA2LjQ0OSAwIC4xMTcuMjQyLjc4MS41NyAxLjQ3My4zMDEuNjk1LjY2NCAxLjc1Ljc4NiAyLjMyLjEyLjU3NC4zMzIgMS4xNzYuNDQ5IDEuMzU1LjEyLjE1My4zOTQgMS4xMTQuNjA1IDIuMTEuMTguOTkyLjQyMiAyLjAyLjUxMiAyLjI1OC4xMjEuMjQyLjM5IDEuNTM1LjYzMyAyLjg2My4zNiAxLjk4OC40NDkgOS40ODguNTcgNDIuNjhsLjEyMSA0MC4zaC0zMi44NmwtLjAzLTMuNTU0Yy0uMDMyLTEuOTI2LS4xMjItNC43MjctLjI0My02LjIwNGwtLjE4LTIuNzEtLjg3NCAxLjIwM2MtMS4zODMgMS44NC01LjkzNCA2LjE3NS03LjczOSA3LjM3OS0zLjk0OSAyLjU5My01IDMuMjIyLTYuMDg2IDMuNTg2LS42NjQuMTgtMS41MzUuNTQzLTEuOTU3Ljc4LS40NTMuMjEyLTEuNTY2LjU3NS0yLjQ3Mi43NTUtLjkwMy4yMS0xLjgwNS40ODQtMS45NTcuNjAxLTEuNTM1IDEuMTQ1LTIwLjUxMiAxLjExNy0yMS45ODktLjAyNy0uMTQ4LS4xMjEtMS4yMzQtLjM5LTIuNDEtLjYwMi0xLjE0NC0uMjEtMi41LS41NDMtMy4wMTEtLjc4NS0uNDgtLjIxLTEuNzc4LS43NTQtMi44MjktMS4xNzZhNDIuNDIgNDIuNDIgMCAwIDEtMy41NTQtMS43NDYgNDkuODY2IDQ5Ljg2NiAwIDAgMC0yLjQ0Mi0xLjQxNGMtMS4yNjUtLjY5NS0xLjY4Ny0xLjA4Ni01LjEyLTQuNTItMy41MjQtMy41MjMtMy45NzctNC4wMDMtMy45NzctNC4zMzUgMC0uMTIxLS4zOTEtLjc4NS0uODQtMS40NzctLjQ4NS0uNjkxLTEuMTc2LTEuOTU3LTEuNTQtMi43NzMtLjM1OS0uODQtLjg0My0xLjgzNi0xLjA1NC0yLjI1OC0uMjM4LS40MjItLjU3LTEuNTA0LS43ODEtMi40MS0uMjExLS45MDMtLjQ4LTEuODA1LS42MDItMS45NTctLjMzMi0uNDIyLS45MDYtNC43LS45MDYtNi41NjcgMC0uODctLjE0OC0xLjc0Ni0uMzI4LTEuOTI1LS4zNjMtLjM2NC0uMjc0LTEuNTY3LjY2LTguODI5LjE4LTEuNDE0LjQ1My0yLjcxLjU3NC0yLjg1OS4xMjEtLjE4LjM5LS45NjUuNTctMS43NzcuMzkxLTEuNTY3IDEuMjA4LTMuNjE0IDIuMDUxLTUuMTUzLjI3LS41MTEuNjMtMS4yMDMuODEzLTEuNTY2LjE4LS4zOS40MjItLjY5MS41Ny0uNjkxLjEyMSAwIC4yMTEtLjE4LjIxMS0uMzkxIDAtLjMzMiAzLjMxMy00LjY0IDMuODg3LTUuMDMxLjEyLS4wOS4zMzItLjM5LjQyMi0uNjkyLjEyLS4zMzIuNDgtLjYzMi44MTItLjcyMi4zMzItLjA5LjYwMi0uMjc0LjYwMi0uMzk1IDAtLjMgNS4wNjItNC4yNzcgNi43NzctNS4yNyAxLjIzNC0uNzUzIDQuMDA4LTIuMTY3IDguMDQzLTQuMDk3LjU3NC0uMyA2LjIwMy0yLjEwNiA4LjY3Ni0yLjguOTAyLS4yNyAyLjY4LS42MzQgMy45MTQtLjgxMyAxLjIzNC0uMjExIDIuNDEtLjQ1MyAyLjU2Mi0uNTcuMTgtLjEyMiAxLjk4NS0uMzk1IDQuMDY3LS41NzUgMi4wNzgtLjE4IDQuNjM3LS40OCA1LjcyMi0uNjMzIDQuMjc4LS42MzIgMTkuMzA1LS41MTEgMjAuOTAzLjE1My41NDMuMjM4LjU3LjEyLjM2LTIuNDQyLS4xMTgtMS40NzYtLjMyOS0yLjc0Mi0uNDUtMi44MzItLjE1Mi0uMDktLjMzMi0uNjYtLjQ1My0xLjI2NS0uMjExLTEuMTE0LTEuMzU2LTMuNTUxLTIuNDM4LTUuMjExLS42OTUtMS4wNTEtMy42MTctNC4wNjctMy45NDktNC4wNjctLjExNyAwLS42MjktLjMtMS4xNDQtLjY5MS0xLjMyNS0uOTY1LTMuNDYxLTEuOTI2LTQuNzU4LTIuMTY4LS42MzMtLjEyMS0xLjE0NS0uMzMyLTEuMTQ1LS40NTMgMC0xLjMyNC0xOS40NTctMS41MzUtMjUuMy0uMjM5LS43NTQuMTQ5LTIuNS40OC0zLjkxNS43MjMtMS40MTguMjM4LTIuODMyLjU3LTMuMTY0LjcyMy0uMzMyLjE0OC0xLjQxNC40MjItMi40MS42MDEtLjk5Mi4xOC0yLjA3OC40NTMtMi40MS42MDItLjMzMi4xNTItMS41MzUuNDg0LTIuNjguNzU0LTEuMTQ0LjI3LTIuMjMuNTctMi40MS43MjItLjE4LjEyMi0uOTkyLjQyMi0xLjgzNi42MzMtLjgxMi4yMTEtMS42NTYuNTEyLTEuODA4LjYzMy0uMTguMTIxLS45OTMuMzktMS44MDkuNjAyLS44NC4xOC0yLjAxNi42MDEtMi42MTcuOTAyLS42MzMuMzMyLTEuMjA3LjU3NC0xLjI5Ny41NzQtLjA5IDAtLjE1Mi02LjI5Ny0uMTUyLTEzLjk3NiAwLTEwLjg3NS4wOTMtMTQuMDM2LjM5NC0xNC4yNzguMjExLS4xOCAxLjA1NS0uNDggMS44NjctLjY5MS44NDQtLjE4IDEuNjU3LS40NTMgMS44MDUtLjU3NC4xODQtLjEyMSAxLjE3Ni0uNDggMi4yNjItLjc1NCAxLjA4Mi0uMzAxIDIuMTA1LS42MyAyLjI1OC0uNzUuMTgtLjE1MyAxLjExMy0uMzk1IDIuMDc4LS42MDIuOTk2LS4yMSAyLjAyLS40ODQgMi4yNTgtLjYzMy4yNzMtLjEyIDEuNTA3LS40NTMgMi43NDItLjcyMmE1OC45NSA1OC45NSAwIDAgMCAyLjg2My0uNjMzYy4zMjgtLjA5NCAyLjAxNi0uMzYzIDMuNzYyLS42MDYgMS43NS0uMjM4IDMuNTg2LS41NyA0LjA2Ni0uNzIyIDEuNzUtLjU0IDE3LjUzMS0xLjUzNSAyMS4wODYtMS4zMjQuOTkyLjA1OCAzLjE2NC4xOCA0LjgyLjI3Wk05OC40OTIgMzI2LjUwOHY1OS45MzdINjMuMjU0VjI2Ni41NjZoMzUuMjM4Wm0yNjYuMjY2LTIyLjU5NGMwIDM1LjY2NC4xNTIgNDIuNTYzLjg3NSA0My41MjcuMTQ4LjE0OS4zMzIuNzUuNDUzIDEuMzI1LjQyMiAyLjI1NyAyLjM3OSA1LjU0MyA0LjYwNSA3Ljc3IDEuMTc2IDEuMjA2IDIuNSAyLjI2IDIuOTIyIDIuMzc4LjQ1My4wOTQuNzg1LjI3NC43ODUuMzk1IDAgLjExNyAxLjA1NS41MzkgMi4zNDguOTYgMS45My42MDYgMi45NTMuNzIzIDUuOTY1LjcyMyAyLjExIDAgMy45NDUtLjE0OCA0LjM2Ny0uMzI4LjM5LS4yMSAxLjMyNC0uNTEyIDIuMDc4LS43MjMuNzU0LS4yMSAyLjExLS44NDMgMy4wMTItMS40NDkgMS42ODctMS4wODIgNC44Mi0zLjk3MiA0LjgyLTQuNDU3IDAtLjE0OC40MjItLjgxMi45MDMtMS40NDUuNTExLS42NjQuOTA2LTEuMzI0LjkwNi0xLjUwNCAwLS4xODQuMjctLjgxNi41Ny0xLjQxOC4zMzItLjYwMi42OTItMS42MjUuODEzLTIuMjU4LjA5LS42NjQuMy0xLjMyNC40NTMtMS40NzYuNzU0LS45NjUuODc1LTcuMDQ3Ljg3NS00Mi4zOHYtMzYuOTg4aDM1LjIzOHYxMTkuODhINDIwLjA2Yy0xMy4wNCAwLTE2Ljc3OC0uMDktMTYuOTU3LS4zOTEtLjEyMi0uMTgtLjI3LTMuMDQzLS4zMzItNi4zMjUtLjA2LTMuMjUzLS4yMTEtNS45MzMtLjMyOS01LjkzMy0uMTIgMC0uNDg0LjM2LS44NDMuODEyLTEuNjg4IDIuMjktNC4zNCA0Ljg4LTguNDk2IDguMzEzLS42MDIuNDgtMS44MzYgMS4xNDQtNC41NDcgMi40NjktMS4yMzUuNjAxLTIuNTkgMS4yOTYtMy4wMTIgMS41MDctLjQyMi4yMTEtMS41NjYuNTQzLTIuNTYzLjc1NC0uOTkyLjIxMS0xLjg2Ny40OC0xLjk1Ny42MDItLjMuNDUtNS42MzIuOTAyLTEwLjkwMi45MDItNS4xOCAwLTkuMzk4LS4zNi0xMC42MzMtLjg3NS0uMzMyLS4xNDgtMS40NzYtLjUxMS0yLjU2Mi0uNzgxLTEuMDgyLS4yNy0yLjA3OC0uNjMzLTIuMjU4LS43NTQtLjE0OC0uMTIxLS44NzEtLjQyMi0xLjU2Ni0uNjMzLS43MjMtLjE4LTEuMjkzLS40NDktMS4yOTMtLjU3IDAtLjEyMS0uNTQzLS4zOS0xLjIwNy0uNjAyLS42Ni0uMjEtMS4yMDQtLjQ4NC0xLjIwNC0uNjA1IDAtLjExNy0uMzMyLS4zNi0uNzIyLS41NC0yLjU5LTEuMTc1LTguNDY1LTYuNjg3LTEwLjkzNC0xMC4yNDEtMS41MDgtMi4xNjgtMy44MjgtNi41MDgtNC4zMDgtOC4xMDItLjE4LS42MzMtLjU0My0xLjU2Ni0uNzU0LTIuMDUtLjIxMS0uNTEyLS41Ny0xLjU5NC0uNzU0LTIuNDEtLjE4LS44NC0uNDUtMS43MTYtLjYwMi0yLjAxNi0uMTQ4LS4yNzQtLjQyMi0xLjY4OC0uNjAxLTMuMTY0LS4xOC0xLjQ0Ni0uNTEyLTIuOTIyLS42OTItMy4yNTQtLjI3My0uNDUtLjM5NC0xMS4yMDQtLjQ1My00My4zMTNsLS4wOS00Mi42OGgzNS4yN1ptMCAwIiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOm5vbnplcm87ZmlsbDojRkY2MjAwO2ZpbGwtb3BhY2l0eToxIi8+PHBhdGggZD0iTTI2MC42OTEgMzMzLjE2NGMtMS40NzIuMTQ5LTIuOTguMzktMy4zMTIuNTQtLjMzMi4xODMtMS40MTQuNDUyLTIuNDEuNjYzLS45NjEuMTgtMi4yNTguNTQzLTIuODYuODEzLTQuNTIgMS45NTctNi43MTggMy4yNTQtOC4yMjIgNC44Mi0xLjQ0NiAxLjUwOC0yLjg5NSA0LjMwOS0zLjEzMyA2LjA1NS0uMDYzLjYwMS0uMjc0IDEuMzg2LS40NTMgMS43MTUtLjMzMi42OTUtLjIxMSAyLjgzMi4zMzIgNS42MzIuNjAxIDMuMDQzIDMuMDEyIDYuNzUgNS4xNDggNy44NjQgMy43OTcgMS45NTcgNC41MiAyLjI1NyA2LjYzIDIuNTkgMy43OTIuNTcgMTEuMDIzLjI0MiAxMi41ODktLjYwMi4yNy0uMTUyIDEuMzg3LS42NjQgMi40NjktMS4xNDUgMS4wODYtLjUxMSAyLjUtMS4zMjggMy4xNjQtMS44NC42NjQtLjUxMSAxLjQxNC0xLjExMyAxLjY4Ny0xLjMyNCAxLjcxNS0xLjI5MyA0Ljg4LTYuNTM1IDUuMzAxLTguNzAzLjA5LS41NDMuMzMyLTEuMTc2LjUxMi0xLjQxOC4yMS0uMjcuMzYtMy4wNDMuNDIyLTguMDEybC4xMi03LjU5LTEuNjI4LS4xNzljLTIuMi0uMjczLTEzLjA0LS4xOC0xNi4zNTYuMTIxWm0wIDAiIHN0eWxlPSJzdHJva2U6bm9uZTtmaWxsLXJ1bGU6bm9uemVybztmaWxsOiNGRjYyMDA7ZmlsbC1vcGFjaXR5OjEiLz48L3N2Zz4=",
|
|
18
|
+
bradesco: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUwMCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMzc4Ljc2MjM0IDM3OC44MDYiIHZlcnNpb249IjEuMSIgaWQ9InN2ZzEwIiBzb2RpcG9kaTpkb2NuYW1lPSJicmFkZXNjby5zdmciIGlua3NjYXBlOnZlcnNpb249IjEuMi4yICg3MzJhMDFkYTYzLCAyMDIyLTEyLTA5KSIgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gPGRlZnMgaWQ9ImRlZnMxNCIgLz4gPHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2aWV3MTIiIHBhZ2Vjb2xvcj0iIzUwNTA1MCIgYm9yZGVyY29sb3I9IiNlZWVlZWUiIGJvcmRlcm9wYWNpdHk9IjEiIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIwIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2NvbG9yPSIjNTA1MDUwIiBzaG93Z3JpZD0iZmFsc2UiIGlua3NjYXBlOnpvb209IjAuMTUzMzAwNzUiIGlua3NjYXBlOmN4PSIxODE5Ljk1MiIgaW5rc2NhcGU6Y3k9IjE1MjYuNDExMyIgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxOTIwIiBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDA5IiBpbmtzY2FwZTp3aW5kb3cteD0iLTgiIGlua3NjYXBlOndpbmRvdy15PSItOCIgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iZzgiIC8+IDxnIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBpZD0iZzgiPiA8cGF0aCBkPSJNIC0wLjAxMTkyODE0LDAuMjA0NzA0MDggSCAzNzguNzE5NTUgViAzNzguOTEwNDQgSCAyMjIuMDc3NTQgViAyMjIuMDE5MjYgSCAxODcuNzQyNjggViAzNzguOTEwNDQgSCAxNjkuNTAzMDMgViAyNzEuNzk0MjkgSCAxNTIuMzM4NyBWIDM3OC45MTA0NCBIIC0wLjAxMTkyODE0IFogTSAxMi44NTk3NzUsMTMyLjIxMjEgQyAzMi44ODM3OTksMTIzLjE5OTM3IDUyLjkxMDI5OCwxMTQuMTgxNjQgNzIuOTQyOTg0LDEwNS4xNjE0MyAxNTMuMzYzMjksLTcuODgzNDU5NiAyNTcuODM1NDMsMzQuOTE0OSAyOTUuMDMyNDUsODguOTMxNTIyIDIwOC40ODE5NCwzMy4wMjk2MTQgMTQ0LjQ2MzcxLDYxLjUyNDQ3MiAxMTIuNjQwODQsOTkuNzUyMjkgMzU1LjgzODMxLDc0LjMxNTI1OSA0MTYuNjM1NTIsMjIzLjYzNDE0IDI4NS4zNzU1OCwyNzguMjgzNzYgNDAxLjYwMjAzLDE4NC4xNDc4MSAyNTMuOTAwNDEsMTA3LjMyNDU4IDk5Ljc2NzksMTE0Ljg5ODEzIDYyLjc0MTY0NSwxODMuNzgyNzIgNzQuODk1NjQyLDIzNC42MzgwOCAxMDkuNDIxMDUsMjgwLjQ0NjkyIDcyLjE5NDM0MSwyNTEuNzA3ODQgNDcuNTA1MjIyLDIwOS43MDMyMiA2Ny41Nzg3NDMsMTIwLjMwODUxIDQ5LjMzNzg0OSwxMjQuMjc5NyAzMS4wOTY5NTYsMTI4LjI0NTkgMTIuODU5Nzc1LDEzMi4yMTIxIFoiIGZpbGw9IiNjYzIyMjkiIGlkPSJwYXRoMiIgc3R5bGU9InN0cm9rZS13aWR0aDoxLjI0MTc0IiAvPiA8L2c+IDwvc3ZnPg==",
|
|
19
|
+
bb: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUwMCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMTkyLjc1NiAxOTIuNzU2IiB2ZXJzaW9uPSIxLjEiIGlkPSJzdmcxMCIgc29kaXBvZGk6ZG9jbmFtZT0iYmFuY28tZG8tYnJhc2lsLXNlbS1mdW5kby5zdmciIGlua3NjYXBlOnZlcnNpb249IjEuMi4yICg3MzJhMDFkYTYzLCAyMDIyLTEyLTA5KSIgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gPGRlZnMgaWQ9ImRlZnMxNCIgLz4gPHNvZGlwb2RpOm5hbWVkdmlldyBpZD0ibmFtZWR2aWV3MTIiIHBhZ2Vjb2xvcj0iIzUwNTA1MCIgYm9yZGVyY29sb3I9IiNlZWVlZWUiIGJvcmRlcm9wYWNpdHk9IjEiIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIwIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2NvbG9yPSIjNTA1MDUwIiBzaG93Z3JpZD0iZmFsc2UiIGlua3NjYXBlOnpvb209IjAuMjE2OCIgaW5rc2NhcGU6Y3g9IjEyNTAiIGlua3NjYXBlOmN5PSIxMjUwIiBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE5MjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMDkiIGlua3NjYXBlOndpbmRvdy14PSItOCIgaW5rc2NhcGU6d2luZG93LXk9Ii04IiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmcxMCIgLz4gPGcgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGlkPSJnOCI+IDxwYXRoIGZpbGw9IiMzMzM0OGUiIGQ9Ik05Ni4zOTYgMTYuOTI1bC03OC44NSA1Mi44NSAzMi44MTkgMjEuMzExTDg5LjU3NyA2NC42NiA3NC4wMjMgNTQuNDQzbDIxLjMwNS0xNC4yNzQgNDYuMjMxIDMwLjY3OS03NS44NDUgNTAuOTE4IDE2LjQwNSAxMC44NjUgOTQuMzc5LTYyLjg0OC0uMjEzLS4yMTMtNzkuODg5LTUyLjY0NXpNMTc1LjAyNyAxNi45NDdsLTMyLjgwOCAyMS43MzEgMTYuNDA0IDExLjA3OCAxNi40MDQtMTEuMDc4VjE2Ljk0N3pNMTcuMDA1IDE3NS44MzJsMzIuODA5LTIxLjczLTE2LjQwNC0xMS4wNzktMTYuNDA1IDExLjA3OXYyMS43M3oiIGlkPSJwYXRoNCIgLz4gPHBhdGggZmlsbD0iIzMzMzQ4ZSIgZD0iTTk2LjM2IDE3NS43ODdsNzguODQ5LTUyLjg1MS0zMi44MTgtMjEuMzExLTM5LjIxMSAyNi40MjYgMTUuNTUyIDEwLjIxNy0yMS4zMDQgMTQuMjc1LTQ2LjIzMS0zMC42OCA3NS44NDQtNTAuOTE3LTE2LjQwNC0xMC44NjYtOTQuMzggNjIuODQ4LjIxMy4yMTUgNzkuODkgNTIuNjQ0eiIgaWQ9InBhdGg2IiAvPiA8L2c+IDwvc3ZnPg==",
|
|
20
|
+
caixa: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUwMCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMTkyLjc1NiAxOTIuNzU2IiB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc3NDI5IiBzb2RpcG9kaTpkb2NuYW1lPSJjYWl4YS1lY29ub21pY2EtZmVkZXJhbC1YLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS4yLjIgKDczMmEwMWRhNjMsIDIwMjItMTItMDkpIiB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPiA8ZGVmcyBpZD0iZGVmczc0MzMiIC8+IDxzb2RpcG9kaTpuYW1lZHZpZXcgaWQ9Im5hbWVkdmlldzc0MzEiIHBhZ2Vjb2xvcj0iIzUwNTA1MCIgYm9yZGVyY29sb3I9IiNlZWVlZWUiIGJvcmRlcm9wYWNpdHk9IjEiIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIwIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2NvbG9yPSIjNTA1MDUwIiBzaG93Z3JpZD0iZmFsc2UiIGlua3NjYXBlOnpvb209IjAuMTUzMzAwNzUiIGlua3NjYXBlOmN4PSIyOTMuNTQwNjQiIGlua3NjYXBlOmN5PSIxNDgwLjc0OTQiIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iMTAwOSIgaW5rc2NhcGU6d2luZG93LXg9Ii04IiBpbmtzY2FwZTp3aW5kb3cteT0iLTgiIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2Zzc0MjkiIC8+IDxnIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBpZD0iZzc0MjciIHRyYW5zZm9ybT0ibWF0cml4KDQuNDMzNTkwOCwwLDAsNC40MzM1OTA4LC00NDguMTk1NzEsLTMyNi4wNzg1OCkiPiA8cGF0aCBkPSJtIDExNC43MjUsOTcuNjU2IGggMTQuNjM2IGwgMTAuMDMsMTYuNjEyIGggLTE0LjYzOSB6IiBmaWxsPSIjMGQ2ZmFiIiBpZD0icGF0aDc0MjEiIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2MiIC8+IDxwYXRoIGZpbGw9IiNkYjgxMzUiIGQ9Im0gMTE2LjI0Niw5NS4xMDQgaCAxNS4xMjkgbCAxMy4xMzksLTE2LjU0IGggLTE1LjEyOSB6IG0gLTE1LjEyOSwxOS4yNjUgaCAxNS4xMjkgbCAxMy4xMzksLTE2Ljc0NCBoIC0xNS4xMjkgeiIgaWQ9InBhdGg3NDIzIiAvPiA8cGF0aCBmaWxsPSIjMGQ2ZmFiIiBkPSJtIDEwNi41NzIsNzguMzYyIGggMTQuMTIxIGwgOS42NzQsMTYuNzQyIGggLTE0LjEyMSB6IiBpZD0icGF0aDc0MjUiIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2MiIC8+IDwvZz4gPC9zdmc+",
|
|
21
|
+
santander: "data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgMC40IDIzOC4yIDI0MC43MTkyNiIgd2lkdGg9IjI1MDAiIHZlcnNpb249IjEuMSIgaWQ9InN2ZzQiIHNvZGlwb2RpOmRvY25hbWU9ImJhbmNvLXNhbnRhbmRlci1sb2dvLnN2ZyIgaW5rc2NhcGU6dmVyc2lvbj0iMS4yLjIgKDczMmEwMWRhNjMsIDIwMjItMTItMDkpIiB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPiA8ZGVmcyBpZD0iZGVmczgiIC8+IDxzb2RpcG9kaTpuYW1lZHZpZXcgaWQ9Im5hbWVkdmlldzYiIHBhZ2Vjb2xvcj0iIzUwNTA1MCIgYm9yZGVyY29sb3I9IiNlZWVlZWUiIGJvcmRlcm9wYWNpdHk9IjEiIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIwIiBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIgaW5rc2NhcGU6ZGVza2NvbG9yPSIjNTA1MDUwIiBzaG93Z3JpZD0iZmFsc2UiIGlua3NjYXBlOnpvb209IjAuMTczMzgyNTgiIGlua3NjYXBlOmN4PSItNDAuMzczMTQ0IiBpbmtzY2FwZTpjeT0iMTEwMS42MTAxIiBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE5MjAiIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMDkiIGlua3NjYXBlOndpbmRvdy14PSItOCIgaW5rc2NhcGU6d2luZG93LXk9Ii04IiBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIiBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmc0IiAvPiA8cGF0aCBkPSJtIDE3MS43MzY1LDExMS43MjI0NyBjIC0wLjU0Nzk4LC04LjY2Mjc2IC0yLjczOTg2LC0xNy4zMjU1MTkgLTcuMTIzNjUsLTI0LjgzMzI0OCBMIDEyNy4zNTA2OSwxOC4xNjQ2NDEgYyAtMi43Mzk4NSwtNS4xOTc2NTYgLTQuOTMxNzUsLTEwLjk3MjgzMDMgLTYuMDI3NywtMTYuNzQ4MDA2IGwgLTEuNjQzOTIsMi44ODc1ODc1IGMgLTkuMzE1NTMsMTYuNzQ4MDA4NSAtOS4zMTU1MywzOC4xMTYxNTQ1IDAsNTQuODY0MTYxNSBsIDMwLjEzODUsNTQuODY0MTU2IGMgOS4zMTU1NSwxNi43NDggOS4zMTU1NSwzOC4xMTYxNiAwLDU0Ljg2NDE2IGwgLTEuNjQzOSwyLjg4NzU4IGMgLTEuMDk1OTQsLTUuNzc1MTcgLTMuMjg3ODQsLTExLjU1MDM1IC02LjAyNzcxLC0xNi43NDgwMSBMIDExNC43NDczMiwxMDQuNzkyMjYgOTcuMjEyMTg2LDcyLjQ1MTI4NSBDIDk0LjQ3MjMyMSw2Ny4yNTM2MjggOTIuMjgwNDI4LDYxLjQ3ODQ1NCA5MS4xODQ0ODMsNTUuNzAzMjc5IGwgLTEuNjQzOTE5LDIuODg3NTg4IGMgLTkuMzE1NTQxLDE2Ljc0ODAwNiAtOS4zMTU1NDEsMzcuNTM4NjM2IDAsNTQuODY0MTczIGwgMzAuMTM4NTA2LDU0Ljg2NDE0IGMgOS4zMTU1NCwxNi43NDggOS4zMTU1NCwzOC4xMTYxNSAwLDU0Ljg2NDE2IGwgLTEuNjQzOTEsMi44ODc1OSBjIC0xLjA5NTk0LC01Ljc3NTE4IC0zLjI4Nzg0LC0xMS41NTAzNiAtNi4wMjc3MSwtMTYuNzQ4MDEgTCA3NC4xOTczMTksMTQwLjU5ODMzIGMgLTQuOTMxNzU0LC05LjI0MDI3IC03LjEyMzY0NywtMTkuNjM1NTcgLTcuMTIzNjQ3LC0zMC4wMzA4OSAtNDAuMDAyMDMsMTAuOTcyODMgLTY3Ljk0ODY1MDk1LDM0LjY1MTAzIC02Ny45NDg2NTA5NSw2MS43OTQzNSAwLDM4LjExNjE2IDUzLjcwMTM1MTk1LDY4LjcyNDU5IDEyMC4wMDYwNzg5NSw2OC43MjQ1OSA2Ni4zMDQ3MywwIDEyMC4wMDYwOSwtMzAuNjA4NDMgMTIwLjAwNjA5LC02OC43MjQ1OSAwLjU0Nzk2LC0yNS45ODgyOCAtMjYuODUwNjgsLTQ5LjY2NjQ5IC02Ny40MDA2OSwtNjAuNjM5MzIgeiIgZmlsbD0iI2VhMWQyNSIgaWQ9InBhdGgyIiBzb2RpcG9kaTpub2RldHlwZXM9ImNjY2NjY2NjY2NjY2NjY2NjY2NjY3NzY2MiIHN0eWxlPSJzdHJva2Utd2lkdGg6NS42MjU1MSIgLz4gPC9zdmc+",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function BankLogo({ bank }: { bank: PixBankId }): JSX.Element {
|
|
25
|
+
return (
|
|
26
|
+
<Box
|
|
27
|
+
component="img"
|
|
28
|
+
src={LOGOS[bank]}
|
|
29
|
+
alt=""
|
|
30
|
+
aria-hidden="true"
|
|
31
|
+
data-bank={bank}
|
|
32
|
+
sx={{ width: 32, height: 32, flex: "none", objectFit: "contain", borderRadius: 1 }}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PixBankCopy } from "./types";
|
|
2
|
+
|
|
3
|
+
/** The Pix-to-bank flow's words, pt-BR (FUT-3612). */
|
|
4
|
+
export const PT_BR_PIX_BANK_COPY: PixBankCopy = {
|
|
5
|
+
names: {
|
|
6
|
+
nubank: { name: "Nubank", the: "o " },
|
|
7
|
+
itau: { name: "Itaú", the: "o " },
|
|
8
|
+
bradesco: { name: "Bradesco", the: "o " },
|
|
9
|
+
bb: { name: "Banco do Brasil", the: "o " },
|
|
10
|
+
caixa: { name: "Caixa", the: "a " },
|
|
11
|
+
santander: { name: "Santander", the: "o " },
|
|
12
|
+
},
|
|
13
|
+
generateAndCopy: "Gerar e copiar o Pix",
|
|
14
|
+
generateCopyAndOpen: (bank) => `Gerar, copiar e abrir ${bank.the}${bank.name}`,
|
|
15
|
+
copyAndOpen: (bank) => `Copiar e abrir ${bank.the}${bank.name}`,
|
|
16
|
+
openOther: "Abrir outro banco",
|
|
17
|
+
listTitle: "Abra seu banco e cole em Pix copia e cola",
|
|
18
|
+
open: (bank) => `Abrir ${bank.name}`,
|
|
19
|
+
opening: (bank) => `Abrindo ${bank.the}**${bank.name}**…`,
|
|
20
|
+
other: "Outro banco",
|
|
21
|
+
notOpened: (bank) => `Não conseguimos abrir ${bank.the}${bank.name}. O app está instalado neste celular?`,
|
|
22
|
+
retry: "Tentar de novo",
|
|
23
|
+
copied: "Código Pix copiado",
|
|
24
|
+
copiedPick: "Código Pix copiado. Escolha o banco.",
|
|
25
|
+
copiedOpening: (bank) => `Código Pix copiado. Abrindo ${bank.the}${bank.name}…`,
|
|
26
|
+
};
|
|
@@ -84,9 +84,11 @@ export function lastUsedCard(saved: readonly SavedCard[]): SavedCard | undefined
|
|
|
84
84
|
/**
|
|
85
85
|
* What is chosen before the buyer touches anything (M7, owner 2026-10-15): a
|
|
86
86
|
* saved card makes "Cartão de crédito" the choice with that card selected —
|
|
87
|
-
* the one used last ({@link lastUsedCard}).
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* the one used last ({@link lastUsedCard}). The buyer's LAST online method
|
|
88
|
+
* (`lastMethod`, FUT-3611) wins when the store offers it: Pix as Pix, since
|
|
89
|
+
* choosing creates nothing any more. Never a door tender (FUT-1478), and not
|
|
90
|
+
* a store's only method by itself either (that pick used to raise an order
|
|
91
|
+
* with no tap at all).
|
|
90
92
|
*
|
|
91
93
|
* A buyer back here because a card was REFUSED (`fresh`) keeps the card
|
|
92
94
|
* chosen, with no saved card selected for them — the one this would pick is
|
|
@@ -96,7 +98,10 @@ export function preselection(
|
|
|
96
98
|
rows: readonly OnlineRow[],
|
|
97
99
|
saved: readonly SavedCard[],
|
|
98
100
|
fresh: boolean,
|
|
101
|
+
lastMethod: "PIX" | "CARD" | null = null,
|
|
99
102
|
): { choice: CheckoutListChoice; selection: string | null } | null {
|
|
103
|
+
const pixOffered = rows.some((row) => row.method === "PIX" && !row.disabled);
|
|
104
|
+
if (lastMethod === "PIX" && pixOffered && !fresh) return { choice: { kind: "online", method: "PIX" }, selection: null };
|
|
100
105
|
const card = rows.find((row) => row.method === "CARD" && !row.disabled);
|
|
101
106
|
if (!card) return null;
|
|
102
107
|
if (fresh) return { choice: { kind: "online", method: "CARD" }, selection: saved.length > 0 ? null : NEW_CARD };
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import { createContext, useContext, useMemo, useState, type JSX, type ReactNode } from "react";
|
|
1
|
+
import { createContext, useContext, useMemo, useRef, useState, type JSX, type MutableRefObject, type ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { DeferredCopy } from "../pix-parts";
|
|
4
|
+
|
|
5
|
+
import type { CheckoutPaymentList, PixBankId } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* What the bar's Pix press asked of the code it is raising (FUT-3612): copy it
|
|
9
|
+
* the moment it arrives (the clipboard was opened inside the tap), then open
|
|
10
|
+
* `bank` — or show the six banks when `pick`. Consumed once by the Pix face.
|
|
11
|
+
*/
|
|
12
|
+
export interface PixIntent {
|
|
13
|
+
copy: DeferredCopy;
|
|
14
|
+
bank: PixBankId | null;
|
|
15
|
+
pick: boolean;
|
|
16
|
+
}
|
|
4
17
|
|
|
5
18
|
/**
|
|
6
19
|
* What the one list shares with the panes it mounts (FUT-3591/3592): its
|
|
@@ -23,6 +36,15 @@ export interface PaymentListMode {
|
|
|
23
36
|
* default — because the list skips that step.
|
|
24
37
|
*/
|
|
25
38
|
consent: ListConsent;
|
|
39
|
+
/** The Pix press's intent, waiting for its code — see {@link PixIntent}. */
|
|
40
|
+
pixIntent: MutableRefObject<PixIntent | null>;
|
|
41
|
+
/**
|
|
42
|
+
* The armed charge (`armedCharge`) for this step: when it was armed and
|
|
43
|
+
* whether it was spent. Held HERE, above the faces, so a list face that
|
|
44
|
+
* remounts (after a Pix, "Prefere pagar com cartão?") can never fire it
|
|
45
|
+
* again — the 1-tap tap consented to ONE charge, right away.
|
|
46
|
+
*/
|
|
47
|
+
armed: MutableRefObject<{ since: number; spent: boolean }>;
|
|
26
48
|
}
|
|
27
49
|
|
|
28
50
|
export interface ListConsent {
|
|
@@ -45,7 +67,9 @@ export function PaymentListProvider({
|
|
|
45
67
|
children: ReactNode;
|
|
46
68
|
}): JSX.Element {
|
|
47
69
|
const [qrOpen, setQrOpen] = useState(false);
|
|
48
|
-
const
|
|
70
|
+
const pixIntent = useRef<PixIntent | null>(null);
|
|
71
|
+
const armed = useRef({ since: Date.now(), spent: false });
|
|
72
|
+
const value = useMemo(() => ({ list, qrOpen, setQrOpen, onLeavePix, consent, pixIntent, armed }), [list, qrOpen, onLeavePix, consent]);
|
|
49
73
|
return <PaymentListContext.Provider value={value}>{children}</PaymentListContext.Provider>;
|
|
50
74
|
}
|
|
51
75
|
|
|
@@ -10,7 +10,11 @@ import type { BuyerContact, CheckoutProviderConfig } from "../types";
|
|
|
10
10
|
import type { useCheckoutController } from "../use-checkout-controller";
|
|
11
11
|
import { useCheckoutComponents } from "../ui";
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
import { actionLabel, blockedReason, cardName } from "./choice";
|
|
15
|
+
import { usePaymentListMode, type PaymentListMode } from "./context";
|
|
16
|
+
import { armPixCopy, armedReady, otherBankShown, pixBankLabel, useArmedCharge, useDropRefusedCopy } from "./list-memory";
|
|
17
|
+
import { OtherBankLink } from "./list-pix";
|
|
14
18
|
import { ChoiceList } from "./choice-list";
|
|
15
19
|
import { CardRun, WalletRun, type ListChargeFailure } from "./charge-runners";
|
|
16
20
|
import { ActionButton, ChargeBar, GooglePayAction, ListBar } from "./list-bar";
|
|
@@ -75,9 +79,10 @@ function onlineTotal(props: ListFaceProps): string {
|
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
/** An online choice's press: the card goes through the bar, Pix and the hand-off raise at once. */
|
|
78
|
-
function actOnline(props: ListFaceProps, method: CheckoutOnlineChoice): void {
|
|
82
|
+
function actOnline(props: ListFaceProps, method: CheckoutOnlineChoice, mode: PaymentListMode | null, pick = false): void {
|
|
79
83
|
const { c, charge, cap } = props;
|
|
80
84
|
saveAsked(props);
|
|
85
|
+
if (method === "PIX" && mode) armPixCopy(props.list, mode, pick);
|
|
81
86
|
if (method === "CARD") return charge.start("CARD", onlineTotal(props));
|
|
82
87
|
const raised = method === "PIX" ? "PIX" : handOffMethod(cap.offered);
|
|
83
88
|
if (method === "HAND_OFF") props.onHandOff();
|
|
@@ -90,13 +95,14 @@ function actOnline(props: ListFaceProps, method: CheckoutOnlineChoice): void {
|
|
|
90
95
|
* or a charge. A door option hands the press to the host; the card counts five
|
|
91
96
|
* seconds first; everything else raises at once.
|
|
92
97
|
*/
|
|
93
|
-
function useAct(props: ListFaceProps, clearFailure: () => void): () => void {
|
|
94
|
-
|
|
98
|
+
function useAct(props: ListFaceProps, clearFailure: () => void): (pick?: boolean) => void {
|
|
99
|
+
const mode = usePaymentListMode();
|
|
100
|
+
return (pick = false) => {
|
|
95
101
|
const { choice } = props.state;
|
|
96
102
|
if (!choice || inFlight(props)) return;
|
|
97
103
|
if (choice.kind === "door") return chosenDoor(props)?.onSend();
|
|
98
104
|
clearFailure();
|
|
99
|
-
actOnline(props, choice.method);
|
|
105
|
+
actOnline(props, choice.method, mode, pick);
|
|
100
106
|
};
|
|
101
107
|
}
|
|
102
108
|
|
|
@@ -176,7 +182,7 @@ function buttonFacts(props: ListFaceProps): { label: string; total: string; busy
|
|
|
176
182
|
const door = chosenDoor(props);
|
|
177
183
|
const online = state.choice?.kind === "online";
|
|
178
184
|
return {
|
|
179
|
-
label: list.hold ? list.hold.action : actionLabel(list.copy, state.choice, door, props.provider),
|
|
185
|
+
label: list.hold ? list.hold.action : pixBankLabel(list, state) ?? actionLabel(list.copy, state.choice, door, props.provider),
|
|
180
186
|
total: door ? (door.totalLabel ?? props.total) : online ? onlineTotal(props) : props.total,
|
|
181
187
|
busy: inFlight(props),
|
|
182
188
|
};
|
|
@@ -198,27 +204,58 @@ function googlePayLive(props: ListFaceProps, reason: string | null, busy: boolea
|
|
|
198
204
|
return choice?.kind === "online" && choice.method === "GOOGLE_PAY" && props.cap.googlePay !== null && reason === null && !busy;
|
|
199
205
|
}
|
|
200
206
|
|
|
207
|
+
/** The 5-second bar (or the charge going out), and the host's footer while it counts. */
|
|
208
|
+
function ChargingBar({ props, onCancel }: { props: ListFaceProps; onCancel: () => void }): JSX.Element {
|
|
209
|
+
const { charge, list } = props;
|
|
210
|
+
const counting = charge.phase === "counting";
|
|
211
|
+
const footer = counting ? list.chargeFooter?.(charge.cancel) : null;
|
|
212
|
+
return (
|
|
213
|
+
<>
|
|
214
|
+
<ChargeBar text={chargingText(props)} full={!counting} cancelLabel={list.copy.cancel} onCancel={onCancel} />
|
|
215
|
+
{footer ? <Box data-testid="list-charge-footer">{footer}</Box> : null}
|
|
216
|
+
</>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** The button, and "Abrir outro banco" under it when a remembered bank would open. */
|
|
221
|
+
function PressButton({ props, act, reason, returnFocus }: {
|
|
222
|
+
props: ListFaceProps;
|
|
223
|
+
act: (pick?: boolean) => void;
|
|
224
|
+
reason: string | null;
|
|
225
|
+
returnFocus: boolean;
|
|
226
|
+
}): JSX.Element {
|
|
227
|
+
const { list, state } = props;
|
|
228
|
+
const { label, total, busy } = buttonFacts(props);
|
|
229
|
+
const other = list.pixBank && otherBankShown(list, state, reason === null && !busy) ? list.pixBank.copy.openOther : null;
|
|
230
|
+
return (
|
|
231
|
+
<>
|
|
232
|
+
<ActionButton label={label} total={total} disabled={reason !== null || busy} loading={busy} onClick={() => act()} focusOnMount={returnFocus} />
|
|
233
|
+
{other ? <OtherBankLink label={other} onClick={() => act(true)} /> : null}
|
|
234
|
+
</>
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
201
238
|
/** The button, the 5-second bar, Google's own button, or nothing for a charge nobody can confirm yet. */
|
|
202
239
|
function BarAction({ props, failure, act, onGooglePay, onCancel, reason, returnFocus }: {
|
|
203
240
|
props: ListFaceProps;
|
|
204
241
|
failure: ListChargeFailure | null;
|
|
205
|
-
act: () => void;
|
|
242
|
+
act: (pick?: boolean) => void;
|
|
206
243
|
onGooglePay: () => void;
|
|
207
244
|
onCancel: () => void;
|
|
208
245
|
reason: string | null;
|
|
209
246
|
returnFocus: boolean;
|
|
210
247
|
}): JSX.Element | null {
|
|
211
|
-
const { charge,
|
|
212
|
-
if (cardCharging(charge)) {
|
|
213
|
-
return <ChargeBar text={chargingText(props)} full={charge.phase !== "counting"} cancelLabel={list.copy.cancel} onCancel={onCancel} />;
|
|
214
|
-
}
|
|
248
|
+
const { charge, cap } = props;
|
|
249
|
+
if (cardCharging(charge)) return <ChargingBar props={props} onCancel={onCancel} />;
|
|
215
250
|
// An UNRESOLVED charge may be holding the buyer's money: no pay control at
|
|
216
251
|
// all under "não pague de novo" (FUT-563), as the card pane does today.
|
|
217
252
|
if (failure?.code === UNRESOLVED_CODE) return null;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
253
|
+
if (googlePayUnpriced(props)) {
|
|
254
|
+
const { label, total } = buttonFacts(props);
|
|
255
|
+
return <ActionButton label={label} total={total} disabled loading={false} onClick={() => act()} />;
|
|
256
|
+
}
|
|
257
|
+
if (googlePayLive(props, reason, inFlight(props)) && cap.googlePay) return <GooglePayAction client={cap.googlePay.client} onPress={onGooglePay} />;
|
|
258
|
+
return <PressButton props={props} act={act} reason={reason} returnFocus={returnFocus} />;
|
|
222
259
|
}
|
|
223
260
|
|
|
224
261
|
/** The charge under way, once there is an order to run it against. */
|
|
@@ -318,6 +355,9 @@ export function ListFace(props: ListFaceProps): JSX.Element {
|
|
|
318
355
|
const door = chosenDoor(props);
|
|
319
356
|
const reason = reasonOf(props, door);
|
|
320
357
|
useChargeGuard(props, reason);
|
|
358
|
+
const free = reason === null && props.charge.phase === "idle" && !c.creating;
|
|
359
|
+
useArmedCharge(armedReady(list, state, free), act);
|
|
360
|
+
useDropRefusedCopy(c.createError);
|
|
321
361
|
const { returnFocus, onCancel } = useCancelWithFocus(charge);
|
|
322
362
|
const shown = charge.phase !== "waiting";
|
|
323
363
|
const facts = barFacts(props, door, reason);
|
|
@@ -327,7 +367,7 @@ export function ListFace(props: ListFaceProps): JSX.Element {
|
|
|
327
367
|
<ChoiceList copy={list.copy} state={state} door={list.door ?? []} buyer={c.buyer} onBuyerChange={c.setBuyer} provider={props.provider} failure={failure} locked={facts.locked} covered={coveredByHost(list)} />
|
|
328
368
|
) : null}
|
|
329
369
|
<Runners props={props} sheet={sheet.current} onFailed={onFailed} />
|
|
330
|
-
<RaiseError c={c} onRetry={act} />
|
|
370
|
+
<RaiseError c={c} onRetry={() => act()} />
|
|
331
371
|
{shown ? (
|
|
332
372
|
<ListBar summary={list.summary} extras={facts.extras} payer={facts.charging ? null : <PayerLine props={props} />} reason={facts.underButton} live={facts.live}>
|
|
333
373
|
<BarAction props={props} failure={failure} act={act} onGooglePay={onGooglePay} onCancel={onCancel} reason={reason} returnFocus={returnFocus} />
|