@greatapps/common 1.1.741 → 1.1.743
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/dist/components/modals/BuyCreditsModal.mjs +42 -30
- package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
- package/dist/components/modals/billing/RequiredBillingDataModal.mjs +14 -30
- package/dist/components/modals/billing/RequiredBillingDataModal.mjs.map +1 -1
- package/dist/components/modals/cards/AddCardModal.mjs +2 -1
- package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
- package/dist/index.mjs +26 -6
- package/dist/index.mjs.map +1 -1
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs +3 -1
- package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -1
- package/dist/modules/accounts/hooks/use-required-billing-data.hook.mjs +3 -4
- package/dist/modules/accounts/hooks/use-required-billing-data.hook.mjs.map +1 -1
- package/dist/modules/accounts/utils/billing-data.mjs +10 -14
- package/dist/modules/accounts/utils/billing-data.mjs.map +1 -1
- package/dist/modules/plans/types/plan.type.mjs +15 -0
- package/dist/modules/plans/types/plan.type.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +10 -2
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/dist/modules/subscriptions/constants/addons.constants.mjs +15 -2
- package/dist/modules/subscriptions/constants/addons.constants.mjs.map +1 -1
- package/dist/utils/format/currency.mjs +4 -1
- package/dist/utils/format/currency.mjs.map +1 -1
- package/dist/utils/format/gateway.mjs +18 -0
- package/dist/utils/format/gateway.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/modals/BuyCreditsModal.tsx +48 -32
- package/src/components/modals/billing/RequiredBillingDataModal.tsx +32 -66
- package/src/components/modals/cards/AddCardModal.tsx +2 -1
- package/src/index.ts +14 -2
- package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +3 -0
- package/src/modules/accounts/hooks/use-required-billing-data.hook.ts +3 -3
- package/src/modules/accounts/utils/billing-data.ts +22 -26
- package/src/modules/plans/types/plan.type.ts +17 -0
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +12 -4
- package/src/modules/subscriptions/constants/addons.constants.ts +41 -28
- package/src/utils/format/currency.ts +5 -29
- package/src/utils/format/gateway.ts +22 -0
|
@@ -44,12 +44,20 @@ function buildMainFeaturesFromItems(items, translate) {
|
|
|
44
44
|
const users = translate ? translate("common.plans.mainFeatures.usersUnlimited") : "Usu\xE1rios ilimitados";
|
|
45
45
|
return { pages, domains, users };
|
|
46
46
|
}
|
|
47
|
-
function computePricingByPeriod(apiPlan
|
|
47
|
+
function computePricingByPeriod(apiPlan) {
|
|
48
48
|
const monthly = apiPlan.value;
|
|
49
49
|
if (monthly == null) {
|
|
50
50
|
return { monthly: 0, semiannual: 0, annual: 0 };
|
|
51
51
|
}
|
|
52
52
|
const round2 = (n) => Math.round(n * 100) / 100;
|
|
53
|
+
const pricing = apiPlan.pricing;
|
|
54
|
+
if (pricing) {
|
|
55
|
+
return {
|
|
56
|
+
monthly,
|
|
57
|
+
semiannual: round2(pricing.semester.charged / 6),
|
|
58
|
+
annual: round2(pricing.annual.charged / 12)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
53
61
|
return {
|
|
54
62
|
monthly,
|
|
55
63
|
semiannual: round2(monthly * (1 - apiPlan.discount_semester / 100)),
|
|
@@ -59,7 +67,7 @@ function computePricingByPeriod(apiPlan, currency) {
|
|
|
59
67
|
function buildUiPlan(plan, currency, translate) {
|
|
60
68
|
const popular = plan.id === 2 || plan.id_plan === 2;
|
|
61
69
|
const buttonVariant = popular ? "brand" : "default";
|
|
62
|
-
const pricingByPeriod = computePricingByPeriod(plan
|
|
70
|
+
const pricingByPeriod = computePricingByPeriod(plan);
|
|
63
71
|
const monthlyFinal = pricingByPeriod.monthly;
|
|
64
72
|
const isStarterPlan = plan.id === STARTER_PLAN_ID || plan.id_plan === STARTER_PLAN_ID;
|
|
65
73
|
const hasProjectAndOnboarding = plan.name.toLowerCase().includes("ag\xEAncia") || plan.name.toLowerCase().includes("agencia");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {\n Plan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n UiPlan,\n} from \"../types/plan.type\";\nimport { ADDON_IDS } from \"../../subscriptions/constants/addons.constants\";\nimport {\n formatCurrencyNumber,\n type CurrencyCode,\n} from \"../../../utils/format/currency\";\n\nexport type PlanBillingPeriod = \"monthly\" | \"semiannual\" | \"annual\";\n\nconst STARTER_PLAN_ID = 415;\n\ntype TranslateFn = (key: any, values?: Record<string, string | number>) => string;\n\nconst BASE_FEATURES_KEYS = [\n { icon: \"check\", key: \"plans.features.unlimitedVisits\", fallback: \"Visitas ilimitadas\" },\n { icon: \"check\", key: \"plans.features.unlimitedLeads\", fallback: \"Leads ilimitadas\" },\n { icon: \"check\", key: \"plans.features.sharePages\", fallback: \"Compartilhar páginas\", tooltip: \"sharePages\" },\n { icon: \"check\", key: \"plans.features.hosting\", fallback: \"Hospedagem inclusa\" },\n // SSL (HTTPS) + CDN — brand/acronym: never translated\n { icon: \"check\", key: null, fallback: \"SSL (HTTPS) + CDN\" },\n { icon: \"check\", key: \"plans.features.freeTemplates\", fallback: \"Templates gratuitos\" },\n] as const;\n\nfunction buildBaseFeatures(translate?: TranslateFn): PlanFeature[] {\n return BASE_FEATURES_KEYS.map(({ icon, key, fallback, ...rest }) => {\n const text = key && translate ? translate(`common.${key}`) : fallback;\n const feature: PlanFeature = { icon, text };\n if (\"tooltip\" in rest && rest.tooltip) feature.tooltip = rest.tooltip;\n return feature;\n });\n}\n\nfunction buildMainFeaturesFromItems(\n items: Plan[\"items\"],\n translate?: TranslateFn\n): PlanMainFeatures {\n const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);\n const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);\n\n const pagesQty = pagesItem?.quantity ?? 0;\n const domainsQty = domainsItem?.quantity ?? 1;\n\n let pages: string;\n if (pagesQty === 0) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesUnlimited\")\n : \"Páginas ilimitadas\";\n } else if (pagesQty === 1) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pageSingular\")\n : \"1 página\";\n } else {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesPlural\", { count: pagesQty })\n : `${pagesQty} páginas`;\n }\n\n let domains: string;\n if (domainsQty >= 999) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsUnlimited\")\n : \"Domínios ilimitados\";\n } else if (domainsQty === 1) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainSingular\")\n : \"1 domínio externo\";\n } else {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsPlural\", { count: domainsQty })\n : `${domainsQty} domínios externos`;\n }\n\n const users = translate\n ? translate(\"common.plans.mainFeatures.usersUnlimited\")\n : \"Usuários ilimitados\";\n\n return { pages, domains, users };\n}\n\nfunction computePricingByPeriod(apiPlan: Plan, currency: CurrencyCode): PlanPricingByPeriod {\n // Backend agora resolve value por moeda da conta; mapper apenas lê.\n // value pode ser null (ex.: conta USD, preço USD não cadastrado).\n const monthly = apiPlan.value;\n if (monthly == null) {\n return { monthly: 0, semiannual: 0, annual: 0 };\n }\n const round2 = (n: number) => Math.round(n * 100) / 100;\n return {\n monthly,\n semiannual: round2(monthly * (1 - apiPlan.discount_semester / 100)),\n annual: round2(monthly * (1 - apiPlan.discount_annual / 100)),\n };\n}\n\nfunction buildUiPlan(plan: Plan, currency: CurrencyCode, translate?: TranslateFn): UiPlan {\n const popular = plan.id === 2 || plan.id_plan === 2;\n const buttonVariant = popular ? \"brand\" : \"default\";\n\n const pricingByPeriod = computePricingByPeriod(plan, currency);\n const monthlyFinal = pricingByPeriod.monthly;\n\n const isStarterPlan = plan.id === STARTER_PLAN_ID || plan.id_plan === STARTER_PLAN_ID;\n const hasProjectAndOnboarding =\n plan.name.toLowerCase().includes(\"agência\") || plan.name.toLowerCase().includes(\"agencia\");\n\n const onboardingText = translate\n ? translate(\"common.plans.features.onboarding\")\n : \"Reunião de Onboarding\";\n const projectMgmtText = translate\n ? translate(\"common.plans.features.projectManagement\")\n : \"Gestão de projetos\";\n const sharePagesText = translate\n ? translate(\"common.plans.features.sharePages\")\n : \"Compartilhar páginas\";\n\n const features: PlanFeature[] = [\n ...buildBaseFeatures(translate).map((feature) =>\n feature.text === sharePagesText && isStarterPlan\n ? { ...feature, icon: \"x\" as const, disabled: true }\n : feature\n ),\n hasProjectAndOnboarding\n ? { icon: \"check\", text: onboardingText }\n : { icon: \"x\", text: onboardingText, disabled: true },\n hasProjectAndOnboarding\n ? { icon: \"check\", text: projectMgmtText, tooltip: \"projectManagement\" }\n : { icon: \"x\", text: projectMgmtText, disabled: true, tooltip: \"projectManagement\" },\n ];\n\n const currencyAwareItems = plan.items.map((item) => ({\n ...item,\n value: item.value ?? 0,\n }));\n\n const priceUnavailable = plan.value == null;\n const unavailableLabel = translate ? translate(\"common.plans.usdNotConfigured\") : \"USD não configurado\";\n\n return {\n planId: plan.id,\n name: plan.name,\n isPopular: popular,\n buttonVariant,\n mainFeatures: buildMainFeaturesFromItems(plan.items, translate),\n features,\n originalPrice: priceUnavailable ? unavailableLabel : formatCurrencyNumber(monthlyFinal, 2, currency),\n price: priceUnavailable ? unavailableLabel : formatCurrencyNumber(monthlyFinal, 2, currency),\n pricingByPeriod,\n priceUnavailable,\n items: currencyAwareItems,\n };\n}\n\n/**\n * Mapeia um plano da API para UiPlan em BRL.\n * Assinatura de 1 argumento — seguro em `plans.map(mapApiPlanToUiPlan)`.\n * Passa `translate` opcional para i18n; sem ele cai nos literais pt-br (back-compat).\n */\nexport function mapApiPlanToUiPlan(plan: Plan, translate?: TranslateFn): UiPlan {\n return buildUiPlan(plan, \"brl\", translate);\n}\n\n/**\n * Variante currency-aware: a moeda vem do gateway da conta (getCurrencyForGateway).\n * Fábrica para uso ergonômico em `.map`: `plans.map(mapApiPlanToUiPlanForCurrency(currency, translate))`.\n * Mantida separada de mapApiPlanToUiPlan para não quebrar callers que passam a fn direto pro `.map`.\n */\nexport const mapApiPlanToUiPlanForCurrency =\n (currency: CurrencyCode, translate?: TranslateFn) =>\n (plan: Plan): UiPlan =>\n buildUiPlan(plan, currency, translate);\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {\n Plan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n UiPlan,\n} from \"../types/plan.type\";\nimport { ADDON_IDS } from \"../../subscriptions/constants/addons.constants\";\nimport {\n formatCurrencyNumber,\n type CurrencyCode,\n} from \"../../../utils/format/currency\";\n\nexport type PlanBillingPeriod = \"monthly\" | \"semiannual\" | \"annual\";\n\nconst STARTER_PLAN_ID = 415;\n\ntype TranslateFn = (key: any, values?: Record<string, string | number>) => string;\n\nconst BASE_FEATURES_KEYS = [\n { icon: \"check\", key: \"plans.features.unlimitedVisits\", fallback: \"Visitas ilimitadas\" },\n { icon: \"check\", key: \"plans.features.unlimitedLeads\", fallback: \"Leads ilimitadas\" },\n { icon: \"check\", key: \"plans.features.sharePages\", fallback: \"Compartilhar páginas\", tooltip: \"sharePages\" },\n { icon: \"check\", key: \"plans.features.hosting\", fallback: \"Hospedagem inclusa\" },\n // SSL (HTTPS) + CDN — brand/acronym: never translated\n { icon: \"check\", key: null, fallback: \"SSL (HTTPS) + CDN\" },\n { icon: \"check\", key: \"plans.features.freeTemplates\", fallback: \"Templates gratuitos\" },\n] as const;\n\nfunction buildBaseFeatures(translate?: TranslateFn): PlanFeature[] {\n return BASE_FEATURES_KEYS.map(({ icon, key, fallback, ...rest }) => {\n const text = key && translate ? translate(`common.${key}`) : fallback;\n const feature: PlanFeature = { icon, text };\n if (\"tooltip\" in rest && rest.tooltip) feature.tooltip = rest.tooltip;\n return feature;\n });\n}\n\nfunction buildMainFeaturesFromItems(\n items: Plan[\"items\"],\n translate?: TranslateFn\n): PlanMainFeatures {\n const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);\n const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);\n\n const pagesQty = pagesItem?.quantity ?? 0;\n const domainsQty = domainsItem?.quantity ?? 1;\n\n let pages: string;\n if (pagesQty === 0) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesUnlimited\")\n : \"Páginas ilimitadas\";\n } else if (pagesQty === 1) {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pageSingular\")\n : \"1 página\";\n } else {\n pages = translate\n ? translate(\"common.plans.mainFeatures.pagesPlural\", { count: pagesQty })\n : `${pagesQty} páginas`;\n }\n\n let domains: string;\n if (domainsQty >= 999) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsUnlimited\")\n : \"Domínios ilimitados\";\n } else if (domainsQty === 1) {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainSingular\")\n : \"1 domínio externo\";\n } else {\n domains = translate\n ? translate(\"common.plans.mainFeatures.domainsPlural\", { count: domainsQty })\n : `${domainsQty} domínios externos`;\n }\n\n const users = translate\n ? translate(\"common.plans.mainFeatures.usersUnlimited\")\n : \"Usuários ilimitados\";\n\n return { pages, domains, users };\n}\n\nfunction computePricingByPeriod(apiPlan: Plan): PlanPricingByPeriod {\n const monthly = apiPlan.value;\n if (monthly == null) {\n return { monthly: 0, semiannual: 0, annual: 0 };\n }\n const round2 = (n: number) => Math.round(n * 100) / 100;\n\n const pricing = apiPlan.pricing;\n if (pricing) {\n return {\n monthly,\n semiannual: round2(pricing.semester.charged / 6),\n annual: round2(pricing.annual.charged / 12),\n };\n }\n\n return {\n monthly,\n semiannual: round2(monthly * (1 - apiPlan.discount_semester / 100)),\n annual: round2(monthly * (1 - apiPlan.discount_annual / 100)),\n };\n}\n\nfunction buildUiPlan(plan: Plan, currency: CurrencyCode, translate?: TranslateFn): UiPlan {\n const popular = plan.id === 2 || plan.id_plan === 2;\n const buttonVariant = popular ? \"brand\" : \"default\";\n\n const pricingByPeriod = computePricingByPeriod(plan);\n const monthlyFinal = pricingByPeriod.monthly;\n\n const isStarterPlan = plan.id === STARTER_PLAN_ID || plan.id_plan === STARTER_PLAN_ID;\n const hasProjectAndOnboarding =\n plan.name.toLowerCase().includes(\"agência\") || plan.name.toLowerCase().includes(\"agencia\");\n\n const onboardingText = translate\n ? translate(\"common.plans.features.onboarding\")\n : \"Reunião de Onboarding\";\n const projectMgmtText = translate\n ? translate(\"common.plans.features.projectManagement\")\n : \"Gestão de projetos\";\n const sharePagesText = translate\n ? translate(\"common.plans.features.sharePages\")\n : \"Compartilhar páginas\";\n\n const features: PlanFeature[] = [\n ...buildBaseFeatures(translate).map((feature) =>\n feature.text === sharePagesText && isStarterPlan\n ? { ...feature, icon: \"x\" as const, disabled: true }\n : feature\n ),\n hasProjectAndOnboarding\n ? { icon: \"check\", text: onboardingText }\n : { icon: \"x\", text: onboardingText, disabled: true },\n hasProjectAndOnboarding\n ? { icon: \"check\", text: projectMgmtText, tooltip: \"projectManagement\" }\n : { icon: \"x\", text: projectMgmtText, disabled: true, tooltip: \"projectManagement\" },\n ];\n\n const currencyAwareItems = plan.items.map((item) => ({\n ...item,\n value: item.value ?? 0,\n }));\n\n const priceUnavailable = plan.value == null;\n const unavailableLabel = translate ? translate(\"common.plans.usdNotConfigured\") : \"USD não configurado\";\n\n return {\n planId: plan.id,\n name: plan.name,\n isPopular: popular,\n buttonVariant,\n mainFeatures: buildMainFeaturesFromItems(plan.items, translate),\n features,\n originalPrice: priceUnavailable ? unavailableLabel : formatCurrencyNumber(monthlyFinal, 2, currency),\n price: priceUnavailable ? unavailableLabel : formatCurrencyNumber(monthlyFinal, 2, currency),\n pricingByPeriod,\n priceUnavailable,\n items: currencyAwareItems,\n };\n}\n\n/**\n * Mapeia um plano da API para UiPlan em BRL.\n * Assinatura de 1 argumento — seguro em `plans.map(mapApiPlanToUiPlan)`.\n * Passa `translate` opcional para i18n; sem ele cai nos literais pt-br (back-compat).\n */\nexport function mapApiPlanToUiPlan(plan: Plan, translate?: TranslateFn): UiPlan {\n return buildUiPlan(plan, \"brl\", translate);\n}\n\n/**\n * Variante currency-aware: a moeda vem do gateway da conta (getCurrencyForGateway).\n * Fábrica para uso ergonômico em `.map`: `plans.map(mapApiPlanToUiPlanForCurrency(currency, translate))`.\n * Mantida separada de mapApiPlanToUiPlan para não quebrar callers que passam a fn direto pro `.map`.\n */\nexport const mapApiPlanToUiPlanForCurrency =\n (currency: CurrencyCode, translate?: TranslateFn) =>\n (plan: Plan): UiPlan =>\n buildUiPlan(plan, currency, translate);\n"],"mappings":"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","names":[]}
|
|
@@ -6,6 +6,16 @@ const ADDON_IDS = {
|
|
|
6
6
|
HEATMAP: 5,
|
|
7
7
|
AI: 6
|
|
8
8
|
};
|
|
9
|
+
const AI_CREDIT_SIZES = [0, 250, 500, 1e3, 2500, 5e3, 1e4];
|
|
10
|
+
function resolveAiCreditPrice(quantity, perCreditPrice) {
|
|
11
|
+
return Math.round(quantity * perCreditPrice * 100) / 100;
|
|
12
|
+
}
|
|
13
|
+
function buildAiCreditOptions(perCreditPrice) {
|
|
14
|
+
return AI_CREDIT_SIZES.map((credits) => ({
|
|
15
|
+
credits,
|
|
16
|
+
price: resolveAiCreditPrice(credits, perCreditPrice)
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
9
19
|
const AI_CREDIT_OPTIONS = [
|
|
10
20
|
{ credits: 0, price: 0, priceLabel: "R$ 0,00" },
|
|
11
21
|
{ credits: 250, price: 9.99, priceLabel: "R$ 9,99" },
|
|
@@ -15,10 +25,13 @@ const AI_CREDIT_OPTIONS = [
|
|
|
15
25
|
{ credits: 5e3, price: 199.8, priceLabel: "R$ 199,80" },
|
|
16
26
|
{ credits: 1e4, price: 399.6, priceLabel: "R$ 399,60" }
|
|
17
27
|
];
|
|
18
|
-
const AI_CREDIT_VALUES = new Set(
|
|
28
|
+
const AI_CREDIT_VALUES = new Set(AI_CREDIT_SIZES);
|
|
19
29
|
export {
|
|
20
30
|
ADDON_IDS,
|
|
21
31
|
AI_CREDIT_OPTIONS,
|
|
22
|
-
|
|
32
|
+
AI_CREDIT_SIZES,
|
|
33
|
+
AI_CREDIT_VALUES,
|
|
34
|
+
buildAiCreditOptions,
|
|
35
|
+
resolveAiCreditPrice
|
|
23
36
|
};
|
|
24
37
|
//# sourceMappingURL=addons.constants.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/subscriptions/constants/addons.constants.ts"],"sourcesContent":["export const ADDON_IDS = {\
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/subscriptions/constants/addons.constants.ts"],"sourcesContent":["export const ADDON_IDS = {\n DOMAINS: 1,\n PAGES: 2,\n PROJECTS: 3,\n AB_TEST: 4,\n HEATMAP: 5,\n AI: 6,\n} as const;\n\nexport type AddonKindEnum = (typeof ADDON_IDS)[keyof typeof ADDON_IDS];\n\nexport interface AiCreditOption {\n credits: number;\n price: number;\n priceLabel?: string;\n}\n\nexport const AI_CREDIT_SIZES = [0, 250, 500, 1000, 2500, 5000, 10000] as const;\n\nexport function resolveAiCreditPrice(quantity: number, perCreditPrice: number): number {\n return Math.round(quantity * perCreditPrice * 100) / 100;\n}\n\nexport function buildAiCreditOptions(perCreditPrice: number): AiCreditOption[] {\n return AI_CREDIT_SIZES.map((credits) => ({\n credits,\n price: resolveAiCreditPrice(credits, perCreditPrice),\n }));\n}\n\nexport const AI_CREDIT_OPTIONS: AiCreditOption[] = [\n { credits: 0, price: 0, priceLabel: 'R$ 0,00' },\n { credits: 250, price: 9.99, priceLabel: 'R$ 9,99' },\n { credits: 500, price: 19.98, priceLabel: 'R$ 19,98' },\n { credits: 1000, price: 39.96, priceLabel: 'R$ 39,96' },\n { credits: 2500, price: 99.90, priceLabel: 'R$ 99,90' },\n { credits: 5000, price: 199.80, priceLabel: 'R$ 199,80' },\n { credits: 10000, price: 399.60, priceLabel: 'R$ 399,60' },\n];\n\nexport const AI_CREDIT_VALUES: ReadonlySet<number> = new Set(AI_CREDIT_SIZES);\n"],"mappings":"AAAO,MAAM,YAAY;AAAA,EACvB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAI;AACN;AAUO,MAAM,kBAAkB,CAAC,GAAG,KAAK,KAAK,KAAM,MAAM,KAAM,GAAK;AAE7D,SAAS,qBAAqB,UAAkB,gBAAgC;AACrF,SAAO,KAAK,MAAM,WAAW,iBAAiB,GAAG,IAAI;AACvD;AAEO,SAAS,qBAAqB,gBAA0C;AAC7E,SAAO,gBAAgB,IAAI,CAAC,aAAa;AAAA,IACvC;AAAA,IACA,OAAO,qBAAqB,SAAS,cAAc;AAAA,EACrD,EAAE;AACJ;AAEO,MAAM,oBAAsC;AAAA,EACjD,EAAE,SAAS,GAAG,OAAO,GAAG,YAAY,UAAU;AAAA,EAC9C,EAAE,SAAS,KAAK,OAAO,MAAM,YAAY,UAAU;AAAA,EACnD,EAAE,SAAS,KAAK,OAAO,OAAO,YAAY,WAAW;AAAA,EACrD,EAAE,SAAS,KAAM,OAAO,OAAO,YAAY,WAAW;AAAA,EACtD,EAAE,SAAS,MAAM,OAAO,MAAO,YAAY,WAAW;AAAA,EACtD,EAAE,SAAS,KAAM,OAAO,OAAQ,YAAY,YAAY;AAAA,EACxD,EAAE,SAAS,KAAO,OAAO,OAAQ,YAAY,YAAY;AAC3D;AAEO,MAAM,mBAAwC,IAAI,IAAI,eAAe;","names":[]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { isUsdGateway } from "./gateway";
|
|
1
2
|
const CURRENCY_FORMAT = {
|
|
2
3
|
brl: { locale: "pt-BR", currency: "BRL" },
|
|
3
4
|
usd: { locale: "en-US", currency: "USD" }
|
|
4
5
|
};
|
|
5
|
-
const getCurrencyForGateway = (gateway) => gateway
|
|
6
|
+
const getCurrencyForGateway = (gateway) => isUsdGateway(gateway) ? "usd" : "brl";
|
|
7
|
+
const getLocaleForCurrency = (currency = "brl") => CURRENCY_FORMAT[currency].locale;
|
|
6
8
|
const formatCurrency = (value, currency = "brl") => {
|
|
7
9
|
const fmt = CURRENCY_FORMAT[currency];
|
|
8
10
|
if (typeof value === "number") {
|
|
@@ -36,6 +38,7 @@ export {
|
|
|
36
38
|
formatCurrency,
|
|
37
39
|
formatCurrencyNumber,
|
|
38
40
|
getCurrencyForGateway,
|
|
41
|
+
getLocaleForCurrency,
|
|
39
42
|
parseCurrencyToNumber
|
|
40
43
|
};
|
|
41
44
|
//# sourceMappingURL=currency.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/format/currency.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/format/currency.ts"],"sourcesContent":["import { isUsdGateway } from './gateway';\n\nexport type CurrencyCode = 'brl' | 'usd';\n\nconst CURRENCY_FORMAT: Record<CurrencyCode, { locale: string; currency: string }> = {\n brl: { locale: 'pt-BR', currency: 'BRL' },\n usd: { locale: 'en-US', currency: 'USD' },\n};\n\nexport const getCurrencyForGateway = (gateway?: string | null): CurrencyCode =>\n isUsdGateway(gateway) ? 'usd' : 'brl';\n\nexport const getLocaleForCurrency = (currency: CurrencyCode = 'brl'): string => CURRENCY_FORMAT[currency].locale;\n\nexport const formatCurrency = (value: string | number, currency: CurrencyCode = 'brl'): string => {\n const fmt = CURRENCY_FORMAT[currency];\n if (typeof value === 'number') {\n return value.toLocaleString(fmt.locale, {\n style: 'currency',\n currency: fmt.currency,\n });\n }\n\n const numericValue = value.replace(/\\D/g, '');\n const numberValue = parseFloat(numericValue) / 100;\n return numberValue.toLocaleString(fmt.locale, {\n style: 'currency',\n currency: fmt.currency,\n });\n};\n\nexport const parseCurrencyToNumber = (value: string): number => {\n const numericValue = value.replace(/\\D/g, '');\n return parseFloat(numericValue) / 100;\n};\n\nexport const formatCurrencyNumber = (value?: number | null, decimals = 2, currency: CurrencyCode = 'brl'): string => {\n const safeValue = value ?? 0;\n const fmt = CURRENCY_FORMAT[currency];\n return safeValue.toLocaleString(fmt.locale, {\n style: 'currency',\n currency: fmt.currency,\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n });\n};\n"],"mappings":"AAAA,SAAS,oBAAoB;AAI7B,MAAM,kBAA8E;AAAA,EAClF,KAAK,EAAE,QAAQ,SAAS,UAAU,MAAM;AAAA,EACxC,KAAK,EAAE,QAAQ,SAAS,UAAU,MAAM;AAC1C;AAEO,MAAM,wBAAwB,CAAC,YACpC,aAAa,OAAO,IAAI,QAAQ;AAE3B,MAAM,uBAAuB,CAAC,WAAyB,UAAkB,gBAAgB,QAAQ,EAAE;AAEnG,MAAM,iBAAiB,CAAC,OAAwB,WAAyB,UAAkB;AAChG,QAAM,MAAM,gBAAgB,QAAQ;AACpC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,MAAM,eAAe,IAAI,QAAQ;AAAA,MACtC,OAAO;AAAA,MACP,UAAU,IAAI;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,eAAe,MAAM,QAAQ,OAAO,EAAE;AAC5C,QAAM,cAAc,WAAW,YAAY,IAAI;AAC/C,SAAO,YAAY,eAAe,IAAI,QAAQ;AAAA,IAC5C,OAAO;AAAA,IACP,UAAU,IAAI;AAAA,EAChB,CAAC;AACH;AAEO,MAAM,wBAAwB,CAAC,UAA0B;AAC9D,QAAM,eAAe,MAAM,QAAQ,OAAO,EAAE;AAC5C,SAAO,WAAW,YAAY,IAAI;AACpC;AAEO,MAAM,uBAAuB,CAAC,OAAuB,WAAW,GAAG,WAAyB,UAAkB;AACnH,QAAM,YAAY,SAAS;AAC3B,QAAM,MAAM,gBAAgB,QAAQ;AACpC,SAAO,UAAU,eAAe,IAAI,QAAQ;AAAA,IAC1C,OAAO;AAAA,IACP,UAAU,IAAI;AAAA,IACd,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,EACzB,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const USD_GATEWAY = "stripe_usd";
|
|
2
|
+
const normalizeGateway = (gateway) => (gateway ?? "").trim().toLowerCase();
|
|
3
|
+
const isUsdGateway = (gateway) => normalizeGateway(gateway) === USD_GATEWAY;
|
|
4
|
+
const isUsdAccount = (account) => isUsdGateway(account?.gateway);
|
|
5
|
+
const USD_PAYMENT_METHODS = ["card"];
|
|
6
|
+
const BRL_PAYMENT_METHODS = ["card", "pix", "boleto"];
|
|
7
|
+
const allowedPaymentMethods = (account) => isUsdAccount(account) ? USD_PAYMENT_METHODS : BRL_PAYMENT_METHODS;
|
|
8
|
+
const isPaymentMethodAllowed = (account, method) => allowedPaymentMethods(account).includes(method);
|
|
9
|
+
const canBuyStandaloneAiCredits = (account) => !isUsdAccount(account);
|
|
10
|
+
export {
|
|
11
|
+
USD_GATEWAY,
|
|
12
|
+
allowedPaymentMethods,
|
|
13
|
+
canBuyStandaloneAiCredits,
|
|
14
|
+
isPaymentMethodAllowed,
|
|
15
|
+
isUsdAccount,
|
|
16
|
+
isUsdGateway
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=gateway.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/format/gateway.ts"],"sourcesContent":["export const USD_GATEWAY = 'stripe_usd';\n\nexport type PaymentMethodKind = 'card' | 'pix' | 'boleto';\n\nexport type AccountGatewayLike = { gateway?: string | null } | null | undefined;\n\nconst normalizeGateway = (gateway?: string | null): string => (gateway ?? '').trim().toLowerCase();\n\nexport const isUsdGateway = (gateway?: string | null): boolean => normalizeGateway(gateway) === USD_GATEWAY;\n\nexport const isUsdAccount = (account: AccountGatewayLike): boolean => isUsdGateway(account?.gateway);\n\nconst USD_PAYMENT_METHODS: readonly PaymentMethodKind[] = ['card'];\nconst BRL_PAYMENT_METHODS: readonly PaymentMethodKind[] = ['card', 'pix', 'boleto'];\n\nexport const allowedPaymentMethods = (account: AccountGatewayLike): readonly PaymentMethodKind[] =>\n isUsdAccount(account) ? USD_PAYMENT_METHODS : BRL_PAYMENT_METHODS;\n\nexport const isPaymentMethodAllowed = (account: AccountGatewayLike, method: PaymentMethodKind): boolean =>\n allowedPaymentMethods(account).includes(method);\n\nexport const canBuyStandaloneAiCredits = (account: AccountGatewayLike): boolean => !isUsdAccount(account);\n"],"mappings":"AAAO,MAAM,cAAc;AAM3B,MAAM,mBAAmB,CAAC,aAAqC,WAAW,IAAI,KAAK,EAAE,YAAY;AAE1F,MAAM,eAAe,CAAC,YAAqC,iBAAiB,OAAO,MAAM;AAEzF,MAAM,eAAe,CAAC,YAAyC,aAAa,SAAS,OAAO;AAEnG,MAAM,sBAAoD,CAAC,MAAM;AACjE,MAAM,sBAAoD,CAAC,QAAQ,OAAO,QAAQ;AAE3E,MAAM,wBAAwB,CAAC,YACpC,aAAa,OAAO,IAAI,sBAAsB;AAEzC,MAAM,yBAAyB,CAAC,SAA6B,WAClE,sBAAsB,OAAO,EAAE,SAAS,MAAM;AAEzC,MAAM,4BAA4B,CAAC,YAAyC,CAAC,aAAa,OAAO;","names":[]}
|
package/package.json
CHANGED
|
@@ -12,14 +12,16 @@ import { Toast } from '../ui/feedback/Toast';
|
|
|
12
12
|
import { SelectField } from '../ui/form/SelectField';
|
|
13
13
|
import { Skeleton } from '../ui/feedback/Skeleton';
|
|
14
14
|
import { PaymentInfoCard } from '../ui/data-display/PaymentInfoCard';
|
|
15
|
-
import { ADDON_IDS } from '../../modules/subscriptions/constants/addons.constants';
|
|
16
15
|
import {
|
|
17
|
-
|
|
16
|
+
ADDON_IDS,
|
|
18
17
|
AI_CREDIT_VALUES,
|
|
18
|
+
buildAiCreditOptions,
|
|
19
19
|
} from '../../modules/subscriptions/constants/addons.constants';
|
|
20
20
|
import { useBuyCreditsModal } from '../../store/useBuyCreditsModal';
|
|
21
21
|
import { useModalManager } from '../../store/useModalManager';
|
|
22
22
|
import { useCards } from '../../modules/cards/hooks/cards.hook';
|
|
23
|
+
import { useCurrencyFormatter } from '../../modules/accounts/hooks/use-currency-formatter.hook';
|
|
24
|
+
import { usePlanById } from '../../modules/plans/hooks/use-plan-by-id.hook';
|
|
23
25
|
import { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';
|
|
24
26
|
import { useCalculateSubscription } from '../../modules/subscriptions/hooks/calculate-subscription.hook';
|
|
25
27
|
import { useUpdateSubscriptionPlan } from '../../modules/subscriptions/hooks/update-subscription-plan.hook';
|
|
@@ -49,6 +51,7 @@ export default function BuyCreditsModal() {
|
|
|
49
51
|
const isDefaultWl = useIsDefaultWhitelabel();
|
|
50
52
|
const { isExternalContracting, redirectToExternal } = useExternalContracting();
|
|
51
53
|
const { data: cardsData } = useCards();
|
|
54
|
+
const { locale, formatCurrencyNumber } = useCurrencyFormatter();
|
|
52
55
|
const { data: subscriptionData } = useActiveSubscription();
|
|
53
56
|
const subscription = subscriptionData?.data?.[0] ?? null;
|
|
54
57
|
const defaultCardId =
|
|
@@ -75,9 +78,20 @@ export default function BuyCreditsModal() {
|
|
|
75
78
|
const subscriptionId = subscription?.id;
|
|
76
79
|
const planId = subscription?.id_plan;
|
|
77
80
|
|
|
81
|
+
const { data: planData } = usePlanById(planId);
|
|
82
|
+
const perCreditPrice = useMemo(() => {
|
|
83
|
+
const planAiItem = planData?.data?.items?.find(
|
|
84
|
+
(item) => item.id_addon === ADDON_IDS.AI && (item.value ?? 0) > 0
|
|
85
|
+
);
|
|
86
|
+
return planAiItem?.value ?? aiItem?.value ?? 0;
|
|
87
|
+
}, [planData, aiItem]);
|
|
88
|
+
|
|
89
|
+
const hasPerCreditPrice = perCreditPrice > 0;
|
|
90
|
+
|
|
91
|
+
const aiCreditOptions = useMemo(() => buildAiCreditOptions(perCreditPrice), [perCreditPrice]);
|
|
92
|
+
|
|
78
93
|
const buildPlanExtras = useCallback(
|
|
79
94
|
(aiQuantity: number) => {
|
|
80
|
-
const aiOption = AI_CREDIT_OPTIONS.find(opt => opt.credits === aiQuantity);
|
|
81
95
|
return [
|
|
82
96
|
...(subscription?.items ?? [])
|
|
83
97
|
.filter((item) => item.id_addon != null && item.id_addon !== ADDON_IDS.AI)
|
|
@@ -87,10 +101,9 @@ export default function BuyCreditsModal() {
|
|
|
87
101
|
value: Number(item.value ?? 0),
|
|
88
102
|
price: item.price,
|
|
89
103
|
})),
|
|
90
|
-
{
|
|
91
|
-
id_addon: ADDON_IDS.AI,
|
|
104
|
+
{
|
|
105
|
+
id_addon: ADDON_IDS.AI,
|
|
92
106
|
quantity: aiQuantity,
|
|
93
|
-
value: aiOption?.price ?? 0
|
|
94
107
|
},
|
|
95
108
|
];
|
|
96
109
|
},
|
|
@@ -161,14 +174,13 @@ export default function BuyCreditsModal() {
|
|
|
161
174
|
shouldDirty: true,
|
|
162
175
|
});
|
|
163
176
|
|
|
164
|
-
|
|
165
|
-
if (!option) return;
|
|
177
|
+
if (!AI_CREDIT_VALUES.has(credits)) return;
|
|
166
178
|
|
|
167
179
|
calculate({
|
|
168
180
|
id_product: 1,
|
|
169
181
|
...(planId != null && { id_plan: planId }),
|
|
170
182
|
...(subscriptionId != null && { id_subscription: subscriptionId }),
|
|
171
|
-
plan_extras: buildPlanExtras(
|
|
183
|
+
plan_extras: buildPlanExtras(credits),
|
|
172
184
|
});
|
|
173
185
|
},
|
|
174
186
|
[form, subscriptionId, planId, calculate, buildPlanExtras]
|
|
@@ -186,14 +198,8 @@ export default function BuyCreditsModal() {
|
|
|
186
198
|
return getPriceFromCalculatedData(calculatedData, subscription?.periodicity);
|
|
187
199
|
}, [calculatedData, subscription]);
|
|
188
200
|
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
style: 'currency',
|
|
192
|
-
currency: 'BRL',
|
|
193
|
-
});
|
|
194
|
-
}, []);
|
|
195
|
-
|
|
196
|
-
const isConfirmDisabled = !isDirty || !isValid || isCalculatePending || isSubmitting;
|
|
201
|
+
const isConfirmDisabled =
|
|
202
|
+
!isDirty || !isValid || isCalculatePending || isSubmitting || !hasPerCreditPrice;
|
|
197
203
|
|
|
198
204
|
const handleClose = useCallback(() => {
|
|
199
205
|
form.reset();
|
|
@@ -205,45 +211,55 @@ export default function BuyCreditsModal() {
|
|
|
205
211
|
}, [openModal]);
|
|
206
212
|
|
|
207
213
|
const selectOptions = useMemo(() => {
|
|
208
|
-
return
|
|
214
|
+
return aiCreditOptions.map((opt) => ({
|
|
209
215
|
value: opt.credits,
|
|
210
216
|
label: (
|
|
211
217
|
<div className="flex items-center justify-between gap-2 w-full">
|
|
212
218
|
<span className="paragraph-small-medium text-zinc-950 flex-1">
|
|
213
|
-
{translate('common.credits.buy.creditsOptionLabel', { credits: opt.credits.toLocaleString(
|
|
219
|
+
{translate('common.credits.buy.creditsOptionLabel', { credits: opt.credits.toLocaleString(locale) })}
|
|
214
220
|
</span>
|
|
215
|
-
|
|
221
|
+
{hasPerCreditPrice && (
|
|
222
|
+
<span className="paragraph-small-medium text-zinc-500 opacity-70">{formatCurrencyNumber(opt.price)}</span>
|
|
223
|
+
)}
|
|
216
224
|
</div>
|
|
217
225
|
),
|
|
218
|
-
displayValue: translate('common.credits.buy.creditsOptionDisplayValue', { credits: opt.credits.toLocaleString(
|
|
226
|
+
displayValue: translate('common.credits.buy.creditsOptionDisplayValue', { credits: opt.credits.toLocaleString(locale) }),
|
|
219
227
|
}));
|
|
220
|
-
}, [translate]);
|
|
228
|
+
}, [aiCreditOptions, translate, locale, formatCurrencyNumber, hasPerCreditPrice]);
|
|
221
229
|
|
|
222
230
|
const onSubmit = useCallback(
|
|
223
231
|
async (data: BuyCreditFormData) => {
|
|
224
232
|
if (!subscriptionId) return;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (!option) return;
|
|
233
|
+
if (!hasPerCreditPrice) return;
|
|
234
|
+
if (!AI_CREDIT_VALUES.has(data.creditOption)) return;
|
|
228
235
|
|
|
229
236
|
await updatePlanMutation.mutateAsync({
|
|
230
237
|
subscriptionId,
|
|
231
238
|
data: {
|
|
232
|
-
plan_extras: buildPlanExtras(
|
|
239
|
+
plan_extras: buildPlanExtras(data.creditOption),
|
|
233
240
|
},
|
|
234
241
|
});
|
|
235
242
|
|
|
236
243
|
toast.custom((t) => (
|
|
237
244
|
<Toast
|
|
238
245
|
variant="success"
|
|
239
|
-
message={translate('common.credits.buy.creditsChangedToast', { credits: data.creditOption.toLocaleString(
|
|
246
|
+
message={translate('common.credits.buy.creditsChangedToast', { credits: data.creditOption.toLocaleString(locale) })}
|
|
240
247
|
toastId={t}
|
|
241
248
|
/>
|
|
242
249
|
));
|
|
243
250
|
form.reset();
|
|
244
251
|
closeModal();
|
|
245
252
|
},
|
|
246
|
-
[
|
|
253
|
+
[
|
|
254
|
+
subscriptionId,
|
|
255
|
+
hasPerCreditPrice,
|
|
256
|
+
updatePlanMutation,
|
|
257
|
+
form,
|
|
258
|
+
closeModal,
|
|
259
|
+
buildPlanExtras,
|
|
260
|
+
translate,
|
|
261
|
+
locale,
|
|
262
|
+
]
|
|
247
263
|
);
|
|
248
264
|
|
|
249
265
|
const renderPriceDisplay = useCallback(() => {
|
|
@@ -253,12 +269,12 @@ export default function BuyCreditsModal() {
|
|
|
253
269
|
if (totalPrice !== null) {
|
|
254
270
|
return (
|
|
255
271
|
<span className="paragraph-xlarge-semibold text-zinc-950">
|
|
256
|
-
{totalPrice === 0 ? translate('common.credits.buy.defaultPrice') :
|
|
272
|
+
{totalPrice === 0 ? translate('common.credits.buy.defaultPrice') : formatCurrencyNumber(totalPrice)}
|
|
257
273
|
</span>
|
|
258
274
|
);
|
|
259
275
|
}
|
|
260
276
|
return <span className="paragraph-xlarge-semibold text-zinc-400">--</span>;
|
|
261
|
-
}, [isCalculatePending, totalPrice,
|
|
277
|
+
}, [isCalculatePending, totalPrice, formatCurrencyNumber, translate]);
|
|
262
278
|
|
|
263
279
|
if (isExternalContracting) {
|
|
264
280
|
return (
|
|
@@ -355,7 +371,7 @@ export default function BuyCreditsModal() {
|
|
|
355
371
|
<Skeleton className="h-5 w-20" />
|
|
356
372
|
) : (
|
|
357
373
|
<span className="paragraph-small-semibold text-zinc-950">
|
|
358
|
-
{
|
|
374
|
+
{formatCurrencyNumber(immediateChargeTotal)}
|
|
359
375
|
</span>
|
|
360
376
|
)}
|
|
361
377
|
</div>
|
|
@@ -385,7 +401,7 @@ export default function BuyCreditsModal() {
|
|
|
385
401
|
<Skeleton className="h-5 w-20" />
|
|
386
402
|
) : (
|
|
387
403
|
<span className="paragraph-small-semibold text-zinc-950">
|
|
388
|
-
{
|
|
404
|
+
{formatCurrencyNumber(immediateChargeTotal)}
|
|
389
405
|
</span>
|
|
390
406
|
)}
|
|
391
407
|
</div>
|
|
@@ -48,7 +48,7 @@ const COUNTRY_OPTIONS = COUNTRIES.map((country: { iso: string; name: string }) =
|
|
|
48
48
|
label: country.name,
|
|
49
49
|
}));
|
|
50
50
|
|
|
51
|
-
function buildBillingDataSchema(
|
|
51
|
+
function buildBillingDataSchema(translate: TranslateFn) {
|
|
52
52
|
const requiredText = z
|
|
53
53
|
.string()
|
|
54
54
|
.trim()
|
|
@@ -73,11 +73,6 @@ function buildBillingDataSchema(isInternational: boolean, translate: TranslateFn
|
|
|
73
73
|
country: requiredText,
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
/* Conta internacional não tem CPF/CNPJ, número nem bairro — mesmo recorte do
|
|
77
|
-
* AddCardModal. Exigir esses campos aqui trancaria o cliente fora do app, já que
|
|
78
|
-
* o modal é bloqueante. */
|
|
79
|
-
if (isInternational) return base;
|
|
80
|
-
|
|
81
76
|
return base.superRefine((data, ctx) => {
|
|
82
77
|
if (!data.streetNumber) {
|
|
83
78
|
ctx.addIssue({
|
|
@@ -140,7 +135,7 @@ function formatDocument(document: string | null | undefined, isCompany: boolean)
|
|
|
140
135
|
function RequiredBillingDataModalContent() {
|
|
141
136
|
const translate = useTranslations();
|
|
142
137
|
const { user } = useAuth();
|
|
143
|
-
const { isRequired, account
|
|
138
|
+
const { isRequired, account } = useRequiredBillingData();
|
|
144
139
|
const { mutateAsync: updateBillingData } = useUpdateBillingData();
|
|
145
140
|
const { mutateAsync: lookupCep } = useViaCep();
|
|
146
141
|
|
|
@@ -150,8 +145,8 @@ function RequiredBillingDataModalContent() {
|
|
|
150
145
|
const isPrefilled = useRef(false);
|
|
151
146
|
|
|
152
147
|
const schema = useMemo(
|
|
153
|
-
() => buildBillingDataSchema(
|
|
154
|
-
[
|
|
148
|
+
() => buildBillingDataSchema(translate),
|
|
149
|
+
[translate],
|
|
155
150
|
);
|
|
156
151
|
|
|
157
152
|
const form = useForm<BillingDataFormValues>({
|
|
@@ -203,9 +198,9 @@ function RequiredBillingDataModalContent() {
|
|
|
203
198
|
neighborhood: account.neighborhood ?? '',
|
|
204
199
|
city: account.city ?? '',
|
|
205
200
|
state: account.state ?? '',
|
|
206
|
-
country: account.country ||
|
|
201
|
+
country: account.country || 'BR',
|
|
207
202
|
});
|
|
208
|
-
}, [account,
|
|
203
|
+
}, [account, reset, user?.email]);
|
|
209
204
|
|
|
210
205
|
const handleDocumentChange = (rawValue: string) => {
|
|
211
206
|
setValue('document', isCompany ? formatCNPJ(rawValue) : formatCPF(rawValue), {
|
|
@@ -222,11 +217,6 @@ function RequiredBillingDataModalContent() {
|
|
|
222
217
|
};
|
|
223
218
|
|
|
224
219
|
const handleCepChange = (rawValue: string) => {
|
|
225
|
-
if (isInternational) {
|
|
226
|
-
setValue('cep', rawValue, { shouldValidate: true });
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
220
|
setValue('cep', formatPostalCode(rawValue), { shouldValidate: true });
|
|
231
221
|
|
|
232
222
|
const digits = rawValue.replace(/\D/g, '');
|
|
@@ -246,12 +236,8 @@ function RequiredBillingDataModalContent() {
|
|
|
246
236
|
|
|
247
237
|
async function onSubmit(data: BillingDataFormValues) {
|
|
248
238
|
const payload: UpdateBillingDataRequest = {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
: {
|
|
252
|
-
financial_document_type: data.personType === 'pf' ? 1 : 2,
|
|
253
|
-
financial_document: data.document,
|
|
254
|
-
}),
|
|
239
|
+
financial_document_type: data.personType === 'pf' ? 1 : 2,
|
|
240
|
+
financial_document: data.document,
|
|
255
241
|
financial_name: data.financialName,
|
|
256
242
|
financial_email: data.financialEmail,
|
|
257
243
|
zipcode: data.cep,
|
|
@@ -322,8 +308,7 @@ function RequiredBillingDataModalContent() {
|
|
|
322
308
|
>
|
|
323
309
|
<div className="flex flex-col gap-6 p-4 lg:p-5 flex-1 overflow-y-auto">
|
|
324
310
|
<div className="flex flex-col gap-5">
|
|
325
|
-
|
|
326
|
-
<div className="flex gap-4">
|
|
311
|
+
<div className="flex gap-4">
|
|
327
312
|
<Controller
|
|
328
313
|
name="personType"
|
|
329
314
|
control={control}
|
|
@@ -362,8 +347,7 @@ function RequiredBillingDataModalContent() {
|
|
|
362
347
|
})}
|
|
363
348
|
/>
|
|
364
349
|
</div>
|
|
365
|
-
|
|
366
|
-
)}
|
|
350
|
+
</div>
|
|
367
351
|
|
|
368
352
|
<FormField
|
|
369
353
|
label={
|
|
@@ -395,12 +379,8 @@ function RequiredBillingDataModalContent() {
|
|
|
395
379
|
</span>
|
|
396
380
|
|
|
397
381
|
<FormField
|
|
398
|
-
label={
|
|
399
|
-
|
|
400
|
-
? translate('common.billing.requiredData.postalCode')
|
|
401
|
-
: translate('common.billing.requiredData.cep')
|
|
402
|
-
}
|
|
403
|
-
placeholder={isInternational ? '' : '_____-___'}
|
|
382
|
+
label={translate('common.billing.requiredData.cep')}
|
|
383
|
+
placeholder="_____-___"
|
|
404
384
|
error={!!errors.cep}
|
|
405
385
|
errorMessage={errors.cep?.message}
|
|
406
386
|
{...register('cep', {
|
|
@@ -418,31 +398,27 @@ function RequiredBillingDataModalContent() {
|
|
|
418
398
|
{...register('street')}
|
|
419
399
|
/>
|
|
420
400
|
</div>
|
|
421
|
-
|
|
422
|
-
<
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
</div>
|
|
431
|
-
)}
|
|
401
|
+
<div className="flex-1">
|
|
402
|
+
<FormField
|
|
403
|
+
label={translate('common.billing.requiredData.streetNumber')}
|
|
404
|
+
placeholder="000"
|
|
405
|
+
error={!!errors.streetNumber}
|
|
406
|
+
errorMessage={errors.streetNumber?.message}
|
|
407
|
+
{...register('streetNumber')}
|
|
408
|
+
/>
|
|
409
|
+
</div>
|
|
432
410
|
</div>
|
|
433
411
|
|
|
434
412
|
<div className="flex gap-4">
|
|
435
|
-
|
|
436
|
-
<
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
</div>
|
|
445
|
-
)}
|
|
413
|
+
<div className="flex-1">
|
|
414
|
+
<FormField
|
|
415
|
+
label={translate('common.billing.requiredData.neighborhood')}
|
|
416
|
+
placeholder={translate('common.billing.requiredData.typeHere')}
|
|
417
|
+
error={!!errors.neighborhood}
|
|
418
|
+
errorMessage={errors.neighborhood?.message}
|
|
419
|
+
{...register('neighborhood')}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
446
422
|
<div className="flex-1">
|
|
447
423
|
<FormField
|
|
448
424
|
label={translate('common.billing.requiredData.complement')}
|
|
@@ -464,16 +440,7 @@ function RequiredBillingDataModalContent() {
|
|
|
464
440
|
/>
|
|
465
441
|
</div>
|
|
466
442
|
<div className="flex-1">
|
|
467
|
-
|
|
468
|
-
<FormField
|
|
469
|
-
label={translate('common.billing.requiredData.stateProvince')}
|
|
470
|
-
placeholder={translate('common.billing.requiredData.typeHere')}
|
|
471
|
-
error={!!errors.state}
|
|
472
|
-
errorMessage={errors.state?.message}
|
|
473
|
-
{...register('state')}
|
|
474
|
-
/>
|
|
475
|
-
) : (
|
|
476
|
-
<Controller
|
|
443
|
+
<Controller
|
|
477
444
|
name="state"
|
|
478
445
|
control={control}
|
|
479
446
|
render={({ field }) => (
|
|
@@ -489,8 +456,7 @@ function RequiredBillingDataModalContent() {
|
|
|
489
456
|
errorMessage={errors.state?.message}
|
|
490
457
|
/>
|
|
491
458
|
)}
|
|
492
|
-
|
|
493
|
-
)}
|
|
459
|
+
/>
|
|
494
460
|
</div>
|
|
495
461
|
</div>
|
|
496
462
|
|
|
@@ -9,6 +9,7 @@ import { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';
|
|
|
9
9
|
import { useCreateSetupIntent } from '../../../modules/cards/hooks/create-setup-intent.hook';
|
|
10
10
|
import { useCurrentAccount } from '../../../modules/accounts/hooks/current-account.hook';
|
|
11
11
|
import { isValidTaxId } from '../../../utils/validators/common';
|
|
12
|
+
import { isUsdAccount } from '../../../utils/format/gateway';
|
|
12
13
|
import { useExternalContracting } from '../../../providers/whitelabel.provider';
|
|
13
14
|
import { CardFormFields, BillingFormFields, buildCardFormSchema } from './CardFormFields';
|
|
14
15
|
import type { CardFormData, StripeElementsStatus } from './CardFormFields';
|
|
@@ -79,7 +80,7 @@ export default function AddCardModal() {
|
|
|
79
80
|
const isOpen = activeModal === 'addCardModal';
|
|
80
81
|
const { isExternalContracting, redirectToExternal } = useExternalContracting();
|
|
81
82
|
const { data: account } = useCurrentAccount();
|
|
82
|
-
const isInternational = account
|
|
83
|
+
const isInternational = isUsdAccount(account);
|
|
83
84
|
const [currentStep, setCurrentStep] = useState(1);
|
|
84
85
|
const [stripeStatus, setStripeStatus] = useState<StripeElementsStatus>(INITIAL_STRIPE_STATUS);
|
|
85
86
|
const [stripeErrors, setStripeErrors] = useState<Record<string, string | undefined>>({});
|
package/src/index.ts
CHANGED
|
@@ -123,7 +123,10 @@ export {
|
|
|
123
123
|
export {
|
|
124
124
|
ADDON_IDS,
|
|
125
125
|
AI_CREDIT_OPTIONS,
|
|
126
|
+
AI_CREDIT_SIZES,
|
|
126
127
|
AI_CREDIT_VALUES,
|
|
128
|
+
buildAiCreditOptions,
|
|
129
|
+
resolveAiCreditPrice,
|
|
127
130
|
} from "./modules/subscriptions/constants/addons.constants";
|
|
128
131
|
export type {
|
|
129
132
|
AddonKindEnum,
|
|
@@ -487,8 +490,18 @@ export {
|
|
|
487
490
|
formatCurrencyNumber,
|
|
488
491
|
parseCurrencyToNumber,
|
|
489
492
|
getCurrencyForGateway,
|
|
493
|
+
getLocaleForCurrency,
|
|
490
494
|
} from "./utils/format/currency";
|
|
491
495
|
export type { CurrencyCode } from "./utils/format/currency";
|
|
496
|
+
export {
|
|
497
|
+
USD_GATEWAY,
|
|
498
|
+
isUsdGateway,
|
|
499
|
+
isUsdAccount,
|
|
500
|
+
allowedPaymentMethods,
|
|
501
|
+
isPaymentMethodAllowed,
|
|
502
|
+
canBuyStandaloneAiCredits,
|
|
503
|
+
} from "./utils/format/gateway";
|
|
504
|
+
export type { AccountGatewayLike, PaymentMethodKind } from "./utils/format/gateway";
|
|
492
505
|
export { isValidCPF, isValidCNPJ, isValidTaxId } from "./utils/validators/common";
|
|
493
506
|
export { BR_STATE_OPTIONS } from "./utils/constants/br-states";
|
|
494
507
|
export type { TimezoneOption } from "./modules/accounts/services/timezone.service";
|
|
@@ -528,8 +541,7 @@ export { useAccountToken } from "./modules/accounts/hooks/use-account-token.hook
|
|
|
528
541
|
export { useRequiredBillingData } from "./modules/accounts/hooks/use-required-billing-data.hook";
|
|
529
542
|
export {
|
|
530
543
|
hasCompleteBillingData,
|
|
531
|
-
|
|
532
|
-
INTERNATIONAL_GATEWAY,
|
|
544
|
+
isBrazilianBillingAccount,
|
|
533
545
|
} from "./modules/accounts/utils/billing-data";
|
|
534
546
|
export type { BillingDataSnapshot } from "./modules/accounts/utils/billing-data";
|
|
535
547
|
|