add pricing page and extract CTA into its own component
This commit is contained in:
parent
42bcf81ee5
commit
8c5cffad7a
3 changed files with 244 additions and 44 deletions
63
src/components/CTA.tsx
Normal file
63
src/components/CTA.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { useAtom } from "jotai/index";
|
||||
import recordVideoModalOpen from "~/atoms/recordVideoModalOpen";
|
||||
import { usePostHog } from "posthog-js/react";
|
||||
|
||||
export default function CTA() {
|
||||
const [, setRecordOpen] = useAtom(recordVideoModalOpen);
|
||||
const posthog = usePostHog();
|
||||
|
||||
const openRecordModal = () => {
|
||||
setRecordOpen(true);
|
||||
|
||||
posthog?.capture("open record video modal", {
|
||||
cta: "cta section",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white">
|
||||
<div className="mx-auto max-w-7xl py-12 sm:px-6 sm:py-16 lg:px-8">
|
||||
<div className="relative isolate overflow-hidden bg-gray-900 px-6 py-24 text-center shadow-2xl sm:rounded-3xl sm:px-16">
|
||||
<h2 className="mx-auto max-w-2xl text-4xl font-bold tracking-tight text-white">
|
||||
Ready to improve how your team communicates?
|
||||
</h2>
|
||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||
<button
|
||||
onClick={openRecordModal}
|
||||
className="inline-flex max-h-[40px] items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
||||
>
|
||||
Record a video
|
||||
</button>
|
||||
</div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1024 1024"
|
||||
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-x-1/2"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle
|
||||
cx={512}
|
||||
cy={512}
|
||||
r={512}
|
||||
fill="url(#827591b1-ce8c-4110-b064-7cb85a0b1217)"
|
||||
fillOpacity="0.7"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient
|
||||
id="827591b1-ce8c-4110-b064-7cb85a0b1217"
|
||||
cx={0}
|
||||
cy={0}
|
||||
r={1}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(512 512) rotate(90) scale(512)"
|
||||
>
|
||||
<stop stopColor="#7775D6" />
|
||||
<stop offset={1} stopColor="#E935C1" stopOpacity={0} />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import { CheckIcon } from "@heroicons/react/20/solid";
|
|||
import { CheckCircleIcon } from "@heroicons/react/24/outline";
|
||||
import Footer from "~/components/Footer";
|
||||
import Header from "~/components/Header";
|
||||
import CTA from "~/components/CTA";
|
||||
|
||||
const navigation = [
|
||||
{ name: "Features", href: "#features" },
|
||||
|
|
@ -291,50 +292,7 @@ const Home: NextPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white">
|
||||
<div className="mx-auto max-w-7xl py-12 sm:px-6 sm:py-16 lg:px-8">
|
||||
<div className="relative isolate overflow-hidden bg-gray-900 px-6 py-24 text-center shadow-2xl sm:rounded-3xl sm:px-16">
|
||||
<h2 className="mx-auto max-w-2xl text-4xl font-bold tracking-tight text-white">
|
||||
Ready to improve how your team communicates?
|
||||
</h2>
|
||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||
<button
|
||||
onClick={openRecordModal}
|
||||
className="inline-flex max-h-[40px] items-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
||||
>
|
||||
Record a video
|
||||
</button>
|
||||
</div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1024 1024"
|
||||
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-x-1/2"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle
|
||||
cx={512}
|
||||
cy={512}
|
||||
r={512}
|
||||
fill="url(#827591b1-ce8c-4110-b064-7cb85a0b1217)"
|
||||
fillOpacity="0.7"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient
|
||||
id="827591b1-ce8c-4110-b064-7cb85a0b1217"
|
||||
cx={0}
|
||||
cy={0}
|
||||
r={1}
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(512 512) rotate(90) scale(512)"
|
||||
>
|
||||
<stop stopColor="#7775D6" />
|
||||
<stop offset={1} stopColor="#E935C1" stopOpacity={0} />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CTA />
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
|
|||
179
src/pages/pricing.tsx
Normal file
179
src/pages/pricing.tsx
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
import Footer from "~/components/Footer";
|
||||
import Header from "~/components/Header";
|
||||
import Head from "next/head";
|
||||
import { useState } from "react";
|
||||
import { CheckIcon } from "@heroicons/react/20/solid";
|
||||
import Tooltip from "~/components/Tooltip";
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
import { ChevronUpIcon } from "@heroicons/react/20/solid";
|
||||
import CTA from "~/components/CTA";
|
||||
import VideoRecordModal from "~/components/VideoRecordModal";
|
||||
|
||||
export default function Pricing() {
|
||||
const [billedAnnually, setBilledAnnually] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{"Snapify | Pricing"}</title>
|
||||
<meta name="description" content="Generated by create-t3-app" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<Header />
|
||||
<div className="m-20 flex h-40 items-center justify-center">
|
||||
<span className="text-center text-7xl font-bold">
|
||||
Choose the plan that fits your needs.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="mx-4 mb-20 flex flex-row gap-4 lg:mx-16 lg:gap-16">
|
||||
{[
|
||||
{
|
||||
name: "Free",
|
||||
price: { monthly: 0, annual: 0 },
|
||||
features: [
|
||||
{
|
||||
feature: "Unlimited video recording",
|
||||
description: "Record and share unlimited videos",
|
||||
},
|
||||
{
|
||||
feature: "10 video uploads",
|
||||
description: "Upload external videos to your Library",
|
||||
},
|
||||
{
|
||||
feature: "Remove branding",
|
||||
description: "Remove Snapify branding from your videos",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Pro",
|
||||
price: { monthly: 5, annual: 4 },
|
||||
features: [
|
||||
{
|
||||
feature: "Unlimited videos",
|
||||
description: "Record and share unlimited videos",
|
||||
},
|
||||
{
|
||||
feature: "Video uploads",
|
||||
description: "Upload external videos to your Library",
|
||||
},
|
||||
{
|
||||
feature: "Remove branding",
|
||||
description: "Remove Snapify branding from your videos",
|
||||
},
|
||||
],
|
||||
},
|
||||
].map(({ name, price, features }) => (
|
||||
<div
|
||||
key={name}
|
||||
className="flex-1 rounded-3xl border bg-white shadow-sm"
|
||||
>
|
||||
<div className="hero relative flex flex-col items-start rounded-3xl px-6 py-6 shadow-sm">
|
||||
<div className="rounded-lg bg-white/20 px-2 font-medium">
|
||||
{name}
|
||||
</div>
|
||||
<div className="mb-2 mt-4 flex items-end text-5xl font-extrabold tracking-tight">
|
||||
{billedAnnually ? price.annual : price.monthly}
|
||||
<span className="mb-1 text-sm opacity-80">/ mo.</span>
|
||||
</div>
|
||||
<div className="mt-2 text-sm">
|
||||
{billedAnnually ? "billed annually" : "billed monthly"}
|
||||
</div>
|
||||
<div className="mt-2 flex-grow" />
|
||||
<button
|
||||
type="submit"
|
||||
className="btn mt-4 block w-full appearance-none rounded-lg bg-black px-4 py-2.5 text-center text-sm font-medium text-white shadow-lg shadow-black/50 duration-100 focus:outline-transparent disabled:opacity-80"
|
||||
>
|
||||
Get started
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-4 flex flex-col gap-2 pb-8">
|
||||
{features.map(({ feature, description }) => (
|
||||
<div
|
||||
key={feature}
|
||||
className="flex items-center gap-2 text-gray-500"
|
||||
>
|
||||
<div className="ml-6 h-5 w-5 flex-none">
|
||||
<CheckIcon />
|
||||
</div>
|
||||
|
||||
<Tooltip title={description}>
|
||||
<div className="text-base text-gray-500 underline decoration-gray-400 decoration-dashed underline-offset-4">
|
||||
{feature}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center justify-center border-y border-[#eaeaea] pb-8">
|
||||
<div className="mb-12 mt-8">
|
||||
<span className="text-5xl font-bold">FAQs</span>
|
||||
</div>
|
||||
<div className="flex flex-1 border-collapse flex-col justify-center px-6">
|
||||
{[
|
||||
{
|
||||
question: "What is your refund policy?",
|
||||
answer:
|
||||
"If you're unhappy with your purchase for any reason, email us within 90 days and we'll refund you in full, no questions asked.",
|
||||
},
|
||||
{
|
||||
question: "Do you offer technical support?",
|
||||
answer: "No",
|
||||
},
|
||||
{
|
||||
question: "Which payment formats and currencies do you accept?",
|
||||
answer:
|
||||
"All payments on our standard plans are via credit card and PayPal.\n" +
|
||||
"\n" +
|
||||
"We use Paddle, the leading Merchant of Record for SaaS companies.\n" +
|
||||
"\n" +
|
||||
"Contact us if you need an alternative payment method.",
|
||||
},
|
||||
].map(({ answer, question }) => (
|
||||
<Disclosure
|
||||
key={question}
|
||||
as="div"
|
||||
className="w-[600px] max-w-[600px]"
|
||||
>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button className="flex h-12 w-full items-center justify-between border-t border-[#eaeaea] px-4 py-8 text-left text-sm font-medium">
|
||||
<span>{question}</span>
|
||||
<ChevronUpIcon
|
||||
className={`transition-transform ${
|
||||
open ? "rotate-180" : ""
|
||||
} h-5 w-5`}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
<Transition
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="transform scale-95 opacity-0"
|
||||
enterTo="transform scale-100 opacity-100"
|
||||
leave="transition duration-75 ease-out"
|
||||
leaveFrom="transform scale-100 opacity-100"
|
||||
leaveTo="transform scale-95 opacity-0"
|
||||
>
|
||||
<Disclosure.Panel className="px-4 pb-2 pt-0 text-sm text-gray-500">
|
||||
{answer}
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CTA />
|
||||
|
||||
<Footer />
|
||||
|
||||
<VideoRecordModal />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue