← back to Open Seo

src/client/features/ai-search/components/AiSearchPaidPlanGate.tsx

50 lines

import { Link } from "@tanstack/react-router";
import { Sparkles, type LucideIcon } from "lucide-react";
import { SUBSCRIBE_ROUTE } from "@/shared/billing";

type Props = {
  feature: string;
  description: string;
  bullets: Array<{ icon: LucideIcon; title: string; body: string }>;
};

export function AiSearchPaidPlanGate({ feature, description, bullets }: Props) {
  return (
    <div className="mx-auto max-w-3xl overflow-hidden rounded-xl border border-base-300 bg-base-100 shadow-sm">
      <div className="flex flex-col gap-5 px-6 py-6 sm:flex-row sm:items-start sm:justify-between">
        <div className="max-w-xl space-y-2">
          <span className="inline-flex items-center gap-1.5 rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary">
            <Sparkles className="size-3.5" />
            Paid plan
          </span>
          <h2 className="text-xl font-semibold tracking-tight">
            Unlock {feature}
          </h2>
          <p className="text-sm text-base-content/70">{description}</p>
        </div>
        <Link
          to={SUBSCRIBE_ROUTE}
          search={{ upgrade: true }}
          className="btn btn-primary shrink-0"
        >
          Upgrade
        </Link>
      </div>

      <div className="grid grid-cols-1 gap-5 border-t border-base-300 px-6 py-6 sm:grid-cols-3">
        {bullets.map(({ icon: Icon, title, body }) => (
          <div key={title} className="space-y-2">
            <div className="inline-flex size-9 items-center justify-center rounded-lg bg-primary/10 text-primary">
              <Icon className="size-4" />
            </div>
            <h3 className="text-sm font-semibold">{title}</h3>
            <p className="text-xs leading-relaxed text-base-content/65">
              {body}
            </p>
          </div>
        ))}
      </div>
    </div>
  );
}