From 85d0255f6ff042aa10c0cc4d5a42d776f75f45fb Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Thu, 20 Mar 2025 00:30:20 -0600 Subject: [PATCH] feat: implement Reset License page and update navigation --- .../app/[locale]/reset-license/page.tsx | 77 +++++++++ apps/website/components/Header.tsx | 1 + apps/website/components/pricing.tsx | 161 +++++++++++++++++- apps/website/locales/en.json | 54 ++++++ 4 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 apps/website/app/[locale]/reset-license/page.tsx diff --git a/apps/website/app/[locale]/reset-license/page.tsx b/apps/website/app/[locale]/reset-license/page.tsx new file mode 100644 index 0000000..f898edb --- /dev/null +++ b/apps/website/app/[locale]/reset-license/page.tsx @@ -0,0 +1,77 @@ +"use client"; + +import { Container } from "@/components/Container"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { useState } from "react"; + +export default function ResetLicensePage() { + const [email, setEmail] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + + try { + // Here you would add the API call to reset the license + // For now, we'll just simulate a success response + await new Promise((resolve) => setTimeout(resolve, 1500)); + + // toast({ + // title: "Success!", + // description: + // "If an account exists with this email, you will receive instructions to reset your license.", + // variant: "default", + // }); + + setEmail(""); + } catch (error) { + // toast({ + // title: "Error", + // description: "Something went wrong. Please try again later.", + // variant: "destructive", + // }); + } finally { + setIsLoading(false); + } + }; + + return ( + +
+

+ Reset Your License +

+

+ Enter your email address and we'll send you instructions to reset your + license. +

+ +
+
+ setEmail(e.target.value)} + required + className="w-full" + disabled={isLoading} + /> +
+ +
+
+
+ ); +} diff --git a/apps/website/components/Header.tsx b/apps/website/components/Header.tsx index b4d9e04..f105ca1 100644 --- a/apps/website/components/Header.tsx +++ b/apps/website/components/Header.tsx @@ -168,6 +168,7 @@ export function Header() { {t("navigation.docs")} {t("navigation.blog")} + Reset License
diff --git a/apps/website/components/pricing.tsx b/apps/website/components/pricing.tsx index 1664d25..bb7ab57 100644 --- a/apps/website/components/pricing.tsx +++ b/apps/website/components/pricing.tsx @@ -87,6 +87,7 @@ export function Pricing() { const router = useRouter(); const t = useTranslations("Pricing"); const [isAnnual, setIsAnnual] = useState(false); + const [isSelfHostedAnnual, setIsSelfHostedAnnual] = useState(false); const [serverQuantity, setServerQuantity] = useState(1); const featured = true; @@ -176,7 +177,6 @@ export function Pricing() {

+ + {/* Divider */} +
+ + {/* Self-hosted License Section */} +
+
+

+ {t("plan.selfHosted.title")} +

+

+ {t("plan.selfHosted.description")} +

+
+ setIsSelfHostedAnnual(e === "annual")} + > + + + {t("plan.selfHosted.billingCycle.monthly")} + + + {t("plan.selfHosted.billingCycle.annual")} + + + +
+
+
+ {/* Basic License */} +
+
+

+ {isSelfHostedAnnual + ? t("plan.selfHosted.basic.priceAnnual") + : t("plan.selfHosted.basic.priceMonthly")}{" "} + USD +

+ + / {isSelfHostedAnnual ? "year" : "month"} + +
+

+ {t("plan.selfHosted.basic.title")} +

+

+ {t("plan.selfHosted.basic.description")} +

+
    + {Object.keys(t.raw("plan.selfHosted.basic.features")).map( + (key) => ( +
  • + + + {t(`plan.selfHosted.basic.features.${key}`)} + +
  • + ), + )} +
+
+ + +
+
+ + {/* Professional License */} +
+
+

+ {isSelfHostedAnnual + ? t("plan.selfHosted.professional.priceAnnual") + : t("plan.selfHosted.professional.priceMonthly")}{" "} + USD +

+ + / {isSelfHostedAnnual ? "year" : "month"} + +
+

+ {t("plan.selfHosted.professional.title")} +

+

+ {t("plan.selfHosted.professional.description")} +

+
    + {Object.keys( + t.raw("plan.selfHosted.professional.features"), + ).map((key) => ( +
  • + + + {t(`plan.selfHosted.professional.features.${key}`)} + +
  • + ))} +
+
+ +
+
+ + {/* Enterprise License */} +
+
+

+ {isSelfHostedAnnual + ? t("plan.selfHosted.enterprise.priceAnnual") + : t("plan.selfHosted.enterprise.priceMonthly")}{" "} + USD +

+ + / {isSelfHostedAnnual ? "year" : "month"} + +
+

+ {t("plan.selfHosted.enterprise.title")} +

+

+ {t("plan.selfHosted.enterprise.description")} +

+
    + {Object.keys( + t.raw("plan.selfHosted.enterprise.features"), + ).map((key) => ( +
  • + + + {t(`plan.selfHosted.enterprise.features.${key}`)} + +
  • + ))} +
+
+ + +
+
+
+
diff --git a/apps/website/locales/en.json b/apps/website/locales/en.json index d4885dc..2bb6284 100644 --- a/apps/website/locales/en.json +++ b/apps/website/locales/en.json @@ -177,6 +177,51 @@ "f8": "New Updates" }, "go": "Subscribe" + }, + "selfHosted": { + "title": "Self-Hosted License", + "description": "Deploy and manage Dokploy on your own infrastructure with enterprise-grade features and support", + "basic": { + "title": "Basic License", + "description": "Perfect for small teams and startups", + "priceAnnual": "$89.99", + "priceMonthly": "$9.99", + "features": { + "f1": "Remote Servers Monitoring", + "f2": "Priority Support", + "f3": "New Updates" + } + }, + "professional": { + "title": "Premium License", + "description": "For growing businesses", + "priceAnnual": "$199.99", + "priceMonthly": "$19.99", + "features": { + "f1": "Remote Servers Monitoring", + "f2": "Priority Support", + "f3": "New Updates", + "f4": "Custom branding" + } + }, + "enterprise": { + "title": "Business License", + "description": "For large organizations", + "priceAnnual": "$299.99", + "priceMonthly": "$29.99", + "features": { + "f1": "Remote Servers Monitoring", + "f2": "24/7 Premium support", + "f3": "Security updates", + "f4": "Custom branding", + "f5": "Custom features" + } + }, + "buyNow": "Buy Now", + "billingCycle": { + "monthly": "Monthly", + "annual": "Annual" + } } }, "faq": { @@ -214,5 +259,14 @@ "backToBlog": "Back to Blog", "tags": "Tags", "postsTaggedWith": "Posts tagged with" + }, + "Header": { + "signIn": "Sign in", + "signInCloud": "Sign in to Dokploy Cloud", + "pricing": "Pricing", + "faqs": "FAQs", + "docs": "Documentation", + "blog": "Blog", + "resetLicense": "Reset License" } }