Update pricing table and billing configuration
Updated the pricing table component to display all line items for a plan, removed condition to exclude primary plan. Adjusted the type of a billing package in the sample configuration to be "metered" instead of "flat". Made related changes in line-item-details component to handle the changes in billing type and to fix the layout.
This commit is contained in:
@@ -33,7 +33,14 @@ export default createBillingSchema({
|
|||||||
id: 'price_1NNwYHI1i3VnbZTqI2UzaHIe',
|
id: 'price_1NNwYHI1i3VnbZTqI2UzaHIe',
|
||||||
name: 'Addon 2',
|
name: 'Addon 2',
|
||||||
cost: 9.99,
|
cost: 9.99,
|
||||||
type: 'flat' as const,
|
type: 'metered' as const,
|
||||||
|
unit: 'GB',
|
||||||
|
tiers: [
|
||||||
|
{
|
||||||
|
cost: 0.5,
|
||||||
|
upTo: 'unlimited',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
"includedUpTo": "Up to {{upTo}} {{unit}} included in the plan",
|
"includedUpTo": "Up to {{upTo}} {{unit}} included in the plan",
|
||||||
"fromPreviousTierUpTo": "for each {{unit}} for the next {{ upTo }} {{ unit }}",
|
"fromPreviousTierUpTo": "for each {{unit}} for the next {{ upTo }} {{ unit }}",
|
||||||
"andAbove": "above {{ previousTier }} {{ unit }}",
|
"andAbove": "above {{ previousTier }} {{ unit }}",
|
||||||
|
"forEveryUnit": "for every {{ unit }}",
|
||||||
"setupFee": "plus a {{ setupFee }} setup fee",
|
"setupFee": "plus a {{ setupFee }} setup fee",
|
||||||
"perUnitIncluded": "({{included}} included)",
|
"perUnitIncluded": "({{included}} included)",
|
||||||
"featuresLabel": "Features",
|
"featuresLabel": "Features",
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { LineItemSchema } from '@kit/billing';
|
|||||||
import { formatCurrency } from '@kit/shared/utils';
|
import { formatCurrency } from '@kit/shared/utils';
|
||||||
import { If } from '@kit/ui/if';
|
import { If } from '@kit/ui/if';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
import { cn } from '@kit/ui/utils';
|
||||||
|
|
||||||
const className =
|
const className = 'flex text-secondary-foreground items-center text-sm';
|
||||||
'flex text-secondary-foreground items-center justify-between text-sm';
|
|
||||||
|
|
||||||
export function LineItemDetails(
|
export function LineItemDetails(
|
||||||
props: React.PropsWithChildren<{
|
props: React.PropsWithChildren<{
|
||||||
@@ -62,7 +62,7 @@ export function LineItemDetails(
|
|||||||
|
|
||||||
const FlatFee = () => (
|
const FlatFee = () => (
|
||||||
<div className={'flex flex-col'}>
|
<div className={'flex flex-col'}>
|
||||||
<div className={className}>
|
<div className={cn(className, 'space-x-1')}>
|
||||||
<span className={'flex items-center space-x-1'}>
|
<span className={'flex items-center space-x-1'}>
|
||||||
<span className={'flex items-center space-x-1.5'}>
|
<span className={'flex items-center space-x-1.5'}>
|
||||||
<PlusSquare className={'w-3'} />
|
<PlusSquare className={'w-3'} />
|
||||||
@@ -72,21 +72,23 @@ export function LineItemDetails(
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>-</span>
|
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<If
|
<If
|
||||||
condition={props.selectedInterval}
|
condition={props.selectedInterval}
|
||||||
fallback={<Trans i18nKey={'billing:lifetime'} />}
|
fallback={<Trans i18nKey={'billing:lifetime'} />}
|
||||||
>
|
>
|
||||||
|
(
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey={`billing:billingInterval.${props.selectedInterval}`}
|
i18nKey={`billing:billingInterval.${props.selectedInterval}`}
|
||||||
/>
|
/>
|
||||||
|
)
|
||||||
</If>
|
</If>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className={'font-semibold'}>
|
<span>-</span>
|
||||||
|
|
||||||
|
<span className={'text-xs font-semibold'}>
|
||||||
{formatCurrency(props?.currency.toLowerCase(), item.cost)}
|
{formatCurrency(props?.currency.toLowerCase(), item.cost)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,6 +187,10 @@ export function LineItemDetails(
|
|||||||
return <PerSeat key={item.id} />;
|
return <PerSeat key={item.id} />;
|
||||||
|
|
||||||
case 'metered': {
|
case 'metered': {
|
||||||
|
if (item.cost > 0) {
|
||||||
|
return <FlatFee key={item.id} />;
|
||||||
|
}
|
||||||
|
|
||||||
return <Metered key={item.id} />;
|
return <Metered key={item.id} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,8 +209,9 @@ function Tiers({
|
|||||||
const unit = item.unit;
|
const unit = item.unit;
|
||||||
|
|
||||||
const tiers = item.tiers?.map((tier, index) => {
|
const tiers = item.tiers?.map((tier, index) => {
|
||||||
|
const tiersLength = item.tiers?.length ?? 0;
|
||||||
const previousTier = item.tiers?.[index - 1];
|
const previousTier = item.tiers?.[index - 1];
|
||||||
const isNoLimit = tier.upTo === 'unlimited';
|
const isLastTier = tier.upTo === 'unlimited';
|
||||||
|
|
||||||
const previousTierFrom =
|
const previousTierFrom =
|
||||||
previousTier?.upTo === 'unlimited'
|
previousTier?.upTo === 'unlimited'
|
||||||
@@ -223,20 +230,36 @@ function Tiers({
|
|||||||
>
|
>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
|
|
||||||
<If condition={isNoLimit}>
|
<If condition={isLastTier}>
|
||||||
<span className={'font-bold'}>
|
<span className={'font-bold'}>
|
||||||
{formatCurrency(currency.toLowerCase(), tier.cost)}
|
{formatCurrency(currency.toLowerCase(), tier.cost)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<If condition={tiersLength > 1}>
|
||||||
<Trans
|
<span>
|
||||||
i18nKey={'billing:andAbove'}
|
<Trans
|
||||||
values={{ unit, previousTier: (previousTierFrom as number) - 1 }}
|
i18nKey={'billing:andAbove'}
|
||||||
/>
|
values={{
|
||||||
</span>
|
unit,
|
||||||
|
previousTier: (previousTierFrom as number) - 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<If condition={tiersLength === 1}>
|
||||||
|
<span>
|
||||||
|
<Trans
|
||||||
|
i18nKey={'billing:forEveryUnit'}
|
||||||
|
values={{
|
||||||
|
unit,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</If>
|
||||||
</If>
|
</If>
|
||||||
|
|
||||||
<If condition={!isNoLimit}>
|
<If condition={!isLastTier}>
|
||||||
<If condition={isIncluded}>
|
<If condition={isIncluded}>
|
||||||
<span>
|
<span>
|
||||||
<Trans i18nKey={'billing:includedUpTo'} values={{ unit, upTo }} />
|
<Trans i18nKey={'billing:includedUpTo'} values={{ unit, upTo }} />
|
||||||
@@ -260,5 +283,5 @@ function Tiers({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <div className={'my-2.5 flex flex-col space-y-1.5'}>{tiers}</div>;
|
return <div className={'my-1 flex flex-col space-y-1.5'}>{tiers}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,9 +152,7 @@ function PricingItem(
|
|||||||
|
|
||||||
// we want to exclude the primary plan from the list of line items
|
// we want to exclude the primary plan from the list of line items
|
||||||
// since we are displaying the primary line item separately as the main price
|
// since we are displaying the primary line item separately as the main price
|
||||||
const lineItemsToDisplay = props.plan.lineItems.filter((item) => {
|
const lineItemsToDisplay = props.plan.lineItems;
|
||||||
return item.id !== lineItem?.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -218,10 +216,10 @@ function PricingItem(
|
|||||||
<If condition={props.plan.name}>
|
<If condition={props.plan.name}>
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
`animate-in slide-in-from-left-4 fade-in flex items-center space-x-0.5 text-sm capitalize`,
|
`animate-in slide-in-from-left-4 fade-in text-muted-foreground flex items-center space-x-0.5 text-sm capitalize`,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className={'text-muted-foreground'}>
|
<span>
|
||||||
<If
|
<If
|
||||||
condition={props.plan.interval}
|
condition={props.plan.interval}
|
||||||
fallback={<Trans i18nKey={'billing:lifetime'} />}
|
fallback={<Trans i18nKey={'billing:lifetime'} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user