@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
package/src/i18n/be.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Папоўніць крэдыты","description":"Выберыце чысты кошт крэдытаў для арганізацыі.","presets":"Гатовыя сумы","custom":"Свая сума","invalid":"Увядзіце карэктную суму, не больш за два знакі пасля коскі.","below":"Мінімальная сума — {{amount}}.","above":"Максімальная сума — {{amount}}.","bounds":"Выберыце суму ад {{minimum}} да {{maximum}}.","credits":"Кошт крэдытаў","adjustment":"Карэкціроўка апрацоўкі","subtotal":"Сума да падатку","tax-note":"Stripe разлічыць падатак падчас аплаты.","cancel":"Скасаваць","continue":"Перайсці ў Stripe","pending":"Адкрываем аплату…","close":"Закрыць"}}
|
|
1
|
+
{"amount-checkout":{"title":"Папоўніць крэдыты","description":"Выберыце чысты кошт крэдытаў для арганізацыі.","presets":"Гатовыя сумы","custom":"Свая сума","invalid":"Увядзіце карэктную суму, не больш за два знакі пасля коскі.","below":"Мінімальная сума — {{amount}}.","above":"Максімальная сума — {{amount}}.","bounds":"Выберыце суму ад {{minimum}} да {{maximum}}.","credits":"Кошт крэдытаў","adjustment":"Карэкціроўка апрацоўкі","subtotal":"Сума да падатку","tax-note":"Stripe разлічыць падатак падчас аплаты.","cancel":"Скасаваць","continue":"Перайсці ў Stripe","pending":"Адкрываем аплату…","close":"Закрыць","above-limit":"Зараз можна дадаць не больш за {{amount}}."},"entitlement":{"plan":{"current":"Бягучы план"},"status":{"trial":"Пробны перыяд","trial-on":"Пробны перыяд да {{date}}","past-due":"Плацёж пратэрмінаваны","cancel-scheduled":"Адмена запланавана","cancel-scheduled-on":"Адмяняецца {{date}}","paused":"На паўзе","paused-on":"На паўзе з {{date}}","suspended":"Прыпынены","free":"Бясплатны план","renews-on":"Падаўжаецца {{date}}","active":"Актыўны","created":"Чакае актывацыі","canceled":"Адменены","expired":"Тэрмін скончыўся","ended":"Завершаны","blocked":"Заблакаваны"},"limit":{"usage":"{{used}} з {{limit}}","usage-unit":"{{used}} з {{limit}} {{unit}}","not-included":"Не ўваходзіць у план","exhausted":"Ліміт вычарпаны","resets-on":"Абновіцца {{date}}"},"promo":{"free-until":"Бясплатна да {{date}}","grandfathered":"Захавана для вашага плана","ended":"Акцыя завершана"},"capability":{"included":"Уваходзіць у план","not-included":"Не ўваходзіць у план"}},"estimate":{"country":"Краіна плацельшчыка","country-placeholder":"Выберыце краіну","tax-type":{"vat":"ПДВ","gst":"GST","sales-tax":"Падатак з продажаў","tax":"Падатак"},"rate":"{{type}} ({{percentage}}%)","total":"Прыблізная сума","converted-note":"Пералічана па бягучым курсе Stripe; дакладная сума і магчымая камісія за канвертацыю будуць пацверджаны падчас аплаты.","status":{"taxed":"Падатак ужо ўключаны ў прыблізную суму ніжэй.","reverse-charge":"Адваротнае налічэнне — пры ўказаным нумары ПДВ вы ўлічваеце падатак самастойна, таму мы нічога не дадаём.","none":"Для гэтай краіны падатак не прымяняецца.","at-checkout":"Дакладны падатак будзе разлічаны падчас аплаты.","location-required":"Выберыце краіну плацельшчыка, каб убачыць разлік."},"loading":"Правяраем падатак…","failed":"Зараз не ўдалося праверыць падатак.","country-locked":"Краіна плацельшчыка ўстаноўлена пры першай пакупцы, змяніць яе тут нельга."},"checkout-limit":{"note":"Зараз можна дадаць да {{amount}}.","blocked":"Зараз дадаць крэдыты нельга.","resets":"Больш стане даступна {{date}}.","reason":{"per-purchase":"Разавыя папаўненні для вашай арганізацыі пакуль абмежаваныя; ліміт расце па меры выкарыстання крэдытаў.","window":"Нядаўнія папаўненні ўлічваюцца ў ліміце за апошнія некалькі дзён.","hold":"Папаўненні для вашай арганізацыі прыпыненыя. Звярніцеся ў падтрымку.","other":"Для вашай арганізацыі дзейнічае ліміт папаўненняў."}},"consumer":{"show-in":"Паказаць на мове: {{language}}","purchases":"Пакупкі ў перыядзе адмовы","continue":"Далей","back":"Назад","close":"Закрыць","print":"Надрукаваць або захаваць","pending":"Адпраўка…","required":"Запоўніце гэта поле.","email-invalid":"Увядзіце карэктны адрас электроннай пошты.","date-invalid":"Выберыце дату не раней за сённяшнюю.","failed":"Не атрымалася. Паспрабуйце яшчэ раз.","review":"Праверце даныя","receipt":"Пацвярджэнне атрымання","received-at":"Дата атрымання","reference":"Нумар звароту","status":"Статус","not-mailed":"Захавайце гэту старонку: ліст з пацвярджэннем яшчэ не адпраўлены.","website":"Вэб-сайт"},"withdrawal":{"none":"Зараз няма дагавораў, ад якіх можна адмовіцца.","purchased":"Куплена {{date}}","paid":"Аплачана {{amount}}","until":"Адмовіцца можна да канца дня {{date}} уключна","estimate":"Арыентыровачная сума вяртання: {{amount}}","estimate-unknown":"Сума вяртання будзе разлічана пры апрацоўцы адмовы.","refund":"Вяртанне","subscription-canceled":"Падпіска спынена.","kind":{"top-up":"Крэдыты","subscription":"Падпіска"},"status":{"received":"Атрымана","processing":"Апрацоўваецца","refunded":"Вернута","review":"На праверцы","failed":"Вяртанне затрымліваецца — паўтараем спробу","expired":"Атрымана пасля заканчэння тэрміну адмовы"}},"cancellation":{"effective-at":"Ваш дагавор заканчваецца {{date}}.","status":{"received":"Атрымана","scheduled":"Растаргненне запланавана","already-scheduled":"Растаргненне ўжо запланавана","review":"Атрымана — мы разгледзім яго і пацвердзім па электроннай пошце"}}}
|
package/src/i18n/de.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Guthaben aufladen","description":"Wähle den Nettowert des Guthabens für deine Organisation.","presets":"Vorgegebene Beträge","custom":"Eigener Betrag","invalid":"Gib einen gültigen Betrag mit höchstens zwei Dezimalstellen ein.","below":"Der Mindestbetrag ist {{amount}}.","above":"Der Höchstbetrag ist {{amount}}.","bounds":"Wähle zwischen {{minimum}} und {{maximum}}.","credits":"Guthabenwert","adjustment":"Verarbeitungsaufschlag","subtotal":"Zwischensumme vor Steuern","tax-note":"Stripe berechnet anwendbare Steuern beim Bezahlen.","cancel":"Abbrechen","continue":"Weiter zu Stripe","pending":"Zahlung wird geöffnet…","close":"Schließen"}}
|
|
1
|
+
{"amount-checkout":{"title":"Guthaben aufladen","description":"Wähle den Nettowert des Guthabens für deine Organisation.","presets":"Vorgegebene Beträge","custom":"Eigener Betrag","invalid":"Gib einen gültigen Betrag mit höchstens zwei Dezimalstellen ein.","below":"Der Mindestbetrag ist {{amount}}.","above":"Der Höchstbetrag ist {{amount}}.","bounds":"Wähle zwischen {{minimum}} und {{maximum}}.","credits":"Guthabenwert","adjustment":"Verarbeitungsaufschlag","subtotal":"Zwischensumme vor Steuern","tax-note":"Stripe berechnet anwendbare Steuern beim Bezahlen.","cancel":"Abbrechen","continue":"Weiter zu Stripe","pending":"Zahlung wird geöffnet…","close":"Schließen","above-limit":"Du kannst gerade höchstens {{amount}} aufladen."},"entitlement":{"plan":{"current":"Aktueller Tarif"},"status":{"trial":"Testphase","trial-on":"Testphase endet am {{date}}","past-due":"Zahlung überfällig","cancel-scheduled":"Kündigung vorgemerkt","cancel-scheduled-on":"Endet am {{date}}","paused":"Pausiert","paused-on":"Pausiert seit {{date}}","suspended":"Ausgesetzt","free":"Kostenloser Tarif","renews-on":"Verlängert sich am {{date}}","active":"Aktiv","created":"Wartet auf Aktivierung","canceled":"Gekündigt","expired":"Abgelaufen","ended":"Beendet","blocked":"Gesperrt"},"limit":{"usage":"{{used}} von {{limit}}","usage-unit":"{{used}} von {{limit}} {{unit}}","not-included":"Nicht enthalten","exhausted":"Limit erreicht","resets-on":"Wird am {{date}} zurückgesetzt"},"promo":{"free-until":"Kostenlos bis {{date}}","grandfathered":"In deinem Tarif enthalten","ended":"Aktion beendet"},"capability":{"included":"Enthalten","not-included":"Nicht enthalten"}},"estimate":{"country":"Rechnungsland","country-placeholder":"Land wählen","tax-type":{"vat":"USt.","gst":"GST","sales-tax":"Umsatzsteuer","tax":"Steuer"},"rate":"{{type}} ({{percentage}}%)","total":"Geschätzter Gesamtbetrag","converted-note":"Umgerechnet zum aktuellen Stripe-Wechselkurs; der genaue Betrag und eine mögliche Umrechnungsgebühr werden beim Bezahlen bestätigt.","status":{"taxed":"Die Steuer ist bereits im geschätzten Gesamtbetrag unten enthalten.","reverse-charge":"Reverse-Charge-Verfahren — mit deiner USt-IdNr. rechnest du diese Steuer selbst ab, daher berechnen wir nichts.","none":"Für dieses Land fällt keine Steuer an.","at-checkout":"Die genaue Steuer wird beim Bezahlen berechnet.","location-required":"Wähle dein Rechnungsland, um eine Schätzung zu sehen."},"loading":"Steuer wird geprüft…","failed":"Die Steuer konnte gerade nicht geprüft werden.","country-locked":"Dein Rechnungsland wurde mit deinem ersten Kauf festgelegt und kann hier nicht geändert werden."},"checkout-limit":{"note":"Du kannst gerade bis zu {{amount}} aufladen.","blocked":"Du kannst gerade kein Guthaben aufladen.","resets":"Mehr ist ab {{date}} verfügbar.","reason":{"per-purchase":"Einzelne Aufladungen deiner Organisation sind vorerst begrenzt; die Grenze steigt, wenn du dein Guthaben nutzt.","window":"Deine letzten Aufladungen zählen zu einer Grenze über die letzten Tage.","hold":"Aufladungen sind für deine Organisation pausiert. Bitte wende dich an den Support.","other":"Für deine Organisation gilt eine Aufladegrenze."}},"consumer":{"show-in":"Auf {{language}} anzeigen","purchases":"Käufe innerhalb der Widerrufsfrist","continue":"Weiter","back":"Zurück","close":"Schließen","print":"Drucken oder speichern","pending":"Wird gesendet…","required":"Bitte füllen Sie dieses Feld aus.","email-invalid":"Geben Sie eine gültige E-Mail-Adresse ein.","date-invalid":"Wählen Sie ein Datum ab heute.","failed":"Das hat nicht geklappt. Bitte versuchen Sie es noch einmal.","review":"Prüfen Sie Ihre Angaben","receipt":"Eingangsbestätigung","received-at":"Eingegangen am","reference":"Referenz","status":"Status","not-mailed":"Bitte bewahren Sie diese Seite auf: Die Bestätigungs-E-Mail wurde noch nicht versandt.","website":"Webseite"},"withdrawal":{"none":"Derzeit kann kein Vertrag widerrufen werden.","purchased":"Gekauft am {{date}}","paid":"Bezahlt: {{amount}}","until":"Widerruf möglich bis einschließlich {{date}}","estimate":"Voraussichtliche Erstattung: {{amount}}","estimate-unknown":"Die Erstattung wird bei der Bearbeitung Ihres Widerrufs berechnet.","refund":"Erstattung","subscription-canceled":"Das Abonnement wurde beendet.","kind":{"top-up":"Guthaben","subscription":"Abonnement"},"status":{"received":"Eingegangen","processing":"In Bearbeitung","refunded":"Erstattet","review":"In Prüfung","failed":"Erstattung verzögert — wir versuchen es erneut","expired":"Nach Ablauf der Widerrufsfrist eingegangen"}},"cancellation":{"effective-at":"Ihr Vertrag endet am {{date}}.","status":{"received":"Eingegangen","scheduled":"Kündigung vorgemerkt","already-scheduled":"Kündigung war bereits vorgemerkt","review":"Eingegangen — wir prüfen sie und bestätigen sie per E-Mail"}}}
|
package/src/i18n/en.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Add credits","description":"Choose the net credit value to add to your organization.","presets":"Preset amounts","custom":"Custom amount","invalid":"Enter a valid amount with no more than two decimal places.","below":"The minimum amount is {{amount}}.","above":"The maximum amount is {{amount}}.","bounds":"Choose between {{minimum}} and {{maximum}}.","credits":"Credit value","adjustment":"Processing adjustment","subtotal":"Pre-tax subtotal","tax-note":"Stripe calculates any applicable tax at checkout.","cancel":"Cancel","continue":"Continue to Stripe","pending":"Opening checkout…","close":"Close"}}
|
|
1
|
+
{"amount-checkout":{"title":"Add credits","description":"Choose the net credit value to add to your organization.","presets":"Preset amounts","custom":"Custom amount","invalid":"Enter a valid amount with no more than two decimal places.","below":"The minimum amount is {{amount}}.","above":"The maximum amount is {{amount}}.","bounds":"Choose between {{minimum}} and {{maximum}}.","credits":"Credit value","adjustment":"Processing adjustment","subtotal":"Pre-tax subtotal","tax-note":"Stripe calculates any applicable tax at checkout.","cancel":"Cancel","continue":"Continue to Stripe","pending":"Opening checkout…","close":"Close","above-limit":"The most you can add right now is {{amount}}."},"entitlement":{"plan":{"current":"Current plan"},"status":{"trial":"Trial","trial-on":"Trial ends on {{date}}","past-due":"Payment past due","cancel-scheduled":"Cancellation scheduled","cancel-scheduled-on":"Cancels on {{date}}","paused":"Paused","paused-on":"Paused since {{date}}","suspended":"Suspended","free":"Free plan","renews-on":"Renews on {{date}}","active":"Active","created":"Awaiting activation","canceled":"Canceled","expired":"Expired","ended":"Ended","blocked":"Blocked"},"limit":{"usage":"{{used}} of {{limit}}","usage-unit":"{{used}} of {{limit}} {{unit}}","not-included":"Not included","exhausted":"Limit reached","resets-on":"Resets on {{date}}"},"promo":{"free-until":"Free until {{date}}","grandfathered":"Included for your plan","ended":"Promotion ended"},"capability":{"included":"Included","not-included":"Not included"}},"estimate":{"country":"Billing country","country-placeholder":"Choose a country","tax-type":{"vat":"VAT","gst":"GST","sales-tax":"Sales tax","tax":"Tax"},"rate":"{{type}} ({{percentage}}%)","total":"Estimated total","converted-note":"Converted at Stripe's current exchange rate; the exact amount and any conversion fee are confirmed at checkout.","status":{"taxed":"Tax is included in the estimated total below.","reverse-charge":"Reverse charge — your VAT ID means you account for this tax yourself, so nothing is added.","none":"No tax applies for this country.","at-checkout":"The exact tax is calculated at checkout.","location-required":"Choose your billing country to see an estimate."},"loading":"Checking tax…","failed":"Tax could not be checked right now.","country-locked":"Your billing country was set by your first purchase and cannot be changed here."},"checkout-limit":{"note":"You can add up to {{amount}} right now.","blocked":"You cannot add credits right now.","resets":"More becomes available on {{date}}.","reason":{"per-purchase":"Single top-ups are limited for your organization for now; the limit grows as you use your credits.","window":"Your recent top-ups count toward a limit over the last few days.","hold":"Top-ups are paused for your organization. Please contact support.","other":"A top-up limit applies to your organization."}},"consumer":{"show-in":"Show in {{language}}","purchases":"Purchases within their withdrawal period","continue":"Continue","back":"Back","close":"Close","print":"Print or save","pending":"Sending…","required":"Please fill in this field.","email-invalid":"Enter a valid e-mail address.","date-invalid":"Choose a date from today on.","failed":"That did not go through. Please try again.","review":"Check your details","receipt":"Acknowledgement of receipt","received-at":"Received on","reference":"Reference","status":"Status","not-mailed":"Please keep this page: the confirmation e-mail has not been sent yet.","website":"Website"},"withdrawal":{"none":"No contract can be withdrawn from right now.","purchased":"Bought on {{date}}","paid":"Paid {{amount}}","until":"Withdraw until the end of {{date}}","estimate":"Estimated refund: {{amount}}","estimate-unknown":"The refund is calculated when your withdrawal is processed.","refund":"Refund","subscription-canceled":"The subscription has been ended.","kind":{"top-up":"Credits","subscription":"Subscription"},"status":{"received":"Received","processing":"Being processed","refunded":"Refunded","review":"Being reviewed","failed":"Refund delayed — we are retrying it","expired":"Received after the withdrawal period"}},"cancellation":{"effective-at":"Your contract ends on {{date}}.","status":{"received":"Received","scheduled":"Termination scheduled","already-scheduled":"Termination already scheduled","review":"Received — we will review it and confirm by e-mail"}}}
|
package/src/i18n/es.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Añadir créditos","description":"Elige el valor neto de créditos para tu organización.","presets":"Importes predefinidos","custom":"Importe personalizado","invalid":"Introduce un importe válido con un máximo de dos decimales.","below":"El importe mínimo es {{amount}}.","above":"El importe máximo es {{amount}}.","bounds":"Elige entre {{minimum}} y {{maximum}}.","credits":"Valor de los créditos","adjustment":"Ajuste de procesamiento","subtotal":"Subtotal antes de impuestos","tax-note":"Stripe calcula los impuestos aplicables al pagar.","cancel":"Cancelar","continue":"Continuar a Stripe","pending":"Abriendo el pago…","close":"Cerrar"}}
|
|
1
|
+
{"amount-checkout":{"title":"Añadir créditos","description":"Elige el valor neto de créditos para tu organización.","presets":"Importes predefinidos","custom":"Importe personalizado","invalid":"Introduce un importe válido con un máximo de dos decimales.","below":"El importe mínimo es {{amount}}.","above":"El importe máximo es {{amount}}.","bounds":"Elige entre {{minimum}} y {{maximum}}.","credits":"Valor de los créditos","adjustment":"Ajuste de procesamiento","subtotal":"Subtotal antes de impuestos","tax-note":"Stripe calcula los impuestos aplicables al pagar.","cancel":"Cancelar","continue":"Continuar a Stripe","pending":"Abriendo el pago…","close":"Cerrar","above-limit":"Lo máximo que puedes añadir ahora es {{amount}}."},"entitlement":{"plan":{"current":"Plan actual"},"status":{"trial":"Prueba","trial-on":"La prueba termina el {{date}}","past-due":"Pago vencido","cancel-scheduled":"Cancelación programada","cancel-scheduled-on":"Se cancela el {{date}}","paused":"En pausa","paused-on":"En pausa desde el {{date}}","suspended":"Suspendido","free":"Plan gratuito","renews-on":"Se renueva el {{date}}","active":"Activo","created":"Pendiente de activación","canceled":"Cancelado","expired":"Vencido","ended":"Finalizado","blocked":"Bloqueado"},"limit":{"usage":"{{used}} de {{limit}}","usage-unit":"{{used}} de {{limit}} {{unit}}","not-included":"No incluido","exhausted":"Límite alcanzado","resets-on":"Se restablece el {{date}}"},"promo":{"free-until":"Gratis hasta el {{date}}","grandfathered":"Incluido en tu plan","ended":"Promoción finalizada"},"capability":{"included":"Incluido","not-included":"No incluido"}},"estimate":{"country":"País de facturación","country-placeholder":"Elige un país","tax-type":{"vat":"IVA","gst":"GST","sales-tax":"Impuesto sobre ventas","tax":"Impuesto"},"rate":"{{type}} ({{percentage}}%)","total":"Total estimado","converted-note":"Convertido al tipo de cambio actual de Stripe; el importe exacto y cualquier comisión de conversión se confirman al pagar.","status":{"taxed":"El impuesto ya está incluido en el total estimado de abajo.","reverse-charge":"Inversión del sujeto pasivo — con tu NIF-IVA, tú mismo declaras este impuesto, así que no añadimos nada.","none":"No se aplica ningún impuesto para este país.","at-checkout":"El impuesto exacto se calcula al pagar.","location-required":"Elige tu país de facturación para ver una estimación."},"loading":"Comprobando el impuesto…","failed":"No se ha podido comprobar el impuesto ahora.","country-locked":"Tu país de facturación se fijó con tu primera compra y no se puede cambiar aquí."},"checkout-limit":{"note":"Ahora puedes añadir hasta {{amount}}.","blocked":"Ahora no puedes añadir créditos.","resets":"Habrá más disponible el {{date}}.","reason":{"per-purchase":"Las recargas individuales de tu organización están limitadas por ahora; el límite crece a medida que usas tus créditos.","window":"Tus recargas recientes cuentan para un límite de los últimos días.","hold":"Las recargas de tu organización están en pausa. Contacta con soporte.","other":"Tu organización tiene un límite de recargas."}},"consumer":{"show-in":"Mostrar en {{language}}","purchases":"Compras dentro de su plazo de desistimiento","continue":"Continuar","back":"Atrás","close":"Cerrar","print":"Imprimir o guardar","pending":"Enviando…","required":"Rellene este campo.","email-invalid":"Introduzca una dirección de correo electrónico válida.","date-invalid":"Elija una fecha a partir de hoy.","failed":"No se ha podido completar. Inténtelo de nuevo.","review":"Revise sus datos","receipt":"Acuse de recibo","received-at":"Fecha de recepción","reference":"Referencia","status":"Estado","not-mailed":"Guarde esta página: el correo de confirmación aún no se ha enviado.","website":"Sitio web"},"withdrawal":{"none":"Ahora no hay ningún contrato del que pueda desistir.","purchased":"Comprado el {{date}}","paid":"Pagado: {{amount}}","until":"Desistimiento posible hasta el final del día {{date}}","estimate":"Reembolso estimado: {{amount}}","estimate-unknown":"El reembolso se calcula al tramitar su desistimiento.","refund":"Reembolso","subscription-canceled":"La suscripción ha finalizado.","kind":{"top-up":"Créditos","subscription":"Suscripción"},"status":{"received":"Recibido","processing":"En tramitación","refunded":"Reembolsado","review":"En revisión","failed":"Reembolso retrasado: lo estamos reintentando","expired":"Recibido tras el plazo de desistimiento"}},"cancellation":{"effective-at":"Su contrato termina el {{date}}.","status":{"received":"Recibida","scheduled":"Baja programada","already-scheduled":"La baja ya estaba programada","review":"Recibida — la revisaremos y la confirmaremos por correo electrónico"}}}
|
package/src/i18n/fr.json
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
{
|
|
2
|
+
"amount-checkout": {
|
|
3
|
+
"title": "Ajouter des crédits",
|
|
4
|
+
"description": "Choisissez la valeur nette de crédits à ajouter à votre organisation.",
|
|
5
|
+
"presets": "Montants prédéfinis",
|
|
6
|
+
"custom": "Montant personnalisé",
|
|
7
|
+
"invalid": "Saisissez un montant valide avec au plus deux décimales.",
|
|
8
|
+
"below": "Le montant minimal est de {{amount}}.",
|
|
9
|
+
"above": "Le montant maximal est de {{amount}}.",
|
|
10
|
+
"bounds": "Choisissez entre {{minimum}} et {{maximum}}.",
|
|
11
|
+
"credits": "Valeur des crédits",
|
|
12
|
+
"adjustment": "Ajustement de traitement",
|
|
13
|
+
"subtotal": "Sous-total hors taxes",
|
|
14
|
+
"tax-note": "Stripe calcule les taxes applicables lors du paiement.",
|
|
15
|
+
"cancel": "Annuler",
|
|
16
|
+
"continue": "Continuer vers Stripe",
|
|
17
|
+
"pending": "Ouverture du paiement…",
|
|
18
|
+
"close": "Fermer",
|
|
19
|
+
"above-limit": "Le maximum que vous pouvez ajouter actuellement est de {{amount}}."
|
|
20
|
+
},
|
|
21
|
+
"entitlement": {
|
|
22
|
+
"plan": {
|
|
23
|
+
"current": "Plan actuel"
|
|
24
|
+
},
|
|
25
|
+
"status": {
|
|
26
|
+
"trial": "Essai",
|
|
27
|
+
"trial-on": "L’essai se termine le {{date}}",
|
|
28
|
+
"past-due": "Paiement en retard",
|
|
29
|
+
"cancel-scheduled": "Annulation programmée",
|
|
30
|
+
"cancel-scheduled-on": "Annulé le {{date}}",
|
|
31
|
+
"paused": "En pause",
|
|
32
|
+
"paused-on": "En pause depuis le {{date}}",
|
|
33
|
+
"suspended": "Suspendu",
|
|
34
|
+
"free": "Plan gratuit",
|
|
35
|
+
"renews-on": "Se renouvelle le {{date}}",
|
|
36
|
+
"active": "Actif",
|
|
37
|
+
"created": "En attente d’activation",
|
|
38
|
+
"canceled": "Annulé",
|
|
39
|
+
"expired": "Expiré",
|
|
40
|
+
"ended": "Terminé",
|
|
41
|
+
"blocked": "Bloqué"
|
|
42
|
+
},
|
|
43
|
+
"limit": {
|
|
44
|
+
"usage": "{{used}} sur {{limit}}",
|
|
45
|
+
"usage-unit": "{{used}} sur {{limit}} {{unit}}",
|
|
46
|
+
"not-included": "Non inclus",
|
|
47
|
+
"exhausted": "Limite atteinte",
|
|
48
|
+
"resets-on": "Se renouvelle le {{date}}"
|
|
49
|
+
},
|
|
50
|
+
"promo": {
|
|
51
|
+
"free-until": "Gratuit jusqu’au {{date}}",
|
|
52
|
+
"grandfathered": "Inclus dans votre plan",
|
|
53
|
+
"ended": "Promotion terminée"
|
|
54
|
+
},
|
|
55
|
+
"capability": {
|
|
56
|
+
"included": "Inclus",
|
|
57
|
+
"not-included": "Non inclus"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"estimate": {
|
|
61
|
+
"country": "Pays de facturation",
|
|
62
|
+
"country-placeholder": "Choisissez un pays",
|
|
63
|
+
"tax-type": {
|
|
64
|
+
"vat": "TVA",
|
|
65
|
+
"gst": "GST",
|
|
66
|
+
"sales-tax": "Taxe de vente",
|
|
67
|
+
"tax": "Taxe"
|
|
68
|
+
},
|
|
69
|
+
"rate": "{{type}} ({{percentage}} %)",
|
|
70
|
+
"total": "Total estimé",
|
|
71
|
+
"converted-note": "Conversion au taux de change actuel de Stripe ; le montant exact et les éventuels frais de conversion sont confirmés lors du paiement.",
|
|
72
|
+
"status": {
|
|
73
|
+
"taxed": "La taxe est incluse dans le total estimé ci-dessous.",
|
|
74
|
+
"reverse-charge": "Autoliquidation : votre numéro de TVA vous fait déclarer vous-même cette taxe, aucun montant n’est ajouté.",
|
|
75
|
+
"none": "Aucune taxe ne s’applique dans ce pays.",
|
|
76
|
+
"at-checkout": "La taxe exacte est calculée lors du paiement.",
|
|
77
|
+
"location-required": "Choisissez votre pays de facturation pour voir une estimation."
|
|
78
|
+
},
|
|
79
|
+
"loading": "Vérification de la taxe…",
|
|
80
|
+
"failed": "La taxe ne peut pas être vérifiée pour le moment.",
|
|
81
|
+
"country-locked": "Votre pays de facturation a été fixé lors de votre premier achat et ne peut pas être modifié ici."
|
|
82
|
+
},
|
|
83
|
+
"checkout-limit": {
|
|
84
|
+
"note": "Vous pouvez actuellement ajouter jusqu’à {{amount}}.",
|
|
85
|
+
"blocked": "Vous ne pouvez pas ajouter de crédits pour le moment.",
|
|
86
|
+
"resets": "Davantage sera disponible le {{date}}.",
|
|
87
|
+
"reason": {
|
|
88
|
+
"per-purchase": "Les recharges individuelles de votre organisation sont limitées pour l’instant ; la limite augmente à mesure que vous utilisez vos crédits.",
|
|
89
|
+
"window": "Vos recharges récentes comptent dans une limite sur les derniers jours.",
|
|
90
|
+
"hold": "Les recharges de votre organisation sont suspendues. Veuillez contacter le support.",
|
|
91
|
+
"other": "Une limite de recharge s’applique à votre organisation."
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"consumer": {
|
|
95
|
+
"show-in": "Afficher en {{language}}",
|
|
96
|
+
"purchases": "Achats dans leur délai de rétractation",
|
|
97
|
+
"continue": "Continuer",
|
|
98
|
+
"back": "Retour",
|
|
99
|
+
"close": "Fermer",
|
|
100
|
+
"print": "Imprimer ou enregistrer",
|
|
101
|
+
"pending": "Envoi…",
|
|
102
|
+
"required": "Veuillez remplir ce champ.",
|
|
103
|
+
"email-invalid": "Saisissez une adresse e-mail valide.",
|
|
104
|
+
"date-invalid": "Choisissez une date à partir d’aujourd’hui.",
|
|
105
|
+
"failed": "Cela n’a pas abouti. Veuillez réessayer.",
|
|
106
|
+
"review": "Vérifiez vos informations",
|
|
107
|
+
"receipt": "Accusé de réception",
|
|
108
|
+
"received-at": "Reçu le",
|
|
109
|
+
"reference": "Référence",
|
|
110
|
+
"status": "Statut",
|
|
111
|
+
"not-mailed": "Conservez cette page : l’e-mail de confirmation n’a pas encore été envoyé.",
|
|
112
|
+
"website": "Site web"
|
|
113
|
+
},
|
|
114
|
+
"withdrawal": {
|
|
115
|
+
"none": "Aucun contrat ne peut faire l’objet d’une rétractation pour le moment.",
|
|
116
|
+
"purchased": "Acheté le {{date}}",
|
|
117
|
+
"paid": "Payé : {{amount}}",
|
|
118
|
+
"until": "Rétractation possible jusqu’au {{date}} inclus",
|
|
119
|
+
"estimate": "Remboursement estimé : {{amount}}",
|
|
120
|
+
"estimate-unknown": "Le remboursement est calculé lors du traitement de votre rétractation.",
|
|
121
|
+
"refund": "Remboursement",
|
|
122
|
+
"subscription-canceled": "L’abonnement a pris fin.",
|
|
123
|
+
"kind": {
|
|
124
|
+
"top-up": "Crédits",
|
|
125
|
+
"subscription": "Abonnement"
|
|
126
|
+
},
|
|
127
|
+
"status": {
|
|
128
|
+
"received": "Reçue",
|
|
129
|
+
"processing": "En cours de traitement",
|
|
130
|
+
"refunded": "Remboursée",
|
|
131
|
+
"review": "En cours d’examen",
|
|
132
|
+
"failed": "Remboursement retardé — nouvelle tentative en cours",
|
|
133
|
+
"expired": "Reçue après le délai de rétractation"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"cancellation": {
|
|
137
|
+
"effective-at": "Votre contrat prend fin le {{date}}.",
|
|
138
|
+
"status": {
|
|
139
|
+
"received": "Reçue",
|
|
140
|
+
"scheduled": "Résiliation programmée",
|
|
141
|
+
"already-scheduled": "Résiliation déjà programmée",
|
|
142
|
+
"review": "Reçue — nous l’examinerons et la confirmerons par e-mail"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
package/src/i18n/pl.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Dodaj kredyty","description":"Wybierz wartość netto kredytów dla organizacji.","presets":"Kwoty sugerowane","custom":"Własna kwota","invalid":"Wpisz prawidłową kwotę z maksymalnie dwoma miejscami dziesiętnymi.","below":"Minimalna kwota to {{amount}}.","above":"Maksymalna kwota to {{amount}}.","bounds":"Wybierz od {{minimum}} do {{maximum}}.","credits":"Wartość kredytów","adjustment":"Korekta przetwarzania","subtotal":"Suma przed podatkiem","tax-note":"Stripe obliczy należny podatek podczas płatności.","cancel":"Anuluj","continue":"Przejdź do Stripe","pending":"Otwieranie płatności…","close":"Zamknij"}}
|
|
1
|
+
{"amount-checkout":{"title":"Dodaj kredyty","description":"Wybierz wartość netto kredytów dla organizacji.","presets":"Kwoty sugerowane","custom":"Własna kwota","invalid":"Wpisz prawidłową kwotę z maksymalnie dwoma miejscami dziesiętnymi.","below":"Minimalna kwota to {{amount}}.","above":"Maksymalna kwota to {{amount}}.","bounds":"Wybierz od {{minimum}} do {{maximum}}.","credits":"Wartość kredytów","adjustment":"Korekta przetwarzania","subtotal":"Suma przed podatkiem","tax-note":"Stripe obliczy należny podatek podczas płatności.","cancel":"Anuluj","continue":"Przejdź do Stripe","pending":"Otwieranie płatności…","close":"Zamknij","above-limit":"Obecnie możesz dodać maksymalnie {{amount}}."},"entitlement":{"plan":{"current":"Obecny plan"},"status":{"trial":"Okres próbny","trial-on":"Okres próbny kończy się {{date}}","past-due":"Zaległa płatność","cancel-scheduled":"Anulowanie zaplanowane","cancel-scheduled-on":"Zostanie anulowany {{date}}","paused":"Wstrzymany","paused-on":"Wstrzymany od {{date}}","suspended":"Zawieszony","free":"Plan darmowy","renews-on":"Odnawia się {{date}}","active":"Aktywny","created":"Oczekuje na aktywację","canceled":"Anulowany","expired":"Wygasł","ended":"Zakończony","blocked":"Zablokowany"},"limit":{"usage":"{{used}} z {{limit}}","usage-unit":"{{used}} z {{limit}} {{unit}}","not-included":"Brak w planie","exhausted":"Limit wyczerpany","resets-on":"Odnowienie {{date}}"},"promo":{"free-until":"Bezpłatnie do {{date}}","grandfathered":"Zachowane w Twoim planie","ended":"Promocja zakończona"},"capability":{"included":"W planie","not-included":"Brak w planie"}},"estimate":{"country":"Kraj rozliczeniowy","country-placeholder":"Wybierz kraj","tax-type":{"vat":"VAT","gst":"GST","sales-tax":"Podatek od sprzedaży","tax":"Podatek"},"rate":"{{type}} ({{percentage}}%)","total":"Szacowana suma","converted-note":"Przeliczone po bieżącym kursie Stripe; dokładna kwota i ewentualna opłata za przewalutowanie zostaną potwierdzone podczas płatności.","status":{"taxed":"Podatek jest wliczony w szacowaną sumę poniżej.","reverse-charge":"Odwrotne obciążenie — Twój numer VAT oznacza, że sam rozliczasz ten podatek, więc nic nie doliczamy.","none":"Dla tego kraju podatek nie ma zastosowania.","at-checkout":"Dokładny podatek zostanie obliczony podczas płatności.","location-required":"Wybierz kraj rozliczeniowy, aby zobaczyć szacunek."},"loading":"Sprawdzanie podatku…","failed":"Nie udało się teraz sprawdzić podatku.","country-locked":"Twój kraj rozliczeniowy został ustalony przy pierwszym zakupie i nie można go tu zmienić."},"checkout-limit":{"note":"Obecnie możesz dodać do {{amount}}.","blocked":"Obecnie nie możesz dodać kredytów.","resets":"Więcej będzie dostępne {{date}}.","reason":{"per-purchase":"Pojedyncze doładowania twojej organizacji są na razie ograniczone; limit rośnie wraz z wykorzystaniem kredytów.","window":"Twoje ostatnie doładowania wliczają się do limitu z ostatnich kilku dni.","hold":"Doładowania twojej organizacji są wstrzymane. Skontaktuj się z pomocą techniczną.","other":"Twoją organizację obowiązuje limit doładowań."}},"consumer":{"show-in":"Pokaż w języku: {{language}}","purchases":"Zakupy w okresie odstąpienia od umowy","continue":"Dalej","back":"Wstecz","close":"Zamknij","print":"Drukuj lub zapisz","pending":"Wysyłanie…","required":"Wypełnij to pole.","email-invalid":"Wpisz prawidłowy adres e-mail.","date-invalid":"Wybierz datę od dziś.","failed":"Nie udało się. Spróbuj ponownie.","review":"Sprawdź swoje dane","receipt":"Potwierdzenie otrzymania","received-at":"Data otrzymania","reference":"Numer referencyjny","status":"Status","not-mailed":"Zachowaj tę stronę: e-mail z potwierdzeniem nie został jeszcze wysłany.","website":"Strona internetowa"},"withdrawal":{"none":"Obecnie nie można odstąpić od żadnej umowy.","purchased":"Kupiono {{date}}","paid":"Zapłacono {{amount}}","until":"Odstąpienie możliwe do końca dnia {{date}}","estimate":"Szacowany zwrot: {{amount}}","estimate-unknown":"Kwota zwrotu zostanie obliczona przy rozpatrywaniu odstąpienia.","refund":"Zwrot","subscription-canceled":"Subskrypcja została zakończona.","kind":{"top-up":"Kredyty","subscription":"Subskrypcja"},"status":{"received":"Otrzymano","processing":"W trakcie realizacji","refunded":"Zwrócono","review":"W trakcie weryfikacji","failed":"Zwrot opóźniony — ponawiamy go","expired":"Otrzymano po upływie terminu odstąpienia"}},"cancellation":{"effective-at":"Twoja umowa kończy się {{date}}.","status":{"received":"Otrzymano","scheduled":"Wypowiedzenie zaplanowane","already-scheduled":"Wypowiedzenie już zaplanowane","review":"Otrzymano — rozpatrzymy je i potwierdzimy e-mailem"}}}
|
package/src/i18n/ru.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Пополнить кредиты","description":"Выберите чистую стоимость кредитов для организации.","presets":"Готовые суммы","custom":"Своя сумма","invalid":"Введите корректную сумму, не более двух знаков после запятой.","below":"Минимальная сумма — {{amount}}.","above":"Максимальная сумма — {{amount}}.","bounds":"Выберите сумму от {{minimum}} до {{maximum}}.","credits":"Стоимость кредитов","adjustment":"Корректировка обработки","subtotal":"Сумма до налога","tax-note":"Stripe рассчитает применимый налог при оплате.","cancel":"Отмена","continue":"Перейти в Stripe","pending":"Открываем оплату…","close":"Закрыть"}}
|
|
1
|
+
{"amount-checkout":{"title":"Пополнить кредиты","description":"Выберите чистую стоимость кредитов для организации.","presets":"Готовые суммы","custom":"Своя сумма","invalid":"Введите корректную сумму, не более двух знаков после запятой.","below":"Минимальная сумма — {{amount}}.","above":"Максимальная сумма — {{amount}}.","bounds":"Выберите сумму от {{minimum}} до {{maximum}}.","credits":"Стоимость кредитов","adjustment":"Корректировка обработки","subtotal":"Сумма до налога","tax-note":"Stripe рассчитает применимый налог при оплате.","cancel":"Отмена","continue":"Перейти в Stripe","pending":"Открываем оплату…","close":"Закрыть","above-limit":"Сейчас можно добавить не более {{amount}}."},"entitlement":{"plan":{"current":"Текущий план"},"status":{"trial":"Пробный период","trial-on":"Пробный период до {{date}}","past-due":"Платёж просрочен","cancel-scheduled":"Отмена запланирована","cancel-scheduled-on":"Отменяется {{date}}","paused":"На паузе","paused-on":"На паузе с {{date}}","suspended":"Приостановлен","free":"Бесплатный план","renews-on":"Продлевается {{date}}","active":"Активен","created":"Ожидает активации","canceled":"Отменён","expired":"Истёк","ended":"Завершён","blocked":"Заблокирован"},"limit":{"usage":"{{used}} из {{limit}}","usage-unit":"{{used}} из {{limit}} {{unit}}","not-included":"Не входит в план","exhausted":"Лимит исчерпан","resets-on":"Обновится {{date}}"},"promo":{"free-until":"Бесплатно до {{date}}","grandfathered":"Сохранено для вашего плана","ended":"Акция завершена"},"capability":{"included":"Входит в план","not-included":"Не входит в план"}},"estimate":{"country":"Страна плательщика","country-placeholder":"Выберите страну","tax-type":{"vat":"НДС","gst":"GST","sales-tax":"Налог с продаж","tax":"Налог"},"rate":"{{type}} ({{percentage}}%)","total":"Примерная сумма","converted-note":"Пересчитано по текущему курсу Stripe; точная сумма и возможная комиссия за конвертацию будут подтверждены при оплате.","status":{"taxed":"Налог уже включён в примерную сумму ниже.","reverse-charge":"Обратное начисление — при указанном номере НДС вы учитываете налог самостоятельно, поэтому мы ничего не добавляем.","none":"Для этой страны налог не применяется.","at-checkout":"Точный налог будет рассчитан при оплате.","location-required":"Выберите страну плательщика, чтобы увидеть расчёт."},"loading":"Проверяем налог…","failed":"Сейчас не удалось проверить налог.","country-locked":"Страна плательщика установлена при первой покупке, изменить её здесь нельзя."},"checkout-limit":{"note":"Сейчас можно добавить до {{amount}}.","blocked":"Сейчас добавить кредиты нельзя.","resets":"Больше станет доступно {{date}}.","reason":{"per-purchase":"Разовые пополнения для вашей организации пока ограничены; лимит растёт по мере использования кредитов.","window":"Недавние пополнения учитываются в лимите за последние несколько дней.","hold":"Пополнения для вашей организации приостановлены. Обратитесь в поддержку.","other":"Для вашей организации действует лимит пополнений."}},"consumer":{"show-in":"Показать на языке: {{language}}","purchases":"Покупки в периоде отказа","continue":"Далее","back":"Назад","close":"Закрыть","print":"Распечатать или сохранить","pending":"Отправка…","required":"Заполните это поле.","email-invalid":"Введите корректный адрес электронной почты.","date-invalid":"Выберите дату не раньше сегодняшней.","failed":"Не получилось. Попробуйте ещё раз.","review":"Проверьте данные","receipt":"Подтверждение получения","received-at":"Дата получения","reference":"Номер обращения","status":"Статус","not-mailed":"Сохраните эту страницу: письмо с подтверждением ещё не отправлено.","website":"Веб-сайт"},"withdrawal":{"none":"Сейчас нет договоров, от которых можно отказаться.","purchased":"Куплено {{date}}","paid":"Оплачено {{amount}}","until":"Отказаться можно до конца дня {{date}} включительно","estimate":"Ориентировочный возврат: {{amount}}","estimate-unknown":"Сумма возврата будет рассчитана при обработке отказа.","refund":"Возврат","subscription-canceled":"Подписка прекращена.","kind":{"top-up":"Кредиты","subscription":"Подписка"},"status":{"received":"Получено","processing":"Обрабатывается","refunded":"Возвращено","review":"На проверке","failed":"Возврат задерживается — повторяем попытку","expired":"Получено после окончания срока отказа"}},"cancellation":{"effective-at":"Ваш договор заканчивается {{date}}.","status":{"received":"Получено","scheduled":"Расторжение запланировано","already-scheduled":"Расторжение уже запланировано","review":"Получено — мы рассмотрим его и подтвердим по электронной почте"}}}
|
package/src/i18n/uk.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"amount-checkout":{"title":"Поповнити кредити","description":"Виберіть чисту вартість кредитів для організації.","presets":"Готові суми","custom":"Власна сума","invalid":"Введіть коректну суму, не більше двох знаків після коми.","below":"Мінімальна сума — {{amount}}.","above":"Максимальна сума — {{amount}}.","bounds":"Виберіть суму від {{minimum}} до {{maximum}}.","credits":"Вартість кредитів","adjustment":"Коригування обробки","subtotal":"Сума до податку","tax-note":"Stripe розрахує застосовний податок під час оплати.","cancel":"Скасувати","continue":"Перейти до Stripe","pending":"Відкриваємо оплату…","close":"Закрити"}}
|
|
1
|
+
{"amount-checkout":{"title":"Поповнити кредити","description":"Виберіть чисту вартість кредитів для організації.","presets":"Готові суми","custom":"Власна сума","invalid":"Введіть коректну суму, не більше двох знаків після коми.","below":"Мінімальна сума — {{amount}}.","above":"Максимальна сума — {{amount}}.","bounds":"Виберіть суму від {{minimum}} до {{maximum}}.","credits":"Вартість кредитів","adjustment":"Коригування обробки","subtotal":"Сума до податку","tax-note":"Stripe розрахує застосовний податок під час оплати.","cancel":"Скасувати","continue":"Перейти до Stripe","pending":"Відкриваємо оплату…","close":"Закрити","above-limit":"Зараз можна додати не більше ніж {{amount}}."},"entitlement":{"plan":{"current":"Поточний план"},"status":{"trial":"Пробний період","trial-on":"Пробний період до {{date}}","past-due":"Платіж прострочено","cancel-scheduled":"Скасування заплановано","cancel-scheduled-on":"Скасовується {{date}}","paused":"На паузі","paused-on":"На паузі з {{date}}","suspended":"Призупинено","free":"Безкоштовний план","renews-on":"Подовжується {{date}}","active":"Активний","created":"Очікує активації","canceled":"Скасовано","expired":"Термін минув","ended":"Завершено","blocked":"Заблоковано"},"limit":{"usage":"{{used}} з {{limit}}","usage-unit":"{{used}} з {{limit}} {{unit}}","not-included":"Не входить до плану","exhausted":"Ліміт вичерпано","resets-on":"Оновиться {{date}}"},"promo":{"free-until":"Безкоштовно до {{date}}","grandfathered":"Збережено для вашого плану","ended":"Акцію завершено"},"capability":{"included":"Входить до плану","not-included":"Не входить до плану"}},"estimate":{"country":"Країна платника","country-placeholder":"Виберіть країну","tax-type":{"vat":"ПДВ","gst":"GST","sales-tax":"Податок з продажів","tax":"Податок"},"rate":"{{type}} ({{percentage}}%)","total":"Орієнтовна сума","converted-note":"Перераховано за поточним курсом Stripe; точна сума та можлива комісія за конвертацію будуть підтверджені під час оплати.","status":{"taxed":"Податок уже включено до орієнтовної суми нижче.","reverse-charge":"Зворотне нарахування — за вказаним номером ПДВ ви обліковуєте цей податок самостійно, тож ми нічого не додаємо.","none":"Для цієї країни податок не застосовується.","at-checkout":"Точний податок буде розраховано під час оплати.","location-required":"Виберіть країну платника, щоб побачити розрахунок."},"loading":"Перевіряємо податок…","failed":"Зараз не вдалося перевірити податок.","country-locked":"Країну платника встановлено під час першої покупки, змінити її тут не можна."},"checkout-limit":{"note":"Зараз можна додати до {{amount}}.","blocked":"Зараз додати кредити не можна.","resets":"Більше стане доступно {{date}}.","reason":{"per-purchase":"Разові поповнення для вашої організації поки обмежені; ліміт зростає в міру використання кредитів.","window":"Нещодавні поповнення враховуються в ліміті за останні кілька днів.","hold":"Поповнення для вашої організації призупинено. Зверніться до підтримки.","other":"Для вашої організації діє ліміт поповнень."}},"consumer":{"show-in":"Показати мовою: {{language}}","purchases":"Покупки в періоді відмови","continue":"Далі","back":"Назад","close":"Закрити","print":"Надрукувати або зберегти","pending":"Надсилання…","required":"Заповніть це поле.","email-invalid":"Введіть коректну адресу електронної пошти.","date-invalid":"Виберіть дату, не ранішу за сьогоднішню.","failed":"Не вдалося. Спробуйте ще раз.","review":"Перевірте дані","receipt":"Підтвердження отримання","received-at":"Дата отримання","reference":"Номер звернення","status":"Статус","not-mailed":"Збережіть цю сторінку: лист із підтвердженням ще не надіслано.","website":"Вебсайт"},"withdrawal":{"none":"Зараз немає договорів, від яких можна відмовитися.","purchased":"Придбано {{date}}","paid":"Сплачено {{amount}}","until":"Відмовитися можна до кінця дня {{date}} включно","estimate":"Орієнтовне повернення: {{amount}}","estimate-unknown":"Суму повернення буде розраховано під час обробки відмови.","refund":"Повернення","subscription-canceled":"Підписку припинено.","kind":{"top-up":"Кредити","subscription":"Підписка"},"status":{"received":"Отримано","processing":"Обробляється","refunded":"Повернено","review":"На перевірці","failed":"Повернення затримується — повторюємо спробу","expired":"Отримано після закінчення строку відмови"}},"cancellation":{"effective-at":"Ваш договір закінчується {{date}}.","status":{"received":"Отримано","scheduled":"Розірвання заплановано","already-scheduled":"Розірвання вже заплановано","review":"Отримано — ми розглянемо його та підтвердимо електронною поштою"}}}
|
package/src/i18n.ts
CHANGED
|
@@ -6,11 +6,16 @@ import be from './i18n/be.json' with { type: 'json' }
|
|
|
6
6
|
import uk from './i18n/uk.json' with { type: 'json' }
|
|
7
7
|
import es from './i18n/es.json' with { type: 'json' }
|
|
8
8
|
import de from './i18n/de.json' with { type: 'json' }
|
|
9
|
+
import fr from './i18n/fr.json' with { type: 'json' }
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
addI18nLib('
|
|
14
|
-
addI18nLib('
|
|
15
|
-
addI18nLib('
|
|
16
|
-
addI18nLib('
|
|
11
|
+
/** The library resource (`lib` namespace) every interface string of this package lives in. */
|
|
12
|
+
export const WEB_PAYMENT_RESOURCE = 'web-payment'
|
|
13
|
+
|
|
14
|
+
addI18nLib('en', WEB_PAYMENT_RESOURCE, en)
|
|
15
|
+
addI18nLib('pl', WEB_PAYMENT_RESOURCE, pl)
|
|
16
|
+
addI18nLib('ru', WEB_PAYMENT_RESOURCE, ru)
|
|
17
|
+
addI18nLib('be', WEB_PAYMENT_RESOURCE, be)
|
|
18
|
+
addI18nLib('uk', WEB_PAYMENT_RESOURCE, uk)
|
|
19
|
+
addI18nLib('es', WEB_PAYMENT_RESOURCE, es)
|
|
20
|
+
addI18nLib('de', WEB_PAYMENT_RESOURCE, de)
|
|
21
|
+
addI18nLib('fr', WEB_PAYMENT_RESOURCE, fr)
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import './i18n.js'
|
|
2
|
+
export { WEB_PAYMENT_RESOURCE } from './i18n.js'
|
|
2
3
|
export type * from './types.js'
|
|
3
4
|
export * from './service.js'
|
|
4
5
|
export * from './hooks.js'
|
|
5
6
|
export * from './amount.js'
|
|
6
7
|
export * from './dialog.js'
|
|
8
|
+
export * from './checkout-limit.js'
|
|
9
|
+
export * from './estimate.js'
|
|
10
|
+
export * from './estimate-summary.js'
|
|
11
|
+
export * from './selectors.js'
|
|
12
|
+
export * from './entitlement.js'
|
|
13
|
+
export * from './plan-card.js'
|
|
14
|
+
export * from './limit-meter.js'
|
|
15
|
+
export * from './capability-list.js'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { LimitKind } from '@owlmeans/payment'
|
|
2
|
+
import { Progress } from '@/components/ui/progress'
|
|
3
|
+
import { PromoNote, useEntitlementCopy } from './copy.js'
|
|
4
|
+
import { limitStatusOf } from './selectors.js'
|
|
5
|
+
import type { LimitMeterProps } from './types.js'
|
|
6
|
+
|
|
7
|
+
const classes = (...names: Array<string | false | null | undefined>): string =>
|
|
8
|
+
names.filter(Boolean).join(' ')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* One limit: `used of limit`, a bar, when a window limit resets and any promo behind it. A limit
|
|
12
|
+
* of `0` is "not included" and draws no bar.
|
|
13
|
+
*/
|
|
14
|
+
export const LimitMeter = ({ limit, label, showReset = true, compact = false, className }: LimitMeterProps) => {
|
|
15
|
+
const copy = useEntitlementCopy()
|
|
16
|
+
const status = limitStatusOf(limit)!
|
|
17
|
+
const included = limit.limit > 0
|
|
18
|
+
const usage = !included
|
|
19
|
+
? copy.text('limit.not-included')
|
|
20
|
+
: copy.text(limit.unit != null ? 'limit.usage-unit' : 'limit.usage', {
|
|
21
|
+
used: copy.count(limit.used), limit: copy.count(limit.limit), unit: limit.unit ?? '',
|
|
22
|
+
})
|
|
23
|
+
const resets = showReset && limit.kind === LimitKind.Window && limit.resetsAt != null
|
|
24
|
+
? copy.text('limit.resets-on', { date: copy.day(limit.resetsAt) })
|
|
25
|
+
: null
|
|
26
|
+
const exhausted = included && status.exhausted
|
|
27
|
+
|
|
28
|
+
return <div
|
|
29
|
+
data-limit-meter=""
|
|
30
|
+
data-limit-key={limit.key}
|
|
31
|
+
data-limit-kind={limit.kind}
|
|
32
|
+
data-included={included ? 'true' : 'false'}
|
|
33
|
+
data-exhausted={status.exhausted ? 'true' : 'false'}
|
|
34
|
+
className={classes('grid', compact ? 'gap-1 text-xs' : 'gap-2 text-sm', className)}
|
|
35
|
+
>
|
|
36
|
+
<div className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
|
|
37
|
+
<span className="font-medium">{label}</span>
|
|
38
|
+
<span data-limit-usage="" className={classes(
|
|
39
|
+
'tabular-nums', exhausted ? 'text-destructive' : 'text-muted-foreground',
|
|
40
|
+
)}>{usage}</span>
|
|
41
|
+
</div>
|
|
42
|
+
{included && <Progress
|
|
43
|
+
value={Math.round(status.ratio * 100)}
|
|
44
|
+
aria-label={label}
|
|
45
|
+
className={classes(compact && 'h-1.5', exhausted && '[&>[data-slot=progress-indicator]]:bg-destructive')}
|
|
46
|
+
/>}
|
|
47
|
+
{(exhausted || resets != null || limit.promo != null) && <p className={classes(
|
|
48
|
+
'text-muted-foreground flex flex-wrap gap-x-3 gap-y-1', compact ? 'text-[0.6875rem]' : 'text-xs',
|
|
49
|
+
)}>
|
|
50
|
+
{exhausted && <span data-limit-exhausted="" className="text-destructive">{copy.text('limit.exhausted')}</span>}
|
|
51
|
+
{resets != null && <span data-limit-resets="">{resets}</span>}
|
|
52
|
+
<PromoNote promo={limit.promo} copy={copy} />
|
|
53
|
+
</p>}
|
|
54
|
+
</div>
|
|
55
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Button } from '@/components/ui/button'
|
|
2
|
+
import {
|
|
3
|
+
Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,
|
|
4
|
+
} from '@/components/ui/card'
|
|
5
|
+
import { useEntitlementCopy } from './copy.js'
|
|
6
|
+
import { planStatusLineOf } from './selectors.js'
|
|
7
|
+
import type { PlanCardProps, PlanStatusTone } from './types.js'
|
|
8
|
+
|
|
9
|
+
const TONE_DOT: Record<PlanStatusTone, string> = {
|
|
10
|
+
ok: 'bg-primary',
|
|
11
|
+
warning: 'bg-destructive/60',
|
|
12
|
+
critical: 'bg-destructive',
|
|
13
|
+
inactive: 'bg-muted-foreground',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const classes = (...names: Array<string | false | null | undefined>): string =>
|
|
17
|
+
names.filter(Boolean).join(' ')
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* One plan: the entity's own (a status line) or an offered one (its price). The package renders no
|
|
21
|
+
* product copy — titles, prices and the action label come from the application.
|
|
22
|
+
*/
|
|
23
|
+
export const PlanCard = ({
|
|
24
|
+
plan, offer, current, pending = false, actionLabel, onAction, className, children,
|
|
25
|
+
}: PlanCardProps) => {
|
|
26
|
+
const copy = useEntitlementCopy()
|
|
27
|
+
const sku = offer?.sku ?? plan.sku
|
|
28
|
+
const isCurrent = current ?? (offer != null && offer.sku === plan.sku)
|
|
29
|
+
const status = offer == null || isCurrent ? planStatusLineOf(plan) : null
|
|
30
|
+
const statusText = status == null
|
|
31
|
+
? null
|
|
32
|
+
: copy.text(status.date != null ? `status.${status.kind}-on` : `status.${status.kind}`, {
|
|
33
|
+
date: copy.day(status.date),
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return <Card
|
|
37
|
+
data-plan-card=""
|
|
38
|
+
data-plan-sku={sku}
|
|
39
|
+
data-plan-status={status?.kind}
|
|
40
|
+
data-plan-tone={status?.tone}
|
|
41
|
+
data-current={isCurrent ? 'true' : undefined}
|
|
42
|
+
className={classes(offer?.highlight === true && 'border-primary ring-1 ring-primary', className)}
|
|
43
|
+
>
|
|
44
|
+
<CardHeader>
|
|
45
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
46
|
+
<CardTitle>{offer?.title ?? plan.title}</CardTitle>
|
|
47
|
+
{isCurrent && <span data-plan-current="" className="bg-muted text-muted-foreground rounded-full px-2 py-0.5 text-xs font-medium">
|
|
48
|
+
{copy.text('plan.current')}
|
|
49
|
+
</span>}
|
|
50
|
+
</div>
|
|
51
|
+
{status != null && <CardDescription data-plan-status-line="" className="flex items-center gap-2">
|
|
52
|
+
<span aria-hidden="true" className={classes('size-2 shrink-0 rounded-full', TONE_DOT[status.tone])} />
|
|
53
|
+
<span>{statusText}</span>
|
|
54
|
+
</CardDescription>}
|
|
55
|
+
</CardHeader>
|
|
56
|
+
{(offer != null || children != null) && <CardContent className="grid gap-4">
|
|
57
|
+
{offer != null && <p data-plan-price="" className="text-2xl font-semibold tracking-tight">{offer.priceLabel}</p>}
|
|
58
|
+
{children}
|
|
59
|
+
</CardContent>}
|
|
60
|
+
{onAction != null && actionLabel != null && <CardFooter>
|
|
61
|
+
<Button
|
|
62
|
+
type="button" className="w-full" variant={isCurrent ? 'outline' : 'default'} disabled={pending}
|
|
63
|
+
onClick={() => void onAction(sku)}
|
|
64
|
+
>{actionLabel}</Button>
|
|
65
|
+
</CardFooter>}
|
|
66
|
+
</Card>
|
|
67
|
+
}
|
package/src/poll.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Load a value now and every `intervalMs`, keeping the last good answer — `null` until the first
|
|
5
|
+
* load succeeds. A failed load is swallowed: explicit actions own their errors, a poller does not.
|
|
6
|
+
* The latest `load` is always the one called, so a caller may pass a fresh closure every render.
|
|
7
|
+
*/
|
|
8
|
+
export const usePolled = <T>(load: () => Promise<T>, intervalMs: number, deps: unknown[]): T | null => {
|
|
9
|
+
const [value, setValue] = useState<T | null>(null)
|
|
10
|
+
const loadRef = useRef(load)
|
|
11
|
+
loadRef.current = load
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
let active = true
|
|
14
|
+
const tick = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const next = await loadRef.current()
|
|
17
|
+
if (active) setValue(next)
|
|
18
|
+
} catch { /* explicit actions own their errors */ }
|
|
19
|
+
}
|
|
20
|
+
void tick()
|
|
21
|
+
const ticker = setInterval(tick, intervalMs)
|
|
22
|
+
return () => { active = false; clearInterval(ticker) }
|
|
23
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
|
+
}, [intervalMs, ...deps])
|
|
25
|
+
|
|
26
|
+
return value
|
|
27
|
+
}
|
package/src/selectors.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { SubscriptionStatus, capabilityOf, hasLimitRoom } from '@owlmeans/payment'
|
|
2
|
+
import type { EntitlementPlanView, EntitlementView, LimitView, PromoView } from '@owlmeans/payment'
|
|
3
|
+
import type { LimitStatus, PlanStatusLine, PlanStatusLineKind, PromoInscription } from './types.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Whether a view grants a capability parameter — `null` while the view is not known, so a caller
|
|
7
|
+
* renders the paid control disabled instead of enabled-then-refused.
|
|
8
|
+
*/
|
|
9
|
+
export const capabilityStateOf = (
|
|
10
|
+
view: EntitlementView | null | undefined, param: string,
|
|
11
|
+
): boolean | null => view == null ? null : capabilityOf(view, param)
|
|
12
|
+
|
|
13
|
+
/** A limit row with `exhausted` and a clamped `ratio`; `null` for no row. */
|
|
14
|
+
export const limitStatusOf = (limit: LimitView | null | undefined): LimitStatus | null => {
|
|
15
|
+
if (limit == null) {
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
const used = Number.isFinite(limit.used) ? Math.max(0, limit.used) : 0
|
|
19
|
+
const ratio = limit.limit > 0 ? Math.min(1, used / limit.limit) : used > 0 ? 1 : 0
|
|
20
|
+
|
|
21
|
+
return { ...limit, exhausted: !hasLimitRoom(limit), ratio }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const INACTIVE: Partial<Record<SubscriptionStatus, PlanStatusLineKind>> = {
|
|
25
|
+
[SubscriptionStatus.Created]: 'created',
|
|
26
|
+
[SubscriptionStatus.Canceled]: 'canceled',
|
|
27
|
+
[SubscriptionStatus.Expired]: 'expired',
|
|
28
|
+
[SubscriptionStatus.Ended]: 'ended',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const dateOf = (value: Date | string | null | undefined): Date | undefined => {
|
|
32
|
+
if (value == null) {
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
const date = value instanceof Date ? value : new Date(value)
|
|
36
|
+
|
|
37
|
+
return Number.isNaN(date.getTime()) ? undefined : date
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const line = (kind: PlanStatusLineKind, tone: PlanStatusLine['tone'], date?: Date): PlanStatusLine =>
|
|
41
|
+
date == null ? { kind, tone } : { kind, tone, date }
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The one status line a plan view earns — first match wins: inactive and blocked statuses, paused
|
|
45
|
+
* (a pause date), suspended, trial, past due, cancellation scheduled, free, renews (a period end),
|
|
46
|
+
* active.
|
|
47
|
+
*/
|
|
48
|
+
export const planStatusLineOf = (plan: EntitlementPlanView): PlanStatusLine => {
|
|
49
|
+
const inactive = INACTIVE[plan.status]
|
|
50
|
+
if (inactive != null) {
|
|
51
|
+
return line(inactive, 'inactive')
|
|
52
|
+
}
|
|
53
|
+
if (plan.status === SubscriptionStatus.Blocked) {
|
|
54
|
+
return line('blocked', 'critical')
|
|
55
|
+
}
|
|
56
|
+
const pausedAt = dateOf(plan.pausedAt)
|
|
57
|
+
if (pausedAt != null) {
|
|
58
|
+
return line('paused', 'warning', pausedAt)
|
|
59
|
+
}
|
|
60
|
+
if (plan.status === SubscriptionStatus.Suspended) {
|
|
61
|
+
return line('suspended', 'critical')
|
|
62
|
+
}
|
|
63
|
+
if (plan.status === SubscriptionStatus.Trial) {
|
|
64
|
+
return line('trial', 'ok', dateOf(plan.trialEnd))
|
|
65
|
+
}
|
|
66
|
+
if (plan.pastDue === true || plan.status === SubscriptionStatus.PastDue) {
|
|
67
|
+
return line('past-due', 'warning')
|
|
68
|
+
}
|
|
69
|
+
const periodEnd = dateOf(plan.periodEnd)
|
|
70
|
+
if (plan.cancelAtPeriodEnd === true) {
|
|
71
|
+
return line('cancel-scheduled', 'warning', periodEnd)
|
|
72
|
+
}
|
|
73
|
+
if (plan.free) {
|
|
74
|
+
return line('free', 'ok')
|
|
75
|
+
}
|
|
76
|
+
if (periodEnd != null) {
|
|
77
|
+
return line('renews', 'ok', periodEnd)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return line('active', 'ok')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** How to inscribe a promo; `null` when the grant has none. */
|
|
84
|
+
export const promoInscriptionOf = (promo: PromoView | null | undefined): PromoInscription | null => {
|
|
85
|
+
if (promo == null) {
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
if (!promo.active) {
|
|
89
|
+
return 'ended'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return promo.grandfathered ? 'grandfathered' : 'free-until'
|
|
93
|
+
}
|