@12-apps/payments-frontend 3.18.0 → 3.19.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/screens/copy-en-US.ts +110 -0
- package/src/activation/screens/copy-pt-BR.ts +126 -0
- package/src/ledger/query.ts +13 -2
- package/src/locales.ts +15 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.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.",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"storybook:build": "storybook build"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@12-apps/payments-backend": "^4.
|
|
25
|
+
"@12-apps/payments-backend": "^4.26.0",
|
|
26
26
|
"react-qr-code": "^2.2.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { EN_US_CARD_COPY } from '../../card';
|
|
2
|
+
|
|
3
|
+
import type { ActivationStepCopy } from './copy';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The twin of `./copy-pt-BR.ts`, key for key (FUT-764).
|
|
7
|
+
*
|
|
8
|
+
* A pack, not a default — see that file for the whole argument, and for the
|
|
9
|
+
* list of strings that deliberately do not move across the pair: **Checkout
|
|
10
|
+
* Integrado** (PagBank's own console label), **CPF** and its `000.000.000-00`
|
|
11
|
+
* mask (a Brazilian document and a FORMAT), the provider names, and this
|
|
12
|
+
* package's `{provider}` placeholder.
|
|
13
|
+
*/
|
|
14
|
+
export const EN_US_ACTIVATION_STEP_COPY: ActivationStepCopy = {
|
|
15
|
+
intro: {
|
|
16
|
+
title: 'Step 3 · Turn selling on',
|
|
17
|
+
cardBody: (amountLabel) =>
|
|
18
|
+
`Make a test charge${amountLabel ? ` of ${amountLabel}` : ''} on your own card. It is ` +
|
|
19
|
+
'refunded automatically, and it is what proves your shop can genuinely take money.',
|
|
20
|
+
realCharge: (amountLabel) =>
|
|
21
|
+
`We raise a real ${amountLabel} charge on your own account. Paying it is what proves your ` +
|
|
22
|
+
'shop can genuinely take money.',
|
|
23
|
+
payingYourself: (amountLabel) =>
|
|
24
|
+
`You are paying yourself: the ${amountLabel} leaves your payment method and lands in the ` +
|
|
25
|
+
"account that receives this shop's sales. There is no refund because the money never left " +
|
|
26
|
+
'your control.',
|
|
27
|
+
},
|
|
28
|
+
actions: {
|
|
29
|
+
chargeAndActivate: (amountLabel) =>
|
|
30
|
+
`Charge${amountLabel ? ` ${amountLabel}` : ''} and activate`,
|
|
31
|
+
payAndActivate: (amountLabel) => `Pay ${amountLabel} and activate`,
|
|
32
|
+
testAgain: 'Test again',
|
|
33
|
+
retry: 'Try again',
|
|
34
|
+
tryAgain: 'Try once more',
|
|
35
|
+
restart: 'I have switched it on — restart Step 3',
|
|
36
|
+
generateNewCharge: 'Generate a new charge',
|
|
37
|
+
checkNow: 'Check now',
|
|
38
|
+
alreadyPaidCheckNow: 'I have paid — check now',
|
|
39
|
+
setProviderOrder: 'Set the order between providers',
|
|
40
|
+
seePublishedStore: 'See the published shop',
|
|
41
|
+
},
|
|
42
|
+
awaiting: {
|
|
43
|
+
receivedTitle: 'Payment received — confirming',
|
|
44
|
+
receivedBody:
|
|
45
|
+
'We are confirming your payment with the provider. This usually takes a few seconds.',
|
|
46
|
+
declinedTitle: 'The payment was declined',
|
|
47
|
+
waitingTitle: 'Waiting for the payment…',
|
|
48
|
+
waitingBody: (amountLabel) =>
|
|
49
|
+
`We raised the ${amountLabel} charge and opened the provider's page in another tab. ` +
|
|
50
|
+
'Pay there and come back: we check for ourselves the moment it lands.',
|
|
51
|
+
lastChecked: (seconds) => `Last checked ${seconds}s ago`,
|
|
52
|
+
openPaymentPage: 'Open the payment page',
|
|
53
|
+
copyLink: 'Copy the link',
|
|
54
|
+
linkCopied: 'Link copied',
|
|
55
|
+
showLink: 'Show the link',
|
|
56
|
+
hideLink: 'Hide the link',
|
|
57
|
+
},
|
|
58
|
+
outcome: {
|
|
59
|
+
approvedTitle: 'Test charge approved',
|
|
60
|
+
refundedBody: (amountLabel) =>
|
|
61
|
+
`Your shop can take payments. The ${amountLabel} was refunded automatically.`,
|
|
62
|
+
refundPendingBody: (amountLabel) =>
|
|
63
|
+
`Your shop can take payments. The ${amountLabel} refund did not complete — ` +
|
|
64
|
+
'it will show up on your statement.',
|
|
65
|
+
someAmount: 'amount',
|
|
66
|
+
authenticatedNotActive: 'Authenticated, but not activated',
|
|
67
|
+
refusedTitle: (displayName) => `${displayName} refused to create the charge`,
|
|
68
|
+
refusedBody: (displayName) =>
|
|
69
|
+
`${displayName} refused to create the charge. That almost always means ` +
|
|
70
|
+
'Checkout Integrado is still switched off on your account. Nothing was charged — ' +
|
|
71
|
+
'we reopened Step 2 above: turn it on there and come back.',
|
|
72
|
+
unreachableTitle: 'We could not reach the provider',
|
|
73
|
+
expiredTitle: 'The charge expired',
|
|
74
|
+
settledTitle: 'Test charge confirmed',
|
|
75
|
+
settledBody: (amountLabel) =>
|
|
76
|
+
`Your shop can take payments. The ${amountLabel} stays in your account — ` +
|
|
77
|
+
'InfinitePay refunds are made in their own app.',
|
|
78
|
+
provenTitle: 'Test charge confirmed',
|
|
79
|
+
provenBody:
|
|
80
|
+
'Your shop has proved it can take money through this provider. We switched sales ' +
|
|
81
|
+
'on automatically — you can pause them with the button at the top whenever you like. ' +
|
|
82
|
+
'No further charge is needed.',
|
|
83
|
+
providerSaid: 'The provider answered:',
|
|
84
|
+
blockedTitle: 'Step 2 is still unconfirmed',
|
|
85
|
+
blockedBody:
|
|
86
|
+
'Confirm above that Checkout Integrado is enabled on your account. Without it the ' +
|
|
87
|
+
'provider creates no payment link at all, and this charge would fail.',
|
|
88
|
+
},
|
|
89
|
+
taxId: {
|
|
90
|
+
label: "Cardholder's CPF",
|
|
91
|
+
hint: 'PagBank requires it on every card charge.',
|
|
92
|
+
placeholder: '000.000.000-00',
|
|
93
|
+
},
|
|
94
|
+
charge: {
|
|
95
|
+
card: EN_US_CARD_COPY,
|
|
96
|
+
noTokenizer:
|
|
97
|
+
'Card tokenization is not implemented for {provider} yet, ' +
|
|
98
|
+
'so the verification charge cannot be made from here.',
|
|
99
|
+
chargeFailed: 'The test charge could not be completed.',
|
|
100
|
+
unreachable: 'Could not connect. Check your connection and try again.',
|
|
101
|
+
},
|
|
102
|
+
redirect: {
|
|
103
|
+
chargeExpired: 'The charge expired.',
|
|
104
|
+
confirmFailed: 'The test charge could not be confirmed.',
|
|
105
|
+
createFailed: 'The test charge could not be raised.',
|
|
106
|
+
confirmTimedOut:
|
|
107
|
+
'We could not confirm the payment in time. If you have already paid, the charge is ' +
|
|
108
|
+
'still valid — reload the page to check again.',
|
|
109
|
+
},
|
|
110
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { PT_BR_CARD_COPY } from '../../card';
|
|
2
|
+
|
|
3
|
+
import type { ActivationStepCopy } from './copy';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Everything step 3 says, in Portuguese (FUT-764).
|
|
7
|
+
*
|
|
8
|
+
* A pack, not a default. Nothing in this package reads it: `createActivationStep`
|
|
9
|
+
* still REQUIRES its copy, and a host that wants these words names them. That
|
|
10
|
+
* distinction is the one `copy.ts` and `settings-copy.ts` argue for — a default
|
|
11
|
+
* in the origin host's language reads as finished to the next host right up
|
|
12
|
+
* until an owner sees it — and it is why the eight packs already on
|
|
13
|
+
* `../../locales` are not a breach of it either.
|
|
14
|
+
*
|
|
15
|
+
* These sentences are here because they are the ACTIVATION STEP's vocabulary
|
|
16
|
+
* and not one product's voice: "a cobrança de teste é o que libera as vendas",
|
|
17
|
+
* "autenticado, mas não ativado", "última verificação há Ns". Every adopter
|
|
18
|
+
* would write them again, word for word, because they describe outcomes this
|
|
19
|
+
* package decides. They came from the first adopting host, where they had been
|
|
20
|
+
* maintained beside a screen that no longer lives there.
|
|
21
|
+
*
|
|
22
|
+
* ## What does NOT get translated, in either half
|
|
23
|
+
*
|
|
24
|
+
* **Checkout Integrado** is the exact label on PagBank's own console; an owner
|
|
25
|
+
* sent looking for "Integrated Checkout" is looking for a screen that does not
|
|
26
|
+
* exist. **CPF** and its `000.000.000-00` mask are a Brazilian document and a
|
|
27
|
+
* FORMAT — a translated mask shows a shape the field refuses. **PagBank** and
|
|
28
|
+
* **InfinitePay** are names. `{provider}` is this package's own placeholder,
|
|
29
|
+
* substituted after the sentence is chosen.
|
|
30
|
+
*/
|
|
31
|
+
export const PT_BR_ACTIVATION_STEP_COPY: ActivationStepCopy = {
|
|
32
|
+
intro: {
|
|
33
|
+
title: 'Passo 3 · Ative as vendas',
|
|
34
|
+
cardBody: (amountLabel) =>
|
|
35
|
+
`Faça uma cobrança de teste${amountLabel ? ` de ${amountLabel}` : ''} no seu próprio ` +
|
|
36
|
+
'cartão. Ela é estornada automaticamente e é o que comprova que sua loja consegue ' +
|
|
37
|
+
'receber de verdade.',
|
|
38
|
+
realCharge: (amountLabel) =>
|
|
39
|
+
`Geramos uma cobrança real de ${amountLabel} na sua própria conta. Pagar por ela é o que ` +
|
|
40
|
+
'comprova que sua loja consegue receber de verdade.',
|
|
41
|
+
payingYourself: (amountLabel) =>
|
|
42
|
+
`Você paga para si mesmo: os ${amountLabel} saem do seu meio de pagamento e caem na conta ` +
|
|
43
|
+
'que recebe as vendas desta loja. Não há estorno porque o valor não sai do seu controle.',
|
|
44
|
+
},
|
|
45
|
+
actions: {
|
|
46
|
+
chargeAndActivate: (amountLabel) => `Cobrar${amountLabel ? ` ${amountLabel}` : ''} e ativar`,
|
|
47
|
+
payAndActivate: (amountLabel) => `Pagar ${amountLabel} e ativar`,
|
|
48
|
+
testAgain: 'Testar novamente',
|
|
49
|
+
retry: 'Tentar novamente',
|
|
50
|
+
tryAgain: 'Tentar de novo',
|
|
51
|
+
restart: 'Já habilitei — recomeçar o Passo 3',
|
|
52
|
+
generateNewCharge: 'Gerar nova cobrança',
|
|
53
|
+
checkNow: 'Conferir agora',
|
|
54
|
+
alreadyPaidCheckNow: 'Já paguei — conferir agora',
|
|
55
|
+
setProviderOrder: 'Definir a ordem entre provedores',
|
|
56
|
+
seePublishedStore: 'Ver a loja publicada',
|
|
57
|
+
},
|
|
58
|
+
awaiting: {
|
|
59
|
+
receivedTitle: 'Pagamento recebido — confirmando',
|
|
60
|
+
receivedBody:
|
|
61
|
+
'Estamos confirmando seu pagamento com o provedor. Isso costuma levar poucos segundos.',
|
|
62
|
+
declinedTitle: 'O pagamento foi recusado',
|
|
63
|
+
waitingTitle: 'Aguardando o pagamento…',
|
|
64
|
+
waitingBody: (amountLabel) =>
|
|
65
|
+
`Geramos a cobrança de ${amountLabel} e abrimos a página do provedor em outra aba. ` +
|
|
66
|
+
'Pague por lá e volte aqui: conferimos sozinhos assim que o pagamento cair.',
|
|
67
|
+
lastChecked: (seconds) => `Última verificação há ${seconds}s`,
|
|
68
|
+
openPaymentPage: 'Abrir a página de pagamento',
|
|
69
|
+
copyLink: 'Copiar link',
|
|
70
|
+
linkCopied: 'Link copiado',
|
|
71
|
+
showLink: 'Ver o link',
|
|
72
|
+
hideLink: 'Esconder o link',
|
|
73
|
+
},
|
|
74
|
+
outcome: {
|
|
75
|
+
approvedTitle: 'Cobrança de teste aprovada',
|
|
76
|
+
refundedBody: (amountLabel) =>
|
|
77
|
+
`Sua loja já consegue receber pagamentos. O ${amountLabel} foi estornado automaticamente.`,
|
|
78
|
+
refundPendingBody: (amountLabel) =>
|
|
79
|
+
`Sua loja já consegue receber pagamentos. O estorno do ${amountLabel} não foi concluído — ` +
|
|
80
|
+
'ele aparecerá na sua fatura.',
|
|
81
|
+
someAmount: 'valor',
|
|
82
|
+
authenticatedNotActive: 'Autenticado, mas não ativado',
|
|
83
|
+
refusedTitle: (displayName) => `A ${displayName} recusou criar a cobrança`,
|
|
84
|
+
refusedBody: (displayName) =>
|
|
85
|
+
`A ${displayName} recusou criar a cobrança. Isso quase sempre significa que o ` +
|
|
86
|
+
'Checkout Integrado ainda está desligado na sua conta. Nada foi cobrado — ' +
|
|
87
|
+
'reabrimos o Passo 2 acima: habilite lá e volte aqui.',
|
|
88
|
+
unreachableTitle: 'Não conseguimos falar com o provedor',
|
|
89
|
+
expiredTitle: 'A cobrança expirou',
|
|
90
|
+
settledTitle: 'Cobrança de teste confirmada',
|
|
91
|
+
settledBody: (amountLabel) =>
|
|
92
|
+
`Sua loja já consegue receber pagamentos. O ${amountLabel} fica na sua conta — ` +
|
|
93
|
+
'estornos da InfinitePay são feitos no app dela.',
|
|
94
|
+
provenTitle: 'Cobrança de teste confirmada',
|
|
95
|
+
provenBody:
|
|
96
|
+
'Sua loja provou que consegue receber por este provedor. Ligamos as vendas ' +
|
|
97
|
+
'automaticamente — você pode pausar pelo botão no topo quando quiser. Nenhuma nova ' +
|
|
98
|
+
'cobrança é necessária.',
|
|
99
|
+
providerSaid: 'Resposta do provedor:',
|
|
100
|
+
blockedTitle: 'Falta confirmar o Passo 2',
|
|
101
|
+
blockedBody:
|
|
102
|
+
'Confirme acima que o Checkout Integrado está habilitado na sua conta. Sem ele o ' +
|
|
103
|
+
'provedor não cria nenhum link de pagamento, e esta cobrança falharia.',
|
|
104
|
+
},
|
|
105
|
+
taxId: {
|
|
106
|
+
label: 'CPF do titular',
|
|
107
|
+
hint: 'Exigido pelo PagBank em qualquer cobrança no cartão.',
|
|
108
|
+
placeholder: '000.000.000-00',
|
|
109
|
+
},
|
|
110
|
+
charge: {
|
|
111
|
+
card: PT_BR_CARD_COPY,
|
|
112
|
+
noTokenizer:
|
|
113
|
+
'Ainda não há tokenização de cartão implementada para {provider}, ' +
|
|
114
|
+
'então a cobrança de verificação não pode ser feita por aqui.',
|
|
115
|
+
chargeFailed: 'Não foi possível concluir a cobrança de teste.',
|
|
116
|
+
unreachable: 'Não foi possível conectar. Verifique sua conexão e tente novamente.',
|
|
117
|
+
},
|
|
118
|
+
redirect: {
|
|
119
|
+
chargeExpired: 'A cobrança expirou.',
|
|
120
|
+
confirmFailed: 'Não foi possível confirmar a cobrança de teste.',
|
|
121
|
+
createFailed: 'Não foi possível gerar a cobrança de teste.',
|
|
122
|
+
confirmTimedOut:
|
|
123
|
+
'Não conseguimos confirmar o pagamento a tempo. Se você já pagou, a cobrança continua ' +
|
|
124
|
+
'válida — recarregue a página para conferir de novo.',
|
|
125
|
+
},
|
|
126
|
+
};
|
package/src/ledger/query.ts
CHANGED
|
@@ -55,11 +55,22 @@ export function ledgerSearchTerm(params: URLSearchParams): string {
|
|
|
55
55
|
return params.get('q') ?? '';
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* A grid query mapped back onto the params a ledger URL owns.
|
|
60
|
+
*
|
|
61
|
+
* `dir` accepts `null` as well as absent, because that is what a real grid
|
|
62
|
+
* produces: a column can be in the sort list with no direction chosen yet, and
|
|
63
|
+
* a data-grid library spells that `null` rather than by leaving the key out.
|
|
64
|
+
* The runtime always treated the two the same — an unsorted column contributes
|
|
65
|
+
* no `sort` param — so this is the TYPE catching up with the behaviour rather
|
|
66
|
+
* than a change to it. Typed the other way, every adopter writes the same
|
|
67
|
+
* `?? undefined` mapping at the call site, which is exactly the boilerplate
|
|
68
|
+
* this module exists to delete.
|
|
69
|
+
*/
|
|
59
70
|
export function ledgerParams(query: {
|
|
60
71
|
search: string;
|
|
61
72
|
page: number;
|
|
62
|
-
sortBy: readonly { id: string; dir?: 'asc' | 'desc' }[];
|
|
73
|
+
sortBy: readonly { id: string; dir?: 'asc' | 'desc' | null }[];
|
|
63
74
|
}): Record<string, string | undefined> {
|
|
64
75
|
const sort = query.sortBy[0];
|
|
65
76
|
return {
|
package/src/locales.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { ActivationStepCopy } from './activation/screens/copy';
|
|
2
|
+
import { EN_US_ACTIVATION_STEP_COPY } from './activation/screens/copy-en-US';
|
|
3
|
+
import { PT_BR_ACTIVATION_STEP_COPY } from './activation/screens/copy-pt-BR';
|
|
1
4
|
import type { CardCopy } from './card/copy';
|
|
2
5
|
import { EN_US_CARD_COPY, PT_BR_CARD_COPY } from './card';
|
|
3
6
|
import type { CheckoutPaymentCopy } from './components/checkout-payment-copy';
|
|
@@ -40,6 +43,17 @@ import { PT_BR_PAYMENTS_SETTINGS_COPY } from './components/settings-pt-BR';
|
|
|
40
43
|
*/
|
|
41
44
|
type LocalePack<T> = { readonly 'pt-BR': T; readonly 'en-US': T };
|
|
42
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Step 3's words (FUT-764). `createActivationStep` still REQUIRES its copy and
|
|
48
|
+
* reads nothing from here — a host that wants these names them, which is the
|
|
49
|
+
* distinction between a pack and a default. They arrived from the first
|
|
50
|
+
* adopting host, where they had outlived the screen they belonged to.
|
|
51
|
+
*/
|
|
52
|
+
export const ACTIVATION_STEP_COPY = {
|
|
53
|
+
'pt-BR': PT_BR_ACTIVATION_STEP_COPY,
|
|
54
|
+
'en-US': EN_US_ACTIVATION_STEP_COPY,
|
|
55
|
+
} as const satisfies LocalePack<ActivationStepCopy>;
|
|
56
|
+
|
|
43
57
|
export const CARD_COPY = {
|
|
44
58
|
'pt-BR': PT_BR_CARD_COPY,
|
|
45
59
|
'en-US': EN_US_CARD_COPY,
|
|
@@ -88,6 +102,7 @@ export const PLATFORM_HOMOLOGACAO_COPY = {
|
|
|
88
102
|
* key them — while the root keeps exporting the pt-BR names it always has, so
|
|
89
103
|
* no existing import moves.
|
|
90
104
|
*/
|
|
105
|
+
export { EN_US_ACTIVATION_STEP_COPY } from './activation/screens/copy-en-US';
|
|
91
106
|
export { EN_US_CARD_COPY } from './card';
|
|
92
107
|
export { EN_US_CHECKOUT_PAYMENT_COPY } from './components/checkout-payment-en-US';
|
|
93
108
|
export {
|