From ab1e90f093c633d77c9ecdffc5e011185ee9874f Mon Sep 17 00:00:00 2001 From: giancarlo Date: Sun, 7 Apr 2024 18:12:45 +0800 Subject: [PATCH] Update Billing Provider and Refactor Pricing UI Updated the billing provider in the environment configuration to use 'stripe' instead of 'lemon-squeezy'. Multiple changes were also made to UI components related to pricing, including better data handling for different billing tiers and enhanced visualization of selected options. These revisions aim to both enhance the user experience and ensure compatibility with the new billing provider. --- apps/web/.env.development | 2 +- apps/web/config/billing.sample.config.ts | 59 +---- .../src/components/line-item-details.tsx | 223 +++++++++++------- .../gateway/src/components/plan-picker.tsx | 30 +-- .../gateway/src/components/pricing-table.tsx | 19 +- 5 files changed, 161 insertions(+), 172 deletions(-) diff --git a/apps/web/.env.development b/apps/web/.env.development index bd96eb1c2..f17125765 100644 --- a/apps/web/.env.development +++ b/apps/web/.env.development @@ -15,7 +15,7 @@ NEXT_PUBLIC_AUTH_PASSWORD=true NEXT_PUBLIC_AUTH_MAGIC_LINK=false # BILLING -NEXT_PUBLIC_BILLING_PROVIDER=lemon-squeezy +NEXT_PUBLIC_BILLING_PROVIDER=stripe # SUPABASE NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 diff --git a/apps/web/config/billing.sample.config.ts b/apps/web/config/billing.sample.config.ts index ebc105f62..295406d34 100644 --- a/apps/web/config/billing.sample.config.ts +++ b/apps/web/config/billing.sample.config.ts @@ -16,28 +16,6 @@ export default createBillingSchema({ provider, // products configuration products: [ - { - id: 'lifetime', - name: 'Lifetime', - description: 'The perfect plan for a lifetime', - currency: 'USD', - features: ['Feature 1', 'Feature 2', 'Feature 3'], - plans: [ - { - name: 'Lifetime', - id: 'lifetime', - paymentType: 'one-time', - lineItems: [ - { - id: '324643', - name: 'Base', - cost: 999.99, - type: 'flat', - }, - ], - }, - ], - }, { id: 'starter', name: 'Starter', @@ -56,42 +34,7 @@ export default createBillingSchema({ id: '324646', name: 'Addon 2', cost: 9.99, - type: 'metered', - unit: 'GBs', - tiers: [ - { - upTo: 5, - cost: 0, - }, - { - upTo: 10, - cost: 6.99, - }, - { - upTo: 'unlimited', - cost: 0.49, - }, - ], - }, - { - id: '324645', - name: 'Addon 2', - cost: 9.99, - type: 'per-seat', - tiers: [ - { - upTo: 5, - cost: 0, - }, - { - upTo: 10, - cost: 6.99, - }, - { - upTo: 'unlimited', - cost: 0.49, - }, - ], + type: 'flat', }, ], }, diff --git a/packages/billing/gateway/src/components/line-item-details.tsx b/packages/billing/gateway/src/components/line-item-details.tsx index 0c3d9051b..42e3278bf 100644 --- a/packages/billing/gateway/src/components/line-item-details.tsx +++ b/packages/billing/gateway/src/components/line-item-details.tsx @@ -38,114 +38,154 @@ export function LineItemDetails( ); } - const BaseFee = () => ( -
- + const SetupFee = () => ( + +
+ + + + + + + +
+
+ ); + + const FlatFee = () => ( +
+
+ + + + + + + + + + - + + + } + > + + + + + + + {formatCurrency(props?.currency.toLowerCase(), item.cost)} + +
+ + + + + + + + + + + + + + + + +
+ ); + + const PerSeat = () => ( +
+
- + - - + + + {formatCurrency(props.currency.toLowerCase(), item.cost)} + + +
- - } - > - - + + + + + +
+ ); + + const Metered = () => ( +
+
+ + + + + + + + + + - - - {formatCurrency(props?.currency.toLowerCase(), item.cost)} - + {/* If there are no tiers, there is a flat cost for usage */} + + + {formatCurrency(props?.currency.toLowerCase(), item.cost)} + + +
+ + + + {/* If there are tiers, we render them as a list */} + + +
); switch (item.type) { - case 'base': - return ; + case 'flat': + return ; case 'per-seat': - return ( -
-
- - - - - - - - - - - {formatCurrency(props.currency.toLowerCase(), item.cost)} - - -
- - - - -
- ); + return ; case 'metered': { - return ( -
-
- - - - - - - - - - - {(fee) => ( - - - - )} - - - - - - {/* If there are no tiers, there is a flat cost for usage */} - - - {formatCurrency(props?.currency.toLowerCase(), item.cost)} - - -
- - {/* If there are tiers, we render them as a list */} - - - -
- ); + return ; } } })} @@ -160,6 +200,8 @@ function Tiers({ currency: string; item: z.infer; }) { + const unit = item.unit; + const tiers = item.tiers?.map((tier, index) => { const previousTier = item.tiers?.[index - 1]; const isNoLimit = tier.upTo === 'unlimited'; @@ -173,7 +215,6 @@ function Tiers({ const upTo = tier.upTo; const isIncluded = tier.cost === 0; - const unit = item.unit; return ( {formatCurrency( product.currency.toLowerCase(), - baseLineItem.cost, + primaryLineItem.cost, )} @@ -420,19 +420,21 @@ function PlanDetails({

- + 0}> + -
- - - +
+ + + - -
+ +
+
diff --git a/packages/billing/gateway/src/components/pricing-table.tsx b/packages/billing/gateway/src/components/pricing-table.tsx index 27f81bc98..457d9ec92 100644 --- a/packages/billing/gateway/src/components/pricing-table.tsx +++ b/packages/billing/gateway/src/components/pricing-table.tsx @@ -386,13 +386,16 @@ function PlanIntervalSwitcher( {props.intervals.map((plan, index) => { const selected = plan === props.interval; - const className = cn('focus:!ring-0 !outline-none', { - 'rounded-r-none border-r-transparent': index === 0, - 'rounded-l-none': index === props.intervals.length - 1, - ['hover:bg-muted']: !selected, - ['font-semibold cursor-default bg-muted hover:bg-muted hover:text-initial']: - selected, - }); + const className = cn( + 'focus:!ring-0 !outline-none animate-in transition-all fade-in', + { + 'rounded-r-none border-r-transparent': index === 0, + 'rounded-l-none': index === props.intervals.length - 1, + ['hover:text-current hover:bg-muted']: !selected, + ['font-semibold cursor-default hover:text-initial hover:bg-background border-primary']: + selected, + }, + ); return (