- {deployments.map((deployment, index) => (
-
-
-
-
-
+
+ {deployments.map((deployment) => (
+
+
+
+
+
+
{deployment.folderPath}
@@ -536,23 +548,122 @@ export function ProjectsPage() {
{deployment.customDomain && getCustomDomainStatusBadge(deployment.customDomainStatus)}
-
+
setOpenDropdownId(open ? deployment.instanceId : null)}
+ >
+
+
+
+
+ openDeployment(deployment.url)}>
+
+ Open
+
+ {
+ if (!deployment.customDomain) {
+ setCustomDomainDialog({ open: true, deployment });
+ setOpenDropdownId(null);
+ }
+ }}
+ >
+
+ {deployment.customDomain ? "Domain Set" : "Custom Domain"}
+
+ {deployment.customDomain && (
+ {
+ setDnsInstructionsDialog({ open: true, deployment });
+ setOpenDropdownId(null);
+ }}>
+
+ DNS Info
+
+ )}
+ {deployment.customDomain && (
+
+
+ e.preventDefault()}
+ >
+
+ Delete Domain
+
+
+
+
+ Delete Custom Domain
+
+ Are you sure you want to delete the custom domain "{deployment.customDomain}"?
+ This will remove the custom domain configuration but won't delete the deployment itself.
+
+
+
+ Cancel
+ handleDeleteCustomDomain(deployment)}
+ className="bg-orange-600 hover:bg-orange-700 text-white"
+ >
+ Delete Domain
+
+
+
+
+ )}
+
+
+ e.preventDefault()}
+ >
+
+ Delete Project
+
+
+
+
+ Delete Project
+
+ Are you sure you want to delete the project "{deployment.folderPath}"?
+ This action cannot be undone and will permanently remove the deployed application.
+
+
+
+ Cancel
+ handleDeleteDeployment(deployment)}
+ className="bg-red-600 hover:bg-red-700 text-white"
+ >
+ Delete
+
+
+
+
+
+
+
+
- {formatDate(deployment.updatedAt)}
-
-
-
- {deployment.instanceName}
-
-
- {deployment.url}
+ {formatDate(deployment.createdAt)}
{deployment.customDomain && (
Custom Domain:
- {deployment.customDomain}
+
+ {deployment.customDomain}
+
{deployment.customDomainStatus === 'pending' && (
(Propagation pending)
@@ -560,18 +671,6 @@ export function ProjectsPage() {
)}
)}
-
-
-
-
{deployment.customDomain && deployment.publicIp && (
)}
-
- {deployment.customDomain && (
-
-
-
-
-
-
- Delete Custom Domain
-
- Are you sure you want to delete the custom domain "{deployment.customDomain}"?
- This will remove the custom domain configuration but won't delete the deployment itself.
-
-
-
- Cancel
- handleDeleteCustomDomain(deployment)}
- className={cn(
- "bg-orange-600 hover:bg-orange-700 focus:ring-orange-500",
- "dark:bg-orange-600 dark:hover:bg-orange-700"
- )}
- >
- Delete Domain
-
-
-
-
- )}
-
+
-
-
-
-
-
-
- Delete Deployment
-
- Are you sure you want to delete the deployment "{deployment.folderPath}"?
- This action cannot be undone and will permanently remove the deployed application.
-
-
-
- Cancel
- handleDeleteDeployment(deployment)}
- className={cn(
- "bg-red-600 hover:bg-red-700 focus:ring-red-500",
- "dark:bg-red-600 dark:hover:bg-red-700"
- )}
- >
- Delete
-
-
-
-
-
- {index < deployments.length - 1 && }
-
+
+
))}
)}
-
-
+
diff --git a/client/src/pages/SubscriptionPage.tsx b/client/src/pages/SubscriptionPage.tsx
index 5086b68..5a1c9f5 100644
--- a/client/src/pages/SubscriptionPage.tsx
+++ b/client/src/pages/SubscriptionPage.tsx
@@ -9,7 +9,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
-import { Check, ExternalLink, AlertCircle, Key, ShieldAlert, CreditCard, ArrowRight, Coins } from "lucide-react";
+import { Check, AlertCircle, Key, ShieldAlert, CreditCard, ArrowRight, Coins } from "lucide-react";
import { Separator } from "@/components/ui/separator";
import {
getCustomerProfile,
@@ -19,12 +19,11 @@ import { cancelSubscription } from "@/api/stripe";
import { Badge } from "@/components/ui/badge";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
-import { PAYMENT_LINKS, TOPUP_TOKENS, PLAN_LINKS } from "@/constants/plans";
+import { PAYMENT_LINKS, TOPUP_TOKENS, PLAN_LINKS, PLAN_FEATURES, PLAN_PRICES } from "@/constants/plans";
import SpinnerShape from "@/components/SpinnerShape";
import { PlanSummary } from "@/components/subscription/PlanSummary";
-import { PlanUpgrade } from "@/components/subscription/PlanUpgrade";
import { TokenUsage } from "@/components/subscription/TokenUsage";
-import { PremiumPlanIcon } from "@/components/icons/PlanIcons";
+import { FreePlanIcon, ProPlanIcon, PremiumPlanIcon } from "@/components/icons/PlanIcons";
interface CustomerProfile {
id?: string;
@@ -97,6 +96,7 @@ export function SubscriptionPage() {
const [error, setError] = useState
(null);
const [currentUser, setCurrentUser] = useState(null);
const [showTopUpModal, setShowTopUpModal] = useState(false);
+ const [showChangePlanModal, setShowChangePlanModal] = useState(false);
const [cancellingSubscription, setCancellingSubscription] = useState(false);
const { toast } = useToast();
@@ -144,9 +144,8 @@ export function SubscriptionPage() {
fetchData();
}, [toast]);
- const handleContactForEnterprise = () => {
- // Point to
- window.open("https://www.pythagora.ai/contact", "_blank");
+ const handleChangePlan = () => {
+ setShowChangePlanModal(true);
};
const handleShowTopUp = () => {
@@ -399,32 +398,14 @@ export function SubscriptionPage() {
>
)}
- {/* Free Trial Status */}
-
-
Free Trial Status
-
-
- {customerProfile?.isFreeTrial ? "On Free Trial" : "Not on Free Trial"}
-
-
-
-
-
-
{/* Plan Summary */}
- {/* Plan Upgrade Section */}
-
-
{/* Token Usage */}