extract public pages layout
This commit is contained in:
parent
47aa722697
commit
1e681ca693
29
app/public-area/components/base-layout.tsx
Normal file
29
app/public-area/components/base-layout.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import type { FunctionComponent } from "react";
|
||||
import { Head } from "blitz";
|
||||
|
||||
import Header from "./header";
|
||||
|
||||
const BaseLayout: FunctionComponent = ({ children }) => (
|
||||
<>
|
||||
<Head>
|
||||
<title>Shellphone: Your Personal Cloud Phone</title>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/P22MackinacPro-ExtraBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Head>
|
||||
|
||||
<section className="font-inter antialiased bg-white text-gray-900 tracking-tight">
|
||||
<section className="flex flex-col min-h-screen overflow-hidden">
|
||||
<Header />
|
||||
|
||||
<main className="flex-grow">{children}</main>
|
||||
</section>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
|
||||
export default BaseLayout;
|
@ -50,14 +50,6 @@ function DesktopNavLink({ href, label }: NavLinkProps) {
|
||||
);
|
||||
}
|
||||
|
||||
function MobileNavLink({ href, label }: NavLinkProps) {
|
||||
return (
|
||||
<Link href={href}>
|
||||
<a className="flex text-gray-600 hover:text-gray-900 py-2">{label}</a>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function MobileNav() {
|
||||
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
||||
|
||||
@ -183,6 +175,16 @@ function MobileNav() {
|
||||
</Transition.Root>
|
||||
</div>
|
||||
);
|
||||
|
||||
function MobileNavLink({ href, label }: NavLinkProps) {
|
||||
return (
|
||||
<Link href={href}>
|
||||
<a onClick={() => setMobileNavOpen(false)} className="flex text-gray-600 hover:text-gray-900 py-2">
|
||||
{label}
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
23
app/public-area/components/layout.tsx
Normal file
23
app/public-area/components/layout.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import type { FunctionComponent } from "react";
|
||||
|
||||
import BaseLayout from "./base-layout";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
};
|
||||
|
||||
const Layout: FunctionComponent<Props> = ({ children, title }) => (
|
||||
<BaseLayout>
|
||||
<section className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div className="pt-32 pb-10 md:pt-34 md:pb-16">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<h1 className="h1 mb-16 font-extrabold font-mackinac">{title}</h1>
|
||||
</div>
|
||||
|
||||
<div className="max-w-3xl mx-auto text-lg xl:text-xl flow-root">{children}</div>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
);
|
||||
|
||||
export default Layout;
|
@ -1,42 +1,21 @@
|
||||
import type { BlitzPage } from "blitz";
|
||||
import { Head } from "blitz";
|
||||
|
||||
import Header from "../components/header";
|
||||
import BaseLayout from "../components/base-layout";
|
||||
import ReferralBanner from "../components/referral-banner";
|
||||
import Hero from "../components/hero";
|
||||
import FAQs from "../components/faqs";
|
||||
import Footer from "../components/footer";
|
||||
|
||||
const LandingPage: BlitzPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Shellphone: Your Personal Cloud Phone</title>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/P22MackinacPro-ExtraBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Head>
|
||||
<ReferralBanner />
|
||||
<section className="font-inter antialiased bg-white text-gray-900 tracking-tight">
|
||||
<section className="flex flex-col min-h-screen overflow-hidden">
|
||||
<Header />
|
||||
|
||||
<main className="flex-grow">
|
||||
<Hero />
|
||||
<FAQs />
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
</section>
|
||||
<Hero />
|
||||
<FAQs />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
LandingPage.getLayout = (page) => <BaseLayout>{page}</BaseLayout>;
|
||||
LandingPage.suppressFirstRenderFlicker = true;
|
||||
|
||||
export default LandingPage;
|
||||
|
@ -1,10 +1,9 @@
|
||||
import type { BlitzPage } from "blitz";
|
||||
import { Head, useQuery } from "blitz";
|
||||
import { useQuery } from "blitz";
|
||||
|
||||
import getMetrics from "../queries/get-metrics";
|
||||
|
||||
import Header from "../components/header";
|
||||
import Footer from "../components/footer";
|
||||
import Layout from "../components/layout";
|
||||
|
||||
const initialData = {
|
||||
phoneNumbers: 0,
|
||||
@ -17,43 +16,11 @@ const OpenMetrics: BlitzPage = () => {
|
||||
const { phoneNumbers, smsExchanged, minutesCalled } = metrics ?? initialData;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Shellphone: Your Personal Cloud Phone</title>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/P22MackinacPro-ExtraBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Head>
|
||||
<section className="font-inter antialiased bg-white text-gray-900 tracking-tight">
|
||||
<section className="flex flex-col min-h-screen overflow-hidden">
|
||||
<Header />
|
||||
|
||||
<main className="flex-grow">
|
||||
<section className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div className="pt-32 pb-10 md:pt-34 md:pb-16">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<h1 className="h1 mb-16 font-extrabold font-mackinac">Open Metrics</h1>
|
||||
</div>
|
||||
|
||||
<div className="max-w-3xl mx-auto text-lg xl:text-xl flow-root">
|
||||
<dl className="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
|
||||
<Card title="Phone Numbers Registered" value={phoneNumbers} />
|
||||
<Card title="SMS Exchanged" value={smsExchanged} />
|
||||
<Card title="Minutes on Call" value={minutesCalled} />
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
</section>
|
||||
</>
|
||||
<dl className="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
|
||||
<Card title="Phone Numbers Registered" value={phoneNumbers} />
|
||||
<Card title="SMS Exchanged" value={smsExchanged} />
|
||||
<Card title="Minutes on Call" value={minutesCalled} />
|
||||
</dl>
|
||||
);
|
||||
};
|
||||
|
||||
@ -66,6 +33,7 @@ function Card({ title, value }: any) {
|
||||
);
|
||||
}
|
||||
|
||||
OpenMetrics.getLayout = (page) => <Layout title="Open Metrics">{page}</Layout>;
|
||||
OpenMetrics.suppressFirstRenderFlicker = true;
|
||||
|
||||
export default OpenMetrics;
|
||||
|
@ -5,104 +5,56 @@ import { CheckIcon, XIcon, TerminalIcon } from "@heroicons/react/solid";
|
||||
|
||||
import Header from "../components/header";
|
||||
import Footer from "../components/footer";
|
||||
import Layout from "../components/layout";
|
||||
|
||||
const Roadmap: BlitzPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Shellphone: Your Personal Cloud Phone</title>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/P22MackinacPro-ExtraBold.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Head>
|
||||
<section className="font-inter antialiased bg-white text-gray-900 tracking-tight">
|
||||
<section className="flex flex-col min-h-screen overflow-hidden">
|
||||
<Header />
|
||||
|
||||
<main className="flex-grow">
|
||||
<section className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div className="pt-32 pb-10 md:pt-34 md:pb-16">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<h1 className="h1 mb-16 font-extrabold font-mackinac">(Rough) Roadmap</h1>
|
||||
<ul role="list" className="-mb-8">
|
||||
{roadmap.map((feature, index) => {
|
||||
const isDone = feature.status === "done";
|
||||
const isInProgress = feature.status === "in-progress";
|
||||
return (
|
||||
<li key={feature.name}>
|
||||
<div className="relative pb-8">
|
||||
{index !== roadmap.length - 1 ? (
|
||||
<span
|
||||
className="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : null}
|
||||
<div className="relative flex space-x-3">
|
||||
<div>
|
||||
<span
|
||||
className={clsx(
|
||||
isDone ? "bg-green-500" : isInProgress ? "bg-yellow-500" : "bg-gray-400",
|
||||
"h-8 w-8 rounded-full flex items-center justify-center ring-8 ring-white",
|
||||
)}
|
||||
>
|
||||
{isDone ? (
|
||||
<CheckIcon className="h-5 w-5 text-white" aria-hidden="true" />
|
||||
) : isInProgress ? (
|
||||
<TerminalIcon className="h-5 w-5 text-white" aria-hidden="true" />
|
||||
) : (
|
||||
<XIcon className="h-5 w-5 text-white" aria-hidden="true" />
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="max-w-3xl mx-auto text-lg xl:text-xl flow-root">
|
||||
<ul role="list" className="-mb-8">
|
||||
{roadmap.map((feature, index) => {
|
||||
const isDone = feature.status === "done";
|
||||
const isInProgress = feature.status === "in-progress";
|
||||
return (
|
||||
<li key={feature.name}>
|
||||
<div className="relative pb-8">
|
||||
{index !== roadmap.length - 1 ? (
|
||||
<span
|
||||
className="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : null}
|
||||
<div className="relative flex space-x-3">
|
||||
<div>
|
||||
<span
|
||||
className={clsx(
|
||||
isDone
|
||||
? "bg-green-500"
|
||||
: isInProgress
|
||||
? "bg-yellow-500"
|
||||
: "bg-gray-400",
|
||||
"h-8 w-8 rounded-full flex items-center justify-center ring-8 ring-white",
|
||||
)}
|
||||
>
|
||||
{isDone ? (
|
||||
<CheckIcon
|
||||
className="h-5 w-5 text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : isInProgress ? (
|
||||
<TerminalIcon
|
||||
className="h-5 w-5 text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : (
|
||||
<XIcon
|
||||
className="h-5 w-5 text-white"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1 items-center flex justify-between space-x-4">
|
||||
<div>
|
||||
<p className="text-md xl:text-lg text-gray-900">
|
||||
{feature.name}
|
||||
</p>
|
||||
</div>
|
||||
{isDone ? (
|
||||
<div className="text-right self-start text-md xl:text-lg whitespace-nowrap text-gray-500">
|
||||
<time>
|
||||
{formatter.format(feature.doneDate)}
|
||||
</time>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className="min-w-0 flex-1 items-center flex justify-between space-x-4">
|
||||
<div>
|
||||
<p className="text-md xl:text-lg text-gray-900">{feature.name}</p>
|
||||
</div>
|
||||
{isDone ? (
|
||||
<div className="text-right self-start text-md xl:text-lg whitespace-nowrap text-gray-500">
|
||||
<time>{formatter.format(feature.doneDate)}</time>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
</section>
|
||||
</>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
@ -185,6 +137,7 @@ const formatter = Intl.DateTimeFormat("en-US", {
|
||||
year: "numeric",
|
||||
});
|
||||
|
||||
Roadmap.getLayout = (page) => <Layout title="(Rough) Roadmap">{page}</Layout>;
|
||||
Roadmap.suppressFirstRenderFlicker = true;
|
||||
|
||||
export default Roadmap;
|
||||
|
Loading…
Reference in New Issue
Block a user