@greatapps/common 1.1.685 → 1.1.687

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.
@@ -35,7 +35,7 @@ function SubscriptionBanner({
35
35
  const expiryDate = getSubscriptionExpiryDate(subscription);
36
36
  const cancellationState = getSubscriptionCancellationState(subscription);
37
37
  if (subscription.type === "trial") {
38
- if (cancellationState !== "none" || daysToDue < 0) return null;
38
+ if (!subscription.active || daysToDue < 0) return null;
39
39
  return /* @__PURE__ */ jsx(TrialBanner, { daysRemaining: daysToDue, onReactivate });
40
40
  }
41
41
  if (cancellationState === "cancelled") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/navigation/SubscriptionBanner.tsx"],"sourcesContent":["\"use client\";\n\nimport { useActiveSubscription } from \"../../modules/subscriptions/hooks/find-active-subscription.hook\";\nimport { useCharges } from \"../../modules/charges/hooks/charges.hook\";\nimport { SUBSCRIPTION_GRACE_PERIOD_DAYS } from \"../../modules/subscriptions/constants/subscription.constants\";\nimport { getSubscriptionExpiryDate } from \"../../modules/subscriptions/utils/get-subscription-expiry-date\";\nimport { getSubscriptionCancellationState } from \"../../modules/subscriptions/utils/get-subscription-cancellation-state\";\nimport { toCalendarDate, daysBetween } from \"../../infra/utils/date\";\nimport { OverdueInvoiceBanner } from \"./OverdueInvoiceBanner\";\nimport { UpcomingInvoiceBanner } from \"./UpcomingInvoiceBanner\";\nimport { CancelledSubscriptionBanner } from \"./CancelledSubscriptionBanner\";\nimport { PendingCancellationBanner } from \"./PendingCancellationBanner\";\nimport { TrialBanner } from \"./TrialBanner\";\n\nconst UPCOMING_WINDOW_DAYS = 7;\nconst PAYMENT_METHOD_BOLETO = 2;\n\ninterface SubscriptionBannerProps {\n onReactivate?: () => void;\n onDetails?: () => void;\n}\n\nexport function SubscriptionBanner({\n onReactivate,\n onDetails,\n}: SubscriptionBannerProps) {\n const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();\n const { data: pendingChargesData, isLoading: isLoadingCharges } = useCharges({\n page: 1,\n limit: 1,\n status: [0],\n });\n\n if (!subscription?.date_due) return null;\n if (subscription.type === \"free\") return null;\n\n const dueDate = toCalendarDate(subscription.date_due);\n const today = toCalendarDate(new Date());\n if (!dueDate || !today) return null;\n\n const daysSinceDue = daysBetween(dueDate, today);\n const daysToDue = daysBetween(today, dueDate);\n const hasPendingCharge = !!pendingChargesData?.data?.[0];\n const isBoleto = subscription.payment_method === PAYMENT_METHOD_BOLETO;\n\n // Estado de cancelamento (fonte da verdade única, compartilhada com o\n // CancelledSubscriptionBanner). `active === false` tem prioridade e cai em\n // \"cancelled\" mesmo com date_due no futuro — é o caso da baixa por falha de\n // pagamento, onde date_due aponta pra uma fatura não paga.\n const expiryDate = getSubscriptionExpiryDate(subscription);\n const cancellationState = getSubscriptionCancellationState(subscription);\n\n // Trial: `date_due` guarda o fim do período de teste (ver auth.service).\n // mostra a contagem regressiva enquanto o teste está vigente não vencido\n // (`daysToDue >= 0`) e não cancelado/baixado (`cancellationState === \"none\"`).\n if (subscription.type === \"trial\") {\n if (cancellationState !== \"none\" || daysToDue < 0) return null;\n return <TrialBanner daysRemaining={daysToDue} onReactivate={onReactivate} />;\n }\n\n if (cancellationState === \"cancelled\") {\n return <CancelledSubscriptionBanner onReactivate={onReactivate} />;\n }\n\n if (cancellationState === \"pending\") {\n return (\n <PendingCancellationBanner\n limitDate={expiryDate}\n onReactivate={onReactivate}\n />\n );\n }\n\n if (subscription.type === \"whitelabel\") return null;\n\n if (daysSinceDue > 0 && daysSinceDue <= SUBSCRIPTION_GRACE_PERIOD_DAYS) {\n return <OverdueInvoiceBanner onDetails={onDetails} />;\n }\n\n if (\n isBoleto &&\n !isLoadingCharges &&\n hasPendingCharge &&\n daysToDue >= 0 &&\n daysToDue <= UPCOMING_WINDOW_DAYS\n ) {\n return <UpcomingInvoiceBanner dueDate={dueDate} onDetails={onDetails} />;\n }\n\n return null;\n}\n"],"mappings":";AAyDW;AAvDX,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;AAC3B,SAAS,sCAAsC;AAC/C,SAAS,iCAAiC;AAC1C,SAAS,wCAAwC;AACjD,SAAS,gBAAgB,mBAAmB;AAC5C,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AACtC,SAAS,mCAAmC;AAC5C,SAAS,iCAAiC;AAC1C,SAAS,mBAAmB;AAE5B,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAOvB,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,sBAAsB;AAC3E,QAAM,EAAE,MAAM,oBAAoB,WAAW,iBAAiB,IAAI,WAAW;AAAA,IAC3E,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ,CAAC,CAAC;AAAA,EACZ,CAAC;AAED,MAAI,CAAC,cAAc,SAAU,QAAO;AACpC,MAAI,aAAa,SAAS,OAAQ,QAAO;AAEzC,QAAM,UAAU,eAAe,aAAa,QAAQ;AACpD,QAAM,QAAQ,eAAe,oBAAI,KAAK,CAAC;AACvC,MAAI,CAAC,WAAW,CAAC,MAAO,QAAO;AAE/B,QAAM,eAAe,YAAY,SAAS,KAAK;AAC/C,QAAM,YAAY,YAAY,OAAO,OAAO;AAC5C,QAAM,mBAAmB,CAAC,CAAC,oBAAoB,OAAO,CAAC;AACvD,QAAM,WAAW,aAAa,mBAAmB;AAMjD,QAAM,aAAa,0BAA0B,YAAY;AACzD,QAAM,oBAAoB,iCAAiC,YAAY;AAKvE,MAAI,aAAa,SAAS,SAAS;AACjC,QAAI,sBAAsB,UAAU,YAAY,EAAG,QAAO;AAC1D,WAAO,oBAAC,eAAY,eAAe,WAAW,cAA4B;AAAA,EAC5E;AAEA,MAAI,sBAAsB,aAAa;AACrC,WAAO,oBAAC,+BAA4B,cAA4B;AAAA,EAClE;AAEA,MAAI,sBAAsB,WAAW;AACnC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,aAAa,SAAS,aAAc,QAAO;AAE/C,MAAI,eAAe,KAAK,gBAAgB,gCAAgC;AACtE,WAAO,oBAAC,wBAAqB,WAAsB;AAAA,EACrD;AAEA,MACE,YACA,CAAC,oBACD,oBACA,aAAa,KACb,aAAa,sBACb;AACA,WAAO,oBAAC,yBAAsB,SAAkB,WAAsB;AAAA,EACxE;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/navigation/SubscriptionBanner.tsx"],"sourcesContent":["\"use client\";\n\nimport { useActiveSubscription } from \"../../modules/subscriptions/hooks/find-active-subscription.hook\";\nimport { useCharges } from \"../../modules/charges/hooks/charges.hook\";\nimport { SUBSCRIPTION_GRACE_PERIOD_DAYS } from \"../../modules/subscriptions/constants/subscription.constants\";\nimport { getSubscriptionExpiryDate } from \"../../modules/subscriptions/utils/get-subscription-expiry-date\";\nimport { getSubscriptionCancellationState } from \"../../modules/subscriptions/utils/get-subscription-cancellation-state\";\nimport { toCalendarDate, daysBetween } from \"../../infra/utils/date\";\nimport { OverdueInvoiceBanner } from \"./OverdueInvoiceBanner\";\nimport { UpcomingInvoiceBanner } from \"./UpcomingInvoiceBanner\";\nimport { CancelledSubscriptionBanner } from \"./CancelledSubscriptionBanner\";\nimport { PendingCancellationBanner } from \"./PendingCancellationBanner\";\nimport { TrialBanner } from \"./TrialBanner\";\n\nconst UPCOMING_WINDOW_DAYS = 7;\nconst PAYMENT_METHOD_BOLETO = 2;\n\ninterface SubscriptionBannerProps {\n onReactivate?: () => void;\n onDetails?: () => void;\n}\n\nexport function SubscriptionBanner({\n onReactivate,\n onDetails,\n}: SubscriptionBannerProps) {\n const { data: { data: [subscription] = [] } = {} } = useActiveSubscription();\n const { data: pendingChargesData, isLoading: isLoadingCharges } = useCharges({\n page: 1,\n limit: 1,\n status: [0],\n });\n\n if (!subscription?.date_due) return null;\n if (subscription.type === \"free\") return null;\n\n const dueDate = toCalendarDate(subscription.date_due);\n const today = toCalendarDate(new Date());\n if (!dueDate || !today) return null;\n\n const daysSinceDue = daysBetween(dueDate, today);\n const daysToDue = daysBetween(today, dueDate);\n const hasPendingCharge = !!pendingChargesData?.data?.[0];\n const isBoleto = subscription.payment_method === PAYMENT_METHOD_BOLETO;\n\n // Estado de cancelamento (fonte da verdade única, compartilhada com o\n // CancelledSubscriptionBanner). `active === false` tem prioridade e cai em\n // \"cancelled\" mesmo com date_due no futuro — é o caso da baixa por falha de\n // pagamento, onde date_due aponta pra uma fatura não paga.\n const expiryDate = getSubscriptionExpiryDate(subscription);\n const cancellationState = getSubscriptionCancellationState(subscription);\n\n // Trial: `date_due` guarda o fim do período de teste (ver auth.service).\n // Mostra a contagem regressiva enquanto o teste está vigente: `active` e não\n // vencido (`daysToDue >= 0`). NÃO usar `cancellationState` aqui — num trial o\n // `date_cancellation` é o agendamento padrão de não-renovação (o Stripe seta\n // = `date_due`), então cairia sempre em \"pending\" e o banner nunca apareceria.\n // Um trial encerrado de verdade vem com `active === false` (date_due placeholder).\n if (subscription.type === \"trial\") {\n if (!subscription.active || daysToDue < 0) return null;\n return <TrialBanner daysRemaining={daysToDue} onReactivate={onReactivate} />;\n }\n\n if (cancellationState === \"cancelled\") {\n return <CancelledSubscriptionBanner onReactivate={onReactivate} />;\n }\n\n if (cancellationState === \"pending\") {\n return (\n <PendingCancellationBanner\n limitDate={expiryDate}\n onReactivate={onReactivate}\n />\n );\n }\n\n if (subscription.type === \"whitelabel\") return null;\n\n if (daysSinceDue > 0 && daysSinceDue <= SUBSCRIPTION_GRACE_PERIOD_DAYS) {\n return <OverdueInvoiceBanner onDetails={onDetails} />;\n }\n\n if (\n isBoleto &&\n !isLoadingCharges &&\n hasPendingCharge &&\n daysToDue >= 0 &&\n daysToDue <= UPCOMING_WINDOW_DAYS\n ) {\n return <UpcomingInvoiceBanner dueDate={dueDate} onDetails={onDetails} />;\n }\n\n return null;\n}\n"],"mappings":";AA4DW;AA1DX,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;AAC3B,SAAS,sCAAsC;AAC/C,SAAS,iCAAiC;AAC1C,SAAS,wCAAwC;AACjD,SAAS,gBAAgB,mBAAmB;AAC5C,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AACtC,SAAS,mCAAmC;AAC5C,SAAS,iCAAiC;AAC1C,SAAS,mBAAmB;AAE5B,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAOvB,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,sBAAsB;AAC3E,QAAM,EAAE,MAAM,oBAAoB,WAAW,iBAAiB,IAAI,WAAW;AAAA,IAC3E,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ,CAAC,CAAC;AAAA,EACZ,CAAC;AAED,MAAI,CAAC,cAAc,SAAU,QAAO;AACpC,MAAI,aAAa,SAAS,OAAQ,QAAO;AAEzC,QAAM,UAAU,eAAe,aAAa,QAAQ;AACpD,QAAM,QAAQ,eAAe,oBAAI,KAAK,CAAC;AACvC,MAAI,CAAC,WAAW,CAAC,MAAO,QAAO;AAE/B,QAAM,eAAe,YAAY,SAAS,KAAK;AAC/C,QAAM,YAAY,YAAY,OAAO,OAAO;AAC5C,QAAM,mBAAmB,CAAC,CAAC,oBAAoB,OAAO,CAAC;AACvD,QAAM,WAAW,aAAa,mBAAmB;AAMjD,QAAM,aAAa,0BAA0B,YAAY;AACzD,QAAM,oBAAoB,iCAAiC,YAAY;AAQvE,MAAI,aAAa,SAAS,SAAS;AACjC,QAAI,CAAC,aAAa,UAAU,YAAY,EAAG,QAAO;AAClD,WAAO,oBAAC,eAAY,eAAe,WAAW,cAA4B;AAAA,EAC5E;AAEA,MAAI,sBAAsB,aAAa;AACrC,WAAO,oBAAC,+BAA4B,cAA4B;AAAA,EAClE;AAEA,MAAI,sBAAsB,WAAW;AACnC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,aAAa,SAAS,aAAc,QAAO;AAE/C,MAAI,eAAe,KAAK,gBAAgB,gCAAgC;AACtE,WAAO,oBAAC,wBAAqB,WAAsB;AAAA,EACrD;AAEA,MACE,YACA,CAAC,oBACD,oBACA,aAAa,KACb,aAAa,sBACb;AACA,WAAO,oBAAC,yBAAsB,SAAkB,WAAsB;AAAA,EACxE;AAEA,SAAO;AACT;","names":[]}
@@ -16,11 +16,11 @@ function TrialBanner({ daysRemaining, onReactivate }) {
16
16
  return /* @__PURE__ */ jsx("div", { className: "fixed top-[80px] md:top-0 left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0", children: /* @__PURE__ */ jsxs(
17
17
  "div",
18
18
  {
19
- className: `flex flex-col sm:flex-row items-start sm:items-center justify-between bg-cyan-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? "translate-y-0 md:translate-y-9" : "-translate-y-full"}`,
19
+ className: `flex flex-col sm:flex-row items-start sm:items-center justify-between bg-amber-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? "translate-y-0 md:translate-y-9" : "-translate-y-full"}`,
20
20
  children: [
21
21
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-1 w-full sm:w-auto", children: [
22
- /* @__PURE__ */ jsx(IconClock, { size: 16, className: "text-white shrink-0" }),
23
- /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-white", children: translate("common.navigation.banners.trial.message", { days: daysRemaining }) })
22
+ /* @__PURE__ */ jsx(IconClock, { size: 16, className: "text-zinc-950 shrink-0" }),
23
+ /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-zinc-950", children: translate("common.navigation.banners.trial.message", { days: daysRemaining }) })
24
24
  ] }),
25
25
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start", children: [
26
26
  /* @__PURE__ */ jsx(
@@ -29,10 +29,10 @@ function TrialBanner({ daysRemaining, onReactivate }) {
29
29
  type: "button",
30
30
  className: "flex items-center justify-center p-1.5 cursor-pointer",
31
31
  onClick: onReactivate,
32
- children: /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-white underline", children: translate("common.navigation.banners.trial.choosePlan") })
32
+ children: /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-zinc-950 underline", children: translate("common.navigation.banners.trial.choosePlan") })
33
33
  }
34
34
  ),
35
- /* @__PURE__ */ jsx("button", { type: "button", className: "cursor-pointer shrink-0", onClick: dismiss, children: /* @__PURE__ */ jsx(IconX, { size: 18, className: "text-cyan-100" }) })
35
+ /* @__PURE__ */ jsx("button", { type: "button", className: "cursor-pointer shrink-0", onClick: dismiss, children: /* @__PURE__ */ jsx(IconX, { size: 18, className: "text-zinc-700" }) })
36
36
  ] })
37
37
  ]
38
38
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/navigation/TrialBanner.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { IconClock, IconX } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\n\ninterface TrialBannerProps {\n daysRemaining: number;\n onReactivate?: () => void;\n}\n\nexport function TrialBanner({ daysRemaining, onReactivate }: TrialBannerProps) {\n const translate = useTranslations();\n const [visible, setVisible] = useState(true);\n const [animated, setAnimated] = useState(false);\n\n useEffect(() => {\n const timer = setTimeout(() => setAnimated(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n const dismiss = useCallback(() => setVisible(false), []);\n\n if (!visible) return null;\n\n return (\n <div className=\"fixed top-[80px] md:top-0 left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0\">\n <div\n className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-cyan-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}\n >\n <div className=\"flex items-center gap-2 flex-1 w-full sm:w-auto\">\n <IconClock size={16} className=\"text-white shrink-0\" />\n <span className=\"paragraph-xsmall-semibold text-white\">\n {translate('common.navigation.banners.trial.message', { days: daysRemaining })}\n </span>\n </div>\n <div className=\"flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start\">\n <button\n type=\"button\"\n className=\"flex items-center justify-center p-1.5 cursor-pointer\"\n onClick={onReactivate}\n >\n <span className=\"paragraph-xsmall-semibold text-white underline\">\n {translate('common.navigation.banners.trial.choosePlan')}\n </span>\n </button>\n <button type=\"button\" className=\"cursor-pointer shrink-0\" onClick={dismiss}>\n <IconX size={18} className=\"text-cyan-100\" />\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AA8BQ,SACE,KADF;AA5BR,SAAS,UAAU,WAAW,mBAAmB;AACjD,SAAS,WAAW,aAAa;AACjC,SAAS,uBAAuB;AAOzB,SAAS,YAAY,EAAE,eAAe,aAAa,GAAqB;AAC7E,QAAM,YAAY,gBAAgB;AAClC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,YAAU,MAAM;AACd,UAAM,QAAQ,WAAW,MAAM,YAAY,IAAI,GAAG,EAAE;AACpD,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,MAAM,WAAW,KAAK,GAAG,CAAC,CAAC;AAEvD,MAAI,CAAC,QAAS,QAAO;AAErB,SACE,oBAAC,SAAI,WAAU,wGACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,+NAA+N,WAAW,mCAAmC,mBAAmB;AAAA,MAE3S;AAAA,6BAAC,SAAI,WAAU,mDACb;AAAA,8BAAC,aAAU,MAAM,IAAI,WAAU,uBAAsB;AAAA,UACrD,oBAAC,UAAK,WAAU,wCACb,oBAAU,2CAA2C,EAAE,MAAM,cAAc,CAAC,GAC/E;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,+EACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cAET,8BAAC,UAAK,WAAU,kDACb,oBAAU,4CAA4C,GACzD;AAAA;AAAA,UACF;AAAA,UACA,oBAAC,YAAO,MAAK,UAAS,WAAU,2BAA0B,SAAS,SACjE,8BAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB,GAC7C;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/navigation/TrialBanner.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { IconClock, IconX } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\n\ninterface TrialBannerProps {\n daysRemaining: number;\n onReactivate?: () => void;\n}\n\nexport function TrialBanner({ daysRemaining, onReactivate }: TrialBannerProps) {\n const translate = useTranslations();\n const [visible, setVisible] = useState(true);\n const [animated, setAnimated] = useState(false);\n\n useEffect(() => {\n const timer = setTimeout(() => setAnimated(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n const dismiss = useCallback(() => setVisible(false), []);\n\n if (!visible) return null;\n\n return (\n <div className=\"fixed top-[80px] md:top-0 left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0\">\n <div\n className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-amber-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}\n >\n <div className=\"flex items-center gap-2 flex-1 w-full sm:w-auto\">\n <IconClock size={16} className=\"text-zinc-950 shrink-0\" />\n <span className=\"paragraph-xsmall-semibold text-zinc-950\">\n {translate('common.navigation.banners.trial.message', { days: daysRemaining })}\n </span>\n </div>\n <div className=\"flex items-center gap-1.5 w-full sm:w-auto justify-between sm:justify-start\">\n <button\n type=\"button\"\n className=\"flex items-center justify-center p-1.5 cursor-pointer\"\n onClick={onReactivate}\n >\n <span className=\"paragraph-xsmall-semibold text-zinc-950 underline\">\n {translate('common.navigation.banners.trial.choosePlan')}\n </span>\n </button>\n <button type=\"button\" className=\"cursor-pointer shrink-0\" onClick={dismiss}>\n <IconX size={18} className=\"text-zinc-700\" />\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AA8BQ,SACE,KADF;AA5BR,SAAS,UAAU,WAAW,mBAAmB;AACjD,SAAS,WAAW,aAAa;AACjC,SAAS,uBAAuB;AAOzB,SAAS,YAAY,EAAE,eAAe,aAAa,GAAqB;AAC7E,QAAM,YAAY,gBAAgB;AAClC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,YAAU,MAAM;AACd,UAAM,QAAQ,WAAW,MAAM,YAAY,IAAI,GAAG,EAAE;AACpD,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,MAAM,WAAW,KAAK,GAAG,CAAC,CAAC;AAEvD,MAAI,CAAC,QAAS,QAAO;AAErB,SACE,oBAAC,SAAI,WAAU,wGACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,gOAAgO,WAAW,mCAAmC,mBAAmB;AAAA,MAE5S;AAAA,6BAAC,SAAI,WAAU,mDACb;AAAA,8BAAC,aAAU,MAAM,IAAI,WAAU,0BAAyB;AAAA,UACxD,oBAAC,UAAK,WAAU,2CACb,oBAAU,2CAA2C,EAAE,MAAM,cAAc,CAAC,GAC/E;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,+EACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cAET,8BAAC,UAAK,WAAU,qDACb,oBAAU,4CAA4C,GACzD;AAAA;AAAA,UACF;AAAA,UACA,oBAAC,YAAO,MAAK,UAAS,WAAU,2BAA0B,SAAS,SACjE,8BAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB,GAC7C;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.685",
3
+ "version": "1.1.687",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -51,10 +51,13 @@ export function SubscriptionBanner({
51
51
  const cancellationState = getSubscriptionCancellationState(subscription);
52
52
 
53
53
  // Trial: `date_due` guarda o fim do período de teste (ver auth.service).
54
- // mostra a contagem regressiva enquanto o teste está vigente não vencido
55
- // (`daysToDue >= 0`) e não cancelado/baixado (`cancellationState === "none"`).
54
+ // Mostra a contagem regressiva enquanto o teste está vigente: `active` e não
55
+ // vencido (`daysToDue >= 0`). NÃO usar `cancellationState` aqui — num trial o
56
+ // `date_cancellation` é o agendamento padrão de não-renovação (o Stripe seta
57
+ // = `date_due`), então cairia sempre em "pending" e o banner nunca apareceria.
58
+ // Um trial encerrado de verdade vem com `active === false` (date_due placeholder).
56
59
  if (subscription.type === "trial") {
57
- if (cancellationState !== "none" || daysToDue < 0) return null;
60
+ if (!subscription.active || daysToDue < 0) return null;
58
61
  return <TrialBanner daysRemaining={daysToDue} onReactivate={onReactivate} />;
59
62
  }
60
63
 
@@ -26,11 +26,11 @@ export function TrialBanner({ daysRemaining, onReactivate }: TrialBannerProps) {
26
26
  return (
27
27
  <div className="fixed top-[80px] md:top-0 left-0 right-0 z-[60] flex justify-center pointer-events-none px-4 lg:px-0">
28
28
  <div
29
- className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-cyan-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}
29
+ className={`flex flex-col sm:flex-row items-start sm:items-center justify-between bg-amber-500 rounded-lg px-3 py-2 sm:py-1 w-full lg:w-[805px] max-w-full pointer-events-auto transition-transform duration-500 ease-out gap-2 sm:gap-0 ${animated ? 'translate-y-0 md:translate-y-9' : '-translate-y-full'}`}
30
30
  >
31
31
  <div className="flex items-center gap-2 flex-1 w-full sm:w-auto">
32
- <IconClock size={16} className="text-white shrink-0" />
33
- <span className="paragraph-xsmall-semibold text-white">
32
+ <IconClock size={16} className="text-zinc-950 shrink-0" />
33
+ <span className="paragraph-xsmall-semibold text-zinc-950">
34
34
  {translate('common.navigation.banners.trial.message', { days: daysRemaining })}
35
35
  </span>
36
36
  </div>
@@ -40,12 +40,12 @@ export function TrialBanner({ daysRemaining, onReactivate }: TrialBannerProps) {
40
40
  className="flex items-center justify-center p-1.5 cursor-pointer"
41
41
  onClick={onReactivate}
42
42
  >
43
- <span className="paragraph-xsmall-semibold text-white underline">
43
+ <span className="paragraph-xsmall-semibold text-zinc-950 underline">
44
44
  {translate('common.navigation.banners.trial.choosePlan')}
45
45
  </span>
46
46
  </button>
47
47
  <button type="button" className="cursor-pointer shrink-0" onClick={dismiss}>
48
- <IconX size={18} className="text-cyan-100" />
48
+ <IconX size={18} className="text-zinc-700" />
49
49
  </button>
50
50
  </div>
51
51
  </div>