@12-apps/payments-frontend 1.15.2 → 1.15.3
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"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.",
|
|
6
6
|
"exports": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"storybook:build": "storybook build"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@12-apps/payments-backend": "^1.15.
|
|
20
|
+
"@12-apps/payments-backend": "^1.15.3",
|
|
21
21
|
"react-qr-code": "^2.2.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"react-dom": ">=19.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@12-apps/eslint-config": "^1.17.
|
|
32
|
-
"@12-apps/typescript-config": "^1.17.
|
|
31
|
+
"@12-apps/eslint-config": "^1.17.3",
|
|
32
|
+
"@12-apps/typescript-config": "^1.17.3",
|
|
33
33
|
"@emotion/react": "^11.14.0",
|
|
34
34
|
"@emotion/styled": "^11.14.0",
|
|
35
35
|
"@mui/material": "^6.5.0",
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
} from '@12-apps/payments-backend';
|
|
23
23
|
|
|
24
24
|
import type { PaymentsSettingsClient } from '../client';
|
|
25
|
-
import { isConnected } from './connection-state';
|
|
25
|
+
import { expiryProximity, isConnected } from './connection-state';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* The `authMode: 'oauth'` half of the settings page: a provider whose
|
|
@@ -49,10 +49,35 @@ export interface ProviderConnectionProps {
|
|
|
49
49
|
onChanged: () => void;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
/**
|
|
53
|
+
* The expiry caption, with PROXIMITY emphasis (FUT-683): the renewal sweep
|
|
54
|
+
* normally refreshes a grant long before it lapses, so an expiry that is
|
|
55
|
+
* actually close means renewal has been failing quietly — and this caption is
|
|
56
|
+
* the only warning an owner gets before checkout starts refusing. A neutral
|
|
57
|
+
* gray line read the same on the eve of an outage as a year out.
|
|
58
|
+
*/
|
|
59
|
+
function ExpiryNote(props: { expiresAt: string }) {
|
|
60
|
+
const when = new Date(props.expiresAt).toLocaleString('pt-BR');
|
|
61
|
+
const proximity = expiryProximity(props.expiresAt);
|
|
62
|
+
if (proximity === 'SAFE' || proximity === null) {
|
|
63
|
+
return (
|
|
64
|
+
<Typography variant="caption" color="text.secondary">
|
|
65
|
+
{`Autorização válida até ${when}`}
|
|
66
|
+
</Typography>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return (
|
|
70
|
+
<Typography
|
|
71
|
+
variant="caption"
|
|
72
|
+
color={proximity === 'PAST' ? 'error.main' : 'warning.main'}
|
|
73
|
+
sx={{ fontWeight: 600 }}
|
|
74
|
+
data-testid="payments-expiry-warning"
|
|
75
|
+
>
|
|
76
|
+
{proximity === 'PAST'
|
|
77
|
+
? `A autorização expirou em ${when}. Reconecte para voltar a receber pagamentos.`
|
|
78
|
+
: `A autorização expira em ${when}. Se o aviso continuar, reconecte a conta.`}
|
|
79
|
+
</Typography>
|
|
80
|
+
);
|
|
56
81
|
}
|
|
57
82
|
|
|
58
83
|
function connectLabel(displayName: string, connected: boolean, busy: string | null) {
|
|
@@ -98,11 +123,7 @@ function ConnectionSummary(props: {
|
|
|
98
123
|
A autorização expirou ou foi revogada. Reconecte para voltar a receber pagamentos.
|
|
99
124
|
</Alert>
|
|
100
125
|
) : null}
|
|
101
|
-
{props.expiresAt ?
|
|
102
|
-
<Typography variant="caption" color="text.secondary">
|
|
103
|
-
{expiryNote(props.expiresAt)}
|
|
104
|
-
</Typography>
|
|
105
|
-
) : null}
|
|
126
|
+
{props.expiresAt ? <ExpiryNote expiresAt={props.expiresAt} /> : null}
|
|
106
127
|
</>
|
|
107
128
|
);
|
|
108
129
|
}
|
|
@@ -46,6 +46,37 @@ export function canAttemptCharge(config: MaskedProviderConfig | null | undefined
|
|
|
46
46
|
return false;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* How close `expiresAt` is to becoming an outage, in buckets the UI can
|
|
51
|
+
* style (FUT-683).
|
|
52
|
+
*
|
|
53
|
+
* The host's renewal sweep normally refreshes a grant long before this ever
|
|
54
|
+
* says `NEAR` — so `NEAR` is not "working as intended", it is the sweep having
|
|
55
|
+
* failed quietly for days, and the caption is the only place an owner can see
|
|
56
|
+
* it coming before checkout starts refusing. `PAST` means the grant is already
|
|
57
|
+
* dead even if the status has not caught up yet.
|
|
58
|
+
*/
|
|
59
|
+
type ExpiryProximity = 'SAFE' | 'NEAR' | 'PAST';
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A week: several sweep cycles' worth of margin, so a single missed run never
|
|
63
|
+
* alarms anyone, while a renewal that keeps failing surfaces well before the
|
|
64
|
+
* grant actually lapses.
|
|
65
|
+
*/
|
|
66
|
+
const EXPIRY_WARNING_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
67
|
+
|
|
68
|
+
/** Where `expiresAt` stands relative to `now`; null when it cannot expire. */
|
|
69
|
+
export function expiryProximity(
|
|
70
|
+
expiresAt: string | null | undefined,
|
|
71
|
+
now: Date = new Date(),
|
|
72
|
+
): ExpiryProximity | null {
|
|
73
|
+
if (!expiresAt) return null;
|
|
74
|
+
const at = new Date(expiresAt).getTime();
|
|
75
|
+
if (Number.isNaN(at)) return null;
|
|
76
|
+
if (at <= now.getTime()) return 'PAST';
|
|
77
|
+
return at - now.getTime() <= EXPIRY_WARNING_WINDOW_MS ? 'NEAR' : 'SAFE';
|
|
78
|
+
}
|
|
79
|
+
|
|
49
80
|
/** What a provider card reports at a glance. */
|
|
50
81
|
type ConnectionBadge =
|
|
51
82
|
| { label: 'Ativo'; color: 'success' }
|