From b837aecb27d0aa9fe6cb6c9c95bbbc29c6ca3c14 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 12 Apr 2023 20:08:45 +0000 Subject: [PATCH 1/2] feat: add subscription cancelled alert --- .../SubscriptionCancelledAlert/index.ee.tsx | 25 +++++++++++++++ .../UsageDataInformation/index.ee.tsx | 3 ++ .../queries/get-subscription-status.ee.ts | 9 ++++++ .../web/src/hooks/useSubscriptionStatus.ee.ts | 31 +++++++++++++++++++ packages/web/src/locales/en.json | 3 +- 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 packages/web/src/components/SubscriptionCancelledAlert/index.ee.tsx create mode 100644 packages/web/src/graphql/queries/get-subscription-status.ee.ts create mode 100644 packages/web/src/hooks/useSubscriptionStatus.ee.ts diff --git a/packages/web/src/components/SubscriptionCancelledAlert/index.ee.tsx b/packages/web/src/components/SubscriptionCancelledAlert/index.ee.tsx new file mode 100644 index 00000000..e65da282 --- /dev/null +++ b/packages/web/src/components/SubscriptionCancelledAlert/index.ee.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import Alert from '@mui/material/Alert'; +import Typography from '@mui/material/Typography'; + +import useSubscriptionStatus from 'hooks/useSubscriptionStatus.ee'; + +export default function SubscriptionCancelledAlert() { + const subscriptionStatus = useSubscriptionStatus(); + + if (!subscriptionStatus) return ; + + return ( + + + {subscriptionStatus.message} + + + ); +} diff --git a/packages/web/src/components/UsageDataInformation/index.ee.tsx b/packages/web/src/components/UsageDataInformation/index.ee.tsx index 275c8cc6..2d247fb7 100644 --- a/packages/web/src/components/UsageDataInformation/index.ee.tsx +++ b/packages/web/src/components/UsageDataInformation/index.ee.tsx @@ -13,6 +13,7 @@ import Typography from '@mui/material/Typography'; import { TBillingCardAction } from '@automatisch/types'; import TrialOverAlert from 'components/TrialOverAlert/index.ee'; +import SubscriptionCancelledAlert from 'components/SubscriptionCancelledAlert/index.ee'; import CheckoutCompletedAlert from 'components/CheckoutCompletedAlert/index.ee'; import * as URLS from 'config/urls'; import useBillingAndUsageData from 'hooks/useBillingAndUsageData.ee'; @@ -97,6 +98,8 @@ export default function UsageDataInformation() { return ( + + diff --git a/packages/web/src/graphql/queries/get-subscription-status.ee.ts b/packages/web/src/graphql/queries/get-subscription-status.ee.ts new file mode 100644 index 00000000..9b799c8f --- /dev/null +++ b/packages/web/src/graphql/queries/get-subscription-status.ee.ts @@ -0,0 +1,9 @@ +import { gql } from '@apollo/client'; + +export const GET_SUBSCRIPTION_STATUS = gql` + query GetSubscriptionStatus { + getSubscriptionStatus { + cancellationEffectiveDate + } + } +`; diff --git a/packages/web/src/hooks/useSubscriptionStatus.ee.ts b/packages/web/src/hooks/useSubscriptionStatus.ee.ts new file mode 100644 index 00000000..853c6424 --- /dev/null +++ b/packages/web/src/hooks/useSubscriptionStatus.ee.ts @@ -0,0 +1,31 @@ +import { useQuery } from '@apollo/client'; +import { DateTime } from 'luxon'; + +import { GET_SUBSCRIPTION_STATUS } from 'graphql/queries/get-subscription-status.ee'; +import useFormatMessage from './useFormatMessage'; + +type UseSubscriptionStatusReturn = { + cancellationEffectiveDate: DateTime; + message: string; +} | null; + +export default function useSubscriptionStatus(): UseSubscriptionStatusReturn { + const formatMessage = useFormatMessage(); + const { data, loading, } = useQuery(GET_SUBSCRIPTION_STATUS); + const cancellationEffectiveDate = data?.getSubscriptionStatus?.cancellationEffectiveDate as string; + const hasCancelled = !!cancellationEffectiveDate; + + if (loading || !hasCancelled) return null; + + const cancellationEffectiveDateObject = DateTime.fromMillis(Number(cancellationEffectiveDate)).startOf('day'); + + return { + message: formatMessage( + 'subscriptionCancelledAlert.text', + { + date: cancellationEffectiveDateObject.toFormat('DDD') + } + ), + cancellationEffectiveDate: cancellationEffectiveDateObject, + }; +} diff --git a/packages/web/src/locales/en.json b/packages/web/src/locales/en.json index 9eb2f990..e9804974 100644 --- a/packages/web/src/locales/en.json +++ b/packages/web/src/locales/en.json @@ -158,5 +158,6 @@ "trialBadge.endsToday": "Trial ends today", "trialBadge.over": "Trial is over", "trialOverAlert.text": "Your free trial is over. Please upgrade your plan to continue using Automatisch.", - "checkoutCompletedAlert.text": "Thank you for upgrading your subscription and supporting our self-funded business!" + "checkoutCompletedAlert.text": "Thank you for upgrading your subscription and supporting our self-funded business!", + "subscriptionCancelledAlert.text": "Your subscription is cancelled, but you can continue using Automatisch until {date}." } From c9536e58cb3467a143e6ba3484f04449e74b4476 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Thu, 13 Apr 2023 18:27:57 +0200 Subject: [PATCH 2/2] feat: Cover active but cancelled subscriptions --- packages/backend/src/models/subscription.ee.ts | 17 +++++++++++++++-- packages/backend/src/models/user.ts | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/models/subscription.ee.ts b/packages/backend/src/models/subscription.ee.ts index a8d9de60..cf7f1939 100644 --- a/packages/backend/src/models/subscription.ee.ts +++ b/packages/backend/src/models/subscription.ee.ts @@ -1,6 +1,7 @@ import Base from './base'; import User from './user'; import UsageData from './usage-data.ee'; +import { DateTime } from 'luxon'; import { getPlanById } from '../helpers/billing/plans.ee'; class Subscription extends Base { @@ -79,8 +80,20 @@ class Subscription extends Base { return getPlanById(this.paddlePlanId); } - get isActive() { - return this.status === 'active' || this.status === 'past_due'; + get isCancelledAndValid() { + return ( + this.status === 'deleted' && + Number(this.cancellationEffectiveDate) > + DateTime.now().startOf('day').toMillis() + ); + } + + get isValid() { + if (this.status === 'active') return true; + if (this.status === 'past_due') return true; + if (this.isCancelledAndValid) return true; + + return false; } } diff --git a/packages/backend/src/models/user.ts b/packages/backend/src/models/user.ts index 2e17203e..43d966ce 100644 --- a/packages/backend/src/models/user.ts +++ b/packages/backend/src/models/user.ts @@ -209,7 +209,7 @@ class User extends Base { const subscription = await this.$relatedQuery('currentSubscription'); - return subscription?.isActive; + return subscription?.isValid; } async withinLimits() {