@owlmeans/web-payment 0.1.18-rc.2 → 0.1.18-rc.21
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/README.md +30 -1
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/web-payment/SKILL.md +287 -20
- package/build/@/components/ui/card.d.ts +10 -0
- package/build/@/components/ui/card.d.ts.map +1 -0
- package/build/@/components/ui/card.js +25 -0
- package/build/@/components/ui/card.js.map +1 -0
- package/build/@/components/ui/checkbox.d.ts +5 -0
- package/build/@/components/ui/checkbox.d.ts.map +1 -0
- package/build/@/components/ui/checkbox.js +6 -0
- package/build/@/components/ui/checkbox.js.map +1 -0
- package/build/@/components/ui/progress.d.ts +5 -0
- package/build/@/components/ui/progress.d.ts.map +1 -0
- package/build/@/components/ui/progress.js +11 -0
- package/build/@/components/ui/progress.js.map +1 -0
- package/build/@/components/ui/select.d.ts +8 -0
- package/build/@/components/ui/select.d.ts.map +1 -0
- package/build/@/components/ui/select.js +9 -0
- package/build/@/components/ui/select.js.map +1 -0
- package/build/capability-list.d.ts +7 -0
- package/build/capability-list.d.ts.map +1 -0
- package/build/capability-list.js +24 -0
- package/build/capability-list.js.map +1 -0
- package/build/checkout-limit.d.ts +11 -0
- package/build/checkout-limit.d.ts.map +1 -0
- package/build/checkout-limit.js +34 -0
- package/build/checkout-limit.js.map +1 -0
- package/build/consumer/cancellation.d.ts +20 -0
- package/build/consumer/cancellation.d.ts.map +1 -0
- package/build/consumer/cancellation.js +115 -0
- package/build/consumer/cancellation.js.map +1 -0
- package/build/consumer/copy.d.ts +23 -0
- package/build/consumer/copy.d.ts.map +1 -0
- package/build/consumer/copy.js +75 -0
- package/build/consumer/copy.js.map +1 -0
- package/build/consumer/ensure.d.ts +56 -0
- package/build/consumer/ensure.d.ts.map +1 -0
- package/build/consumer/ensure.js +71 -0
- package/build/consumer/ensure.js.map +1 -0
- package/build/consumer/fields.d.ts +43 -0
- package/build/consumer/fields.d.ts.map +1 -0
- package/build/consumer/fields.js +19 -0
- package/build/consumer/fields.js.map +1 -0
- package/build/consumer/hooks.d.ts +113 -0
- package/build/consumer/hooks.d.ts.map +1 -0
- package/build/consumer/hooks.js +225 -0
- package/build/consumer/hooks.js.map +1 -0
- package/build/consumer/index.d.ts +14 -0
- package/build/consumer/index.d.ts.map +1 -0
- package/build/consumer/index.js +12 -0
- package/build/consumer/index.js.map +1 -0
- package/build/consumer/legal.d.ts +53 -0
- package/build/consumer/legal.d.ts.map +1 -0
- package/build/consumer/legal.js +77 -0
- package/build/consumer/legal.js.map +1 -0
- package/build/consumer/performance-consent-dialog.d.ts +18 -0
- package/build/consumer/performance-consent-dialog.d.ts.map +1 -0
- package/build/consumer/performance-consent-dialog.js +71 -0
- package/build/consumer/performance-consent-dialog.js.map +1 -0
- package/build/consumer/provider.d.ts +33 -0
- package/build/consumer/provider.d.ts.map +1 -0
- package/build/consumer/provider.js +26 -0
- package/build/consumer/provider.js.map +1 -0
- package/build/consumer/refusal.d.ts +35 -0
- package/build/consumer/refusal.d.ts.map +1 -0
- package/build/consumer/refusal.js +98 -0
- package/build/consumer/refusal.js.map +1 -0
- package/build/consumer/subscription-start-dialog.d.ts +16 -0
- package/build/consumer/subscription-start-dialog.d.ts.map +1 -0
- package/build/consumer/subscription-start-dialog.js +43 -0
- package/build/consumer/subscription-start-dialog.js.map +1 -0
- package/build/consumer/types.d.ts +114 -0
- package/build/consumer/types.d.ts.map +1 -0
- package/build/consumer/types.js +2 -0
- package/build/consumer/types.js.map +1 -0
- package/build/consumer/withdrawal.d.ts +29 -0
- package/build/consumer/withdrawal.d.ts.map +1 -0
- package/build/consumer/withdrawal.js +140 -0
- package/build/consumer/withdrawal.js.map +1 -0
- package/build/copy.d.ts +14 -0
- package/build/copy.d.ts.map +1 -0
- package/build/copy.js +51 -0
- package/build/copy.js.map +1 -0
- package/build/dialog.d.ts +1 -1
- package/build/dialog.d.ts.map +1 -1
- package/build/dialog.js +46 -17
- package/build/dialog.js.map +1 -1
- package/build/entitlement.d.ts +26 -0
- package/build/entitlement.d.ts.map +1 -0
- package/build/entitlement.js +42 -0
- package/build/entitlement.js.map +1 -0
- package/build/estimate-cache.d.ts +14 -0
- package/build/estimate-cache.d.ts.map +1 -0
- package/build/estimate-cache.js +39 -0
- package/build/estimate-cache.js.map +1 -0
- package/build/estimate-summary.d.ts +64 -0
- package/build/estimate-summary.d.ts.map +1 -0
- package/build/estimate-summary.js +94 -0
- package/build/estimate-summary.js.map +1 -0
- package/build/estimate.d.ts +34 -0
- package/build/estimate.d.ts.map +1 -0
- package/build/estimate.js +92 -0
- package/build/estimate.js.map +1 -0
- package/build/format.d.ts +15 -0
- package/build/format.d.ts.map +1 -0
- package/build/format.js +68 -0
- package/build/format.js.map +1 -0
- package/build/hooks.d.ts +0 -4
- package/build/hooks.d.ts.map +1 -1
- package/build/hooks.js +3 -30
- package/build/hooks.js.map +1 -1
- package/build/i18n/be.json +1 -1
- package/build/i18n/de.json +1 -1
- package/build/i18n/en.json +1 -1
- package/build/i18n/es.json +1 -1
- package/build/i18n/fr.json +145 -0
- package/build/i18n/pl.json +1 -1
- package/build/i18n/ru.json +1 -1
- package/build/i18n/uk.json +1 -1
- package/build/i18n.d.ts +2 -1
- package/build/i18n.d.ts.map +1 -1
- package/build/i18n.js +11 -7
- package/build/i18n.js.map +1 -1
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -0
- package/build/index.js.map +1 -1
- package/build/limit-meter.d.ts +7 -0
- package/build/limit-meter.d.ts.map +1 -0
- package/build/limit-meter.js +26 -0
- package/build/limit-meter.js.map +1 -0
- package/build/plan-card.d.ts +7 -0
- package/build/plan-card.d.ts.map +1 -0
- package/build/plan-card.js +29 -0
- package/build/plan-card.js.map +1 -0
- package/build/poll.d.ts +7 -0
- package/build/poll.d.ts.map +1 -0
- package/build/poll.js +28 -0
- package/build/poll.js.map +1 -0
- package/build/selectors.d.ts +18 -0
- package/build/selectors.d.ts.map +1 -0
- package/build/selectors.js +78 -0
- package/build/selectors.js.map +1 -0
- package/build/types.d.ts +120 -2
- package/build/types.d.ts.map +1 -1
- package/package.json +22 -7
- package/src/@/components/ui/card.tsx +93 -0
- package/src/@/components/ui/checkbox.tsx +23 -0
- package/src/@/components/ui/progress.tsx +44 -0
- package/src/@/components/ui/select.tsx +62 -0
- package/src/@/globals.css +10 -0
- package/src/capability-list.tsx +50 -0
- package/src/checkout-limit.tsx +48 -0
- package/src/consumer/cancellation.tsx +214 -0
- package/src/consumer/copy.ts +93 -0
- package/src/consumer/ensure.ts +124 -0
- package/src/consumer/fields.tsx +89 -0
- package/src/consumer/hooks.ts +358 -0
- package/src/consumer/index.ts +13 -0
- package/src/consumer/legal.tsx +129 -0
- package/src/consumer/performance-consent-dialog.tsx +132 -0
- package/src/consumer/provider.tsx +49 -0
- package/src/consumer/refusal.ts +110 -0
- package/src/consumer/subscription-start-dialog.tsx +87 -0
- package/src/consumer/types.ts +121 -0
- package/src/consumer/withdrawal.tsx +279 -0
- package/src/copy.tsx +62 -0
- package/src/dialog.tsx +58 -25
- package/src/entitlement.ts +56 -0
- package/src/estimate-cache.ts +40 -0
- package/src/estimate-summary.tsx +172 -0
- package/src/estimate.ts +119 -0
- package/src/format.ts +71 -0
- package/src/hooks.ts +3 -35
- package/src/i18n/be.json +1 -1
- package/src/i18n/de.json +1 -1
- package/src/i18n/en.json +1 -1
- package/src/i18n/es.json +1 -1
- package/src/i18n/fr.json +145 -0
- package/src/i18n/pl.json +1 -1
- package/src/i18n/ru.json +1 -1
- package/src/i18n/uk.json +1 -1
- package/src/i18n.ts +12 -7
- package/src/index.ts +9 -0
- package/src/limit-meter.tsx +55 -0
- package/src/plan-card.tsx +67 -0
- package/src/poll.ts +27 -0
- package/src/selectors.ts +93 -0
- package/src/types.ts +142 -2
- package/tests/consent-refusal.spec.ts +83 -0
- package/tests/consumer-hooks.spec.ts +205 -0
- package/tests/consumer.spec.ts +343 -0
- package/tests/context.ts +9 -0
- package/tests/dialog.spec.ts +49 -0
- package/tests/entitlement.spec.ts +117 -0
- package/tests/estimate-cache.spec.ts +46 -0
- package/tests/harness/consumer-fixtures.ts +105 -0
- package/tests/harness/consumer.tsx +197 -0
- package/tests/harness/entitlement.tsx +159 -0
- package/tests/harness/estimate-fixtures.ts +48 -0
- package/tests/harness/mount.tsx +19 -3
- package/tests/i18n.spec.ts +78 -8
- package/tests/pieces.spec.ts +134 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { Checkbox } from '@/components/ui/checkbox';
|
|
6
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog';
|
|
7
|
+
import { Label } from '@/components/ui/label';
|
|
8
|
+
import { lastDayUtc, dayUtc, money } from '../format.js';
|
|
9
|
+
import { useLegalText, usePaymentText } from './copy.js';
|
|
10
|
+
import { ErrorLine, LanguageToggle, LegalLinks, linksFor, useShownLanguage } from './legal.js';
|
|
11
|
+
/** The latest deadline of the view — its own, else the latest of its purchases. */
|
|
12
|
+
const deadlineOf = (view) => {
|
|
13
|
+
if (view.deadline != null) {
|
|
14
|
+
return new Date(view.deadline);
|
|
15
|
+
}
|
|
16
|
+
const times = view.purchases
|
|
17
|
+
.map(purchase => purchase.deadline != null ? new Date(purchase.deadline).getTime() : NaN)
|
|
18
|
+
.filter(time => !Number.isNaN(time));
|
|
19
|
+
return times.length > 0 ? new Date(Math.max(...times)) : undefined;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The express request to start performing now, asked before credits bought inside their
|
|
23
|
+
* withdrawal window are spent (CRD Art. 16(m), § 356 Abs. 5 BGB, art. 38 UoPK, L221-28).
|
|
24
|
+
*
|
|
25
|
+
* The legal copy is shown in the CONTRACT language (`view.language`) with a toggle to the
|
|
26
|
+
* interface language; the purchases it covers are listed with their deadlines; ONE checkbox
|
|
27
|
+
* carries the whole statement and starts unchecked, and the confirm button stays disabled until
|
|
28
|
+
* it is ticked. Toggling the language unticks it — the statement agreed to is the one on screen —
|
|
29
|
+
* and `onConfirm` records the language actually shown.
|
|
30
|
+
*
|
|
31
|
+
* Selectors: `[data-consent-dialog]` (with `data-language`, `data-contract-language`),
|
|
32
|
+
* `[data-consent-purchase]` (`data-purchase-id`, `data-deadline`), `[data-consent-checkbox]`,
|
|
33
|
+
* `[data-consent-confirm]`, `[data-consent-decline]`, `[data-consent-language-toggle]`,
|
|
34
|
+
* `[data-legal-link]`.
|
|
35
|
+
*/
|
|
36
|
+
export const PerformanceConsentDialog = ({ open, onOpenChange, view, uiLanguage, pending = false, error, onConfirm, onDecline, links, onWithdraw, formatAmount, className, }) => {
|
|
37
|
+
const language = useShownLanguage(view?.language ?? '', uiLanguage, open);
|
|
38
|
+
const legal = useLegalText(language.shown);
|
|
39
|
+
const text = usePaymentText(language.shown);
|
|
40
|
+
const [ticked, setTicked] = useState(false);
|
|
41
|
+
useEffect(() => { setTicked(false); }, [open, language.shown, view?.textVersion]);
|
|
42
|
+
if (view == null) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const format = (minor, currency) => formatAmount != null
|
|
46
|
+
? formatAmount(minor, currency, language.shown) : money(minor, currency, language.shown);
|
|
47
|
+
// The same text `consentStatementOf(lng, 'performance', { trader })` renders on the server.
|
|
48
|
+
const checkbox = legal('performance-consent.checkbox', { trader: view.trader });
|
|
49
|
+
const deadline = deadlineOf(view);
|
|
50
|
+
const shownLinks = linksFor(language.shown, view.links, links);
|
|
51
|
+
const confirm = async () => {
|
|
52
|
+
if (!ticked || pending) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
await onConfirm({
|
|
56
|
+
purchaseIds: view.purchases.map(purchase => purchase.purchaseId),
|
|
57
|
+
textVersion: view.textVersion,
|
|
58
|
+
language: language.shown,
|
|
59
|
+
acknowledged: true,
|
|
60
|
+
uiLanguage: language.ui,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
return _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { closeLabel: text('consumer.close'), "data-consent-dialog": "", "data-performance-consent": "", "data-language": language.shown, "data-contract-language": language.contract, "data-text-version": view.textVersion, className: cn('max-h-[90vh] overflow-y-auto', className), ...(deadline == null ? { 'aria-describedby': undefined } : {}), children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { lang: language.shown, children: legal('performance-consent.title') }), deadline != null && _jsx(DialogDescription, { lang: language.shown, children: legal('performance-consent.intro', { count: view.purchases.length, deadline: lastDayUtc(deadline, language.shown) }) })] }), _jsx(LanguageToggle, { language: language, hook: "data-consent-language-toggle" }), _jsxs("div", { className: "grid gap-4", lang: language.shown, children: [view.purchases.length > 0 && _jsxs("section", { className: "grid gap-2", "aria-label": text('consumer.purchases'), children: [_jsx("h3", { className: "text-sm font-medium", children: text('consumer.purchases') }), _jsx("ul", { className: "grid gap-1.5 text-sm", children: view.purchases.map(purchase => _jsx("li", { "data-consent-purchase": "", "data-purchase-id": purchase.purchaseId, "data-deadline": purchase.deadline != null ? new Date(purchase.deadline).toISOString() : undefined, className: "rounded-md border px-3 py-2", children: purchase.deadline != null
|
|
64
|
+
? legal('performance-consent.purchase', {
|
|
65
|
+
date: dayUtc(purchase.purchasedAt, language.shown),
|
|
66
|
+
amount: format(purchase.amountTotalMinor, purchase.currency),
|
|
67
|
+
deadline: lastDayUtc(purchase.deadline, language.shown),
|
|
68
|
+
})
|
|
69
|
+
: `${dayUtc(purchase.purchasedAt, language.shown)} (${format(purchase.amountTotalMinor, purchase.currency)})` }, purchase.purchaseId)) })] }), _jsxs("div", { className: "flex items-start gap-3 rounded-md border p-3", children: [_jsx(Checkbox, { id: "performance-consent-checkbox", "data-consent-checkbox": "", checked: ticked, disabled: pending, onCheckedChange: value => setTicked(value === true), className: "mt-0.5" }), _jsx(Label, { htmlFor: "performance-consent-checkbox", className: "block text-sm leading-snug font-normal", "data-consent-statement": "", children: checkbox })] }), _jsx(LegalLinks, { links: shownLinks, legal: legal, onWithdraw: onWithdraw }), _jsx(ErrorLine, { error: error, text: text })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", "data-consent-decline": "", disabled: pending, onClick: () => onDecline != null ? onDecline() : onOpenChange(false), children: legal('performance-consent.decline') }), _jsx(Button, { type: "button", "data-consent-confirm": "", disabled: !ticked || pending, onClick: () => void confirm(), children: pending ? text('consumer.pending') : legal('performance-consent.confirm') })] })] }) });
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=performance-consent-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-consent-dialog.js","sourceRoot":"","sources":["../../src/consumer/performance-consent-dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EACL,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,GAClF,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAG9F,mFAAmF;AACnF,MAAM,UAAU,GAAG,CAAC,IAA4B,EAAoB,EAAE;IACpE,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC1B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS;SACzB,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;SACxF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;IAEtC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACpE,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EACvC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EACrG,YAAY,EAAE,SAAS,GACO,EAAE,EAAE;IAClC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;IACzE,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,SAAS,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAA;IAChF,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAE,EAAE,CAAC,YAAY,IAAI,IAAI;QACtE,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC1F,4FAA4F;IAC5F,MAAM,QAAQ,GAAG,KAAK,CAAC,8BAA8B,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/E,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAC9D,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QACD,MAAM,SAAS,CAAC;YACd,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC;YAChE,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,QAAQ,EAAE,QAAQ,CAAC,KAAK;YACxB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,QAAQ,CAAC,EAAE;SACxB,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,OAAO,KAAC,MAAM,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,YACnD,MAAC,aAAa,IACZ,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,yBACd,EAAE,8BAA0B,EAAE,mBAAgB,QAAQ,CAAC,KAAK,4BACxD,QAAQ,CAAC,QAAQ,uBAAqB,IAAI,CAAC,WAAW,EAC9E,SAAS,EAAE,EAAE,CAAC,8BAA8B,EAAE,SAAS,CAAC,KACpD,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAE/D,MAAC,YAAY,eACX,KAAC,WAAW,IAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,YAAG,KAAK,CAAC,2BAA2B,CAAC,GAAe,EACpF,QAAQ,IAAI,IAAI,IAAI,KAAC,iBAAiB,IAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,YACzD,KAAK,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GACnG,IACP,EACf,KAAC,cAAc,IAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAC,8BAA8B,GAAG,EAC1E,eAAK,SAAS,EAAC,YAAY,EAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,aAC7C,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,mBAAS,SAAS,EAAC,YAAY,gBAAa,IAAI,CAAC,oBAAoB,CAAC,aAClG,aAAI,SAAS,EAAC,qBAAqB,YAAE,IAAI,CAAC,oBAAoB,CAAC,GAAM,EACrE,aAAI,SAAS,EAAC,sBAAsB,YACjC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,sCACkB,EAAE,sBAAmB,QAAQ,CAAC,UAAU,mBACzE,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,EAChG,SAAS,EAAC,6BAA6B,YAEtC,QAAQ,CAAC,QAAQ,IAAI,IAAI;4CACxB,CAAC,CAAC,KAAK,CAAC,8BAA8B,EAAE;gDACtC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC;gDAClD,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAC;gDAC5D,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC;6CACxD,CAAC;4CACF,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAV1G,QAAQ,CAAC,UAAU,CAWrB,CAAC,GACH,IACG,EACV,eAAK,SAAS,EAAC,8CAA8C,aAC3D,KAAC,QAAQ,IACP,EAAE,EAAC,8BAA8B,2BAAuB,EAAE,EAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAC7F,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,SAAS,EAAC,QAAQ,GACvE,EACF,KAAC,KAAK,IAAC,OAAO,EAAC,8BAA8B,EAAC,SAAS,EAAC,wCAAwC,4BACvE,EAAE,YACxB,QAAQ,GACH,IACJ,EACN,KAAC,UAAU,IAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,GAAI,EACvE,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAI,IACnC,EACN,MAAC,YAAY,eACX,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,0BAAsB,EAAE,EAAC,QAAQ,EAAE,OAAO,EAC/E,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,YACnE,KAAK,CAAC,6BAA6B,CAAC,GAC9B,EACT,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,0BAAsB,EAAE,EAAC,QAAQ,EAAE,CAAC,MAAM,IAAI,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,YACtG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,6BAA6B,CAAC,GACnE,IACI,IACD,GACT,CAAA;AACX,CAAC,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { RegisteredEntrypoint, RequestShape } from '@owlmeans/entrypoint';
|
|
3
|
+
import type { PerformanceConsentBody, PerformanceConsentResponse, PerformanceConsentView } from '@owlmeans/payment';
|
|
4
|
+
import { type ConsentGate } from './ensure.js';
|
|
5
|
+
import { type UsePerformanceConsentOptions } from './hooks.js';
|
|
6
|
+
export interface ConsentGateValue extends ConsentGate {
|
|
7
|
+
/** From the last read of the view; `null` before any, and always outside a provider. */
|
|
8
|
+
required: boolean | null;
|
|
9
|
+
}
|
|
10
|
+
export interface PerformanceConsentProviderProps<RecordRequest extends RequestShape & {
|
|
11
|
+
body: PerformanceConsentBody;
|
|
12
|
+
}> {
|
|
13
|
+
view: RegisteredEntrypoint<{}, PerformanceConsentView>;
|
|
14
|
+
record: RegisteredEntrypoint<RecordRequest, PerformanceConsentResponse>;
|
|
15
|
+
options?: UsePerformanceConsentOptions;
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* ONE spend-consent dialog for the whole application, and the gate every action that may spend
|
|
20
|
+
* credits reads with `useConsentGate()`: however many buttons ask at once, one dialog opens and
|
|
21
|
+
* they all get its answer.
|
|
22
|
+
*/
|
|
23
|
+
export declare const PerformanceConsentProvider: <RecordRequest extends RequestShape & {
|
|
24
|
+
body: PerformanceConsentBody;
|
|
25
|
+
}>({ view, record, options, children, }: PerformanceConsentProviderProps<RecordRequest>) => import("react").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* The application's consent gate: `ensure()` asks proactively, `withConsent(action)` runs an
|
|
28
|
+
* action and, when it is refused for the spend consent, asks and retries it exactly once
|
|
29
|
+
* (`ConsentDeclined` on a decline). Outside a `PerformanceConsentProvider` nothing can be asked:
|
|
30
|
+
* `ensure` answers `true` and a refusal propagates unchanged.
|
|
31
|
+
*/
|
|
32
|
+
export declare const useConsentGate: () => ConsentGateValue;
|
|
33
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/consumer/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AACnH,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAChF,OAAO,EAAyB,KAAK,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAGrF,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,wFAAwF;IACxF,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAA;CACzB;AAID,MAAM,WAAW,+BAA+B,CAAC,aAAa,SAAS,YAAY,GAAG;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE;IACpH,IAAI,EAAE,oBAAoB,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAA;IACtD,MAAM,EAAE,oBAAoB,CAAC,aAAa,EAAE,0BAA0B,CAAC,CAAA;IACvE,OAAO,CAAC,EAAE,4BAA4B,CAAA;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GAAI,aAAa,SAAS,YAAY,GAAG;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,wCAE7G,+BAA+B,CAAC,aAAa,CAAC,gCAShD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAO,gBACc,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
import { makeConsentGate, passThroughGate } from './ensure.js';
|
|
4
|
+
import { usePerformanceConsent } from './hooks.js';
|
|
5
|
+
import { PerformanceConsentDialog } from './performance-consent-dialog.js';
|
|
6
|
+
const ConsentGateContext = createContext(null);
|
|
7
|
+
/**
|
|
8
|
+
* ONE spend-consent dialog for the whole application, and the gate every action that may spend
|
|
9
|
+
* credits reads with `useConsentGate()`: however many buttons ask at once, one dialog opens and
|
|
10
|
+
* they all get its answer.
|
|
11
|
+
*/
|
|
12
|
+
export const PerformanceConsentProvider = ({ view, record, options, children, }) => {
|
|
13
|
+
const consent = usePerformanceConsent(view, record, options);
|
|
14
|
+
const { ensure, required } = consent;
|
|
15
|
+
const value = useMemo(() => ({ ...makeConsentGate(ensure), required }), [ensure, required]);
|
|
16
|
+
return _jsxs(ConsentGateContext.Provider, { value: value, children: [children, _jsx(PerformanceConsentDialog, { ...consent.dialog })] });
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The application's consent gate: `ensure()` asks proactively, `withConsent(action)` runs an
|
|
20
|
+
* action and, when it is refused for the spend consent, asks and retries it exactly once
|
|
21
|
+
* (`ConsentDeclined` on a decline). Outside a `PerformanceConsentProvider` nothing can be asked:
|
|
22
|
+
* `ensure` answers `true` and a refusal propagates unchanged.
|
|
23
|
+
*/
|
|
24
|
+
export const useConsentGate = () => useContext(ConsentGateContext) ?? PASS_THROUGH;
|
|
25
|
+
const PASS_THROUGH = { ...passThroughGate, required: null };
|
|
26
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/consumer/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAA;AAG1E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,qBAAqB,EAAqC,MAAM,YAAY,CAAA;AACrF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAA;AAO1E,MAAM,kBAAkB,GAAG,aAAa,CAA0B,IAAI,CAAC,CAAA;AASvE;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAwE,EAChH,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GACgB,EAAE,EAAE;IACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IACpC,MAAM,KAAK,GAAG,OAAO,CAAmB,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAE7G,OAAO,MAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,aAC7C,QAAQ,EACT,KAAC,wBAAwB,OAAK,OAAO,CAAC,MAAM,GAAI,IACpB,CAAA;AAChC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAqB,EAAE,CACnD,UAAU,CAAC,kBAAkB,CAAC,IAAI,YAAY,CAAA;AAEhD,MAAM,YAAY,GAAqB,EAAE,GAAG,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ConsentKind, PaymentError } from '@owlmeans/payment';
|
|
2
|
+
/**
|
|
3
|
+
* Which express request a failure asks for: `performance` (spend consent), `subscription-start`,
|
|
4
|
+
* `unknown` for a bare HTTP 428 that names neither (a production body carries only an incident
|
|
5
|
+
* id), or `null` for anything else.
|
|
6
|
+
*
|
|
7
|
+
* Read on the error itself and on whatever it wraps (`cause`, `error`, `original`, `inner`, an
|
|
8
|
+
* aggregate's `errors`), and on text as well as objects, because a refusal travels in three shapes:
|
|
9
|
+
* the class (a development body, rebuilt by the registry); its marker inside another error's
|
|
10
|
+
* message or a stored string (a planning commit that failed on the refusal answers
|
|
11
|
+
* `planning:commit-failed:<transition>:<the refusal's text>`); and the bare status of a production
|
|
12
|
+
* body (`@owlmeans/api`'s `ApiStatusError`, `api:client:status:428[:<incident>]`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const consentRefusalKindOf: (error: unknown) => ConsentKind | 'unknown' | null;
|
|
15
|
+
/**
|
|
16
|
+
* Whether a failure is a consent refusal — the class or its marker (`consentRefusalOf`), or an
|
|
17
|
+
* HTTP 428 (`httpStatusOf`), on the error or anything it wraps. What decides that the consent
|
|
18
|
+
* dialog opens and the action is retried once.
|
|
19
|
+
*/
|
|
20
|
+
export declare const isConsentRefusal: (error: unknown) => boolean;
|
|
21
|
+
/** A refusal the performance-consent dialog answers: the spend consent, or a bare 428. */
|
|
22
|
+
export declare const isPerformanceConsentRefusal: (error: unknown) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The person declined the express request, so the action that needed it did not run. Raised by
|
|
25
|
+
* `useConsentGate().withConsent` — never by a server, and never a refusal a gate retries.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ConsentDeclined extends PaymentError {
|
|
28
|
+
static typeName: string;
|
|
29
|
+
kind: string;
|
|
30
|
+
constructor(kind?: string);
|
|
31
|
+
private applyFields;
|
|
32
|
+
finalizeUnmarshal(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare const isConsentDeclined: (error: unknown) => error is ConsentDeclined;
|
|
35
|
+
//# sourceMappingURL=refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.d.ts","sourceRoot":"","sources":["../../src/consumer/refusal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAA;AAU/E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,UAAW,OAAO,KAAG,WAAW,GAAG,SAAS,GAAG,IAwC/E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAW,OAAO,KAAG,OAA8C,CAAA;AAEhG,0FAA0F;AAC1F,eAAO,MAAM,2BAA2B,UAAW,OAAO,KAAG,OAI5D,CAAA;AAID;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAuB,QAAQ,EAAE,MAAM,CAA4C;IAE5E,IAAI,EAAE,MAAM,CAA0B;IAE7C,YAAY,IAAI,GAAE,MAAgC,EAIjD;IAED,OAAO,CAAC,WAAW;IAKV,iBAAiB,IAAI,IAAI,CAEjC;CACF;AAID,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,KAAK,IAAI,eAAmD,CAAA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ResilientError } from '@owlmeans/error';
|
|
2
|
+
import { httpStatusOf } from '@owlmeans/api/status';
|
|
3
|
+
import { ConsentKind, PaymentError, consentRefusalOf } from '@owlmeans/payment';
|
|
4
|
+
/** Where a wrapping error keeps the one it wraps — `cause`, and the fields frameworks use for it. */
|
|
5
|
+
const NESTED_FIELDS = ['cause', 'error', 'original', 'originalError', 'inner', 'reason'];
|
|
6
|
+
/** How deep a wrapped chain is followed — a planning `CommitFailed` inside a transport error is two. */
|
|
7
|
+
const MAX_DEPTH = 5;
|
|
8
|
+
const PRECONDITION_REQUIRED = 428;
|
|
9
|
+
/**
|
|
10
|
+
* Which express request a failure asks for: `performance` (spend consent), `subscription-start`,
|
|
11
|
+
* `unknown` for a bare HTTP 428 that names neither (a production body carries only an incident
|
|
12
|
+
* id), or `null` for anything else.
|
|
13
|
+
*
|
|
14
|
+
* Read on the error itself and on whatever it wraps (`cause`, `error`, `original`, `inner`, an
|
|
15
|
+
* aggregate's `errors`), and on text as well as objects, because a refusal travels in three shapes:
|
|
16
|
+
* the class (a development body, rebuilt by the registry); its marker inside another error's
|
|
17
|
+
* message or a stored string (a planning commit that failed on the refusal answers
|
|
18
|
+
* `planning:commit-failed:<transition>:<the refusal's text>`); and the bare status of a production
|
|
19
|
+
* body (`@owlmeans/api`'s `ApiStatusError`, `api:client:status:428[:<incident>]`).
|
|
20
|
+
*/
|
|
21
|
+
export const consentRefusalKindOf = (error) => {
|
|
22
|
+
let status = false;
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
const visit = (value, depth) => {
|
|
25
|
+
if (value == null || depth > MAX_DEPTH) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
const holder = { message: value };
|
|
30
|
+
if (httpStatusOf(holder) === PRECONDITION_REQUIRED)
|
|
31
|
+
status = true;
|
|
32
|
+
return consentRefusalOf(holder);
|
|
33
|
+
}
|
|
34
|
+
if (typeof value !== 'object' || seen.has(value)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
seen.add(value);
|
|
38
|
+
const kind = consentRefusalOf(value);
|
|
39
|
+
if (kind != null) {
|
|
40
|
+
return kind;
|
|
41
|
+
}
|
|
42
|
+
if (httpStatusOf(value) === PRECONDITION_REQUIRED) {
|
|
43
|
+
status = true;
|
|
44
|
+
}
|
|
45
|
+
for (const field of NESTED_FIELDS) {
|
|
46
|
+
const nested = visit(value[field], depth + 1);
|
|
47
|
+
if (nested != null)
|
|
48
|
+
return nested;
|
|
49
|
+
}
|
|
50
|
+
const errors = value.errors;
|
|
51
|
+
if (Array.isArray(errors)) {
|
|
52
|
+
for (const item of errors) {
|
|
53
|
+
const nested = visit(item, depth + 1);
|
|
54
|
+
if (nested != null)
|
|
55
|
+
return nested;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
60
|
+
const kind = visit(error, 0);
|
|
61
|
+
return kind ?? (status ? 'unknown' : null);
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Whether a failure is a consent refusal — the class or its marker (`consentRefusalOf`), or an
|
|
65
|
+
* HTTP 428 (`httpStatusOf`), on the error or anything it wraps. What decides that the consent
|
|
66
|
+
* dialog opens and the action is retried once.
|
|
67
|
+
*/
|
|
68
|
+
export const isConsentRefusal = (error) => consentRefusalKindOf(error) != null;
|
|
69
|
+
/** A refusal the performance-consent dialog answers: the spend consent, or a bare 428. */
|
|
70
|
+
export const isPerformanceConsentRefusal = (error) => {
|
|
71
|
+
const kind = consentRefusalKindOf(error);
|
|
72
|
+
return kind === ConsentKind.Performance || kind === 'unknown';
|
|
73
|
+
};
|
|
74
|
+
const DECLINED_MARKER = 'consent-declined:';
|
|
75
|
+
/**
|
|
76
|
+
* The person declined the express request, so the action that needed it did not run. Raised by
|
|
77
|
+
* `useConsentGate().withConsent` — never by a server, and never a refusal a gate retries.
|
|
78
|
+
*/
|
|
79
|
+
export class ConsentDeclined extends PaymentError {
|
|
80
|
+
static typeName = `${PaymentError.typeName}ConsentDeclined`;
|
|
81
|
+
kind = ConsentKind.Performance;
|
|
82
|
+
constructor(kind = ConsentKind.Performance) {
|
|
83
|
+
super(`${DECLINED_MARKER}${kind}`);
|
|
84
|
+
this.type = ConsentDeclined.typeName;
|
|
85
|
+
this.applyFields();
|
|
86
|
+
}
|
|
87
|
+
applyFields() {
|
|
88
|
+
const at = this.message.lastIndexOf(DECLINED_MARKER);
|
|
89
|
+
if (at >= 0)
|
|
90
|
+
this.kind = this.message.slice(at + DECLINED_MARKER.length) || ConsentKind.Performance;
|
|
91
|
+
}
|
|
92
|
+
finalizeUnmarshal() {
|
|
93
|
+
this.applyFields();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
ResilientError.registerErrorClass(ConsentDeclined);
|
|
97
|
+
export const isConsentDeclined = (error) => error instanceof ConsentDeclined;
|
|
98
|
+
//# sourceMappingURL=refusal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.js","sourceRoot":"","sources":["../../src/consumer/refusal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SubscriptionStartDialogProps } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The express request to start a subscription's services before its withdrawal period ends,
|
|
4
|
+
* asked BEFORE the subscription checkout (§ 357a Abs. 2 BGB, art. 35 UoPK, L221-25; CJEU C-641/19).
|
|
5
|
+
* Without it a withdrawal owes nothing for the time used.
|
|
6
|
+
*
|
|
7
|
+
* Same shape as the performance consent: the contract language first with a toggle, one
|
|
8
|
+
* unchecked checkbox carrying the whole statement, and the confirm button — "Continue to payment",
|
|
9
|
+
* the step before the paygate's own order button — disabled until it is ticked.
|
|
10
|
+
*
|
|
11
|
+
* Selectors: `[data-start-dialog]` (`data-language`, `data-contract-language`, `data-plan-sku`),
|
|
12
|
+
* `[data-start-checkbox]`, `[data-start-confirm]`, `[data-start-decline]`,
|
|
13
|
+
* `[data-start-language-toggle]`, `[data-legal-link]`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SubscriptionStartDialog: ({ open, onOpenChange, view, planTitle, price, uiLanguage, pending, error, onConfirm, onDecline, links, onWithdraw, className, }: SubscriptionStartDialogProps) => import("react").JSX.Element | null;
|
|
16
|
+
//# sourceMappingURL=subscription-start-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-start-dialog.d.ts","sourceRoot":"","sources":["../../src/consumer/subscription-start-dialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAA;AAE9D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,oIAGjC,4BAA4B,uCA0D9B,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { Checkbox } from '@/components/ui/checkbox';
|
|
6
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog';
|
|
7
|
+
import { Label } from '@/components/ui/label';
|
|
8
|
+
import { useLegalText, usePaymentText } from './copy.js';
|
|
9
|
+
import { ErrorLine, LanguageToggle, LegalLinks, linksFor, useShownLanguage } from './legal.js';
|
|
10
|
+
/**
|
|
11
|
+
* The express request to start a subscription's services before its withdrawal period ends,
|
|
12
|
+
* asked BEFORE the subscription checkout (§ 357a Abs. 2 BGB, art. 35 UoPK, L221-25; CJEU C-641/19).
|
|
13
|
+
* Without it a withdrawal owes nothing for the time used.
|
|
14
|
+
*
|
|
15
|
+
* Same shape as the performance consent: the contract language first with a toggle, one
|
|
16
|
+
* unchecked checkbox carrying the whole statement, and the confirm button — "Continue to payment",
|
|
17
|
+
* the step before the paygate's own order button — disabled until it is ticked.
|
|
18
|
+
*
|
|
19
|
+
* Selectors: `[data-start-dialog]` (`data-language`, `data-contract-language`, `data-plan-sku`),
|
|
20
|
+
* `[data-start-checkbox]`, `[data-start-confirm]`, `[data-start-decline]`,
|
|
21
|
+
* `[data-start-language-toggle]`, `[data-legal-link]`.
|
|
22
|
+
*/
|
|
23
|
+
export const SubscriptionStartDialog = ({ open, onOpenChange, view, planTitle, price, uiLanguage, pending = false, error, onConfirm, onDecline, links, onWithdraw, className, }) => {
|
|
24
|
+
const language = useShownLanguage(view?.language ?? '', uiLanguage, open);
|
|
25
|
+
const legal = useLegalText(language.shown);
|
|
26
|
+
const text = usePaymentText(language.shown);
|
|
27
|
+
const [ticked, setTicked] = useState(false);
|
|
28
|
+
useEffect(() => { setTicked(false); }, [open, language.shown, view?.textVersion, view?.planSku]);
|
|
29
|
+
if (view == null) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// The same text `consentStatementOf(lng, 'subscription-start', { trader, plan })` renders on the server.
|
|
33
|
+
const checkbox = legal('subscription-start.checkbox', { trader: view.trader, plan: planTitle });
|
|
34
|
+
const shownLinks = linksFor(language.shown, view.links, links);
|
|
35
|
+
const confirm = async () => {
|
|
36
|
+
if (!ticked || pending) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await onConfirm({ planSku: view.planSku, textVersion: view.textVersion, language: language.shown, acknowledged: true });
|
|
40
|
+
};
|
|
41
|
+
return _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { closeLabel: text('consumer.close'), "data-start-dialog": "", "data-subscription-start": "", "data-language": language.shown, "data-contract-language": language.contract, "data-plan-sku": view.planSku, "data-text-version": view.textVersion, className: cn('max-h-[90vh] overflow-y-auto', className), children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { lang: language.shown, children: legal('subscription-start.title', { plan: planTitle }) }), _jsx(DialogDescription, { lang: language.shown, children: legal('subscription-start.intro') })] }), _jsx(LanguageToggle, { language: language, hook: "data-start-language-toggle" }), _jsxs("div", { className: "grid gap-4", lang: language.shown, children: [price != null && _jsx("div", { className: "text-sm", "data-start-price": "", children: price }), _jsxs("div", { className: "flex items-start gap-3 rounded-md border p-3", children: [_jsx(Checkbox, { id: "subscription-start-checkbox", "data-start-checkbox": "", checked: ticked, disabled: pending, onCheckedChange: value => setTicked(value === true), className: "mt-0.5" }), _jsx(Label, { htmlFor: "subscription-start-checkbox", className: "block text-sm leading-snug font-normal", "data-start-statement": "", children: checkbox })] }), _jsx(LegalLinks, { links: shownLinks, legal: legal, onWithdraw: onWithdraw }), _jsx(ErrorLine, { error: error, text: text })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", "data-start-decline": "", disabled: pending, onClick: () => onDecline != null ? onDecline() : onOpenChange(false), children: legal('subscription-start.decline') }), _jsx(Button, { type: "button", "data-start-confirm": "", disabled: !ticked || pending, onClick: () => void confirm(), children: pending ? text('consumer.pending') : legal('subscription-start.confirm') })] })] }) });
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=subscription-start-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-start-dialog.js","sourceRoot":"","sources":["../../src/consumer/subscription-start-dialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { CancellationBody, CancellationReceipt, ConsumerRightsLinks, DeclarationReceipt, PerformanceConsentBody, PerformanceConsentView, SubscriptionStartBody, SubscriptionStartView, WithdrawalBody, WithdrawalCandidateList, WithdrawalReceipt } from '@owlmeans/payment';
|
|
3
|
+
/**
|
|
4
|
+
* The legal documents of a language: a record by language (`de`, `de-AT` → `de`) or a function (a
|
|
5
|
+
* policy read through `linksOf(policy, lng)`). Absent for a language, the view's own links are used.
|
|
6
|
+
*/
|
|
7
|
+
export type LegalLinksSource = Record<string, ConsumerRightsLinks | undefined> | ((language: string) => ConsumerRightsLinks | null | undefined);
|
|
8
|
+
/** Formats an amount of minor units for a language; the default is `Intl.NumberFormat`. */
|
|
9
|
+
export type AmountFormatter = (minor: number, currency: string, language: string) => string;
|
|
10
|
+
/** `true` shows the package's generic failure sentence; a node is shown as given. */
|
|
11
|
+
export type PieceError = ReactNode | boolean;
|
|
12
|
+
/** What every consumer-rights dialog shares. */
|
|
13
|
+
export interface LegalDialogProps {
|
|
14
|
+
open: boolean;
|
|
15
|
+
onOpenChange: (open: boolean) => void;
|
|
16
|
+
/**
|
|
17
|
+
* The interface language — what the toggle switches to, and what the toggle itself is phrased
|
|
18
|
+
* in. Default: the active i18n language.
|
|
19
|
+
*/
|
|
20
|
+
uiLanguage?: string;
|
|
21
|
+
pending?: boolean;
|
|
22
|
+
error?: PieceError;
|
|
23
|
+
/** Links per language; default: the view's own links. */
|
|
24
|
+
links?: LegalLinksSource;
|
|
25
|
+
/**
|
|
26
|
+
* Opens the withdrawal function in-app. Absent, the "withdraw from contract here" link points at
|
|
27
|
+
* the links' `withdrawalFunction` page, and is left out when there is none.
|
|
28
|
+
*/
|
|
29
|
+
onWithdraw?: () => void;
|
|
30
|
+
/** Called on the decline button; closing the dialog any other way is `onOpenChange(false)`. */
|
|
31
|
+
onDecline?: () => void;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface PerformanceConsentDialogProps extends LegalDialogProps {
|
|
35
|
+
/** `null` renders nothing. */
|
|
36
|
+
view: PerformanceConsentView | null;
|
|
37
|
+
/**
|
|
38
|
+
* The express request, recorded in the language it was SHOWN in (`language`), with the
|
|
39
|
+
* interface language beside it (`uiLanguage`) — pass it to the record protocol as the body.
|
|
40
|
+
*/
|
|
41
|
+
onConfirm: (body: PerformanceConsentBody) => Promise<unknown> | unknown;
|
|
42
|
+
formatAmount?: AmountFormatter;
|
|
43
|
+
}
|
|
44
|
+
export interface SubscriptionStartDialogProps extends LegalDialogProps {
|
|
45
|
+
view: SubscriptionStartView | null;
|
|
46
|
+
/** The plan's title, as the application names it — it is part of the statement. */
|
|
47
|
+
planTitle: string;
|
|
48
|
+
/** What the application shows about the price (amount, split, tax) above the statement. */
|
|
49
|
+
price?: ReactNode;
|
|
50
|
+
onConfirm: (body: SubscriptionStartBody) => Promise<unknown> | unknown;
|
|
51
|
+
}
|
|
52
|
+
/** Where a declaration is made: signed in (a candidate list) or on the public page (a contract reference). */
|
|
53
|
+
export type DeclarationMode = 'in-app' | 'public';
|
|
54
|
+
/** The three steps every statutory function takes: the form, the review with the statutory button, the receipt. */
|
|
55
|
+
export type DeclarationStep = 'form' | 'review' | 'receipt';
|
|
56
|
+
export interface WithdrawalFormProps {
|
|
57
|
+
mode: DeclarationMode;
|
|
58
|
+
/** The language of the contract (the billing country's); the form shows its legal copy in it. */
|
|
59
|
+
language: string;
|
|
60
|
+
uiLanguage?: string;
|
|
61
|
+
/** In-app: the contracts that can still be withdrawn from. */
|
|
62
|
+
list?: WithdrawalCandidateList | null;
|
|
63
|
+
/** Prefill. In-app, `purchaseId` (or `contractRef`) preselects a candidate. */
|
|
64
|
+
defaults?: {
|
|
65
|
+
name?: string;
|
|
66
|
+
email?: string;
|
|
67
|
+
contractRef?: string;
|
|
68
|
+
purchaseId?: string;
|
|
69
|
+
};
|
|
70
|
+
pending?: boolean;
|
|
71
|
+
error?: PieceError;
|
|
72
|
+
/** The answer to the submitted declaration — its presence is the receipt step. */
|
|
73
|
+
receipt?: WithdrawalReceipt | DeclarationReceipt | null;
|
|
74
|
+
onSubmit: (body: WithdrawalBody) => Promise<unknown> | unknown;
|
|
75
|
+
/** Offered on the receipt step. */
|
|
76
|
+
onClose?: () => void;
|
|
77
|
+
formatAmount?: AmountFormatter;
|
|
78
|
+
className?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface WithdrawalDialogProps extends Omit<WithdrawalFormProps, 'onClose' | 'className'> {
|
|
81
|
+
open: boolean;
|
|
82
|
+
onOpenChange: (open: boolean) => void;
|
|
83
|
+
className?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface WithdrawalFunctionButtonProps {
|
|
86
|
+
/** The contract language: the statutory label is shown in it. */
|
|
87
|
+
language: string;
|
|
88
|
+
/** Its label in this language becomes the `title` when the two differ. Default: the active language. */
|
|
89
|
+
uiLanguage?: string;
|
|
90
|
+
onClick: () => void;
|
|
91
|
+
disabled?: boolean;
|
|
92
|
+
variant?: 'default' | 'outline';
|
|
93
|
+
className?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface CancellationFormProps {
|
|
96
|
+
mode: DeclarationMode;
|
|
97
|
+
language: string;
|
|
98
|
+
uiLanguage?: string;
|
|
99
|
+
defaults?: {
|
|
100
|
+
name?: string;
|
|
101
|
+
email?: string;
|
|
102
|
+
contractRef?: string;
|
|
103
|
+
subscriptionId?: string;
|
|
104
|
+
};
|
|
105
|
+
pending?: boolean;
|
|
106
|
+
error?: PieceError;
|
|
107
|
+
receipt?: CancellationReceipt | DeclarationReceipt | null;
|
|
108
|
+
onSubmit: (body: CancellationBody) => Promise<unknown> | unknown;
|
|
109
|
+
/** The receipt's print button; default `window.print()`. */
|
|
110
|
+
onPrint?: () => void;
|
|
111
|
+
onClose?: () => void;
|
|
112
|
+
className?: string;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/consumer/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/consumer/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { WithdrawalDialogProps, WithdrawalFormProps, WithdrawalFunctionButtonProps } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The withdrawal function's entry (CRD Art. 11a; § 356a BGB "Vertrag widerrufen"; L221-21
|
|
4
|
+
* "Renoncer au contrat ici"): the statutory label in the CONTRACT language, and the interface
|
|
5
|
+
* language's label as its `title` when the two differ.
|
|
6
|
+
*
|
|
7
|
+
* `[data-withdrawal-function]` with `data-language`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const WithdrawalFunctionButton: ({ language, uiLanguage, onClick, disabled, variant, className, }: WithdrawalFunctionButtonProps) => import("react").JSX.Element;
|
|
10
|
+
/**
|
|
11
|
+
* The withdrawal function as a page section: the form (in-app a contract picker with the estimated
|
|
12
|
+
* refund, publicly a contract reference — and nothing but name, contract and e-mail is asked),
|
|
13
|
+
* the review with the statutory confirm button ("Confirm withdrawal", "Widerruf bestätigen",
|
|
14
|
+
* "Confirmer la rétractation"), and the receipt with the date and time of receipt in UTC. Legal
|
|
15
|
+
* copy in the contract language, with a toggle to the interface language.
|
|
16
|
+
*
|
|
17
|
+
* Selectors: `[data-withdrawal-form]` / `[data-withdrawal-step="form|review|receipt"]` (also
|
|
18
|
+
* `data-step`, `data-language`, `data-mode`), `[data-withdrawal-candidate]` (`data-purchase-id`),
|
|
19
|
+
* `[data-withdrawal-estimate]`, `[data-withdrawal-field="contract|name|email"]`,
|
|
20
|
+
* `[data-withdrawal-continue]`, `[data-withdrawal-confirm]`, `[data-withdrawal-receipt]`
|
|
21
|
+
* (`data-status`, `data-declaration-id`, `data-received-at`), `[data-withdrawal-reference]`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const WithdrawalForm: ({ className, ...props }: WithdrawalFormProps) => import("react").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* `WithdrawalForm` in a dialog: `[data-withdrawal-dialog]` carries `data-language` and `data-step`.
|
|
26
|
+
* Closing it does not clear a receipt the application holds — reset it when the dialog closes.
|
|
27
|
+
*/
|
|
28
|
+
export declare const WithdrawalDialog: ({ open, onOpenChange, className, ...props }: WithdrawalDialogProps) => import("react").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=withdrawal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdrawal.d.ts","sourceRoot":"","sources":["../../src/consumer/withdrawal.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACO,qBAAqB,EAAE,mBAAmB,EAAE,6BAA6B,EAC3F,MAAM,YAAY,CAAA;AAEnB;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,qEAElC,6BAA6B,gCAU/B,CAAA;AAuMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,4BAA6B,mBAAmB,gCAUzE,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,gDAAiD,qBAAqB,gCAiBxF,CAAA"}
|