From 474904ddd7787db9ad45bbd54cdde9ae5464233e Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 1 Sep 2025 08:43:24 -0400 Subject: [PATCH] open pricing window to stripe --- .../api_clients/storyteller_client/src/lib.rs | 1 + .../create_subscription_checkout.rs | 18 +++ .../src/stripe_artcraft/mod.rs | 1 + crates/desktop/artcraft/src/lib.rs | 4 +- .../src/services/storyteller/commands/mod.rs | 1 + .../storyteller_open_billing_command.rs | 71 +++++++++++ .../artcraft/src/services/storyteller/mod.rs | 4 +- .../src/services/storyteller/windows/mod.rs | 1 + .../open_storyteller_billing_window.rs | 114 ++++++++++++++++++ .../public/api/artcraft_api_defs/src/lib.rs | 3 +- .../create_subscription_checkout.rs | 39 ++++++ .../src/stripe_artcraft/mod.rs | 1 + .../configs/stripe_artcraft_metadata_keys.rs | 2 - .../endpoints/stripe_artcraft/checkout/mod.rs | 2 +- ..._subscription_checkout_session_handler.rs} | 45 +------ .../routes/add_stripe_artcraft_routes.rs | 2 +- .../components/pricing-modal/package.json | 3 + .../pricing-modal/src/lib/pricing-config.ts | 6 +- .../pricing-modal/src/lib/pricing-modal.tsx | 22 ++-- .../components/pricing-modal/tsconfig.json | 3 + .../pricing-modal/tsconfig.lib.json | 3 + 21 files changed, 287 insertions(+), 59 deletions(-) create mode 100644 crates/api_clients/storyteller_client/src/stripe_artcraft/create_subscription_checkout.rs create mode 100644 crates/api_clients/storyteller_client/src/stripe_artcraft/mod.rs create mode 100644 crates/desktop/artcraft/src/services/storyteller/commands/mod.rs create mode 100644 crates/desktop/artcraft/src/services/storyteller/commands/storyteller_open_billing_command.rs create mode 100644 crates/desktop/artcraft/src/services/storyteller/windows/mod.rs create mode 100644 crates/desktop/artcraft/src/services/storyteller/windows/open_storyteller_billing_window.rs create mode 100644 crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/create_subscription_checkout.rs create mode 100644 crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/mod.rs rename crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/{stripe_artcraft_create_checkout_session_handler.rs => stripe_artcraft_create_subscription_checkout_session_handler.rs} (87%) diff --git a/crates/api_clients/storyteller_client/src/lib.rs b/crates/api_clients/storyteller_client/src/lib.rs index e068d657e9..ae98fba307 100644 --- a/crates/api_clients/storyteller_client/src/lib.rs +++ b/crates/api_clients/storyteller_client/src/lib.rs @@ -7,4 +7,5 @@ pub mod jobs; pub mod media_files; pub mod prompts; pub mod recipes; +pub mod stripe_artcraft; pub mod utils; diff --git a/crates/api_clients/storyteller_client/src/stripe_artcraft/create_subscription_checkout.rs b/crates/api_clients/storyteller_client/src/stripe_artcraft/create_subscription_checkout.rs new file mode 100644 index 0000000000..3c5ee83fb8 --- /dev/null +++ b/crates/api_clients/storyteller_client/src/stripe_artcraft/create_subscription_checkout.rs @@ -0,0 +1,18 @@ +use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; +use crate::error::storyteller_error::StorytellerError; +use crate::utils::api_host::ApiHost; +use crate::utils::basic_json_post_request::basic_json_post_request; +use artcraft_api_defs::stripe_artcraft::create_subscription_checkout::{StripeArtcraftCreateCheckoutSessionRequest, StripeArtcraftCreateCheckoutSessionResponse, CREATE_SUBSCRIPTION_CHECKOUT_URL_PATH}; + +pub async fn create_subscription_checkout( + api_host: &ApiHost, + maybe_creds: Option<&StorytellerCredentialSet>, + request: StripeArtcraftCreateCheckoutSessionRequest, +) -> Result { + Ok(basic_json_post_request( + api_host, + CREATE_SUBSCRIPTION_CHECKOUT_URL_PATH, + maybe_creds, + request, + ).await?) +} diff --git a/crates/api_clients/storyteller_client/src/stripe_artcraft/mod.rs b/crates/api_clients/storyteller_client/src/stripe_artcraft/mod.rs new file mode 100644 index 0000000000..3f6dca510d --- /dev/null +++ b/crates/api_clients/storyteller_client/src/stripe_artcraft/mod.rs @@ -0,0 +1 @@ +pub mod create_subscription_checkout; \ No newline at end of file diff --git a/crates/desktop/artcraft/src/lib.rs b/crates/desktop/artcraft/src/lib.rs index 1e68139d71..14385777b7 100644 --- a/crates/desktop/artcraft/src/lib.rs +++ b/crates/desktop/artcraft/src/lib.rs @@ -45,6 +45,7 @@ use crate::services::sora::commands::sora_logout_command::sora_logout_command; use crate::services::sora::state::sora_credential_manager::SoraCredentialManager; use crate::services::sora::state::sora_task_queue::SoraTaskQueue; use crate::services::sora::threads::sora_task_polling_thread::sora_task_polling_thread; +use crate::services::storyteller::commands::storyteller_open_billing_command::storyteller_open_billing_command; use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager; use log::error; @@ -170,16 +171,17 @@ pub fn run() { get_fal_api_key_command, get_provider_order_command, load_without_cors_command, - open_sora_login_command, midjourney_clear_credentials_command, midjourney_get_credential_info_command, midjourney_open_login_command, + open_sora_login_command, platform_info_command, set_fal_api_key_command, set_provider_order_command, sora_image_generation_command, sora_image_remix_command, sora_logout_command, + storyteller_open_billing_command, update_app_preferences_command, ]) .run(tauri::generate_context!("tauri.conf.json")) diff --git a/crates/desktop/artcraft/src/services/storyteller/commands/mod.rs b/crates/desktop/artcraft/src/services/storyteller/commands/mod.rs new file mode 100644 index 0000000000..a33db36d60 --- /dev/null +++ b/crates/desktop/artcraft/src/services/storyteller/commands/mod.rs @@ -0,0 +1 @@ +pub mod storyteller_open_billing_command; \ No newline at end of file diff --git a/crates/desktop/artcraft/src/services/storyteller/commands/storyteller_open_billing_command.rs b/crates/desktop/artcraft/src/services/storyteller/commands/storyteller_open_billing_command.rs new file mode 100644 index 0000000000..61fcaf3192 --- /dev/null +++ b/crates/desktop/artcraft/src/services/storyteller/commands/storyteller_open_billing_command.rs @@ -0,0 +1,71 @@ +use crate::core::commands::enqueue::image_edit::enqueue_contextual_edit_image_command::{ContextualImageEditModel, EditImageQuality, EditImageSize}; +use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; +use crate::core::state::data_dir::app_data_root::AppDataRoot; +use crate::services::midjourney::state::midjourney_credential_manager::MidjourneyCredentialManager; +use crate::services::midjourney::windows::open_midjourney_login_window::open_midjourney_login_window; +use crate::services::sora::windows::sora_login_window::open_sora_login_window::open_sora_login_window; +use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager; +use crate::services::storyteller::windows::open_storyteller_billing_window::open_storyteller_billing_window; +use artcraft_api_defs::stripe_artcraft::create_subscription_checkout::{PlanBillingCadence, PlanName}; +use enums::tauri::ux::tauri_command_caller::TauriCommandCaller; +use errors::AnyhowResult; +use log::{error, info}; +use serde_derive::Deserialize; +use tauri::{AppHandle, State}; +use tokens::tokens::media_files::MediaFileToken; + +#[derive(Deserialize, Debug)] +pub struct StorytellerOpenBillingCommand { + pub plan: Option, + pub cadence: Option, +} + +#[tauri::command] +pub async fn storyteller_open_billing_command( + app: AppHandle, + request: StorytellerOpenBillingCommand, + app_data_root: State<'_, AppDataRoot>, + app_env_configs: State<'_, AppEnvConfigs>, + storyteller_creds_manager: State<'_, StorytellerCredentialManager>, +) -> Result { + info!("storyteller_open_billing_command called"); + + do_open_billing( + &app, + &app_data_root, + &app_env_configs, + &storyteller_creds_manager, + request.plan, + request.cadence, + ) + .await + .map_err(|err| { + error!("Error opening login: {:?}", err); + format!("Error opening login: {:?}", err) + })?; + + Ok("result".to_string()) +} + +async fn do_open_billing( + app: &AppHandle, + app_data_root: &AppDataRoot, + app_env_configs: &AppEnvConfigs, + storyteller_creds_manager: &StorytellerCredentialManager, + plan: Option, + cadence: Option, +) -> AnyhowResult<()> { + info!("Building billing window..."); + + open_storyteller_billing_window( + app, + app_env_configs, + app_data_root, + storyteller_creds_manager, + plan, + cadence, + ).await?; + + info!("Done."); + Ok(()) +} diff --git a/crates/desktop/artcraft/src/services/storyteller/mod.rs b/crates/desktop/artcraft/src/services/storyteller/mod.rs index 51f42a9be7..7b5a42c0bf 100644 --- a/crates/desktop/artcraft/src/services/storyteller/mod.rs +++ b/crates/desktop/artcraft/src/services/storyteller/mod.rs @@ -1,2 +1,4 @@ pub mod state; -pub mod threads; \ No newline at end of file +pub mod threads; +pub mod windows; +pub mod commands; \ No newline at end of file diff --git a/crates/desktop/artcraft/src/services/storyteller/windows/mod.rs b/crates/desktop/artcraft/src/services/storyteller/windows/mod.rs new file mode 100644 index 0000000000..35816d8b47 --- /dev/null +++ b/crates/desktop/artcraft/src/services/storyteller/windows/mod.rs @@ -0,0 +1 @@ +pub mod open_storyteller_billing_window; \ No newline at end of file diff --git a/crates/desktop/artcraft/src/services/storyteller/windows/open_storyteller_billing_window.rs b/crates/desktop/artcraft/src/services/storyteller/windows/open_storyteller_billing_window.rs new file mode 100644 index 0000000000..d031f67e10 --- /dev/null +++ b/crates/desktop/artcraft/src/services/storyteller/windows/open_storyteller_billing_window.rs @@ -0,0 +1,114 @@ +use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; +use crate::core::state::data_dir::app_data_root::AppDataRoot; +use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager; +use anyhow::anyhow; +use artcraft_api_defs::stripe_artcraft::create_subscription_checkout::{PlanBillingCadence, PlanName, StripeArtcraftCreateCheckoutSessionRequest}; +use errors::AnyhowResult; +use log::info; +use reqwest::Url; +use storyteller_client::stripe_artcraft::create_subscription_checkout::create_subscription_checkout; +use tauri::{AppHandle, Manager, WebviewUrl, WebviewWindowBuilder}; + +const BILLING_WINDOW_NAME: &str = "artcraft_billing_window"; + +pub async fn open_storyteller_billing_window( + app: &AppHandle, + app_env_configs: &AppEnvConfigs, + app_data_root: &AppDataRoot, + storyteller_creds_manager: &StorytellerCredentialManager, + plan: Option, + cadence: Option, +) -> AnyhowResult<()> { + + if app.get_window(BILLING_WINDOW_NAME).is_some() { + return Err(anyhow!("Billing window already open")); + } + + let url = do_get_url( + app, + app_env_configs, + app_data_root, + storyteller_creds_manager, + plan, + cadence, + ).await?; + + do_open_window(app, app_data_root, url).await?; + + Ok(()) +} + +async fn do_get_url( + app: &AppHandle, + app_env_configs: &AppEnvConfigs, + app_data_root: &AppDataRoot, + storyteller_creds_manager: &StorytellerCredentialManager, + plan: Option, + cadence: Option, +) -> AnyhowResult { + + info!("Checkout session requires session..."); + + let creds = storyteller_creds_manager.get_credentials_required()?; + + info!("Creating checkout session..."); + + let request = StripeArtcraftCreateCheckoutSessionRequest { + plan, + cadence, + }; + + let result = create_subscription_checkout( + &app_env_configs.storyteller_host, + Some(&creds), + request, + ).await?; + + info!("Checkout session created..."); + + let url = Url::parse(&result.stripe_checkout_redirect_url)?; + Ok(url) +} + +async fn do_open_window( + app: &AppHandle, + app_data_root: &AppDataRoot, + url: Url, +) -> AnyhowResult<()> { + let url = WebviewUrl::External(url); + + info!("Opening checkout window..."); + + // TODO(bt,2025-09-01): We probably need to open this in a real browser to get autocomplete. + let window = WebviewWindowBuilder::new(app, BILLING_WINDOW_NAME, url) + //.user_agent(openai_sora_client::credentials::USER_AGENT) + .always_on_top(false) + .title("Sign up for ArtCraft") + .center() + .resizable(true) + .visible(true) + .closable(true) + .min_inner_size(1000.0, 800.0) + .focused(true) + .devtools(true) + .build()?; + + let webview = window.get_webview(BILLING_WINDOW_NAME) + .ok_or_else(|| anyhow!("no webview found"))?; + + //webview.navigate(MIDJOURNEY_HOMEPAGE_URL.clone())?; + + // NB: We're starting to get Cloudflare protection screens. Let's try to avoid. + //tokio::time::sleep(Duration::from_millis(100)).await; + + //webview.navigate(MIDJOURNEY_LOGIN_URL.clone())?; + + let app_handle = app.clone(); + let app_data_root = app_data_root.clone(); + + //let _ = tauri::async_runtime::spawn(async move { + // midjourney_login_window_thread(app_handle, app_data_root).await; + //}); + + Ok(()) +} diff --git a/crates/schema/public/api/artcraft_api_defs/src/lib.rs b/crates/schema/public/api/artcraft_api_defs/src/lib.rs index d314b86ccc..8a64bab91c 100644 --- a/crates/schema/public/api/artcraft_api_defs/src/lib.rs +++ b/crates/schema/public/api/artcraft_api_defs/src/lib.rs @@ -2,4 +2,5 @@ pub mod common; pub mod generate; pub mod jobs; pub mod media_file; -pub mod prompts; \ No newline at end of file +pub mod prompts; +pub mod stripe_artcraft; \ No newline at end of file diff --git a/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/create_subscription_checkout.rs b/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/create_subscription_checkout.rs new file mode 100644 index 0000000000..8cc56485ef --- /dev/null +++ b/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/create_subscription_checkout.rs @@ -0,0 +1,39 @@ +use serde_derive::{Deserialize, Serialize}; +use utoipa::ToSchema; + +pub const CREATE_SUBSCRIPTION_CHECKOUT_URL_PATH: &str = "/v1/stripe_artcraft/checkout/create_subscription"; + +#[derive(Serialize, Deserialize, ToSchema)] +pub struct StripeArtcraftCreateCheckoutSessionRequest { + /// The (non-Stripe) internal identifier for the product or subscription. + /// This will be translated into a Stripe identifier. + pub plan: Option, + + pub cadence: Option, +} + +#[derive(Serialize, Deserialize, ToSchema, Debug, Copy, Clone)] +pub enum PlanName { + #[serde(rename = "basic")] + Basic, + #[serde(rename = "pro")] + Pro, + #[serde(rename = "max")] + Max, +} + +#[derive(Serialize, Deserialize, ToSchema, Debug, Copy, Clone)] +pub enum PlanBillingCadence { + #[serde(rename = "monthly")] + Monthly, + + #[serde(rename = "yearly")] + Yearly, +} + +#[derive(Serialize, Deserialize, ToSchema)] +pub struct StripeArtcraftCreateCheckoutSessionResponse { + pub success: bool, + pub stripe_checkout_redirect_url: String, +} + diff --git a/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/mod.rs b/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/mod.rs new file mode 100644 index 0000000000..3f6dca510d --- /dev/null +++ b/crates/schema/public/api/artcraft_api_defs/src/stripe_artcraft/mod.rs @@ -0,0 +1 @@ +pub mod create_subscription_checkout; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/configs/stripe_artcraft_metadata_keys.rs b/crates/service/web/storyteller_web/src/configs/stripe_artcraft_metadata_keys.rs index de6e72a7cb..a9d46c376c 100644 --- a/crates/service/web/storyteller_web/src/configs/stripe_artcraft_metadata_keys.rs +++ b/crates/service/web/storyteller_web/src/configs/stripe_artcraft_metadata_keys.rs @@ -2,5 +2,3 @@ pub const STRIPE_ARTCRAFT_METADATA_USER_TOKEN : &str = "user_token"; pub const STRIPE_ARTCRAFT_METADATA_USERNAME : &str = "username"; pub const STRIPE_ARTCRAFT_METADATA_EMAIL : &str = "email"; - -pub const STRIPE_ARTCRAFT_METADATA_TOLT_REFERRAL: &str = "tolt_referral"; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/mod.rs index ae01b3fba1..814bc35488 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/mod.rs @@ -1 +1 @@ -pub mod stripe_artcraft_create_checkout_session_handler; \ No newline at end of file +pub mod stripe_artcraft_create_subscription_checkout_session_handler; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_checkout_session_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_subscription_checkout_session_handler.rs similarity index 87% rename from crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_checkout_session_handler.rs rename to crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_subscription_checkout_session_handler.rs index 5445a5ea90..e3212e9ba1 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_checkout_session_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/stripe_artcraft/checkout/stripe_artcraft_create_subscription_checkout_session_handler.rs @@ -1,4 +1,4 @@ -use crate::configs::stripe_artcraft_metadata_keys::{STRIPE_ARTCRAFT_METADATA_EMAIL, STRIPE_ARTCRAFT_METADATA_TOLT_REFERRAL, STRIPE_ARTCRAFT_METADATA_USERNAME, STRIPE_ARTCRAFT_METADATA_USER_TOKEN}; +use crate::configs::stripe_artcraft_metadata_keys::{STRIPE_ARTCRAFT_METADATA_EMAIL, STRIPE_ARTCRAFT_METADATA_USERNAME, STRIPE_ARTCRAFT_METADATA_USER_TOKEN}; use crate::configs::stripe_artcraft_product_info_list::{ARTCRAFT_BASIC_SANDBOX, ARTCRAFT_MAX_SANDBOX, ARTCRAFT_PRO_SANDBOX}; use crate::http_server::common_responses::common_web_error::CommonWebError; use crate::state::server_state::ServerState; @@ -14,44 +14,7 @@ use std::sync::Arc; use url_config::third_party_url_redirector::ThirdPartyUrlRedirector; use user_traits_component::traits::internal_session_cache_purge::InternalSessionCachePurge; use utoipa::ToSchema; - -#[derive(Deserialize, ToSchema)] -pub struct StripeArtcraftCreateCheckoutSessionRequest { - /// The (non-Stripe) internal identifier for the product or subscription. - /// This will be translated into a Stripe identifier. - plan: Option, - - cadence: Option, - - /// Optional Tolt referral code - /// See: https://help.tolt.io/en/articles/6843411-how-to-set-up-stripe-with-tolt - maybe_tolt_referral: Option, -} - -#[derive(Deserialize, ToSchema)] -pub enum PlanName { - #[serde(rename = "basic")] - Basic, - #[serde(rename = "pro")] - Pro, - #[serde(rename = "max")] - Max, -} - -#[derive(Deserialize, ToSchema)] -pub enum PlanBillingCadence { - #[serde(rename = "monthly")] - Monthly, - - #[serde(rename = "yearly")] - Yearly, -} - -#[derive(Serialize, ToSchema)] -pub struct StripeArtcraftCreateCheckoutSessionResponse { - pub success: bool, - pub stripe_checkout_redirect_url: String, -} +use artcraft_api_defs::stripe_artcraft::create_subscription_checkout::{PlanBillingCadence, PlanName, StripeArtcraftCreateCheckoutSessionRequest, StripeArtcraftCreateCheckoutSessionResponse}; /// Create a Stripe Checkout session and return the redirect URL in Json. #[utoipa::path( @@ -156,10 +119,6 @@ pub async fn stripe_artcraft_create_checkout_session_handler( metadata.insert(STRIPE_ARTCRAFT_METADATA_EMAIL.to_string(), user_email.to_string()); } - if let Some(tolt_referral) = request.maybe_tolt_referral.as_deref() { - metadata.insert(STRIPE_ARTCRAFT_METADATA_TOLT_REFERRAL.to_string(), tolt_referral.to_string()); - } - // NB: This metadata attaches to Stripe's Checkout Session object. // This does not attach to the subscription or payment intent, which have their own metadata // objects. (TODO: Confirm this.) diff --git a/crates/service/web/storyteller_web/src/http_server/routes/add_stripe_artcraft_routes.rs b/crates/service/web/storyteller_web/src/http_server/routes/add_stripe_artcraft_routes.rs index 301486e361..7f2d47ed69 100644 --- a/crates/service/web/storyteller_web/src/http_server/routes/add_stripe_artcraft_routes.rs +++ b/crates/service/web/storyteller_web/src/http_server/routes/add_stripe_artcraft_routes.rs @@ -1,4 +1,4 @@ -use crate::http_server::endpoints::stripe_artcraft::checkout::stripe_artcraft_create_checkout_session_handler::stripe_artcraft_create_checkout_session_handler; +use crate::http_server::endpoints::stripe_artcraft::checkout::stripe_artcraft_create_subscription_checkout_session_handler::stripe_artcraft_create_checkout_session_handler; use crate::http_server::endpoints::stripe_artcraft::webhook::stripe_artcraft_webhook_handler::stripe_artcraft_webhook_handler; use actix_http::body::MessageBody; use actix_service::ServiceFactory; diff --git a/frontend/libs/components/pricing-modal/package.json b/frontend/libs/components/pricing-modal/package.json index f4f702c199..74dd45d00a 100644 --- a/frontend/libs/components/pricing-modal/package.json +++ b/frontend/libs/components/pricing-modal/package.json @@ -13,5 +13,8 @@ "import": "./dist/index.js", "default": "./dist/index.js" } + }, + "dependencies": { + "@tauri-apps/api": "^2.4.0" } } diff --git a/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts b/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts index cf759ff8f8..b261675f34 100644 --- a/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts +++ b/frontend/libs/components/pricing-modal/src/lib/pricing-config.ts @@ -38,8 +38,10 @@ export const pricingConfig = { colorScheme: "dark" as const, }, { - id: "plus", - name: "Plus", + //id: "plus", + //name: "Plus", + id: "basic", + name: "Basic", monthlyPrice: 8, yearlyPrice: 96, originalMonthlyPrice: 10, 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 0ee0c4af3f..01bd64a434 100644 --- a/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx +++ b/frontend/libs/components/pricing-modal/src/lib/pricing-modal.tsx @@ -5,6 +5,7 @@ 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"; const billingTabs = [ { id: "yearly", label: "Yearly" }, @@ -32,14 +33,21 @@ export function PricingModal({ 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 priceId = isYearly ? tier?.yearlyPriceId : tier?.monthlyPriceId; - console.log( - `Upgrading to ${tierId} plan with ${ - isYearly ? "yearly" : "monthly" - } billing`, - { priceId, tierId } - ); + const planName = tier?.id; + const cadence = isYearly? "yearly" : "monthly"; + + if (planName === "free") { + return; + } + + await invoke("storyteller_open_billing_command", { + request: { + plan:planName, + cadence: cadence, + } + }); // Example Stripe checkout implementation: // await stripe.redirectToCheckout({ diff --git a/frontend/libs/components/pricing-modal/tsconfig.json b/frontend/libs/components/pricing-modal/tsconfig.json index f9b436f518..5547a34ef4 100644 --- a/frontend/libs/components/pricing-modal/tsconfig.json +++ b/frontend/libs/components/pricing-modal/tsconfig.json @@ -2,6 +2,9 @@ "files": [], "include": [], "references": [ + { + "path": "../../tauri-api" + }, { "path": "../tab-selector" }, diff --git a/frontend/libs/components/pricing-modal/tsconfig.lib.json b/frontend/libs/components/pricing-modal/tsconfig.lib.json index 2db570cf1b..e0e0e7035d 100644 --- a/frontend/libs/components/pricing-modal/tsconfig.lib.json +++ b/frontend/libs/components/pricing-modal/tsconfig.lib.json @@ -43,6 +43,9 @@ "src/**/*.tsx" ], "references": [ + { + "path": "../../tauri-api/tsconfig.lib.json" + }, { "path": "../tab-selector/tsconfig.lib.json" },