@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.
Files changed (38) hide show
  1. package/dist/components/layouts/AppMobileNavBar.mjs +5 -64
  2. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  3. package/dist/components/layouts/AppNavBar.mjs +0 -2
  4. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  5. package/dist/components/layouts/NavBar.mjs +52 -109
  6. package/dist/components/layouts/NavBar.mjs.map +1 -1
  7. package/dist/components/modals/cards/AddCardModal.mjs +3 -2
  8. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  9. package/dist/i18n/messages/en-us.mjs +1 -3
  10. package/dist/i18n/messages/en-us.mjs.map +1 -1
  11. package/dist/i18n/messages/es-es.mjs +1 -3
  12. package/dist/i18n/messages/es-es.mjs.map +1 -1
  13. package/dist/i18n/messages/pt-br.mjs +1 -3
  14. package/dist/i18n/messages/pt-br.mjs.map +1 -1
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/modules/subscriptions/actions/update-subscription-payment.action.mjs.map +1 -1
  17. package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs +10 -2
  18. package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs.map +1 -1
  19. package/dist/modules/subscriptions/services/subscriptions.service.mjs +12 -1
  20. package/dist/modules/subscriptions/services/subscriptions.service.mjs.map +1 -1
  21. package/dist/modules/subscriptions/types/subscription.type.mjs.map +1 -1
  22. package/package.json +1 -1
  23. package/src/components/layouts/AppMobileNavBar.tsx +6 -90
  24. package/src/components/layouts/AppNavBar.tsx +1 -5
  25. package/src/components/layouts/NavBar.tsx +66 -158
  26. package/src/components/modals/cards/AddCardModal.tsx +15 -2
  27. package/src/i18n/messages/en-us.ts +0 -2
  28. package/src/i18n/messages/es-es.ts +0 -2
  29. package/src/i18n/messages/pt-br.ts +0 -2
  30. package/src/index.ts +1 -0
  31. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +1 -1
  32. package/src/modules/subscriptions/actions/update-subscription-payment.action.ts +6 -1
  33. package/src/modules/subscriptions/hooks/update-subscription-payment.hook.ts +21 -3
  34. package/src/modules/subscriptions/services/subscriptions.service.ts +46 -4
  35. package/src/modules/subscriptions/types/subscription.type.ts +27 -0
  36. package/dist/components/layouts/GreatDomainIcon.mjs +0 -40
  37. package/dist/components/layouts/GreatDomainIcon.mjs.map +0 -1
  38. package/src/components/layouts/GreatDomainIcon.tsx +0 -43
@@ -2,10 +2,8 @@
2
2
 
3
3
  import { ReactNode } from "react";
4
4
  import Image from "next/image";
5
- import { useTranslations } from "next-intl";
6
5
  import { IconMenu2, IconX } from "@tabler/icons-react";
7
6
  import { ProfilePopover } from "./ProfilePopover";
8
- import { GreatDomainIcon } from "./GreatDomainIcon";
9
7
  import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
10
8
  import { useMobileNavbarSheet } from "../../store/useMobileNavbarSheet";
11
9
  import {
@@ -17,13 +15,11 @@ import type { ProfileMenuItem } from "./ProfilePopover";
17
15
 
18
16
  export interface AppMobileNavBarProps {
19
17
  /** Which app is currently active — controls which icon gets the indicator */
20
- activeApp?: "gapps" | "gpages" | "gdomain";
18
+ activeApp?: "gapps" | "gpages";
21
19
  /** Called when the GreatApps logo is clicked */
22
20
  onLogoClick?: () => void;
23
21
  /** Called when the app icon (e.g. GreatPages) is clicked */
24
22
  onAppIconClick?: () => void;
25
- /** Called when the GreatDomain icon is clicked; without it the icon is not rendered (app flag) */
26
- onDomainIconClick?: () => void;
27
23
  /** Extra slot rendered after the app icon (e.g. project selector) */
28
24
  extraLeftSlot?: ReactNode;
29
25
  menuItems?: ProfileMenuItem[];
@@ -34,12 +30,10 @@ export function AppMobileNavBar({
34
30
  activeApp,
35
31
  onLogoClick,
36
32
  onAppIconClick,
37
- onDomainIconClick,
38
33
  extraLeftSlot,
39
34
  menuItems = [],
40
35
  showMenuToggle = true,
41
36
  }: AppMobileNavBarProps) {
42
- const translate = useTranslations();
43
37
  const { isOpen, toggle } = useMobileNavbarSheet();
44
38
  const { whitelabel } = useWhitelabel();
45
39
  const isDefaultWl = useIsDefaultWhitelabel();
@@ -48,7 +42,6 @@ export function AppMobileNavBar({
48
42
 
49
43
  const isGappsActive = activeApp === "gapps";
50
44
  const isGpagesActive = activeApp === "gpages";
51
- const isGdomainActive = activeApp === "gdomain";
52
45
 
53
46
  const wlIcon = whitelabel?.secondary_logo ? (
54
47
  <Image
@@ -87,9 +80,9 @@ export function AppMobileNavBar({
87
80
 
88
81
  return (
89
82
  <div className="fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200">
90
- <div className="flex items-center gap-1.5 min-w-0">
83
+ <div className="flex items-center gap-1.5">
91
84
  {/* GreatApps logo */}
92
- <div className="relative shrink-0">
85
+ <div className="relative">
93
86
  <Tooltip>
94
87
  <TooltipTrigger asChild>
95
88
  <div
@@ -126,7 +119,7 @@ export function AppMobileNavBar({
126
119
  </div>
127
120
 
128
121
  {/* GreatPages icon */}
129
- <div className="relative shrink-0">
122
+ <div className="relative">
130
123
  <Tooltip>
131
124
  <TooltipTrigger asChild>
132
125
  <div
@@ -194,86 +187,9 @@ export function AppMobileNavBar({
194
187
  />
195
188
  </div>
196
189
 
197
- {/* GreatDomain icon */}
198
- {onDomainIconClick ? (
199
- <div className="relative shrink-0">
200
- <Tooltip>
201
- <TooltipTrigger asChild>
202
- <div
203
- aria-label={
204
- isDefaultWl
205
- ? translate("common.layout.navbar.greatDomain")
206
- : translate("common.layout.navbar.domains")
207
- }
208
- className={cn(
209
- "size-10 rounded-[10px] flex items-center justify-center border-2 ring-2 transition-colors duration-300",
210
- isGdomainActive
211
- ? isDefaultWl
212
- ? "bg-[#EDE9FE] border-white ring-[#C092FF]"
213
- : "border-white ring-transparent"
214
- : isDefaultWl
215
- ? "hover:bg-gray-100 border-transparent ring-transparent"
216
- : "border-transparent ring-transparent",
217
- "cursor-pointer",
218
- )}
219
- style={
220
- !isDefaultWl
221
- ? {
222
- backgroundColor: primaryColor,
223
- boxShadow: isGdomainActive
224
- ? `0 0 0 2px ${primaryColor}40`
225
- : undefined,
226
- opacity: !isGdomainActive ? 0.2 : undefined,
227
- }
228
- : undefined
229
- }
230
- onClick={onDomainIconClick}
231
- >
232
- {isDefaultWl ? (
233
- <GreatDomainIcon active={isGdomainActive} />
234
- ) : (
235
- <svg
236
- xmlns="http://www.w3.org/2000/svg"
237
- width="24"
238
- height="24"
239
- viewBox="0 0 24 24"
240
- fill="none"
241
- stroke="white"
242
- strokeWidth="2"
243
- strokeLinecap="round"
244
- strokeLinejoin="round"
245
- >
246
- <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
247
- <path d="M3.6 9h16.8" />
248
- <path d="M3.6 15h16.8" />
249
- <path d="M11.5 3a17 17 0 0 0 0 18" />
250
- <path d="M12.5 3a17 17 0 0 1 0 18" />
251
- </svg>
252
- )}
253
- </div>
254
- </TooltipTrigger>
255
- <TooltipContent side="bottom">
256
- {isDefaultWl
257
- ? translate("common.layout.navbar.greatDomain")
258
- : translate("common.layout.navbar.domains")}
259
- </TooltipContent>
260
- </Tooltip>
261
- <div
262
- className={cn(
263
- "absolute -bottom-[17px] left-1/2 -translate-x-1/2 w-5 h-[3px] rounded-t-xl transition-opacity duration-300",
264
- isDefaultWl ? "bg-[#984DFF]" : "",
265
- isGdomainActive ? "opacity-100" : "opacity-0",
266
- )}
267
- style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}
268
- />
269
- </div>
270
- ) : null}
271
-
272
- {extraLeftSlot ? (
273
- <div className="min-w-0 shrink [&>*]:max-w-full">{extraLeftSlot}</div>
274
- ) : null}
190
+ {extraLeftSlot}
275
191
  </div>
276
- <div className="flex items-center gap-1.5 shrink-0">
192
+ <div className="flex items-center gap-1.5">
277
193
  <ProfilePopover
278
194
  side="bottom"
279
195
  align="end"
@@ -8,10 +8,8 @@ import type { ProfileMenuItem } from "./ProfilePopover";
8
8
  export interface AppNavBarProps {
9
9
  logoHref: string;
10
10
  appIconHref: string;
11
- /** Sem href o ícone do GreatDomain não é renderizado: é a flag do app. */
12
- domainIconHref?: string;
13
11
  /** Which app is currently active — controls which icon gets the indicator */
14
- activeApp?: "gapps" | "gpages" | "gdomain";
12
+ activeApp?: "gapps" | "gpages";
15
13
  showExpandButton?: boolean;
16
14
  onExpandClick?: () => void;
17
15
  menuItems?: ProfileMenuItem[];
@@ -21,7 +19,6 @@ export interface AppNavBarProps {
21
19
  export function AppNavBar({
22
20
  logoHref,
23
21
  appIconHref,
24
- domainIconHref,
25
22
  activeApp,
26
23
  showExpandButton = false,
27
24
  onExpandClick,
@@ -32,7 +29,6 @@ export function AppNavBar({
32
29
  <NavBar
33
30
  logoHref={logoHref}
34
31
  appIconHref={appIconHref}
35
- domainIconHref={domainIconHref}
36
32
  activeApp={activeApp}
37
33
  showExpandButton={showExpandButton}
38
34
  onExpandClick={onExpandClick}
@@ -6,7 +6,6 @@ import Link from "next/link";
6
6
  import { useTranslations } from "next-intl";
7
7
  import { IconChevronRight } from "@tabler/icons-react";
8
8
  import { Separator } from "../ui/data-display/Separator";
9
- import { GreatDomainIcon } from "./GreatDomainIcon";
10
9
  import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
11
10
  import {
12
11
  useDesktopSidebarStore,
@@ -21,9 +20,7 @@ import { cn } from "../../infra/utils/clsx";
21
20
  type NavBarProps = {
22
21
  logoHref: string;
23
22
  appIconHref: string;
24
- /** Sem href o ícone do GreatDomain não é renderizado: é a flag do app. */
25
- domainIconHref?: string;
26
- activeApp?: "gapps" | "gpages" | "gdomain";
23
+ activeApp?: "gapps" | "gpages";
27
24
  showExpandButton?: boolean;
28
25
  onExpandClick?: () => void;
29
26
  children?: React.ReactNode;
@@ -33,7 +30,6 @@ type NavBarProps = {
33
30
  function NavBar({
34
31
  logoHref,
35
32
  appIconHref,
36
- domainIconHref,
37
33
  activeApp,
38
34
  showExpandButton = false,
39
35
  onExpandClick,
@@ -134,9 +130,7 @@ function NavBar({
134
130
  <IconChevronRight size={16} className="text-gray-500" />
135
131
  </button>
136
132
  </TooltipTrigger>
137
- <TooltipContent side="right">
138
- {translate("common.layout.navbar.expandMenu")}
139
- </TooltipContent>
133
+ <TooltipContent side="right">{translate('common.layout.navbar.expandMenu')}</TooltipContent>
140
134
  </Tooltip>
141
135
  )}
142
136
  {/* Desktop expand button */}
@@ -150,164 +144,78 @@ function NavBar({
150
144
  <IconChevronRight size={16} className="text-gray-500" />
151
145
  </button>
152
146
  </TooltipTrigger>
153
- <TooltipContent side="right">
154
- {translate("common.layout.navbar.expandMenu")}
155
- </TooltipContent>
147
+ <TooltipContent side="right">{translate('common.layout.navbar.expandMenu')}</TooltipContent>
156
148
  </Tooltip>
157
149
  )}
158
150
  </div>
159
151
 
160
- {/* Ícones de app — 8px entre eles (Figma 5929:2676) */}
161
- <div className="flex flex-col gap-2 items-center">
162
- {/* GreatPages icon */}
163
- <div className="relative">
164
- <Tooltip>
165
- <TooltipTrigger asChild>
166
- <Link
167
- href={appIconHref}
168
- className={cn(
169
- "size-10 rounded-lg cursor-pointer flex items-center justify-center border-2 ring-2 transition-colors duration-300",
170
- activeApp === "gpages"
171
- ? isDefaultWl
172
- ? "bg-cyan-100 border-white ring-cyan-300"
173
- : "border-white ring-transparent"
174
- : isDefaultWl
175
- ? "hover:bg-gray-100 border-transparent ring-transparent"
176
- : "border-transparent ring-transparent",
177
- )}
178
- style={
179
- !isDefaultWl
180
- ? {
181
- backgroundColor: primaryColor,
182
- boxShadow:
183
- activeApp === "gpages"
184
- ? `0 0 0 2px ${primaryColor}40`
185
- : undefined,
186
- opacity: activeApp !== "gpages" ? 0.2 : undefined,
187
- }
188
- : undefined
189
- }
190
- >
191
- {isDefaultWl ? (
192
- <Image
193
- src="/icons/icon-navbar.svg"
194
- alt="GreatPages"
195
- width={24}
196
- height={24}
197
- />
198
- ) : (
199
- <svg
200
- xmlns="http://www.w3.org/2000/svg"
201
- width="24"
202
- height="24"
203
- viewBox="0 0 24 24"
204
- fill="none"
205
- stroke="white"
206
- strokeWidth="2"
207
- strokeLinecap="round"
208
- strokeLinejoin="round"
209
- >
210
- <path d="M4 8h16" />
211
- <path d="M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" />
212
- <path d="M8 4v4" />
213
- </svg>
214
- )}
215
- </Link>
216
- </TooltipTrigger>
217
- <TooltipContent side="right">
218
- {isDefaultWl
219
- ? translate("common.layout.navbar.greatPages")
220
- : translate("common.layout.navbar.pages")}
221
- </TooltipContent>
222
- </Tooltip>
223
- <div
224
- className={cn(
225
- "absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 rounded-r-xl transition-opacity duration-300",
226
- isDefaultWl ? "bg-cyan-300" : "",
227
- activeApp === "gpages" ? "opacity-100" : "opacity-0",
228
- )}
229
- style={
230
- !isDefaultWl ? { backgroundColor: primaryColor } : undefined
231
- }
232
- />
233
- </div>
234
-
235
- {/* GreatDomain icon */}
236
- {domainIconHref ? (
237
- <div className="relative">
238
- <Tooltip>
239
- <TooltipTrigger asChild>
240
- <Link
241
- href={domainIconHref}
242
- aria-label={
243
- isDefaultWl
244
- ? translate("common.layout.navbar.greatDomain")
245
- : translate("common.layout.navbar.domains")
246
- }
247
- className={cn(
248
- "size-10 rounded-[10px] cursor-pointer flex items-center justify-center border-2 ring-2 transition-colors duration-300",
249
- activeApp === "gdomain"
250
- ? isDefaultWl
251
- ? "bg-[#EDE9FE] border-white ring-[#C092FF]"
252
- : "border-white ring-transparent"
253
- : isDefaultWl
254
- ? "hover:bg-gray-100 border-transparent ring-transparent"
255
- : "border-transparent ring-transparent",
256
- )}
257
- style={
258
- !isDefaultWl
259
- ? {
260
- backgroundColor: primaryColor,
261
- boxShadow:
262
- activeApp === "gdomain"
263
- ? `0 0 0 2px ${primaryColor}40`
264
- : undefined,
265
- opacity: activeApp !== "gdomain" ? 0.2 : undefined,
266
- }
267
- : undefined
268
- }
269
- >
270
- {isDefaultWl ? (
271
- <GreatDomainIcon active={activeApp === "gdomain"} />
272
- ) : (
273
- <svg
274
- xmlns="http://www.w3.org/2000/svg"
275
- width="24"
276
- height="24"
277
- viewBox="0 0 24 24"
278
- fill="none"
279
- stroke="white"
280
- strokeWidth="2"
281
- strokeLinecap="round"
282
- strokeLinejoin="round"
283
- >
284
- <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
285
- <path d="M3.6 9h16.8" />
286
- <path d="M3.6 15h16.8" />
287
- <path d="M11.5 3a17 17 0 0 0 0 18" />
288
- <path d="M12.5 3a17 17 0 0 1 0 18" />
289
- </svg>
290
- )}
291
- </Link>
292
- </TooltipTrigger>
293
- <TooltipContent side="right">
294
- {isDefaultWl
295
- ? translate("common.layout.navbar.greatDomain")
296
- : translate("common.layout.navbar.domains")}
297
- </TooltipContent>
298
- </Tooltip>
299
- <div
152
+ {/* GreatPages icon */}
153
+ <div className="relative">
154
+ <Tooltip>
155
+ <TooltipTrigger asChild>
156
+ <Link
157
+ href={appIconHref}
300
158
  className={cn(
301
- "absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 rounded-r-xl transition-opacity duration-300",
302
- isDefaultWl ? "bg-[#984DFF]" : "",
303
- activeApp === "gdomain" ? "opacity-100" : "opacity-0",
159
+ "size-10 rounded-lg cursor-pointer flex items-center justify-center border-2 ring-2 transition-colors duration-300",
160
+ activeApp === "gpages"
161
+ ? isDefaultWl
162
+ ? "bg-cyan-100 border-white ring-cyan-300"
163
+ : "border-white ring-transparent"
164
+ : isDefaultWl
165
+ ? "hover:bg-gray-100 border-transparent ring-transparent"
166
+ : "border-transparent ring-transparent",
304
167
  )}
305
168
  style={
306
- !isDefaultWl ? { backgroundColor: primaryColor } : undefined
169
+ !isDefaultWl
170
+ ? {
171
+ backgroundColor: primaryColor,
172
+ boxShadow:
173
+ activeApp === "gpages"
174
+ ? `0 0 0 2px ${primaryColor}40`
175
+ : undefined,
176
+ opacity: activeApp !== "gpages" ? 0.2 : undefined,
177
+ }
178
+ : undefined
307
179
  }
308
- />
309
- </div>
310
- ) : null}
180
+ >
181
+ {isDefaultWl ? (
182
+ <Image
183
+ src="/icons/icon-navbar.svg"
184
+ alt="GreatPages"
185
+ width={24}
186
+ height={24}
187
+ />
188
+ ) : (
189
+ <svg
190
+ xmlns="http://www.w3.org/2000/svg"
191
+ width="24"
192
+ height="24"
193
+ viewBox="0 0 24 24"
194
+ fill="none"
195
+ stroke="white"
196
+ strokeWidth="2"
197
+ strokeLinecap="round"
198
+ strokeLinejoin="round"
199
+ >
200
+ <path d="M4 8h16" />
201
+ <path d="M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" />
202
+ <path d="M8 4v4" />
203
+ </svg>
204
+ )}
205
+ </Link>
206
+ </TooltipTrigger>
207
+ <TooltipContent side="right">
208
+ {isDefaultWl ? translate('common.layout.navbar.greatPages') : translate('common.layout.navbar.pages')}
209
+ </TooltipContent>
210
+ </Tooltip>
211
+ <div
212
+ className={cn(
213
+ "absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 rounded-r-xl transition-opacity duration-300",
214
+ isDefaultWl ? "bg-cyan-300" : "",
215
+ activeApp === "gpages" ? "opacity-100" : "opacity-0",
216
+ )}
217
+ style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}
218
+ />
311
219
  </div>
312
220
  </div>
313
221
 
@@ -87,6 +87,15 @@ export default function AddCardModal() {
87
87
  const [isAuthenticating, setIsAuthenticating] = useState(false);
88
88
 
89
89
  const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;
90
+ /* `set_default` continua true por omissão — todo chamador que só quer cadastrar um cartão segue
91
+ * com o comportamento de sempre. Quem passa `false` é quem vai perguntar ao usuário, logo depois
92
+ * do cadastro, se a assinatura deve migrar para este cartão.
93
+ *
94
+ * Sem esse controle a pergunta seria decorativa: o backend, ao receber `set_default: true`, já
95
+ * grava o padrão do customer E reaponta as assinaturas cobráveis (`#propagateDefaultPm` em
96
+ * cards/services.js), então quando o modal abrisse a troca já teria acontecido e "Recusar" não
97
+ * teria nada para recusar. */
98
+ const setAsDefault = modalData.setAsDefault !== false;
90
99
 
91
100
  const createSetupIntentMutation = useCreateSetupIntent();
92
101
  const createCardMutation = useCreateCard();
@@ -232,7 +241,7 @@ export default function AddCardModal() {
232
241
  const cardResult = await createCardMutation.mutateAsync({
233
242
  setup_intent_id: intent.setup_intent_id,
234
243
  name: data.name,
235
- set_default: true,
244
+ set_default: setAsDefault,
236
245
  ...(isInternational
237
246
  ? {}
238
247
  : {
@@ -250,6 +259,11 @@ export default function AddCardModal() {
250
259
  country: data.country,
251
260
  });
252
261
 
262
+ /* Fecha ANTES de avisar quem chamou. `closeModal()` remove o topo da pilha do
263
+ * useModalManager, então um modal aberto de dentro do `onCardAdded` seria justamente o topo
264
+ * e sairia junto — abriria e fecharia no mesmo tick, sem o usuário ver nada. */
265
+ handleClose();
266
+
253
267
  if (cardResult.success && cardResult.data?.id != null) {
254
268
  onCardAdded?.(cardResult.data.id.toString());
255
269
  }
@@ -258,7 +272,6 @@ export default function AddCardModal() {
258
272
  (t) => <Toast variant="success" message={translate('common.cards.add.successToast')} toastId={t} />,
259
273
  { duration: 5000 }
260
274
  );
261
- handleClose();
262
275
  } catch (error) {
263
276
  /* O backend fail-closed devolve a razão exata da recusa (ex.: "CPF do pagador inválido —
264
277
  * confira os dígitos verificadores"), e o withAction relança como Error com essa mensagem.
@@ -540,8 +540,6 @@ const messages = {
540
540
  expandMenu: 'Expand menu',
541
541
  greatPages: 'GreatPages',
542
542
  pages: 'Pages',
543
- greatDomain: 'GreatDomain',
544
- domains: 'Domains',
545
543
  },
546
544
  profile: {
547
545
  usedCredits: 'Credits used',
@@ -541,8 +541,6 @@ const messages = {
541
541
  expandMenu: 'Expandir menú',
542
542
  greatPages: 'GreatPages',
543
543
  pages: 'Páginas',
544
- greatDomain: 'GreatDomain',
545
- domains: 'Dominios',
546
544
  },
547
545
  profile: {
548
546
  usedCredits: 'Créditos utilizados',
@@ -620,8 +620,6 @@ const messages = {
620
620
  expandMenu: 'Expandir menu',
621
621
  greatPages: 'GreatPages',
622
622
  pages: 'Páginas',
623
- greatDomain: 'GreatDomain',
624
- domains: 'Domínios',
625
623
  },
626
624
  profile: {
627
625
  usedCredits: 'Créditos usados',
package/src/index.ts CHANGED
@@ -140,6 +140,7 @@ export type {
140
140
  Subscription,
141
141
  SubscriptionItem,
142
142
  FindSubscriptionsParams,
143
+ ChargeNowResult,
143
144
  } from "./modules/subscriptions/types/subscription.type";
144
145
  export {
145
146
  SubscriptionSchema,
@@ -11,7 +11,7 @@ export function usePlanById(idPlan?: number | string | null) {
11
11
  const queryClient = useQueryClient();
12
12
  const plansKey = useAuthQueryKey([...PLANS_QUERY_KEY]);
13
13
 
14
- return useQuery<SuccessResult<Plan>>({
14
+ return useQuery({
15
15
  queryKey: [...plansKey, idPlan],
16
16
  queryFn: ({ signal }) =>
17
17
  apiFetch<SuccessResult<Plan>>(`/api/plans/${idPlan}`, { signal }),
@@ -5,7 +5,12 @@ import { subscriptionsService } from "../services/subscriptions.service";
5
5
 
6
6
  export async function updateSubscriptionPaymentAction(
7
7
  subscriptionId: number | string,
8
- data: { id_card?: string; payment_method_id?: string; payment_method: number },
8
+ data: {
9
+ id_card?: string;
10
+ payment_method_id?: string;
11
+ payment_method: number;
12
+ charge_now?: boolean;
13
+ },
9
14
  ) {
10
15
  return safeMutationAction(async () => {
11
16
  return subscriptionsService.updateSubscriptionPayment(subscriptionId, data);
@@ -3,12 +3,15 @@
3
3
  import { useMutation, useQueryClient } from '@tanstack/react-query';
4
4
  import { withAction } from '../../../utils/withAction';
5
5
  import { updateSubscriptionPaymentAction } from '../actions/update-subscription-payment.action';
6
- import { SUBSCRIPTIONS_QUERY_KEY } from '../constants/query-keys.constants';
6
+ import { SUBSCRIPTIONS_QUERY_KEY, CHARGES_QUERY_KEY } from '../constants/query-keys.constants';
7
7
  import { useAuthQueryKey } from '../../../hooks/useAuthQueryKey';
8
+ import { CARDS_QUERY_KEY } from '../../cards/hooks/cards.hook';
8
9
 
9
10
  export function useUpdateSubscriptionPayment() {
10
11
  const queryClient = useQueryClient();
11
12
  const subscriptionsKey = useAuthQueryKey([...SUBSCRIPTIONS_QUERY_KEY]);
13
+ const cardsKey = useAuthQueryKey([...CARDS_QUERY_KEY]);
14
+ const chargesKey = useAuthQueryKey([...CHARGES_QUERY_KEY]);
12
15
 
13
16
  return useMutation({
14
17
  mutationFn: ({
@@ -16,10 +19,25 @@ export function useUpdateSubscriptionPayment() {
16
19
  data,
17
20
  }: {
18
21
  subscriptionId: number | string;
19
- data: { id_card?: string; payment_method_id?: string; payment_method: number };
22
+ data: {
23
+ id_card?: string;
24
+ payment_method_id?: string;
25
+ payment_method: number;
26
+ charge_now?: boolean;
27
+ };
20
28
  }) => withAction(updateSubscriptionPaymentAction)(subscriptionId, data),
21
- onSuccess: () => {
29
+ /* `onSettled`, e não `onSuccess`, pelo mesmo motivo do irmão `updateSubscriptionPlan`: a troca
30
+ * é aplicada no backend ANTES do 3DS, então a falha de autenticação também precisa refletir na
31
+ * tela. */
32
+ onSettled: () => {
22
33
  queryClient.invalidateQueries({ queryKey: subscriptionsKey });
34
+ /* A troca reaponta o cartão padrão da conta na mesma operação, então sem esta invalidação o
35
+ * selo "padrão" continuaria no cartão antigo depois de uma troca que já aconteceu. */
36
+ queryClient.invalidateQueries({ queryKey: cardsKey });
37
+ /* A operação passou a mutar um TERCEIRO estado: com `charge_now`, ela paga a fatura. A mesma
38
+ * tela lê isso por `useCharges`, e com `refetchOnWindowFocus: false` nada refaz a busca —
39
+ * a fatura recém-paga seguiria com selo "pendente" e botão "Pagar". */
40
+ queryClient.invalidateQueries({ queryKey: chargesKey });
23
41
  },
24
42
  });
25
43
  }