@greatapps/common 1.1.782 → 1.1.785
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/layouts/AppMobileNavBar.mjs +5 -64
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/AppNavBar.mjs +0 -2
- package/dist/components/layouts/AppNavBar.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +52 -109
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/modals/cards/AddCardModal.mjs +3 -2
- package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
- package/dist/i18n/messages/en-us.mjs +1 -3
- package/dist/i18n/messages/en-us.mjs.map +1 -1
- package/dist/i18n/messages/es-es.mjs +1 -3
- package/dist/i18n/messages/es-es.mjs.map +1 -1
- package/dist/i18n/messages/pt-br.mjs +1 -3
- package/dist/i18n/messages/pt-br.mjs.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/update-subscription-payment.action.mjs.map +1 -1
- package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs +10 -2
- package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs.map +1 -1
- package/dist/modules/subscriptions/services/subscriptions.service.mjs +12 -1
- package/dist/modules/subscriptions/services/subscriptions.service.mjs.map +1 -1
- package/dist/modules/subscriptions/types/subscription.type.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/layouts/AppMobileNavBar.tsx +6 -90
- package/src/components/layouts/AppNavBar.tsx +1 -5
- package/src/components/layouts/NavBar.tsx +66 -158
- package/src/components/modals/cards/AddCardModal.tsx +15 -2
- package/src/i18n/messages/en-us.ts +0 -2
- package/src/i18n/messages/es-es.ts +0 -2
- package/src/i18n/messages/pt-br.ts +0 -2
- package/src/index.ts +1 -0
- package/src/modules/plans/hooks/use-plan-by-id.hook.ts +1 -1
- package/src/modules/subscriptions/actions/update-subscription-payment.action.ts +6 -1
- package/src/modules/subscriptions/hooks/update-subscription-payment.hook.ts +21 -3
- package/src/modules/subscriptions/services/subscriptions.service.ts +46 -4
- package/src/modules/subscriptions/types/subscription.type.ts +27 -0
- package/dist/components/layouts/GreatDomainIcon.mjs +0 -40
- package/dist/components/layouts/GreatDomainIcon.mjs.map +0 -1
- package/src/components/layouts/GreatDomainIcon.tsx +0 -43
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
Subscription,
|
|
16
16
|
SubscriptionSchema,
|
|
17
17
|
FindSubscriptionsParams,
|
|
18
|
+
type ChargeNowResult,
|
|
18
19
|
} from "../types/subscription.type";
|
|
19
20
|
import {
|
|
20
21
|
type CalculateSubscriptionRequest,
|
|
@@ -161,12 +162,31 @@ class SubscriptionsService {
|
|
|
161
162
|
|
|
162
163
|
async updateSubscriptionPayment(
|
|
163
164
|
subscriptionId: number | string,
|
|
164
|
-
data: {
|
|
165
|
-
|
|
165
|
+
data: {
|
|
166
|
+
id_card?: string;
|
|
167
|
+
payment_method_id?: string;
|
|
168
|
+
payment_method: number;
|
|
169
|
+
charge_now?: boolean;
|
|
170
|
+
},
|
|
171
|
+
): Promise<
|
|
172
|
+
SuccessResult<void> & {
|
|
173
|
+
applied: boolean;
|
|
174
|
+
client_secret?: string;
|
|
175
|
+
charge_now?: ChargeNowResult;
|
|
176
|
+
}
|
|
177
|
+
> {
|
|
166
178
|
await assertManagementPermission("manage_subscriptions");
|
|
167
179
|
const { id_account } = await getUserContext();
|
|
168
180
|
|
|
169
|
-
|
|
181
|
+
/* O `status: 2` do guard de 3DS pendente não cabe em `ApiActionResult`, que só conhece 0 e 1.
|
|
182
|
+
* Declarar o terceiro estado aqui é o que permite tratá-lo — sem isso o TypeScript apaga o
|
|
183
|
+
* ramo como inalcançável e o caso volta a atravessar como sucesso. */
|
|
184
|
+
const response = await api.apps.put<
|
|
185
|
+
(ApiActionResult<void> | { status: 2; message?: string }) & {
|
|
186
|
+
charge_now?: ChargeNowResult;
|
|
187
|
+
client_secret?: string;
|
|
188
|
+
}
|
|
189
|
+
>(
|
|
170
190
|
`/accounts/${id_account}/subscriptions/${subscriptionId}/action/payment`,
|
|
171
191
|
data,
|
|
172
192
|
{ timeout: SUBSCRIPTION_WRITE_TIMEOUT_MS },
|
|
@@ -180,7 +200,29 @@ class SubscriptionsService {
|
|
|
180
200
|
);
|
|
181
201
|
}
|
|
182
202
|
|
|
183
|
-
|
|
203
|
+
/* `status: 2` NÃO é sucesso: o guard de 3DS pendente do paymentEdit devolve esse status sem
|
|
204
|
+
* aplicar a troca, e como só o `status === 0` era tratado como erro, a chamada caía no
|
|
205
|
+
* `success: true` e a tela dizia "sua assinatura passou a ser cobrada neste cartão" para uma
|
|
206
|
+
* troca que não aconteceu — descartando junto o `client_secret` que resolveria a pendência.
|
|
207
|
+
*
|
|
208
|
+
* Por isso o retorno carrega `applied`: quem chama precisa poder distinguir "trocou" de
|
|
209
|
+
* "não trocou, conclua o pagamento pendente primeiro". */
|
|
210
|
+
if (response.status === 2) {
|
|
211
|
+
return {
|
|
212
|
+
success: true,
|
|
213
|
+
applied: false,
|
|
214
|
+
...(response.client_secret ? { client_secret: response.client_secret } : {}),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* O desfecho da cobrança imediata precisa atravessar: descartá-lo (como este método fazia com
|
|
219
|
+
* o corpo inteiro) apagaria tanto a recusa quanto o `client_secret` do 3DS, e a tela
|
|
220
|
+
* anunciaria "tudo certo" para uma fatura que continua em aberto. */
|
|
221
|
+
return {
|
|
222
|
+
success: true,
|
|
223
|
+
applied: true,
|
|
224
|
+
...(response.charge_now ? { charge_now: response.charge_now } : {}),
|
|
225
|
+
};
|
|
184
226
|
}
|
|
185
227
|
|
|
186
228
|
async getFreezeNotice(): Promise<FreezeNotice> {
|
|
@@ -107,6 +107,33 @@ export const SubscriptionSchema = z.object({
|
|
|
107
107
|
|
|
108
108
|
export type Subscription = z.infer<typeof SubscriptionSchema>;
|
|
109
109
|
|
|
110
|
+
/* Desfecho da cobrança imediata pedida com `charge_now` na troca de forma de pagamento
|
|
111
|
+
* (gapps-r3-api, PUT subscriptions/:id/action/payment).
|
|
112
|
+
*
|
|
113
|
+
* Vem separado do `status` da resposta de propósito: quando isto chega, a troca JÁ está firmada
|
|
114
|
+
* no banco e na Stripe. Uma cobrança recusada aqui não desfaz a troca — o dunning da Stripe segue
|
|
115
|
+
* armado no cartão novo —, então a tela precisa contar as duas coisas em separado.
|
|
116
|
+
*
|
|
117
|
+
* `outcome` é a ÚNICA fonte da verdade sobre o que aconteceu, e a tela deve falar só a partir dele.
|
|
118
|
+
* Substituiu um par de booleanos (`attempted`/`paid`) que não distinguia recusa de 3DS pendente: a
|
|
119
|
+
* tela lia `paid: false` depois de um desafio bem-sucedido e anunciava falha para um pagamento que
|
|
120
|
+
* tinha acabado de completar.
|
|
121
|
+
*
|
|
122
|
+
* `amount` vem em centavos, na `currency` da fatura, e é o valor REALMENTE cobrado — não uma
|
|
123
|
+
* previsão feita antes da chamada. */
|
|
124
|
+
export interface ChargeNowResult {
|
|
125
|
+
outcome: 'charged' | 'requires_action' | 'declined' | 'none';
|
|
126
|
+
invoice_id?: string;
|
|
127
|
+
amount?: number | null;
|
|
128
|
+
currency?: string | null;
|
|
129
|
+
client_secret?: string;
|
|
130
|
+
/* Presente em `declined`: a razão que o emissor deu. */
|
|
131
|
+
message?: string;
|
|
132
|
+
/* Presente em `none`: por que não houve o que cobrar (`sem_fatura_de_ciclo_aberta`,
|
|
133
|
+
* `deteccao_falhou`, `sem_contexto_de_cobranca`). */
|
|
134
|
+
reason?: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
110
137
|
export interface FindSubscriptionsParams {
|
|
111
138
|
active?: boolean;
|
|
112
139
|
trial?: boolean;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { cn } from "../../infra/utils/clsx";
|
|
4
|
-
function GreatDomainIcon({ active, className }) {
|
|
5
|
-
return /* @__PURE__ */ jsxs(
|
|
6
|
-
"svg",
|
|
7
|
-
{
|
|
8
|
-
width: "23",
|
|
9
|
-
height: "23",
|
|
10
|
-
viewBox: "0 0 23 23",
|
|
11
|
-
fill: "none",
|
|
12
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
13
|
-
className,
|
|
14
|
-
"aria-hidden": "true",
|
|
15
|
-
children: [
|
|
16
|
-
/* @__PURE__ */ jsx(
|
|
17
|
-
"path",
|
|
18
|
-
{
|
|
19
|
-
d: "M11.8444 17.0777C11.8444 20.3487 9.19292 23.0003 5.92218 23.0003C2.65145 23.0003 0 20.3487 0 17.0777C0 13.8068 2.65145 11.1551 5.92218 11.1551C9.19292 11.1551 11.8444 13.8068 11.8444 17.0777Z",
|
|
20
|
-
className: cn(
|
|
21
|
-
"transition-colors duration-300",
|
|
22
|
-
active ? "fill-[#984DFF]" : "fill-[#650CE4]"
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
),
|
|
26
|
-
/* @__PURE__ */ jsx(
|
|
27
|
-
"path",
|
|
28
|
-
{
|
|
29
|
-
d: "M11.8436 3.06666C11.8436 1.37299 13.2166 0 14.9103 0H19.9331C21.6267 0 22.9997 1.37299 22.9997 3.06666V19.9333C22.9997 21.6269 21.6267 22.9999 19.9331 22.9999H14.9103C13.2166 22.9999 11.8436 21.6269 11.8436 19.9333V3.06666Z",
|
|
30
|
-
fill: "#C9B2FF"
|
|
31
|
-
}
|
|
32
|
-
)
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
export {
|
|
38
|
-
GreatDomainIcon
|
|
39
|
-
};
|
|
40
|
-
//# sourceMappingURL=GreatDomainIcon.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/layouts/GreatDomainIcon.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"../../infra/utils/clsx\";\n\ntype GreatDomainIconProps = {\n /** Em repouso o círculo é #650CE4; só no estado ativo vira #984DFF. */\n active?: boolean;\n className?: string;\n};\n\n/**\n * Glifo do GreatDomain — geometria exportada do Figma (node 5929:2700), 23×23.\n * O círculo só troca de cor quando ativo. No hover o container ganha fundo cinza\n * (igual ao GreatPages) e o glifo fica como está.\n */\nfunction GreatDomainIcon({ active, className }: GreatDomainIconProps) {\n return (\n <svg\n width=\"23\"\n height=\"23\"\n viewBox=\"0 0 23 23\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n aria-hidden=\"true\"\n >\n <path\n d=\"M11.8444 17.0777C11.8444 20.3487 9.19292 23.0003 5.92218 23.0003C2.65145 23.0003 0 20.3487 0 17.0777C0 13.8068 2.65145 11.1551 5.92218 11.1551C9.19292 11.1551 11.8444 13.8068 11.8444 17.0777Z\"\n className={cn(\n \"transition-colors duration-300\",\n active ? \"fill-[#984DFF]\" : \"fill-[#650CE4]\",\n )}\n />\n <path\n d=\"M11.8436 3.06666C11.8436 1.37299 13.2166 0 14.9103 0H19.9331C21.6267 0 22.9997 1.37299 22.9997 3.06666V19.9333C22.9997 21.6269 21.6267 22.9999 19.9331 22.9999H14.9103C13.2166 22.9999 11.8436 21.6269 11.8436 19.9333V3.06666Z\"\n fill=\"#C9B2FF\"\n />\n </svg>\n );\n}\n\nexport { GreatDomainIcon };\nexport type { GreatDomainIconProps };\n"],"mappings":";AAiBI,SASE,KATF;AAfJ,SAAS,UAAU;AAanB,SAAS,gBAAgB,EAAE,QAAQ,UAAU,GAAyB;AACpE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAM;AAAA,MACN;AAAA,MACA,eAAY;AAAA,MAEZ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,GAAE;AAAA,YACF,WAAW;AAAA,cACT;AAAA,cACA,SAAS,mBAAmB;AAAA,YAC9B;AAAA;AAAA,QACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,GAAE;AAAA,YACF,MAAK;AAAA;AAAA,QACP;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../infra/utils/clsx";
|
|
4
|
-
|
|
5
|
-
type GreatDomainIconProps = {
|
|
6
|
-
/** Em repouso o círculo é #650CE4; só no estado ativo vira #984DFF. */
|
|
7
|
-
active?: boolean;
|
|
8
|
-
className?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Glifo do GreatDomain — geometria exportada do Figma (node 5929:2700), 23×23.
|
|
13
|
-
* O círculo só troca de cor quando ativo. No hover o container ganha fundo cinza
|
|
14
|
-
* (igual ao GreatPages) e o glifo fica como está.
|
|
15
|
-
*/
|
|
16
|
-
function GreatDomainIcon({ active, className }: GreatDomainIconProps) {
|
|
17
|
-
return (
|
|
18
|
-
<svg
|
|
19
|
-
width="23"
|
|
20
|
-
height="23"
|
|
21
|
-
viewBox="0 0 23 23"
|
|
22
|
-
fill="none"
|
|
23
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
-
className={className}
|
|
25
|
-
aria-hidden="true"
|
|
26
|
-
>
|
|
27
|
-
<path
|
|
28
|
-
d="M11.8444 17.0777C11.8444 20.3487 9.19292 23.0003 5.92218 23.0003C2.65145 23.0003 0 20.3487 0 17.0777C0 13.8068 2.65145 11.1551 5.92218 11.1551C9.19292 11.1551 11.8444 13.8068 11.8444 17.0777Z"
|
|
29
|
-
className={cn(
|
|
30
|
-
"transition-colors duration-300",
|
|
31
|
-
active ? "fill-[#984DFF]" : "fill-[#650CE4]",
|
|
32
|
-
)}
|
|
33
|
-
/>
|
|
34
|
-
<path
|
|
35
|
-
d="M11.8436 3.06666C11.8436 1.37299 13.2166 0 14.9103 0H19.9331C21.6267 0 22.9997 1.37299 22.9997 3.06666V19.9333C22.9997 21.6269 21.6267 22.9999 19.9331 22.9999H14.9103C13.2166 22.9999 11.8436 21.6269 11.8436 19.9333V3.06666Z"
|
|
36
|
-
fill="#C9B2FF"
|
|
37
|
-
/>
|
|
38
|
-
</svg>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { GreatDomainIcon };
|
|
43
|
-
export type { GreatDomainIconProps };
|