add pricing page and extract CTA into its own component

This commit is contained in:
MarconLP 2023-04-27 17:58:02 +02:00
parent 42bcf81ee5
commit 8c5cffad7a
No known key found for this signature in database
GPG key ID: A08A9C8B623F5EA5
3 changed files with 244 additions and 44 deletions

63
src/components/CTA.tsx Normal file
View 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>
);
}

View file

@ -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
View 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 />
</>
);
}