feat: add inline pricing section with launch offer (first 100 at €47)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
119
apps/web/src/modules/marketing/home/pricing.tsx
Normal file
119
apps/web/src/modules/marketing/home/pricing.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslation } from "@turbostarter/i18n";
|
||||
import { cn } from "@turbostarter/ui";
|
||||
import { buttonVariants } from "@turbostarter/ui-web/button";
|
||||
|
||||
import { pathsConfig } from "~/config/paths";
|
||||
import { TurboLink } from "~/modules/common/turbo-link";
|
||||
import {
|
||||
Section,
|
||||
SectionBadge,
|
||||
SectionDescription,
|
||||
SectionHeader,
|
||||
SectionTitle,
|
||||
} from "~/modules/marketing/layout/section";
|
||||
|
||||
const INCLUDED = [
|
||||
"pricing.includes.score",
|
||||
"pricing.includes.domains",
|
||||
"pricing.includes.themes",
|
||||
"pricing.includes.issues",
|
||||
"pricing.includes.actions",
|
||||
"pricing.includes.trends",
|
||||
"pricing.includes.evidence",
|
||||
] as const;
|
||||
|
||||
export const Pricing = () => {
|
||||
const { t } = useTranslation("marketing");
|
||||
|
||||
return (
|
||||
<Section id="pricing">
|
||||
<SectionHeader>
|
||||
<SectionBadge>{t("pricing.label")}</SectionBadge>
|
||||
<SectionTitle>{t("pricing.title")}</SectionTitle>
|
||||
<SectionDescription>{t("pricing.description")}</SectionDescription>
|
||||
</SectionHeader>
|
||||
|
||||
{/* Anchor comparison */}
|
||||
<p className="text-muted-foreground -mt-4 text-center text-sm">
|
||||
{t("pricing.anchor")}
|
||||
</p>
|
||||
|
||||
{/* Pricing card */}
|
||||
<div className="relative w-full max-w-md">
|
||||
{/* Launch badge */}
|
||||
<div className="absolute -top-4 left-1/2 z-10 -translate-x-1/2">
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full bg-amber-500 px-4 py-1.5 text-xs font-bold text-white shadow-md">
|
||||
{t("pricing.launchBadge")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="bg-background relative overflow-hidden rounded-2xl border-2 border-amber-500/40 p-8 pt-10 shadow-lg">
|
||||
{/* Price */}
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="text-muted-foreground text-2xl line-through">
|
||||
€97
|
||||
</span>
|
||||
<span className="text-foreground text-6xl font-bold tracking-tight">
|
||||
€47
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-muted-foreground text-sm">
|
||||
{t("pricing.oneTime")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="my-6 h-px bg-gradient-to-r from-transparent via-border to-transparent" />
|
||||
|
||||
{/* What's included */}
|
||||
<div className="mb-6">
|
||||
<p className="text-foreground mb-3 text-sm font-semibold">
|
||||
{t("pricing.includesTitle")}
|
||||
</p>
|
||||
<ul className="flex flex-col gap-2.5">
|
||||
{INCLUDED.map((key) => (
|
||||
<li key={key} className="flex items-start gap-2.5">
|
||||
<svg
|
||||
className="mt-0.5 size-4 shrink-0 text-green-500"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2.5}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
<span className="text-muted-foreground text-sm">
|
||||
{t(key as any)}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<TurboLink
|
||||
href={pathsConfig.auth.login}
|
||||
className={cn(
|
||||
buttonVariants({ size: "lg" }),
|
||||
"w-full text-base font-semibold",
|
||||
)}
|
||||
>
|
||||
{t("pricing.cta")}
|
||||
</TurboLink>
|
||||
|
||||
{/* Trust line */}
|
||||
<p className="text-muted-foreground mt-4 text-center text-xs">
|
||||
{t("pricing.trust")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -18,8 +18,8 @@ const links = [
|
||||
href: "/#how-it-works",
|
||||
},
|
||||
{
|
||||
label: "billing:pricing.label",
|
||||
href: pathsConfig.marketing.pricing,
|
||||
label: "marketing:pricing.navLabel",
|
||||
href: "/#pricing",
|
||||
},
|
||||
{
|
||||
label: "marketing:contact.label",
|
||||
|
||||
Reference in New Issue
Block a user