Skip to content

Commit 6ac7b4d

Browse files
committed
fix nullable fees in BillingPlan
1 parent 4731af2 commit 6ac7b4d

File tree

12 files changed

+55
-32
lines changed

12 files changed

+55
-32
lines changed

packages/clerk-js/src/core/resources/BillingPlan.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export class BillingPlan extends BaseResource implements BillingPlanResource {
88
id!: string;
99
name!: string;
1010
fee!: BillingMoneyAmount;
11-
annualFee!: BillingMoneyAmount;
12-
annualMonthlyFee!: BillingMoneyAmount;
11+
annualFee: BillingMoneyAmount | null = null;
12+
annualMonthlyFee: BillingMoneyAmount | null = null;
1313
description!: string;
1414
isDefault!: boolean;
1515
isRecurring!: boolean;
@@ -32,11 +32,17 @@ export class BillingPlan extends BaseResource implements BillingPlanResource {
3232
return this;
3333
}
3434

35+
console.log('data', {
36+
fee: data.fee,
37+
annual_fee: data.annual_fee,
38+
annual_monthly_fee: data.annual_monthly_fee,
39+
});
40+
3541
this.id = data.id;
3642
this.name = data.name;
3743
this.fee = billingMoneyAmountFromJSON(data.fee);
38-
this.annualFee = billingMoneyAmountFromJSON(data.annual_fee);
39-
this.annualMonthlyFee = billingMoneyAmountFromJSON(data.annual_monthly_fee);
44+
this.annualFee = data.annual_fee ? billingMoneyAmountFromJSON(data.annual_fee) : null;
45+
this.annualMonthlyFee = data.annual_monthly_fee ? billingMoneyAmountFromJSON(data.annual_monthly_fee) : null;
4046
this.description = data.description;
4147
this.isDefault = data.is_default;
4248
this.isRecurring = data.is_recurring;

packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ export const CheckoutForm = withCardStateProvider(() => {
3939
const showPastDue = !!totals.pastDue?.amount && totals.pastDue.amount > 0;
4040
const showDowngradeInfo = !isImmediatePlanChange;
4141

42-
const fee = planPeriod === 'month' ? plan.fee : plan.annualMonthlyFee;
42+
const fee =
43+
planPeriod === 'month'
44+
? plan.fee
45+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
46+
plan.annualMonthlyFee!;
4347

4448
return (
4549
<Drawer.Body>

packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,10 @@ function PaymentAttemptBody({ subscriptionItem }: { subscriptionItem: BillingSub
215215
}
216216

217217
const fee =
218-
subscriptionItem.planPeriod === 'month' ? subscriptionItem.plan.fee : subscriptionItem.plan.annualMonthlyFee;
218+
subscriptionItem.planPeriod === 'month'
219+
? subscriptionItem.plan.fee
220+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
221+
subscriptionItem.plan.annualMonthlyFee!;
219222

220223
return (
221224
<Box

packages/clerk-js/src/ui/components/Plans/PlanDetails.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ const Header = React.forwardRef<HTMLDivElement, HeaderProps>((props, ref) => {
227227
const { plan, closeSlot, planPeriod, setPlanPeriod } = props;
228228

229229
const fee = useMemo(() => {
230-
if (plan.annualMonthlyFee.amount <= 0) {
230+
if (!plan.annualMonthlyFee) {
231231
return plan.fee;
232232
}
233233
return planPeriod === 'annual' ? plan.annualMonthlyFee : plan.fee;
@@ -333,7 +333,7 @@ const Header = React.forwardRef<HTMLDivElement, HeaderProps>((props, ref) => {
333333
</>
334334
</Flex>
335335

336-
{plan.annualMonthlyFee.amount > 0 ? (
336+
{plan.annualMonthlyFee ? (
337337
<Box
338338
elementDescriptor={descriptors.planDetailPeriodToggle}
339339
sx={t => ({

packages/clerk-js/src/ui/components/PricingTable/PricingTableDefault.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,17 @@ const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>((props, ref
282282
const { plan, isCompact, planPeriod, setPlanPeriod, badge } = props;
283283
const { name, annualMonthlyFee } = plan;
284284

285-
const planSupportsAnnual = annualMonthlyFee.amount > 0;
285+
const planSupportsAnnual = Boolean(annualMonthlyFee);
286286

287287
const fee = React.useMemo(() => {
288288
if (!planSupportsAnnual) {
289289
return plan.fee;
290290
}
291-
return planPeriod === 'annual' ? plan.annualMonthlyFee : plan.fee;
291+
292+
return planPeriod === 'annual'
293+
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
294+
plan.annualMonthlyFee!
295+
: plan.fee;
292296
}, [planSupportsAnnual, planPeriod, plan.fee, plan.annualMonthlyFee]);
293297

294298
const feeFormatted = React.useMemo(() => {

packages/clerk-js/src/ui/components/PricingTable/PricingTableMatrix.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function PricingTableMatrix({
6060

6161
const gridTemplateColumns = React.useMemo(() => `repeat(${plans.length + 1}, minmax(9.375rem,1fr))`, [plans.length]);
6262

63-
const renderBillingCycleControls = React.useMemo(() => plans.some(plan => plan.annualMonthlyFee.amount > 0), [plans]);
63+
const renderBillingCycleControls = React.useMemo(() => plans.some(plan => Boolean(plan.annualMonthlyFee)), [plans]);
6464

6565
const getAllFeatures = React.useMemo(() => {
6666
const featuresSet = new Set<string>();
@@ -156,12 +156,11 @@ export function PricingTableMatrix({
156156
</Box>
157157
{plans.map(plan => {
158158
const highlight = plan.slug === highlightedPlan;
159-
const planFee =
160-
plan.annualMonthlyFee.amount <= 0
161-
? plan.fee
162-
: planPeriod === 'annual'
163-
? plan.annualMonthlyFee
164-
: plan.fee;
159+
const planFee = !plan.annualMonthlyFee
160+
? plan.fee
161+
: planPeriod === 'annual'
162+
? plan.annualMonthlyFee
163+
: plan.fee;
165164

166165
return (
167166
<Box
@@ -253,7 +252,7 @@ export function PricingTableMatrix({
253252
})}
254253
localizationKey={localizationKeys('billing.month')}
255254
/>
256-
{plan.annualMonthlyFee.amount > 0 ? (
255+
{plan.annualMonthlyFee ? (
257256
<Box
258257
elementDescriptor={descriptors.pricingTableMatrixFeePeriodNotice}
259258
sx={[

packages/clerk-js/src/ui/components/PricingTable/utils/pricing-footer-state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const valueResolution = (params: UsePricingFooterStateParams): [boolean, boolean
3434
// Active subscription
3535
if (subscription.status === 'active') {
3636
const isCanceled = !!subscription.canceledAt;
37-
const isSwitchingPaidPeriod = planPeriod !== subscription.planPeriod && plan.annualMonthlyFee.amount > 0;
37+
const isSwitchingPaidPeriod = planPeriod !== subscription.planPeriod && Boolean(plan.annualMonthlyFee);
3838
const isActiveFreeTrial = plan.freeTrialEnabled && subscription.isFreeTrial;
3939

4040
if (isCanceled || isSwitchingPaidPeriod) {

packages/clerk-js/src/ui/components/SubscriptionDetails/index.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ const SubscriptionCardActions = ({ subscription }: { subscription: BillingSubscr
374374
const canManageBilling = subscriberType === 'user' || canOrgManageBilling;
375375

376376
const isSwitchable =
377-
((subscription.planPeriod === 'month' && subscription.plan.annualMonthlyFee.amount > 0) ||
377+
((subscription.planPeriod === 'month' && Boolean(subscription.plan.annualMonthlyFee)) ||
378378
subscription.planPeriod === 'annual') &&
379379
subscription.status !== 'past_due';
380380
const isFree = isFreePlan(subscription.plan);
@@ -409,8 +409,10 @@ const SubscriptionCardActions = ({ subscription }: { subscription: BillingSubscr
409409
label:
410410
subscription.planPeriod === 'month'
411411
? localizationKeys('billing.switchToAnnualWithAnnualPrice', {
412-
price: normalizeFormatted(subscription.plan.annualFee.amountFormatted),
413-
currency: subscription.plan.annualFee.currencySymbol,
412+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
413+
price: normalizeFormatted(subscription.plan.annualFee!.amountFormatted),
414+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
415+
currency: subscription.plan.annualFee!.currencySymbol,
414416
})
415417
: localizationKeys('billing.switchToMonthlyWithPrice', {
416418
price: normalizeFormatted(subscription.plan.fee.amountFormatted),
@@ -480,7 +482,11 @@ const SubscriptionCardActions = ({ subscription }: { subscription: BillingSubscr
480482
const SubscriptionCard = ({ subscription }: { subscription: BillingSubscriptionItemResource }) => {
481483
const { t } = useLocalizations();
482484

483-
const fee = subscription.planPeriod === 'month' ? subscription.plan.fee : subscription.plan.annualFee;
485+
const fee =
486+
subscription.planPeriod === 'month'
487+
? subscription.plan.fee
488+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
489+
subscription.plan.annualFee!;
484490

485491
return (
486492
<Col

packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ export function SubscriptionsList({
153153
}
154154

155155
function SubscriptionRow({ subscription, length }: { subscription: BillingSubscriptionItemResource; length: number }) {
156-
const fee = subscription.planPeriod === 'annual' ? subscription.plan.annualFee : subscription.plan.fee;
156+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
157+
const fee = subscription.planPeriod === 'annual' ? subscription.plan.annualFee! : subscription.plan.fee;
157158
const { captionForSubscription } = usePlansContext();
158159

159160
const feeFormatted = useMemo(() => {

packages/clerk-js/src/ui/contexts/components/Plans.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ export const usePlansContext = () => {
213213
const subscription =
214214
sub ?? (plan ? activeOrUpcomingSubscriptionWithPlanPeriod(plan, selectedPlanPeriod) : undefined);
215215
let _selectedPlanPeriod = selectedPlanPeriod;
216-
const isEligibleForSwitchToAnnual = (plan?.annualMonthlyFee.amount ?? 0) > 0;
216+
const isEligibleForSwitchToAnnual = Boolean(plan?.annualMonthlyFee);
217217

218218
if (_selectedPlanPeriod === 'annual' && !isEligibleForSwitchToAnnual) {
219219
_selectedPlanPeriod = 'month';
@@ -326,7 +326,7 @@ export const usePlansContext = () => {
326326
clerk.__internal_openCheckout({
327327
planId: plan.id,
328328
// if the plan doesn't support annual, use monthly
329-
planPeriod: planPeriod === 'annual' && plan.annualMonthlyFee.amount === 0 ? 'month' : planPeriod,
329+
planPeriod: planPeriod === 'annual' && Boolean(plan.annualMonthlyFee) ? 'month' : planPeriod,
330330
for: subscriberType,
331331
onSubscriptionComplete: () => {
332332
revalidateAll();

0 commit comments

Comments
 (0)