@12-apps/payments-frontend 3.5.0 → 3.7.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.
@@ -0,0 +1,74 @@
1
+ import type {
2
+ CheckoutViewCopy,
3
+ PaymentsUnavailableCopy,
4
+ PaymentStatusCopy,
5
+ } from "./view-copy";
6
+
7
+ /**
8
+ * The pt-BR pack — the exact sentences these views compiled in until 6.0.0,
9
+ * now NAMED exports a host passes by hand, never defaults. The filename is
10
+ * what exempts this file from the copy-portability gate: Portuguese may ship,
11
+ * it may not be silent.
12
+ */
13
+ export const PT_BR_PAYMENTS_UNAVAILABLE_COPY: PaymentsUnavailableCopy = {
14
+ title: "Pagamento online indisponível",
15
+ body: "Esta loja não recebe pagamentos pelo site. Combine o pagamento diretamente com a loja para concluir seu pedido.",
16
+ remedyTitle: "Pagamento com o garçom",
17
+ remedyBody: "Esta loja não recebe pagamentos pelo site. Chame o garçom para fechar a conta na mesa.",
18
+ callAction: "Chamar garçom",
19
+ callingAction: "Chamando...",
20
+ };
21
+
22
+ export const PT_BR_PAYMENT_STATUS_COPY: PaymentStatusCopy = {
23
+ paid: {
24
+ heading: "Pedido confirmado",
25
+ support: "Recebemos seu pagamento e já registramos o pedido.",
26
+ },
27
+ awaiting: {
28
+ heading: "Confirmando seu pagamento",
29
+ support: "Isso costuma levar alguns segundos. Pode deixar esta tela aberta.",
30
+ },
31
+ failed: {
32
+ // Said plainly and first: the fear on this screen is having been charged
33
+ // for an order that failed.
34
+ heading: "Pagamento não concluído",
35
+ support: "Nenhum valor foi cobrado. Você pode tentar novamente.",
36
+ },
37
+ expired: {
38
+ heading: "O código expirou",
39
+ support: "Nenhum valor foi cobrado. Gere um novo código para continuar.",
40
+ },
41
+ awaitingTimedOut: {
42
+ heading: "Ainda não recebemos a confirmação",
43
+ support:
44
+ "Se você já pagou, o pedido é confirmado assim que a operadora avisar — " +
45
+ "não pague de novo. Você pode fechar esta tela.",
46
+ },
47
+ retryAction: "Tentar novamente",
48
+ regenerateAction: "Gerar novo código",
49
+ backAction: "Voltar ao cardápio",
50
+ amountLabel: "Valor pago",
51
+ referenceLabel: "Pedido",
52
+ receiptEmailLabel: "Comprovante enviado para",
53
+ };
54
+
55
+ export const PT_BR_CHECKOUT_VIEW_COPY: CheckoutViewCopy = {
56
+ steps: {
57
+ dados: "Dados",
58
+ payment: "Pagamento",
59
+ status: "Confirmação",
60
+ },
61
+ dados: {
62
+ saveProfile: "Salvar meus dados para a próxima compra",
63
+ cannotContinueTitle: "Não foi possível continuar",
64
+ continueAction: "Continuar",
65
+ secureNotice: "Pagamento seguro",
66
+ keepShopping: "Continuar comprando",
67
+ back: "Voltar",
68
+ },
69
+ emptyCart: {
70
+ title: "Seu carrinho está vazio.",
71
+ action: "Ver cardápio",
72
+ },
73
+ status: PT_BR_PAYMENT_STATUS_COPY,
74
+ };
@@ -250,6 +250,17 @@ export interface CheckoutCustomerField {
250
250
  */
251
251
  export interface CheckoutChainLink {
252
252
  provider: string;
253
+ /**
254
+ * The provider's own name as a BUYER should read it ("InfinitePay"), which
255
+ * `GET /api/checkout/config` publishes per entry.
256
+ *
257
+ * Optional, and the DEGRADE DIRECTION IS "SAY NOTHING": an older host serves
258
+ * no name, and a hand-off screen then describes where the buyer is going
259
+ * without naming it, rather than printing the internal `provider` id — a
260
+ * buyer shown "infinitepay" learns less than one shown nothing, and learns
261
+ * it in a vocabulary that is ours rather than theirs.
262
+ */
263
+ displayName?: string | null;
253
264
  tokenization: "NONE" | "PUBLIC_KEY" | "SDK" | "REDIRECT";
254
265
  publicKey: string | null;
255
266
  mockTokenization: boolean;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Every string the legacy checkout views render — required props, with NO
3
+ * defaults, deliberately (the payments extraction's own doctrine, FUT-760):
4
+ * a default in the origin host's language reads as finished to the next host
5
+ * right up until a buyer sees it. These three views proved the point — the
6
+ * flows factory's copy port existed, was REQUIRED, declared
7
+ * `unavailableWithRemedyTitle` and `emptyCartAction`, and the views simply
8
+ * never read it, so a host that dutifully passed copy still rendered another
9
+ * product's voice.
10
+ *
11
+ * A pt-BR host imports {@link PT_BR_CHECKOUT_VIEW_COPY} from `./pt-BR` (the
12
+ * package root re-exports it) and passes it by hand — one reviewable line,
13
+ * never a silence.
14
+ */
15
+
16
+ /** The screen shown when the store cannot take money online. */
17
+ export interface PaymentsUnavailableCopy {
18
+ /** No remedy: the store simply does not charge online. */
19
+ title: string;
20
+ body: string;
21
+ /** A remedy exists (the origin host: the waiter; a clinic: the front desk). */
22
+ remedyTitle: string;
23
+ remedyBody: string;
24
+ /** The remedy button, idle and in flight. */
25
+ callAction: string;
26
+ callingAction: string;
27
+ }
28
+
29
+ /** The stepper's three labels, in flow order. */
30
+ export interface CheckoutStepperCopy {
31
+ dados: string;
32
+ payment: string;
33
+ status: string;
34
+ }
35
+
36
+ /** The buyer-details step: its bar, its refusal, and the slim header. */
37
+ export interface DadosStepCopy {
38
+ /** The save-my-details checkbox. */
39
+ saveProfile: string;
40
+ /** The refusal Alert's title (its body is the server's own sentence). */
41
+ cannotContinueTitle: string;
42
+ /** The sticky bar's one action. */
43
+ continueAction: string;
44
+ /**
45
+ * The reassurance caption under it. OPTIONAL, on the flows port's
46
+ * `secureNotice` precedent: a host that has not written the sentence gets
47
+ * NO caption rather than someone else's.
48
+ */
49
+ secureNotice?: string;
50
+ /** The slim header's back control, on Dados and after it. */
51
+ keepShopping: string;
52
+ back: string;
53
+ }
54
+
55
+ /** Nothing to check out (cart mode only). */
56
+ export interface EmptyCartCopy {
57
+ title: string;
58
+ action: string;
59
+ }
60
+
61
+ /** One outcome's headline and its single supporting line. */
62
+ export interface StatusOutcomeCopy {
63
+ heading: string;
64
+ support: string;
65
+ }
66
+
67
+ /**
68
+ * The confirmation screen. Icons and tones stay the component's — they are
69
+ * visual grammar, not language; every SENTENCE is the host's, including the
70
+ * timed-out wait's "do not pay again", which is the one instruction on this
71
+ * screen that matters (FUT-556).
72
+ */
73
+ export interface PaymentStatusCopy {
74
+ paid: StatusOutcomeCopy;
75
+ awaiting: StatusOutcomeCopy;
76
+ failed: StatusOutcomeCopy;
77
+ expired: StatusOutcomeCopy;
78
+ awaitingTimedOut: StatusOutcomeCopy;
79
+ retryAction: string;
80
+ regenerateAction: string;
81
+ backAction: string;
82
+ /** The paid receipt's three row labels. */
83
+ amountLabel: string;
84
+ referenceLabel: string;
85
+ receiptEmailLabel: string;
86
+ }
87
+
88
+ /** What the legacy `CheckoutFlow` itself renders and must be handed. */
89
+ export interface CheckoutViewCopy {
90
+ steps: CheckoutStepperCopy;
91
+ dados: DadosStepCopy;
92
+ emptyCart: EmptyCartCopy;
93
+ status: PaymentStatusCopy;
94
+ }
package/src/flows/copy.ts CHANGED
@@ -18,8 +18,20 @@
18
18
  * the port and nothing else.
19
19
  */
20
20
 
21
+ import type { CheckoutViewCopy } from "../components/checkout/view-copy";
22
+
23
+ export type { CheckoutViewCopy };
24
+
21
25
  /** Every buyer-facing string the factory's own screens render. */
22
26
  export interface CheckoutCopyFE {
27
+ /**
28
+ * Everything the wrapped `CheckoutFlow` itself renders — stepper labels,
29
+ * the Dados step, the empty cart, the whole confirmation screen. FUT-741
30
+ * scoped those screens out as "already carried their own product copy";
31
+ * that copy was one application's Portuguese, so the scope-out WAS the
32
+ * leak. A pt-BR host passes `PT_BR_CHECKOUT_VIEW_COPY` here by hand.
33
+ */
34
+ views: CheckoutViewCopy;
23
35
  /** No provider connected AND no host remedy: the store simply does not charge. */
24
36
  unavailableTitle: string;
25
37
  unavailableBody: string;
@@ -47,11 +59,23 @@ export interface CheckoutCopyFE {
47
59
  * part only a host can own.
48
60
  */
49
61
  returnTimedOut?: string;
50
- /** Nothing to check out (cart mode only). */
51
- emptyCartTitle: string;
52
- emptyCartAction: string;
53
62
  /** The Dados step's primary action. */
54
63
  continueAction: string;
64
+ /**
65
+ * The reassurance caption under that action.
66
+ *
67
+ * The screen rendered "Pagamento seguro" inline — one line below a sibling
68
+ * reading `runtime.copy.continueAction`, so the port was already there and
69
+ * already required; this string simply never asked it. That is the shape
70
+ * FUT-760 left behind: defaults removed from the CONFIG surface without the
71
+ * rendering being rewired, so a host that dutifully passes copy still gets
72
+ * the origin product's voice.
73
+ *
74
+ * OPTIONAL, on the {@link CheckoutCopyFE.returnTimedOut} precedent: a host
75
+ * that has not written the sentence gets NO caption rather than someone
76
+ * else's. Reassurance nobody chose is worth less than silence.
77
+ */
78
+ secureNotice?: string;
55
79
  /** The add-card screen (FUT-183): putting a card on file outside a purchase. */
56
80
  addCardTitle: string;
57
81
  addCardAction: string;
@@ -85,6 +85,7 @@ function buildCheckout(
85
85
 
86
86
  return (
87
87
  <CheckoutFlow
88
+ copy={runtime.copy.views}
88
89
  cart={cart}
89
90
  createOrder={createOrder}
90
91
  saveBuyerContact={ports.saveBuyerContact}
@@ -87,9 +87,11 @@ function buildBuyerDetails(runtime: FlowsRuntime): CheckoutScreens["BuyerDetails
87
87
  {runtime.copy.continueAction}
88
88
  </Button>
89
89
  </Box>
90
- <Text variant="caption" size="xs" color="secondary" as="p">
91
- Pagamento seguro
92
- </Text>
90
+ {runtime.copy.secureNotice ? (
91
+ <Text variant="caption" size="xs" color="secondary" as="p">
92
+ {runtime.copy.secureNotice}
93
+ </Text>
94
+ ) : null}
93
95
  </Box>
94
96
  );
95
97
  }
@@ -155,7 +157,7 @@ function buildEmptyCart(runtime: FlowsRuntime): CheckoutScreens["EmptyCart"] {
155
157
  return function EmptyCart() {
156
158
  return (
157
159
  <FlowsShell runtime={runtime}>
158
- <EmptyCartView onBack={runtime.config.ports.exitToCatalog} />
160
+ <EmptyCartView copy={runtime.copy.views.emptyCart} onBack={runtime.config.ports.exitToCatalog} />
159
161
  </FlowsShell>
160
162
  );
161
163
  };
@@ -82,6 +82,7 @@ function buildPaymentStatus(runtime: FlowsRuntime): CheckoutScreens["PaymentStat
82
82
  return (
83
83
  <FlowsShell runtime={runtime}>
84
84
  <PaymentStatusView
85
+ copy={runtime.copy.views.status}
85
86
  status={status}
86
87
  totalLabel={payable?.totalLabel ?? ""}
87
88
  orderId={payable?.orderId}
package/src/index.ts CHANGED
@@ -85,6 +85,20 @@ export {
85
85
  } from './components/checkout/transport';
86
86
  export { type CheckoutHostPorts } from './components/checkout/use-checkout-controller';
87
87
  export { PaymentsUnavailable } from './components/checkout/payments-unavailable';
88
+ export type {
89
+ CheckoutStepperCopy,
90
+ CheckoutViewCopy,
91
+ DadosStepCopy,
92
+ EmptyCartCopy,
93
+ PaymentStatusCopy,
94
+ PaymentsUnavailableCopy,
95
+ StatusOutcomeCopy,
96
+ } from './components/checkout/view-copy';
97
+ export {
98
+ PT_BR_CHECKOUT_VIEW_COPY,
99
+ PT_BR_PAYMENTS_UNAVAILABLE_COPY,
100
+ PT_BR_PAYMENT_STATUS_COPY,
101
+ } from './components/checkout/pt-BR';
88
102
  export { fetchCheckoutConfig } from './components/checkout/client';
89
103
  /**
90
104
  * The `sessionStorage` key the hosted-checkout return leg parks the raised