diff --git a/apps/web/src/views/settings/components/CustomURLConfirmation.tsx b/apps/web/src/views/settings/components/CustomURLConfirmation.tsx
deleted file mode 100644
index 45bec735..00000000
--- a/apps/web/src/views/settings/components/CustomURLConfirmation.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { t } from "@lingui/core/macro";
-
-import { authClient } from "@kan/auth/client";
-
-import Button from "~/components/Button";
-import { useModal } from "~/providers/modal";
-import { usePopup } from "~/providers/popup";
-
-export function CustomURLConfirmation({
- userId,
- workspacePublicId,
-}: {
- userId: string;
- workspacePublicId: string;
-}) {
- const { closeModal, entityId } = useModal();
- const { showPopup } = usePopup();
-
- const handleUpgrade = async () => {
- const { data, error } = await authClient.subscription.upgrade({
- plan: "pro",
- referenceId: workspacePublicId,
- metadata: { userId, workspacePublicId, workspaceSlug: entityId },
- successUrl: "/settings",
- cancelUrl: "/settings",
- returnUrl: "/settings",
- disableRedirect: true,
- });
-
- if (data?.url) {
- window.location.href = data.url;
- }
-
- if (error) {
- showPopup({
- header: t`Error upgrading subscription`,
- message: t`Please try again later, or contact customer support.`,
- icon: "error",
- });
- }
- };
-
- return (
-
-
-
- {t`Confirm URL change`}
-
-
- {t`Custom URLs are a premium feature. You'll be directed to upgrade your account.`}
-
-
-
-
-
-
-
- );
-}
diff --git a/apps/web/src/views/settings/components/UpdateWorkspaceUrlForm.tsx b/apps/web/src/views/settings/components/UpdateWorkspaceUrlForm.tsx
index b71a8839..4205e3c7 100644
--- a/apps/web/src/views/settings/components/UpdateWorkspaceUrlForm.tsx
+++ b/apps/web/src/views/settings/components/UpdateWorkspaceUrlForm.tsx
@@ -98,7 +98,7 @@ const UpdateWorkspaceUrlForm = ({
if (!isWorkspaceSlugAvailable?.isAvailable) return;
if (workspacePlan !== "pro" && env("NEXT_PUBLIC_KAN_ENV") === "cloud")
- return openModal("UPDATE_WORKSPACE_URL", data.slug);
+ return openModal("UPGRADE_TO_PRO", data.slug);
updateWorkspaceSlug.mutate({
workspacePublicId,
diff --git a/apps/web/src/views/settings/components/UpgradeToProConfirmation.tsx b/apps/web/src/views/settings/components/UpgradeToProConfirmation.tsx
new file mode 100644
index 00000000..b25a3980
--- /dev/null
+++ b/apps/web/src/views/settings/components/UpgradeToProConfirmation.tsx
@@ -0,0 +1,103 @@
+import { t } from "@lingui/core/macro";
+import { HiBolt, HiCheckBadge } from "react-icons/hi2";
+
+import { authClient } from "@kan/auth/client";
+
+import Button from "~/components/Button";
+import { useModal } from "~/providers/modal";
+import { usePopup } from "~/providers/popup";
+
+export function UpgradeToProConfirmation({
+ userId,
+ workspacePublicId,
+}: {
+ userId: string;
+ workspacePublicId: string;
+}) {
+ const { closeModal, entityId } = useModal();
+ const { showPopup } = usePopup();
+
+ const handleUpgrade = async () => {
+ const { data, error } = await authClient.subscription.upgrade({
+ plan: "pro",
+ referenceId: workspacePublicId,
+ metadata: {
+ userId,
+ workspacePublicId,
+ ...(entityId && { workspaceSlug: entityId }),
+ },
+ successUrl: "/settings",
+ cancelUrl: "/settings",
+ returnUrl: "/settings",
+ disableRedirect: true,
+ });
+
+ if (data?.url) {
+ window.location.href = data.url;
+ }
+
+ if (error) {
+ showPopup({
+ header: t`Error upgrading subscription`,
+ message: t`Please try again later, or contact customer support.`,
+ icon: "error",
+ });
+ }
+ };
+
+ return (
+
+
+
+ {t`Upgrade to Pro`}
+
+
+ {t`Supercharge your workspace for just $29/month. Here's what you'll get:`}
+
+
+
+
+
+
+
+
+ {t`Unlimited members`}
+
+
+ {t`Launch offer`}
+
+
+
+
+
+
+ {t`Custom workspace URL`}
+
+
+
+
+
+ {t`Board analytics (coming soon)`}
+
+
+
+
+
+ {t`Priority email support`}
+
+
+
+
+
+
+
+ }
+ >{t`Upgrade`}
+
+
+ );
+}
diff --git a/apps/web/src/views/settings/index.tsx b/apps/web/src/views/settings/index.tsx
index 356c886f..10f3459a 100644
--- a/apps/web/src/views/settings/index.tsx
+++ b/apps/web/src/views/settings/index.tsx
@@ -2,7 +2,10 @@ import { useRouter } from "next/router";
import { t } from "@lingui/core/macro";
import { env } from "next-runtime-env";
import { useEffect, useRef } from "react";
-import { HiMiniArrowTopRightOnSquare } from "react-icons/hi2";
+import { HiBolt, HiMiniArrowTopRightOnSquare } from "react-icons/hi2";
+
+import type { Subscription } from "@kan/shared/utils";
+import { hasActiveSubscription } from "@kan/shared/utils";
import Button from "~/components/Button";
import FeedbackModal from "~/components/FeedbackModal";
@@ -17,13 +20,13 @@ import { api } from "~/utils/api";
import Avatar from "./components/Avatar";
import { ChangePasswordFormConfirmation } from "./components/ChangePasswordConfirmation";
import CreateAPIKeyForm from "./components/CreateAPIKeyForm";
-import { CustomURLConfirmation } from "./components/CustomURLConfirmation";
import { DeleteAccountConfirmation } from "./components/DeleteAccountConfirmation";
import { DeleteWorkspaceConfirmation } from "./components/DeleteWorkspaceConfirmation";
import UpdateDisplayNameForm from "./components/UpdateDisplayNameForm";
import UpdateWorkspaceDescriptionForm from "./components/UpdateWorkspaceDescriptionForm";
import UpdateWorkspaceNameForm from "./components/UpdateWorkspaceNameForm";
import UpdateWorkspaceUrlForm from "./components/UpdateWorkspaceUrlForm";
+import { UpgradeToProConfirmation } from "./components/UpgradeToProConfirmation";
export default function SettingsPage() {
const { modalContentType, openModal, isOpen } = useModal();
@@ -37,6 +40,14 @@ export default function SettingsPage() {
env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true";
const { data } = api.user.getUser.useQuery();
+ const { data: workspaceData } = api.workspace.byId.useQuery({
+ workspacePublicId: workspace.publicId,
+ });
+
+ const subscriptions = workspaceData?.subscriptions as
+ | Subscription[]
+ | undefined;
+
const {
data: integrations,
refetch: refetchIntegrations,
@@ -180,6 +191,18 @@ export default function SettingsPage() {
workspacePublicId={workspace.publicId}
workspaceDescription={workspace.description ?? ""}
/>
+
+ {env("NEXT_PUBLIC_KAN_ENV") === "cloud" &&
+ !hasActiveSubscription(subscriptions, "pro") && (
+
+
+
+ )}
@@ -346,9 +369,12 @@ export default function SettingsPage() {
-
+