From f3ce47b445a23211ab7d2bbf0b7b406ecee66a7c Mon Sep 17 00:00:00 2001 From: sabaimran <65192171+sabaimran@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:29:23 -0700 Subject: [PATCH] Create explicit flow to enable the free trial (#944) * Create explicit flow to enable the free trial The current design is confusing. It obfuscates the fact that the user is on a free trial. This design will make the opt-in explicit and more intuitive. * Use the Subscription Type enum instead of hardcoded strings everywhere * Use length of free trial in the frontend code as well --- documentation/docs/clients/whatsapp.md | 2 +- src/interface/web/app/common/auth.ts | 4 +- src/interface/web/app/settings/page.tsx | 75 +++++++++++++++++-- src/khoj/configure.py | 4 +- src/khoj/database/adapters/__init__.py | 36 +++++++-- ..._subscription_enabled_trial_at_and_more.py | 32 ++++++++ src/khoj/database/models/__init__.py | 3 +- .../{subscription.py => api_subscription.py} | 22 +++++- src/khoj/routers/helpers.py | 11 ++- tests/helpers.py | 2 +- 10 files changed, 167 insertions(+), 24 deletions(-) create mode 100644 src/khoj/database/migrations/0071_subscription_enabled_trial_at_and_more.py rename src/khoj/routers/{subscription.py => api_subscription.py} (87%) diff --git a/documentation/docs/clients/whatsapp.md b/documentation/docs/clients/whatsapp.md index dccd0cab..39b48a0d 100644 --- a/documentation/docs/clients/whatsapp.md +++ b/documentation/docs/clients/whatsapp.md @@ -12,7 +12,7 @@ Without any desktop clients, you can start chatting with Khoj on WhatsApp. Bear In order to use Khoj on WhatsApp with your own data, you need to setup a Khoj Cloud account and connect your WhatsApp account to it. This is a one time setup and you can do it from the [Khoj Cloud config page](https://app.khoj.dev/settings). -If you hit usage limits for the WhatsApp bot, upgrade to [a paid plan](https://khoj.dev/pricing) on Khoj Cloud. +If you hit usage limits for the WhatsApp bot, upgrade to [a paid plan](https://khoj.dev/#pricing) on Khoj Cloud. diff --git a/src/interface/web/app/common/auth.ts b/src/interface/web/app/common/auth.ts index 2ece265d..1c634184 100644 --- a/src/interface/web/app/common/auth.ts +++ b/src/interface/web/app/common/auth.ts @@ -68,7 +68,8 @@ export interface UserConfig { selected_voice_model_config: number; // user billing info subscription_state: SubscriptionStates; - subscription_renewal_date: string; + subscription_renewal_date: string | undefined; + subscription_enabled_trial_at: string | undefined; // server settings khoj_cloud_subscription_url: string | undefined; billing_enabled: boolean; @@ -78,6 +79,7 @@ export interface UserConfig { anonymous_mode: boolean; notion_oauth_url: string; detail: string; + length_of_free_trial: number; } export function useUserConfig(detailed: boolean = false) { diff --git a/src/interface/web/app/settings/page.tsx b/src/interface/web/app/settings/page.tsx index ea0232bb..d79eeff4 100644 --- a/src/interface/web/app/settings/page.tsx +++ b/src/interface/web/app/settings/page.tsx @@ -513,7 +513,7 @@ export default function SettingsView() { const isMobileWidth = useIsMobileWidth(); const cardClassName = - "w-full lg:w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg bg-gradient-to-b from-background to-gray-50 dark:to-gray-950"; + "w-full lg:w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg bg-gradient-to-b from-background to-gray-50 dark:to-gray-950 border border-opacity-50"; useEffect(() => { setUserConfig(initialUserConfig); @@ -640,6 +640,51 @@ export default function SettingsView() { } }; + const enableFreeTrial = async () => { + const formatDate = (dateString: Date) => { + const date = new Date(dateString); + return new Intl.DateTimeFormat("en-US", { + day: "2-digit", + month: "short", + year: "numeric", + }).format(date); + }; + + try { + const response = await fetch(`/api/subscription/trial`, { + method: "POST", + }); + if (!response.ok) throw new Error("Failed to enable free trial"); + + const responseBody = await response.json(); + + // Set updated user settings + if (responseBody.trial_enabled && userConfig) { + let newUserConfig = userConfig; + newUserConfig.subscription_state = SubscriptionStates.TRIAL; + const renewalDate = new Date( + Date.now() + userConfig.length_of_free_trial * 24 * 60 * 60 * 1000, + ); + newUserConfig.subscription_renewal_date = formatDate(renewalDate); + newUserConfig.subscription_enabled_trial_at = new Date().toISOString(); + setUserConfig(newUserConfig); + + // Notify user of free trial + toast({ + title: "🎉 Trial Enabled", + description: `Your free trial will end on ${newUserConfig.subscription_renewal_date}`, + }); + } + } catch (error) { + console.error("Error enabling free trial:", error); + toast({ + title: "⚠️ Failed to Enable Free Trial", + description: + "Failed to enable free trial. Try again or contact us at team@khoj.dev", + }); + } + }; + const saveName = async () => { if (!name) return; try { @@ -866,10 +911,13 @@ export default function SettingsView() { Futurist (Trial)
- You are on a 14 day trial of the Khoj
- Futurist plan. Check{" "}
+ You are on a{" "}
+ {userConfig.length_of_free_trial} day trial
+ of the Khoj Futurist plan. Your trial ends
+ on {userConfig.subscription_renewal_date}.
+ Check{" "}
pricing page
@@ -909,7 +957,7 @@ export default function SettingsView() {
)) ||
(userConfig.subscription_state === "expired" && (
<>
- Free Plan Humanist
Subscription expired on{" "}
@@ -923,7 +971,7 @@ export default function SettingsView() {