mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-14 09:27:41 +00:00
feat: add Free subscription tier support (#8864)
## Summary Add frontend support for a Free subscription tier — login/signup page restructuring, telemetry instrumentation, and tier-aware billing gating. ## Changes - **What**: - Restructure login/signup pages: OAuth buttons promoted as primary sign-in method, email login available via progressive disclosure - Add Free tier badge on Google sign-up button with dynamic credit count from remote config - Add `FREE` subscription tier to type system (tier pricing, tier rank, registry types) - Add `isFreeTier` computed to `useSubscription()` - Disable credit top-up for Free tier users (dialogService, purchaseCredits, popover CTA) - Show subscription/upgrade dialog instead of top-up dialog when Free tier user hits out-of-credits - Add funnel telemetry: `trackLoginOpened`, enrich `trackSignupOpened` with `free_tier_badge_shown`, track email toggle clicks ## Review Focus - Tier gating logic: Free tier users should see "Upgrade" instead of "Add Credits" and never reach the top-up flow - Telemetry event design for Mixpanel funnel analysis - Progressive disclosure UX on login/signup pages ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8864-feat-add-Free-subscription-tier-support-3076d73d36508133b84ec5f0a67ccb03) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -2,7 +2,7 @@ import type { TierKey } from '@/platform/cloud/subscription/constants/tierPricin
|
||||
|
||||
export type BillingCycle = 'monthly' | 'yearly'
|
||||
|
||||
type RankedTierKey = Exclude<TierKey, 'founder'>
|
||||
type RankedTierKey = Exclude<TierKey, 'founder' | 'free'>
|
||||
type RankedPlanKey = `${BillingCycle}-${RankedTierKey}`
|
||||
|
||||
interface PlanDescriptor {
|
||||
@@ -28,7 +28,7 @@ const toRankedPlanKey = (
|
||||
tierKey: TierKey,
|
||||
billingCycle: BillingCycle
|
||||
): RankedPlanKey | null => {
|
||||
if (tierKey === 'founder') return null
|
||||
if (tierKey === 'founder' || tierKey === 'free') return null
|
||||
return `${billingCycle}-${tierKey}` as RankedPlanKey
|
||||
}
|
||||
|
||||
|
||||
67
src/platform/cloud/subscription/utils/tierBenefits.ts
Normal file
67
src/platform/cloud/subscription/utils/tierBenefits.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
getTierCredits,
|
||||
getTierFeatures
|
||||
} from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
import type { TierKey } from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
|
||||
type BenefitType = 'metric' | 'feature' | 'icon'
|
||||
|
||||
export interface TierBenefit {
|
||||
key: string
|
||||
type: BenefitType
|
||||
label: string
|
||||
value?: string
|
||||
icon?: string
|
||||
}
|
||||
|
||||
export function getCommonTierBenefits(
|
||||
key: TierKey,
|
||||
t: (key: string, params?: Record<string, unknown>) => string,
|
||||
n: (value: number) => string
|
||||
): TierBenefit[] {
|
||||
const benefits: TierBenefit[] = []
|
||||
const isFree = key === 'free'
|
||||
|
||||
if (isFree) {
|
||||
const credits = getTierCredits(key)
|
||||
if (credits !== null) {
|
||||
benefits.push({
|
||||
key: 'monthlyCredits',
|
||||
type: 'metric',
|
||||
value: n(credits),
|
||||
label: t('subscription.monthlyCreditsLabel')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
benefits.push({
|
||||
key: 'maxDuration',
|
||||
type: 'metric',
|
||||
value: t(`subscription.maxDuration.${key}`),
|
||||
label: t('subscription.maxDurationLabel')
|
||||
})
|
||||
|
||||
benefits.push({
|
||||
key: 'gpu',
|
||||
type: 'feature',
|
||||
label: t('subscription.gpuLabel')
|
||||
})
|
||||
|
||||
if (!isFree) {
|
||||
benefits.push({
|
||||
key: 'addCredits',
|
||||
type: 'feature',
|
||||
label: t('subscription.addCreditsLabel')
|
||||
})
|
||||
}
|
||||
|
||||
if (getTierFeatures(key).customLoRAs) {
|
||||
benefits.push({
|
||||
key: 'customLoRAs',
|
||||
type: 'feature',
|
||||
label: t('subscription.customLoRAsLabel')
|
||||
})
|
||||
}
|
||||
|
||||
return benefits
|
||||
}
|
||||
Reference in New Issue
Block a user