diff --git a/frontend/libs/components/pricing-modal/src/index.ts b/frontend/libs/components/pricing-modal/src/index.ts index a02f1fb21c..8d176a31ec 100644 --- a/frontend/libs/components/pricing-modal/src/index.ts +++ b/frontend/libs/components/pricing-modal/src/index.ts @@ -1,5 +1,4 @@ export * from "./lib/pricing-modal"; -export * from "./lib/pricing-config"; export * from "./lib/pricing-modal-store"; export * from "./lib/credits-modal"; export * from "./lib/credits-modal-store"; diff --git a/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts b/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts deleted file mode 100644 index 971777a4f1..0000000000 --- a/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts +++ /dev/null @@ -1,97 +0,0 @@ -export interface PricingFeature { - text: string; - included: boolean; - tooltip?: string; -} - -export interface PricingTier { - id: string; - name: string; - monthlyPrice: number; - yearlyPrice: number; - originalMonthlyPrice?: number; - originalYearlyPrice?: number; - monthlyPriceId?: string; - yearlyPriceId?: string; - features: PricingFeature[]; - isPopular?: boolean; - colorScheme: "dark" | "green" | "purple" | "orange"; -} - -export const pricingConfig = { - header: { - title: "Purchase a subscription", - subtitle: - "Upgrade to gain access to Pro features and generate more, faster.", - }, - yearlyDiscount: 20, - tiers: [ - { - id: "free", - name: "Free", - monthlyPrice: 0, - yearlyPrice: 0, - features: [ - { text: "Free daily generations", included: true }, - { text: "Limited access to ArtCraft tools", included: true }, - ], - colorScheme: "dark" as const, - }, - { - //id: "plus", - //name: "Plus", - id: "artcraft_basic", - name: "Basic", - monthlyPrice: 8, - yearlyPrice: 96, - originalMonthlyPrice: 10, - originalYearlyPrice: 120, - monthlyPriceId: "price_1234567890abcdef", //dummy - yearlyPriceId: "price_abcdef1234567890", //dummy - features: [ - { text: "~1,010 Flux images", included: true }, - { text: "~36,000 real-time images", included: true }, - { text: "~180 enhanced images", included: true }, - { text: "~6 training jobs", included: true }, - { text: "Commercial license", included: true }, - ], - colorScheme: "green" as const, - }, - { - id: "artcraft_pro", - name: "Pro", - monthlyPrice: 28, - yearlyPrice: 336, - originalMonthlyPrice: 35, - originalYearlyPrice: 420, - monthlyPriceId: "price_fedcba0987654321", //dummy - yearlyPriceId: "price_123456789fedcba0", //dummy - features: [ - { text: "~5,048 Flux images", included: true }, - { text: "~180,000 real-time images", included: true }, - { text: "~900 enhanced images", included: true }, - { text: "~30 training jobs", included: true }, - { text: "Commercial license", included: true }, - ], - colorScheme: "purple" as const, - }, - { - id: "artcraft_max", - name: "Max", - monthlyPrice: 48, - yearlyPrice: 576, - originalMonthlyPrice: 60, - originalYearlyPrice: 720, - monthlyPriceId: "price_9876543210fedcba", //dummy - yearlyPriceId: "price_abcdef9876543210", //dummy - features: [ - { text: "~15,142 Flux images", included: true }, - { text: "~540,000 real-time images", included: true }, - { text: "~2,700 enhanced images", included: true }, - { text: "~90 training jobs", included: true }, - { text: "Commercial license", included: true }, - ], - colorScheme: "orange" as const, - }, - ] as PricingTier[], -}; diff --git a/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx b/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx index 382e385c7c..2f158745d4 100644 --- a/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx +++ b/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx @@ -2,16 +2,25 @@ import { Modal } from "@storyteller/ui-modal"; import { Button } from "@storyteller/ui-button"; import { useState } from "react"; import { twMerge } from "tailwind-merge"; -import { pricingConfig, PricingTier } from "./pricing-config"; import { usePricingModalStore } from "./pricing-modal-store"; import { TabSelector } from "@storyteller/ui-tab-selector"; import { invoke } from "@tauri-apps/api/core"; +import { SUBSCRIPTION_PLANS, SubscriptionPlanDetails } from "@storyteller/subscription"; const billingTabs = [ { id: "yearly", label: "Yearly" }, { id: "monthly", label: "Monthly" }, ]; +const pricingConfig = { + header: { + title: "Purchase a subscription", + subtitle: + "Upgrade to gain access to Pro features and generate more, faster.", + }, + yearlyDiscount: 20, +} + interface PricingModalProps { currentPlanId?: string; hasActiveSubscription?: boolean; @@ -30,32 +39,21 @@ export function PricingModal({ const [billingType, setBillingType] = useState("yearly"); const isYearly = billingType === "yearly"; - const handleUpgrade = async (tierId: string) => { - // TODO: Implement Stripe checkout - const tier = pricingConfig.tiers.find((t) => t.id === tierId); - //const priceId = isYearly ? tier?.yearlyPriceId : tier?.monthlyPriceId; - - const planName = tier?.id; + const handleUpgrade = async (tierSlug: string) => { + const tier = SUBSCRIPTION_PLANS.find((t) => t.slug === tierSlug); + const planSlug = tier?.slug; const cadence = isYearly? "yearly" : "monthly"; - if (planName === "free") { + if (planSlug === "free") { return; } await invoke("storyteller_open_subscription_purchase_command", { request: { - plan:planName, + plan: planSlug, cadence: cadence, } }); - - // Example Stripe checkout implementation: - // await stripe.redirectToCheckout({ - // lineItems: [{ price: priceId, quantity: 1 }], - // mode: 'subscription', - // successUrl: `${window.location.origin}/success`, - // cancelUrl: `${window.location.origin}/cancel`, - // }); }; const handleManageSubscription = () => { @@ -69,8 +67,8 @@ export function PricingModal({ return tierId === activePlanId; }; - const getButtonText = (tier: PricingTier) => { - if (isCurrentPlan(tier.id)) { + const getButtonText = (tier: SubscriptionPlanDetails) => { + if (isCurrentPlan(tier.slug)) { return "Current Plan"; } @@ -89,7 +87,7 @@ export function PricingModal({ }; const getColorSchemeClasses = ( - colorScheme: PricingTier["colorScheme"], + colorScheme: SubscriptionPlanDetails["colorScheme"], isCurrent: boolean ) => { const baseClasses = @@ -136,8 +134,8 @@ export function PricingModal({ } }; - const formatPrice = (tier: PricingTier) => { - if (tier.monthlyPrice === 0) { + const formatPrice = (plan: SubscriptionPlanDetails) => { + if (plan.monthlyPrice === 0) { return { current: "$0", original: null, @@ -145,9 +143,9 @@ export function PricingModal({ } if (isYearly) { - const discountedMonthlyPrice = Math.round(tier.yearlyPrice / 12); - const originalMonthlyPrice = tier.originalYearlyPrice - ? Math.round(tier.originalYearlyPrice / 12) + const discountedMonthlyPrice = Math.round(plan.yearlyPrice / 12); + const originalMonthlyPrice = plan.originalYearlyPrice + ? Math.round(plan.originalYearlyPrice / 12) : null; return { @@ -155,7 +153,7 @@ export function PricingModal({ original: originalMonthlyPrice ? `$${originalMonthlyPrice}` : null, }; } else { - const monthlyPrice = tier.originalMonthlyPrice || tier.monthlyPrice; + const monthlyPrice = plan.originalMonthlyPrice || plan.monthlyPrice; return { current: `$${monthlyPrice}`, @@ -204,19 +202,19 @@ export function PricingModal({ {/* Pricing Tiers */}
- {pricingConfig.tiers.map((tier) => { - const pricing = formatPrice(tier); + {SUBSCRIPTION_PLANS.map((plan) => { + const pricing = formatPrice(plan); return (
{/* Current Plan Badge */} - {isCurrentPlan(tier.id) && ( + {isCurrentPlan(plan.slug) && (
Active
@@ -225,7 +223,7 @@ export function PricingModal({ {/* Tier Header */}

- {tier.name} + {plan.name}

{pricing.original && ( @@ -246,7 +244,7 @@ export function PricingModal({ {/* Features */}
- {tier.features.map((feature, index) => ( + {plan.features.map((feature, index) => (
handleUpgrade(tier.id)} - disabled={isCurrentPlan(tier.id)} + onClick={() => handleUpgrade(plan.slug)} + disabled={isCurrentPlan(plan.slug)} className="w-full bg-white text-black hover:bg-white/90 h-12 rounded-xl" > - {getButtonText(tier)} + {getButtonText(plan)}
);