Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
type KiloClawSignupDisplay,
type KiloPassUpsellActivationPreview,
} from './billing-types';
import { KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF } from '@/lib/kilo-pass/constants';
import { dayjs } from '@/lib/kilo-pass/dayjs';

type Cadence = 'monthly' | 'yearly';
type Tier = '19' | '49' | '199';
Expand Down Expand Up @@ -293,8 +291,6 @@ function HostingOnlyPlanCard({

function CreditsHowItWorks() {
const [open, setOpen] = useState(false);
const showTwoMonthPromo = dayjs().utc().isBefore(KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF);

return (
<div className="border-border/50 mb-3.5 overflow-hidden rounded-lg border">
<button
Expand All @@ -320,15 +316,6 @@ function CreditsHowItWorks() {
expire monthly.
</span>
</div>
{showTwoMonthPromo ? (
<div className="text-muted-foreground flex items-start gap-2 py-0.5 text-xs">
<Check className="mt-0.5 h-3.5 w-3.5 shrink-0 text-emerald-400" />
<span>
First-time subscribers receive <span className="text-emerald-300">50%</span> free
bonus credits for the first two months.
</span>
</div>
) : null}
</div>
)}
</div>
Expand Down
13 changes: 0 additions & 13 deletions apps/web/src/app/(app)/claw/components/billing/WelcomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import {
type KiloClawSignupDisplay,
type KiloPassUpsellActivationPreview,
} from './billing-types';
import { KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF } from '@/lib/kilo-pass/constants';
import { dayjs } from '@/lib/kilo-pass/dayjs';

type Cadence = 'monthly' | 'yearly';
type Tier = '19' | '49' | '199';
Expand Down Expand Up @@ -286,8 +284,6 @@ function HostingOnlyPlanCard({

function CreditsHowItWorks() {
const [open, setOpen] = useState(false);
const showTwoMonthPromo = dayjs().utc().isBefore(KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF);

return (
<div className="border-border/50 mb-3.5 overflow-hidden rounded-lg border">
<button
Expand All @@ -313,15 +309,6 @@ function CreditsHowItWorks() {
expire monthly.
</span>
</div>
{showTwoMonthPromo ? (
<div className="text-muted-foreground flex items-start gap-2 py-0.5 text-xs">
<Check className="mt-0.5 h-3.5 w-3.5 shrink-0 text-emerald-400" />
<span>
First-time subscribers receive <span className="text-emerald-300">50%</span> free
bonus credits for the first two months.
</span>
</div>
) : null}
</div>
)}
</div>
Expand Down
10 changes: 0 additions & 10 deletions apps/web/src/components/profile/ProfileKiloPassSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ import { KiloPassLoadingCard } from '@/components/profile/kilo-pass/KiloPassLoad
import { KiloPassSubscribeCard } from '@/components/profile/kilo-pass/KiloPassSubscribeCard';
import { isStripeSubscriptionEnded } from '@/lib/kilo-pass/stripe-subscription-status';
import { recommendKiloPassTierFromAverageMonthlyUsageUsd } from '@/lib/kilo-pass/recommend-tier';
import { KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF } from '@/lib/kilo-pass/constants';
import { dayjs } from '@/lib/kilo-pass/dayjs';

function getShowKiloPassTwoMonthPromo(showFirstMonthPromo: boolean): boolean {
return (
showFirstMonthPromo && dayjs().utc().isBefore(KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF)
);
}

export function ProfileKiloPassSection() {
const trpc = useTRPC();
Expand Down Expand Up @@ -65,7 +57,6 @@ export function ProfileKiloPassSection() {
if (!activeSubscription) {
const pending = checkoutMutation.isPending;
const showFirstMonthPromo = query.data.isEligibleForFirstMonthPromo;
const showSecondMonthPromo = getShowKiloPassTwoMonthPromo(showFirstMonthPromo);
const averageMonthlyUsageUsd = averageMonthlyUsageQuery.data?.averageMonthlyUsageUsd;
const recommendedTier =
typeof averageMonthlyUsageUsd === 'number'
Expand All @@ -78,7 +69,6 @@ export function ProfileKiloPassSection() {
setCadence={setCadence}
pending={pending}
showFirstMonthPromo={showFirstMonthPromo}
showSecondMonthPromo={showSecondMonthPromo}
recommendedTier={recommendedTier}
onSelectTier={tier => checkoutMutation.mutate({ tier, cadence })}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ function computeRefillRowModel(params: {
tier: baseTier,
streakMonths: Math.max(1, params.subscription.currentStreakMonths + 1),
isFirstTimeSubscriberEver: params.subscription.isFirstTimeSubscriberEver,
subscriptionStartedAtIso: params.subscription.startedAt,
})
: null;
if (typeof bonusUsd !== 'number' || bonusUsd <= 0) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,12 @@ const clampMonth = (month: number) => Math.min(12, Math.max(1, Math.round(month)
export function KiloPassBonusRampDialog(props: {
tier: KiloPassTier;
showFirstMonthPromo?: boolean;
showSecondMonthPromo?: boolean;
streakMonths?: number;
showSlider?: boolean;
subscriptionStartedAtIso?: string;
}) {
const {
tier,
showFirstMonthPromo = false,
showSecondMonthPromo = false,
streakMonths,
showSlider = true,
subscriptionStartedAtIso,
} = props;
const { tier, showFirstMonthPromo = false, streakMonths, showSlider = true } = props;
const [open, setOpen] = useState(false);

const fallbackSubscriptionStartedAtIso = useMemo(() => {
const now = new Date();
now.setSeconds(0, 0);
return now.toISOString();
}, []);

const resolvedSubscriptionStartedAtIso =
subscriptionStartedAtIso ?? fallbackSubscriptionStartedAtIso;
const resolvedMonth =
typeof streakMonths === 'number' && !Number.isNaN(streakMonths) ? clampMonth(streakMonths) : 1;
const [sliderMonth, setSliderMonth] = useState(resolvedMonth);
Expand All @@ -60,7 +43,6 @@ export function KiloPassBonusRampDialog(props: {
tier,
streakMonths: effectiveMonth,
isFirstTimeSubscriberEver: showFirstMonthPromo,
subscriptionStartedAtIso: resolvedSubscriptionStartedAtIso,
});

const totalBonusUsd = useMemo(
Expand All @@ -71,18 +53,10 @@ export function KiloPassBonusRampDialog(props: {
tier,
streakMonths: index + 1,
isFirstTimeSubscriberEver: showFirstMonthPromo,
subscriptionStartedAtIso: resolvedSubscriptionStartedAtIso,
})
).reduce((total, percent) => total + config.monthlyPriceUsd * percent, 0)
: 0,
[
config.monthlyPriceUsd,
effectiveMonth,
showFirstMonthPromo,
showSlider,
resolvedSubscriptionStartedAtIso,
tier,
]
[config.monthlyPriceUsd, effectiveMonth, showFirstMonthPromo, showSlider, tier]
);

return (
Expand Down Expand Up @@ -172,9 +146,7 @@ export function KiloPassBonusRampDialog(props: {

{showPromoCallout && (
<div className="rounded-lg border border-emerald-500/20 bg-emerald-500/10 px-3 py-2 text-emerald-100">
As a new subscriber, your{' '}
<strong>first {showSecondMonthPromo ? '2 paid months' : 'paid month'}</strong> get a
one-time promo of{' '}
As a new subscriber, your <strong>first paid month</strong> gets a one-time promo of{' '}
<strong>
+{formatPercent(KILO_PASS_FIRST_MONTH_PROMO_BONUS_PERCENT)} free bonus credits
</strong>{' '}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { KiloPassCadence } from '@/lib/kilo-pass/enums';
import type { KiloPassTier } from '@/lib/kilo-pass/enums';
import {
KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF,
KILO_PASS_TIER_CONFIG,
} from '@/lib/kilo-pass/constants';
import { KILO_PASS_TIER_CONFIG } from '@/lib/kilo-pass/constants';
import { cn } from '@/lib/utils';
import { formatIsoDateString_UsaDateOnlyFormat } from '@/lib/utils';

import { KiloPassTierCard } from './KiloPassTierCard';

Expand All @@ -21,7 +17,6 @@ export function KiloPassSubscribeCard(props: {
setCadence: (cadence: KiloPassCadence) => void;
pending: boolean;
showFirstMonthPromo?: boolean;
showSecondMonthPromo: boolean;
showHeader?: boolean;
className?: string;
contentClassName?: string;
Expand All @@ -33,7 +28,6 @@ export function KiloPassSubscribeCard(props: {
setCadence,
pending,
showFirstMonthPromo = false,
showSecondMonthPromo,
showHeader = true,
className,
contentClassName,
Expand All @@ -43,14 +37,9 @@ export function KiloPassSubscribeCard(props: {

const tiers = Object.keys(KILO_PASS_TIER_CONFIG) as KiloPassTier[];

const promoCutoffLabel = formatIsoDateString_UsaDateOnlyFormat(
KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF.toISOString()
);
const monthlyPromoDescription =
cadence === KiloPassCadence.Monthly && showFirstMonthPromo
? showSecondMonthPromo
? `First-time subscribers receive 50% free bonus credits for the first two months when they start before ${promoCutoffLabel}.`
: 'First-time subscribers receive 50% free bonus credits for the first month.'
? 'First-time subscribers receive 50% free bonus credits for the first month.'
: null;
const cadenceOptions = [
{ value: KiloPassCadence.Monthly, label: 'Monthly' },
Expand Down Expand Up @@ -121,7 +110,6 @@ export function KiloPassSubscribeCard(props: {
cadence={cadence}
pending={pending}
showFirstMonthPromo={showFirstMonthPromo}
showSecondMonthPromo={showSecondMonthPromo}
isRecommended={recommendedTier != null && tier === recommendedTier}
onSelect={onSelectTier}
/>
Expand Down
21 changes: 4 additions & 17 deletions apps/web/src/components/profile/kilo-pass/KiloPassTierCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,10 @@ export function KiloPassTierCard(props: {
cadence: KiloPassCadence;
pending: boolean;
showFirstMonthPromo?: boolean;
showSecondMonthPromo?: boolean;
isRecommended: boolean;
onSelect: (tier: KiloPassTier) => void;
}) {
const {
tier,
cadence,
pending,
showFirstMonthPromo = false,
showSecondMonthPromo = false,
isRecommended,
onSelect,
} = props;
const { tier, cadence, pending, showFirstMonthPromo = false, isRecommended, onSelect } = props;
const config = KILO_PASS_TIER_CONFIG[tier];
const handleSelect = () => {
if (pending) return;
Expand Down Expand Up @@ -99,17 +90,13 @@ export function KiloPassTierCard(props: {
</span>{' '}
free bonus credits
</span>
<KiloPassBonusRampDialog
tier={tier}
showFirstMonthPromo={showFirstMonthPromo}
showSecondMonthPromo={showSecondMonthPromo}
/>
<KiloPassBonusRampDialog tier={tier} showFirstMonthPromo={showFirstMonthPromo} />
</div>

{showFirstMonthPromo && (
<div className="text-xs leading-5 text-emerald-300">
{showSecondMonthPromo ? 'First 2 months:' : 'First month:'} +
{formatPercent(KILO_PASS_FIRST_MONTH_PROMO_BONUS_PERCENT)} free bonus credits
First month: +{formatPercent(KILO_PASS_FIRST_MONTH_PROMO_BONUS_PERCENT)} free bonus
credits
</div>
)}
</>
Expand Down
15 changes: 0 additions & 15 deletions apps/web/src/components/subscriptions/kilo-pass/KiloPassDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,10 @@ export function KiloPassDetail() {
tier: subscription.tier,
streakMonths: Math.max(1, subscription.currentStreakMonths),
isFirstTimeSubscriberEver: subscription.isFirstTimeSubscriberEver,
subscriptionStartedAtIso: subscription.startedAt,
});
return promoPercent === KILO_PASS_FIRST_MONTH_PROMO_BONUS_PERCENT;
}, [subscription]);

const showSecondMonthPromoInDialog = useMemo(() => {
if (!subscription || subscription.cadence !== 'monthly') return false;
if (subscription.currentStreakMonths > 2) return false;
const month2Percent = computeMonthlyCadenceBonusPercent({
tier: subscription.tier,
streakMonths: 2,
isFirstTimeSubscriberEver: subscription.isFirstTimeSubscriberEver,
subscriptionStartedAtIso: subscription.startedAt,
});
return month2Percent === KILO_PASS_FIRST_MONTH_PROMO_BONUS_PERCENT;
}, [subscription]);

async function refreshData() {
await Promise.all([
queryClient.invalidateQueries({ queryKey: trpc.kiloPass.getState.queryKey() }),
Expand Down Expand Up @@ -262,9 +249,7 @@ export function KiloPassDetail() {
<KiloPassBonusRampDialog
tier={subscription.tier}
showFirstMonthPromo={showFirstMonthPromoInDialog}
showSecondMonthPromo={showSecondMonthPromoInDialog}
streakMonths={subscription.currentStreakMonths}
subscriptionStartedAtIso={subscription.startedAt ?? undefined}
/>
</CardTitle>
</CardHeader>
Expand Down
10 changes: 0 additions & 10 deletions apps/web/src/components/subscriptions/kilo-pass/KiloPassGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { useState } from 'react';
import { toast } from 'sonner';
import { Crown } from 'lucide-react';
import { useTRPC } from '@/lib/trpc/utils';
import { KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF } from '@/lib/kilo-pass/constants';
import { dayjs } from '@/lib/kilo-pass/dayjs';
import { KiloPassCadence } from '@/lib/kilo-pass/enums';
import type { KiloPassTier } from '@/lib/kilo-pass/enums';
import { recommendKiloPassTierFromAverageMonthlyUsageUsd } from '@/lib/kilo-pass/recommend-tier';
Expand All @@ -27,12 +25,6 @@ import {
getKiloPassSubscriptionDisplayModel,
} from './KiloPassDetail.logic';

function getShowKiloPassTwoMonthPromo(showFirstMonthPromo: boolean): boolean {
return (
showFirstMonthPromo && dayjs().utc().isBefore(KILO_PASS_MONTHLY_FIRST_2_MONTHS_PROMO_CUTOFF)
);
}

export function KiloPassGroup({
showTerminal,
accordionValue,
Expand Down Expand Up @@ -73,7 +65,6 @@ export function KiloPassGroup({
}

const showFirstMonthPromo = query.data?.isEligibleForFirstMonthPromo ?? false;
const showSecondMonthPromo = getShowKiloPassTwoMonthPromo(showFirstMonthPromo);
const averageMonthlyUsageUsd = averageMonthlyUsageQuery.data?.averageMonthlyUsageUsd;
const recommendedTier =
typeof averageMonthlyUsageUsd === 'number'
Expand Down Expand Up @@ -134,7 +125,6 @@ export function KiloPassGroup({
setCadence={setCadence}
pending={checkout.isPending}
showFirstMonthPromo={showFirstMonthPromo}
showSecondMonthPromo={showSecondMonthPromo}
recommendedTier={recommendedTier}
onSelectTier={tier => void startCheckout(tier)}
showHeader={false}
Expand Down
Loading
Loading