diff --git a/web/sdk/react/components/organization/billing/cycle-switch/index.tsx b/web/sdk/react/components/organization/billing/cycle-switch/index.tsx
index ad4d3d8a8..1c1252966 100644
--- a/web/sdk/react/components/organization/billing/cycle-switch/index.tsx
+++ b/web/sdk/react/components/organization/billing/cycle-switch/index.tsx
@@ -12,11 +12,11 @@ import { useNavigate, useParams } from '@tanstack/react-router';
import { useFrontier } from '~/react/contexts/FrontierContext';
import { getPlanIntervalName, getPlanPrice } from '~/react/utils';
import * as _ from 'lodash';
-import { usePlans } from '../../plans/hooks/usePlans';
import { DEFAULT_DATE_FORMAT } from '~/react/utils/constants';
import cross from '~/react/assets/cross.svg';
import styles from '../../organization.module.css';
import { timestampToDayjs } from '~/utils/timestamp';
+import { usePlans } from '~/react/views/plans/hooks/usePlans';
export function ConfirmCycleSwitch() {
const {
@@ -61,7 +61,7 @@ export function ConfirmCycleSwitch() {
const isUpgrade =
(Number(nextPlanMetadata?.weightage) || 0) -
- (Number(activePlanMetadata?.weightage) || 0) >
+ (Number(activePlanMetadata?.weightage) || 0) >
0;
const isLoading = isAllPlansLoading;
@@ -100,8 +100,8 @@ export function ConfirmCycleSwitch() {
const cycleSwitchDate = activeSubscription?.currentPeriodEndAt
? timestampToDayjs(activeSubscription?.currentPeriodEndAt)?.format(
- config?.dateFormat || DEFAULT_DATE_FORMAT
- )
+ config?.dateFormat || DEFAULT_DATE_FORMAT
+ )
: 'the next billing cycle';
return (
diff --git a/web/sdk/react/components/organization/plans/index.tsx b/web/sdk/react/components/organization/plans/index.tsx
index 520ade198..490b7995b 100644
--- a/web/sdk/react/components/organization/plans/index.tsx
+++ b/web/sdk/react/components/organization/plans/index.tsx
@@ -1,189 +1,7 @@
-import { EmptyState, Skeleton, Text, Flex } from '@raystack/apsara';
-import { Outlet } from '@tanstack/react-router';
-import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
-import { useFrontier } from '~/react/contexts/FrontierContext';
-import { groupPlansPricingByInterval } from './helpers';
-import { IntervalPricingWithPlan } from '~/src/types';
-import { UpcomingPlanChangeBanner } from '~/react/components/common/upcoming-plan-change-banner';
-import { PlansHeader } from './header';
-import { PlanPricingColumn } from './pricing-column';
-import { useBillingPermission } from '~/react/hooks/useBillingPermission';
-import { useQuery as useConnectQuery } from '@connectrpc/connect-query';
-import { FrontierServiceQueries } from '~hooks';
-import { create } from '@bufbuild/protobuf';
-import { Feature, ListFeaturesRequestSchema } from '@raystack/proton/frontier';
-import { Plan } from '@raystack/proton/frontier';
-import sharedStyles from '../styles.module.css';
-import plansStyles from './plans.module.css';
+'use client';
-const PlansLoader = () => {
- return (
-
- {[...new Array(2)].map((_, i) => (
-
- ))}
-
- );
-};
-
-const NoPlans = () => {
- return (
- }
- heading={No Plans Available}
- subHeading={
- 'Sorry, No plans available at this moment. Please try again later'
- }
- />
- );
-};
-
-interface PlansListProps {
- plans: Plan[];
- currentPlanId: string;
- allowAction: boolean;
- features: Feature[];
-}
-
-const PlansList = ({
- plans = [],
- features = [],
- currentPlanId,
- allowAction
-}: PlansListProps) => {
- if (plans.length === 0) return ;
-
- const groupedPlans = groupPlansPricingByInterval(plans).sort(
- (a, b) => a.weightage - b.weightage
- );
-
- let currentPlanPricing: IntervalPricingWithPlan | undefined;
- groupedPlans.forEach(group => {
- Object.values(group.intervals).forEach(plan => {
- if (plan.planId === currentPlanId) {
- currentPlanPricing = plan;
- }
- });
- });
-
- const totalFeatures = features.length;
-
- const featureTitleMap = features.reduce((acc, f) => {
- const weightage =
- (f.metadata as Record)?.weightage || totalFeatures;
- acc[f.title || ''] = weightage;
- return acc;
- }, {} as Record);
-
- const sortedFeatures = Object.entries(featureTitleMap)
- .sort((f1, f2) => f1[1] - f2[1])
- .map(f => f[0])
- .filter(f => Boolean(f));
-
- return (
-
-
-
-
{''}
-
-
-
- Features
-
-
- {sortedFeatures.map(feature => {
- return (
-
-
- {feature}
-
-
- );
- })}
-
-
-
- {groupedPlans.map(plan => (
-
- ))}
-
-
-
- );
-};
+import { PlansPage } from '~/react/views/plans';
export default function Plans() {
- const {
- config,
- activeSubscription,
- isActiveSubscriptionLoading,
- isActiveOrganizationLoading,
- basePlan,
- allPlans,
- isAllPlansLoading
- } = useFrontier();
-
- const { isFetching: isPermissionsFetching, isAllowed: canChangePlan } =
- useBillingPermission();
-
- const { data: featuresData } = useConnectQuery(
- FrontierServiceQueries.listFeatures,
- create(ListFeaturesRequestSchema, {})
- );
-
- const features = (featuresData?.features || []) as Feature[];
-
- const plans = [...(basePlan ? [basePlan] : []), ...allPlans];
-
- const isLoading =
- isAllPlansLoading ||
- isPermissionsFetching ||
- isActiveSubscriptionLoading ||
- isActiveOrganizationLoading;
-
- return (
-
-
-
-
-
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
-
-
-
- );
+ return ;
}
diff --git a/web/sdk/react/components/organization/routes.tsx b/web/sdk/react/components/organization/routes.tsx
index b4d158d6c..ef6d0eb19 100644
--- a/web/sdk/react/components/organization/routes.tsx
+++ b/web/sdk/react/components/organization/routes.tsx
@@ -30,7 +30,6 @@ import Tokens from './tokens';
import { AddTokens } from './tokens/add-tokens';
import { ConfirmCycleSwitch } from './billing/cycle-switch';
import Plans from './plans';
-import ConfirmPlanChange from './plans/confirm-change';
import APIKeys from './api-keys';
import { AddServiceAccount } from './api-keys/add';
import ServiceUserPage from './api-keys/service-user';
@@ -229,11 +228,6 @@ const plansRoute = createRoute({
component: Plans
});
-const planDowngradeRoute = createRoute({
- getParentRoute: () => plansRoute,
- path: '/confirm-change/$planId',
- component: ConfirmPlanChange
-});
const tokensRoute = createRoute({
getParentRoute: () => rootRoute,
@@ -320,7 +314,7 @@ export function getRootTree({ customScreens = [] }: getRootTreeOptions) {
profileRoute,
preferencesRoute,
billingRoute.addChildren([switchBillingCycleModalRoute]),
- plansRoute.addChildren([planDowngradeRoute]),
+ plansRoute,
tokensRoute.addChildren([addTokensRoute]),
apiKeysRoute.addChildren([
addServiceAccountRoute,
diff --git a/web/sdk/react/components/organization/plans/confirm-change/index.tsx b/web/sdk/react/views/plans/confirm-plan-change-dialog.tsx
similarity index 89%
rename from web/sdk/react/components/organization/plans/confirm-change/index.tsx
rename to web/sdk/react/views/plans/confirm-plan-change-dialog.tsx
index 305699d28..057e1ba5a 100644
--- a/web/sdk/react/components/organization/plans/confirm-change/index.tsx
+++ b/web/sdk/react/views/plans/confirm-plan-change-dialog.tsx
@@ -8,7 +8,6 @@ import {
Flex,
Dialog
} from '@raystack/apsara';
-import { useNavigate, useParams } from '@tanstack/react-router';
import * as _ from 'lodash';
import { useFrontier } from '~/react/contexts/FrontierContext';
import {
@@ -16,17 +15,25 @@ import {
DEFAULT_PLAN_UPGRADE_MESSAGE
} from '~/react/utils/constants';
import { getPlanChangeAction, getPlanNameWithInterval } from '~/react/utils';
-import planStyles from '../plans.module.css';
-import { usePlans } from '../hooks/usePlans';
+import planStyles from './plans.module.css';
+import { usePlans } from './hooks/usePlans';
import cross from '~/react/assets/cross.svg';
-import styles from '../../organization.module.css';
+import orgStyles from '../../components/organization/organization.module.css';
import { useMessages } from '~/react/hooks/useMessages';
import { timestampToDayjs } from '~/utils/timestamp';
import { Plan } from '@raystack/proton/frontier';
-export default function ConfirmPlanChange() {
- const navigate = useNavigate({ from: '/plans/confirm-change/$planId' });
- const { planId } = useParams({ from: '/plans/confirm-change/$planId' });
+export interface ConfirmPlanChangeDialogProps {
+ open: boolean;
+ onOpenChange?: (value: boolean) => void;
+ planId: string;
+}
+
+export function ConfirmPlanChangeDialog({
+ open,
+ onOpenChange,
+ planId
+}: ConfirmPlanChangeDialogProps) {
const {
activePlan,
isAllPlansLoading,
@@ -63,7 +70,7 @@ export default function ConfirmPlanChange() {
Number(activePlanMetadata?.weightage)
);
- const cancel = useCallback(() => navigate({ to: '/plans' }), [navigate]);
+ const handleClose = useCallback(() => onOpenChange?.(false), [onOpenChange]);
const newPlanSlug = isNewPlanBasePlan ? 'base' : newPlan?.name;
const planChangeSlug = activePlan?.name
@@ -88,10 +95,10 @@ export default function ConfirmPlanChange() {
toast.success(`Plan ${actionName} successful`, {
description: `Your plan will ${actionName} on ${changeDate}`
});
- cancel();
+ handleClose();
}
}, [
- cancel,
+ handleClose,
config?.dateFormat,
planAction?.btnLabel,
planId,
@@ -139,10 +146,10 @@ export default function ConfirmPlanChange() {
}, [isNewPlanBasePlan, basePlan, currentPlan]);
useEffect(() => {
- if (planId) {
+ if (planId && open) {
getPlan();
}
- }, [getPlan, planId]);
+ }, [getPlan, planId, open]);
const isLoading = isAllPlansLoading || isNewPlanLoading;
@@ -161,10 +168,10 @@ export default function ConfirmPlanChange() {
: 'the next billing cycle';
return (
-