diff --git a/packages/server/src/services/Subscription/GetSubscriptionsTransformer.ts b/packages/server/src/services/Subscription/GetSubscriptionsTransformer.ts
index edc7d5dc0..194b41f78 100644
--- a/packages/server/src/services/Subscription/GetSubscriptionsTransformer.ts
+++ b/packages/server/src/services/Subscription/GetSubscriptionsTransformer.ts
@@ -6,6 +6,165 @@ export class GetSubscriptionsTransformer extends Transformer {
* @returns {Array}
*/
public includeAttributes = (): string[] => {
- return [];
+ return [
+ 'canceledAtFormatted',
+ 'cancelsAtFormatted',
+ 'trialStartsAtFormatted',
+ 'trialEndsAtFormatted',
+ 'statusFormatted',
+ 'planName',
+ 'planSlug',
+ 'planPrice',
+ 'planPriceCurrency',
+ 'planPriceFormatted',
+ 'planPeriod',
+ 'lemonUrls',
+ ];
+ };
+
+ /**
+ * Exclude attributes.
+ * @returns {string[]}
+ */
+ public excludeAttributes = (): string[] => {
+ return ['id', 'plan'];
+ };
+
+ /**
+ * Retrieves the canceled at formatted.
+ * @param subscription
+ * @returns {string}
+ */
+ public canceledAtFormatted = (subscription) => {
+ return subscription.canceledAt
+ ? this.formatDate(subscription.canceledAt)
+ : null;
+ };
+
+ /**
+ * Retrieves the cancels at formatted.
+ * @param subscription
+ * @returns {string}
+ */
+ public cancelsAtFormatted = (subscription) => {
+ return subscription.cancelsAt
+ ? this.formatDate(subscription.cancelsAt)
+ : null;
+ };
+
+ /**
+ * Retrieves the trial starts at formatted date.
+ * @returns {string}
+ */
+ public trialStartsAtFormatted = (subscription) => {
+ return subscription.trialStartsAt
+ ? this.formatDate(subscription.trialStartsAt)
+ : null;
+ };
+
+ /**
+ * Retrieves the trial ends at formatted date.
+ * @returns {string}
+ */
+ public trialEndsAtFormatted = (subscription) => {
+ return subscription.trialEndsAt
+ ? this.formatDate(subscription.trialEndsAt)
+ : null;
+ };
+
+ /**
+ * Retrieves the Lemon subscription metadata.
+ * @param subscription
+ * @returns
+ */
+ public lemonSubscription = (subscription) => {
+ return (
+ this.options.lemonSubscriptions[subscription.lemonSubscriptionId] || null
+ );
+ };
+
+ /**
+ * Retrieves the formatted subscription status.
+ * @param subscription
+ * @returns {string}
+ */
+ public statusFormatted = (subscription) => {
+ const pairs = {
+ canceled: 'Canceled',
+ active: 'Active',
+ inactive: 'Inactive',
+ expired: 'Expired',
+ on_trial: 'On Trial',
+ };
+ return pairs[subscription.status] || '';
+ };
+
+ /**
+ * Retrieves the subscription plan name.
+ * @param subscription
+ * @returns {string}
+ */
+ public planName(subscription) {
+ return subscription.plan?.name;
+ }
+
+ /**
+ * Retrieves the subscription plan slug.
+ * @param subscription
+ * @returns {string}
+ */
+ public planSlug(subscription) {
+ return subscription.plan?.slug;
+ }
+
+ /**
+ * Retrieves the subscription plan price.
+ * @param subscription
+ * @returns {number}
+ */
+ public planPrice(subscription) {
+ return subscription.plan?.price;
+ }
+
+ /**
+ * Retrieves the subscription plan price currency.
+ * @param subscription
+ * @returns {string}
+ */
+ public planPriceCurrency(subscription) {
+ return subscription.plan?.currency;
+ }
+
+ /**
+ * Retrieves the subscription plan formatted price.
+ * @param subscription
+ * @returns {string}
+ */
+ public planPriceFormatted(subscription) {
+ return this.formatMoney(subscription.plan?.price, {
+ currencyCode: subscription.plan?.currency,
+ precision: 0
+ });
+ }
+
+ /**
+ * Retrieves the subscription plan period.
+ * @param subscription
+ * @returns {string}
+ */
+ public planPeriod(subscription) {
+ return subscription?.plan?.period;
+ }
+
+ /**
+ * Retrieve the subscription Lemon Urls.
+ * @param subscription
+ * @returns
+ */
+ public lemonUrls = (subscription) => {
+ const lemonSusbcription = this.lemonSubscription(subscription);
+ console.log(lemonSusbcription);
+
+ return lemonSusbcription?.data?.attributes?.urls;
};
}
diff --git a/packages/server/src/services/Subscription/LemonResumeSubscription.ts b/packages/server/src/services/Subscription/LemonResumeSubscription.ts
index e6628cc0c..cd0ee0d2e 100644
--- a/packages/server/src/services/Subscription/LemonResumeSubscription.ts
+++ b/packages/server/src/services/Subscription/LemonResumeSubscription.ts
@@ -1,6 +1,6 @@
+import { Inject, Service } from 'typedi';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';
-import { Inject, Service } from 'typedi';
import { configureLemonSqueezy } from './utils';
import { PlanSubscription } from '@/system/models';
import { ServiceError } from '@/exceptions';
diff --git a/packages/server/src/services/Subscription/SubscriptionService.ts b/packages/server/src/services/Subscription/SubscriptionService.ts
index de3b1db93..a61714af3 100644
--- a/packages/server/src/services/Subscription/SubscriptionService.ts
+++ b/packages/server/src/services/Subscription/SubscriptionService.ts
@@ -1,7 +1,11 @@
import { Inject, Service } from 'typedi';
+import { getSubscription } from '@lemonsqueezy/lemonsqueezy.js';
+import { PromisePool } from '@supercharge/promise-pool';
import { PlanSubscription } from '@/system/models';
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
import { GetSubscriptionsTransformer } from './GetSubscriptionsTransformer';
+import { configureLemonSqueezy } from './utils';
+import { fromPairs } from 'lodash';
@Service()
export default class SubscriptionService {
@@ -13,14 +17,34 @@ export default class SubscriptionService {
* @param {number} tenantId
*/
public async getSubscriptions(tenantId: number) {
- const subscriptions = await PlanSubscription.query().where(
- 'tenant_id',
- tenantId
+ configureLemonSqueezy();
+
+ const subscriptions = await PlanSubscription.query()
+ .where('tenant_id', tenantId)
+ .withGraphFetched('plan');
+
+ const lemonSubscriptionsResult = await PromisePool.withConcurrency(1)
+ .for(subscriptions)
+ .process(async (subscription, index, pool) => {
+ if (subscription.lemonSubscriptionId) {
+ const res = await getSubscription(subscription.lemonSubscriptionId);
+
+ if (res.error) {
+ return;
+ }
+ return [subscription.lemonSubscriptionId, res.data];
+ }
+ });
+ const lemonSubscriptions = fromPairs(
+ lemonSubscriptionsResult?.results.filter((result) => !!result[1])
);
return this.transformer.transform(
tenantId,
subscriptions,
- new GetSubscriptionsTransformer()
+ new GetSubscriptionsTransformer(),
+ {
+ lemonSubscriptions,
+ }
);
}
}
diff --git a/packages/server/src/system/migrations/20240728123419_add_trial_columns_to_subscription_table.js b/packages/server/src/system/migrations/20240728123419_add_trial_columns_to_subscription_table.js
new file mode 100644
index 000000000..1843b120a
--- /dev/null
+++ b/packages/server/src/system/migrations/20240728123419_add_trial_columns_to_subscription_table.js
@@ -0,0 +1,13 @@
+exports.up = function (knex) {
+ return knex.schema.table('subscription_plan_subscriptions', (table) => {
+ table.dateTime('trial_starts_at').nullable();
+ table.dateTime('trial_ends_at').nullable();
+ });
+};
+
+exports.down = function (knex) {
+ return knex.schema.table('subscription_plan_subscriptions', (table) => {
+ table.dropColumn('trial_starts_at').nullable();
+ table.dropColumn('trial_ends_at').nullable();
+ });
+};
diff --git a/packages/server/src/system/models/Subscriptions/PlanSubscription.ts b/packages/server/src/system/models/Subscriptions/PlanSubscription.ts
index c3e63530c..3ae1c1fac 100644
--- a/packages/server/src/system/models/Subscriptions/PlanSubscription.ts
+++ b/packages/server/src/system/models/Subscriptions/PlanSubscription.ts
@@ -5,7 +5,16 @@ import SubscriptionPeriod from '@/services/Subscription/SubscriptionPeriod';
export default class PlanSubscription extends mixin(SystemModel) {
lemonSubscriptionId: number;
-
+
+ canceledAt: Date;
+ cancelsAt: Date;
+
+ trialStartsAt: Date;
+ trialEndsAt: Date;
+
+ endsAt: Date;
+ startsAt: Date;
+
/**
* Table name.
*/
@@ -24,7 +33,7 @@ export default class PlanSubscription extends mixin(SystemModel) {
* Defined virtual attributes.
*/
static get virtualAttributes() {
- return ['active', 'inactive', 'ended', 'onTrial'];
+ return ['active', 'inactive', 'ended', 'canceled', 'onTrial', 'status'];
}
/**
@@ -40,7 +49,7 @@ export default class PlanSubscription extends mixin(SystemModel) {
builder.where('trial_ends_at', '>', now);
},
- inactiveSubscriptions() {
+ inactiveSubscriptions(builder) {
builder.modify('endedTrial');
builder.modify('endedPeriod');
},
@@ -100,35 +109,80 @@ export default class PlanSubscription extends mixin(SystemModel) {
}
/**
- * Check if subscription is active.
+ * Check if the subscription is expired.
+ * Expired mens the user his lost the right to use the product.
+ * @returns {Boolean}
+ */
+ public expired() {
+ return this.ended() && !this.onTrial();
+ }
+
+ /**
+ * Check if paid subscription is active.
* @return {Boolean}
*/
- active() {
- return !this.ended() || this.onTrial();
+ public active() {
+ return (
+ !this.canceled() && !this.onTrial() && !this.ended() && this.started()
+ );
}
/**
* Check if subscription is inactive.
* @return {Boolean}
*/
- inactive() {
+ public inactive() {
return !this.active();
}
/**
- * Check if subscription period has ended.
+ * Check if paid subscription period has ended.
* @return {Boolean}
*/
- ended() {
+ public ended() {
return this.endsAt ? moment().isAfter(this.endsAt) : false;
}
+ /**
+ * Check if the paid subscription has started.
+ * @returns {Boolean}
+ */
+ public started() {
+ return this.startsAt ? moment().isAfter(this.startsAt) : false;
+ }
+
/**
* Check if subscription is currently on trial.
* @return {Boolean}
*/
- onTrial() {
- return this.trailEndsAt ? moment().isAfter(this.trailEndsAt) : false;
+ public onTrial() {
+ return this.trialEndsAt ? moment().isBefore(this.trialEndsAt) : false;
+ }
+
+ /**
+ * Check if the subscription is canceled.
+ * @returns {boolean}
+ */
+ public canceled() {
+ return (
+ this.canceledAt ||
+ (this.cancelsAt && moment().isAfter(this.cancelsAt)) ||
+ false
+ );
+ }
+
+ /**
+ * Retrieves the subscription status.
+ * @returns {string}
+ */
+ public status() {
+ return this.canceled()
+ ? 'canceled'
+ : this.onTrial()
+ ? 'on_trial'
+ : this.active()
+ ? 'active'
+ : 'inactive';
}
/**
@@ -143,7 +197,7 @@ export default class PlanSubscription extends mixin(SystemModel) {
const period = new SubscriptionPeriod(
invoiceInterval,
invoicePeriod,
- start,
+ start
);
const startsAt = period.getStartDate();
@@ -159,7 +213,7 @@ export default class PlanSubscription extends mixin(SystemModel) {
renew(invoiceInterval, invoicePeriod) {
const { startsAt, endsAt } = PlanSubscription.setNewPeriod(
invoiceInterval,
- invoicePeriod,
+ invoicePeriod
);
return this.$query().update({ startsAt, endsAt });
}
diff --git a/packages/webapp/src/components/DrawersContainer.tsx b/packages/webapp/src/components/DrawersContainer.tsx
index af3c97525..cf9451d1c 100644
--- a/packages/webapp/src/components/DrawersContainer.tsx
+++ b/packages/webapp/src/components/DrawersContainer.tsx
@@ -22,6 +22,7 @@ import RefundVendorCreditDetailDrawer from '@/containers/Drawers/RefundVendorCre
import WarehouseTransferDetailDrawer from '@/containers/Drawers/WarehouseTransferDetailDrawer';
import TaxRateDetailsDrawer from '@/containers/TaxRates/drawers/TaxRateDetailsDrawer/TaxRateDetailsDrawer';
import CategorizeTransactionDrawer from '@/containers/CashFlow/CategorizeTransaction/drawers/CategorizeTransactionDrawer/CategorizeTransactionDrawer';
+import ChangeSubscriptionPlanDrawer from '@/containers/Subscriptions/drawers/ChangeSubscriptionPlanDrawer/ChangeSubscriptionPlanDrawer';
import { DRAWERS } from '@/constants/drawers';
@@ -63,6 +64,7 @@ export default function DrawersContainer() {
/>
+
);
}
diff --git a/packages/webapp/src/constants/drawers.ts b/packages/webapp/src/constants/drawers.ts
index 2dc3e92e9..c4e477352 100644
--- a/packages/webapp/src/constants/drawers.ts
+++ b/packages/webapp/src/constants/drawers.ts
@@ -24,4 +24,5 @@ export enum DRAWERS {
WAREHOUSE_TRANSFER_DETAILS = 'warehouse-transfer-detail-drawer',
TAX_RATE_DETAILS = 'tax-rate-detail-drawer',
CATEGORIZE_TRANSACTION = 'categorize-transaction',
+ CHANGE_SUBSCARIPTION_PLAN = 'change-subscription-plan'
}
diff --git a/packages/webapp/src/containers/Setup/SetupSubscription/SubscriptionPlan.tsx b/packages/webapp/src/containers/Setup/SetupSubscription/SubscriptionPlan.tsx
index 4ebb88d5f..e4463ad70 100644
--- a/packages/webapp/src/containers/Setup/SetupSubscription/SubscriptionPlan.tsx
+++ b/packages/webapp/src/containers/Setup/SetupSubscription/SubscriptionPlan.tsx
@@ -29,6 +29,7 @@ interface SubscriptionPricingProps {
annuallyPriceLabel: string;
monthlyVariantId?: string;
annuallyVariantId?: string;
+ onSubscribe?: (variantId: number) => void;
}
interface SubscriptionPricingCombinedProps
@@ -46,6 +47,7 @@ function SubscriptionPlanRoot({
annuallyPriceLabel,
monthlyVariantId,
annuallyVariantId,
+ onSubscribe,
// #withPlans
plansPeriod,
@@ -59,17 +61,19 @@ function SubscriptionPlanRoot({
? monthlyVariantId
: annuallyVariantId;
- getLemonCheckout({ variantId })
- .then((res) => {
- const checkoutUrl = res.data.data.attributes.url;
- window.LemonSqueezy.Url.Open(checkoutUrl);
- })
- .catch(() => {
- AppToaster.show({
- message: 'Something went wrong!',
- intent: Intent.DANGER,
- });
- });
+ onSubscribe && onSubscribe(variantId);
+
+ // getLemonCheckout({ variantId })
+ // .then((res) => {
+ // const checkoutUrl = res.data.data.attributes.url;
+ // window.LemonSqueezy.Url.Open(checkoutUrl);
+ // })
+ // .catch(() => {
+ // AppToaster.show({
+ // message: 'Something went wrong!',
+ // intent: Intent.DANGER,
+ // });
+ // });
};
return (
diff --git a/packages/webapp/src/containers/Subscriptions/BillingPageBoot.tsx b/packages/webapp/src/containers/Subscriptions/BillingPageBoot.tsx
index 7cebf9759..06bb3513e 100644
--- a/packages/webapp/src/containers/Subscriptions/BillingPageBoot.tsx
+++ b/packages/webapp/src/containers/Subscriptions/BillingPageBoot.tsx
@@ -15,12 +15,17 @@ interface BillingPageBootProps {
}
export function BillingPageBoot({ children }: BillingPageBootProps) {
- const { isLoading: isSubscriptionsLoading, data: subscriptions } =
+ const { isLoading: isSubscriptionsLoading, data: subscriptionsRes } =
useGetSubscriptions();
+ const mainSubscription = subscriptionsRes?.subscriptions?.find(
+ (s) => s.slug === 'main',
+ );
+
const value = {
isSubscriptionsLoading,
- subscriptions,
+ subscriptions: subscriptionsRes?.subscriptions,
+ mainSubscription,
};
return {children};
}
diff --git a/packages/webapp/src/containers/Subscriptions/BillingPageContent.tsx b/packages/webapp/src/containers/Subscriptions/BillingPageContent.tsx
index bea0ec377..dee9d0159 100644
--- a/packages/webapp/src/containers/Subscriptions/BillingPageContent.tsx
+++ b/packages/webapp/src/containers/Subscriptions/BillingPageContent.tsx
@@ -1,9 +1,17 @@
+// @ts-nocheck
import { Box, Group } from '@/components';
-import { Text } from '@blueprintjs/core';
+import { Spinner, Text } from '@blueprintjs/core';
import { Subscription } from './BillingSubscription';
+import { useBillingPageBoot } from './BillingPageBoot';
import styles from './BillingPageContent.module.scss';
export function BillingPageContent() {
+ const { isSubscriptionsLoading, subscriptions } = useBillingPageBoot();
+
+ if (isSubscriptionsLoading || !subscriptions) {
+ return ;
+ }
+
return (
diff --git a/packages/webapp/src/containers/Subscriptions/BillingSubscription.module.scss b/packages/webapp/src/containers/Subscriptions/BillingSubscription.module.scss
index 7f218431d..f99f30d8e 100644
--- a/packages/webapp/src/containers/Subscriptions/BillingSubscription.module.scss
+++ b/packages/webapp/src/containers/Subscriptions/BillingSubscription.module.scss
@@ -12,7 +12,7 @@
.title{
margin: 0;
- font-size: 20px;
+ font-size: 18px;
font-weight: 600;
color: #3D4C58;
}
@@ -56,8 +56,4 @@
}
.actions{
margin-top: 16px;
-
- button{
- font-size: 15px;
- }
}
\ No newline at end of file
diff --git a/packages/webapp/src/containers/Subscriptions/BillingSubscription.tsx b/packages/webapp/src/containers/Subscriptions/BillingSubscription.tsx
index 0bef787a1..aff31eecb 100644
--- a/packages/webapp/src/containers/Subscriptions/BillingSubscription.tsx
+++ b/packages/webapp/src/containers/Subscriptions/BillingSubscription.tsx
@@ -4,25 +4,42 @@ import { Box, Group, Stack } from '@/components';
import { Button, Card, Intent, Text } from '@blueprintjs/core';
import withAlertActions from '../Alert/withAlertActions';
import styles from './BillingSubscription.module.scss';
+import withDrawerActions from '../Drawer/withDrawerActions';
+import { DRAWERS } from '@/constants/drawers';
+import { useBillingPageBoot } from './BillingPageBoot';
-function SubscriptionRoot({ openAlert }) {
+function SubscriptionRoot({ openAlert, openDrawer }) {
+ const { mainSubscription } = useBillingPageBoot();
+
+ // Can't continue if the main subscription is not loaded.
+ if (!mainSubscription) {
+ return null;
+ }
const handleCancelSubBtnClick = () => {
openAlert('cancel-main-subscription');
};
const handleResumeSubBtnClick = () => {
openAlert('resume-main-subscription');
};
- const handleUpdatePaymentMethod = () => {};
-
- const handleUpgradeBtnClick = () => {};
+ const handleUpdatePaymentMethod = () => {
+ window.LemonSqueezy.Url.Open(
+ mainSubscription.lemonUrls?.updatePaymentMethod,
+ );
+ };
+ // Handle upgrade button click.
+ const handleUpgradeBtnClick = () => {
+ openDrawer(DRAWERS.CHANGE_SUBSCARIPTION_PLAN);
+ };
return (
-
- Capital Essential
+
+ {mainSubscription.planName}
- Trial
+
+ {mainSubscription.statusFormatted}
+
Trial ends in 10 days.
@@ -43,15 +60,29 @@ function SubscriptionRoot({ openAlert }) {
>
Upgrade the Plan
-
+
+ {mainSubscription.canceled && (
+
+ )}
+ {!mainSubscription.canceled && (
+
+ )}
);
}
-export const Subscription = R.compose(withAlertActions)(SubscriptionRoot);
+export const Subscription = R.compose(
+ withAlertActions,
+ withDrawerActions,
+)(SubscriptionRoot);
diff --git a/packages/webapp/src/containers/Subscriptions/drawers/ChangeSubscriptionPlanDrawer/ChangeSubscriptionPlanContent.tsx b/packages/webapp/src/containers/Subscriptions/drawers/ChangeSubscriptionPlanDrawer/ChangeSubscriptionPlanContent.tsx
new file mode 100644
index 000000000..7c99e17e8
--- /dev/null
+++ b/packages/webapp/src/containers/Subscriptions/drawers/ChangeSubscriptionPlanDrawer/ChangeSubscriptionPlanContent.tsx
@@ -0,0 +1,54 @@
+// @ts-nocheck
+import * as R from 'ramda';
+import { Callout, Classes, Intent } from '@blueprintjs/core';
+import { AppToaster, Box } from '@/components';
+import { SubscriptionPlans } from '@/containers/Setup/SetupSubscription/SubscriptionPlans';
+import { SubscriptionPlansPeriodSwitcher } from '@/containers/Setup/SetupSubscription/SubscriptionPlansPeriodSwitcher';
+import { useChangeSubscriptionPlan } from '@/hooks/query/subscription';
+import withDrawerActions from '@/containers/Drawer/withDrawerActions';
+import { DRAWERS } from '@/constants/drawers';
+
+function ChangeSubscriptionPlanContent({ closeDrawer }) {
+ const { mutateAsync: changeSubscriptionPlan } = useChangeSubscriptionPlan();
+
+ // Handle the subscribe button click.
+ const handleSubscribe = (variantId: number) => {
+ changeSubscriptionPlan({ variant_id: variantId })
+ .then(() => {
+ closeDrawer(DRAWERS.CHANGE_SUBSCARIPTION_PLAN);
+ AppToaster.show({
+ intent: Intent.SUCCESS,
+ message: 'The subscription plan has been changed successfully.',
+ });
+ })
+ .catch(() => {
+ AppToaster.show({
+ intent: Intent.DANGER,
+ message: 'Something went wrong.',
+ });
+ });
+ };
+
+ return (
+
+
+
+ Simple plans. Simple prices. Only pay for what you really need. All
+ plans come with award-winning 24/7 customer support. Prices do not
+ include applicable taxes.
+
+
+
+
+
+
+ );
+}
+
+export default R.compose(withDrawerActions)(ChangeSubscriptionPlanContent);
diff --git a/packages/webapp/src/hooks/query/subscription.tsx b/packages/webapp/src/hooks/query/subscription.tsx
index c9bbeec4e..9050aca1d 100644
--- a/packages/webapp/src/hooks/query/subscription.tsx
+++ b/packages/webapp/src/hooks/query/subscription.tsx
@@ -9,6 +9,11 @@ import {
UseQueryResult,
} from 'react-query';
import useApiRequest from '../useRequest';
+import { transformToCamelCase } from '@/utils';
+
+const QueryKeys = {
+ Subscriptions: 'Subscriptions',
+};
interface CancelMainSubscriptionValues {}
interface CancelMainSubscriptionResponse {}
@@ -40,6 +45,9 @@ export function useCancelMainSubscription(
(values) =>
apiRequest.post(`/subscription/cancel`, values).then((res) => res.data),
{
+ onSuccess: () => {
+ queryClient.invalidateQueries(QueryKeys.Subscriptions);
+ },
...options,
},
);
@@ -75,6 +83,9 @@ export function useResumeMainSubscription(
(values) =>
apiRequest.post(`/subscription/resume`, values).then((res) => res.data),
{
+ onSuccess: () => {
+ queryClient.invalidateQueries(QueryKeys.Subscriptions);
+ },
...options,
},
);
@@ -105,20 +116,58 @@ export function useChangeSubscriptionPlan(
const apiRequest = useApiRequest();
return useMutation<
- ChangeMainSubscriptionPlanValues,
+ ChangeMainSubscriptionPlanResponse,
Error,
- ChangeMainSubscriptionPlanResponse
+ ChangeMainSubscriptionPlanValues
>(
(values) =>
apiRequest.post(`/subscription/change`, values).then((res) => res.data),
{
+ onSuccess: () => {
+ queryClient.invalidateQueries(QueryKeys.Subscriptions);
+ },
...options,
},
);
}
+interface LemonSubscription {
+ active: boolean;
+ canceled: string | null;
+ canceledAt: string | null;
+ canceledAtFormatted: string | null;
+ cancelsAt: string | null;
+ cancelsAtFormatted: string | null;
+ createdAt: string;
+ ended: boolean;
+ endsAt: string | null;
+ inactive: boolean;
+ lemonSubscriptionId: string;
+ lemon_urls: {
+ updatePaymentMethod: string;
+ customerPortal: string;
+ customerPortalUpdateSubscription: string;
+ };
+ onTrial: boolean;
+ planId: number;
+ planName: string;
+ planSlug: string;
+ slug: string;
+ startsAt: string | null;
+ status: string;
+ statusFormatted: string;
+ tenantId: number;
+ trialEndsAt: string | null;
+ trialEndsAtFormatted: string | null;
+ trialStartsAt: string | null;
+ trialStartsAtFormatted: string | null;
+ updatedAt: string;
+}
+
interface GetSubscriptionsQuery {}
-interface GetSubscriptionsResponse {}
+interface GetSubscriptionsResponse {
+ subscriptions: Array;
+}
/**
* Changese the main subscription of the current organization.
@@ -135,8 +184,11 @@ export function useGetSubscriptions(
const apiRequest = useApiRequest();
return useQuery(
- ['SUBSCRIPTIONS'],
- (values) => apiRequest.get(`/subscription`).then((res) => res.data),
+ [QueryKeys.Subscriptions],
+ (values) =>
+ apiRequest
+ .get(`/subscription`)
+ .then((res) => transformToCamelCase(res.data)),
{
...options,
},