️ Use nextjs layout feature

This commit is contained in:
Luke Vella 2023-02-09 19:50:36 +00:00
parent 02ef9000a7
commit c2c000f770
9 changed files with 168 additions and 154 deletions

View file

@ -17,7 +17,6 @@ import {
UserDetailsData,
UserDetailsForm,
} from "./forms";
import StandardLayout from "./layouts/standard-layout";
import Steps from "./steps";
import { useUser } from "./user-provider";
@ -144,7 +143,6 @@ const Page: NextPage<CreatePollPageProps> = ({
};
return (
<StandardLayout>
<div className="max-w-full px-3 pb-3 sm:p-4">
<div className="max-w-full">
<div className="max-w-full overflow-hidden rounded-lg border bg-white shadow-sm">
@ -219,7 +217,6 @@ const Page: NextPage<CreatePollPageProps> = ({
</div>
</div>
</div>
</StandardLayout>
);
};

View file

@ -1,16 +0,0 @@
import { MobileNavigation } from "./standard-layout/mobile-navigation";
export const ParticipantLayout = ({
children,
}: {
children?: React.ReactNode;
}) => {
return (
<div className="bg-pattern min-h-full sm:space-y-8">
<MobileNavigation />
<div className="mx-auto max-w-4xl space-y-4 px-3 pb-8">
<div>{children}</div>
</div>
</div>
);
};

View file

@ -2,19 +2,28 @@ import React from "react";
import { DayjsProvider } from "@/utils/dayjs";
import { NextPageWithLayout } from "../../types";
import { UserProvider } from "../user-provider";
import { MobileNavigation } from "./standard-layout/mobile-navigation";
const StandardLayout: React.VoidFunctionComponent<{
children?: React.ReactNode;
}> = ({ children, ...rest }) => {
return (
<UserProvider>
<DayjsProvider>
<div className="bg-pattern relative min-h-full" {...rest}>
<div className={"bg-pattern relative min-h-full"} {...rest}>
<MobileNavigation />
<div className="mx-auto max-w-4xl">{children}</div>
</div>
</DayjsProvider>
</UserProvider>
);
};
export default StandardLayout;
export const getStandardLayout: NextPageWithLayout["getLayout"] =
function getLayout(page) {
return <StandardLayout>{page}</StandardLayout>;
};

View file

@ -16,7 +16,9 @@ import Maintenance from "@/components/maintenance";
import { useCrispChat } from "../components/crisp-chat";
import ModalProvider from "../components/modal/modal-provider";
import { NextPageWithLayout } from "../types";
import { absoluteUrl } from "../utils/absolute-url";
import { UserSession } from "../utils/auth";
import { trpcNext } from "../utils/trpc";
const inter = Inter({
@ -29,7 +31,15 @@ const noto = Noto_Sans_Mono({
display: "swap",
});
const MyApp: NextPage<AppProps> = ({ Component, pageProps }) => {
type PageProps = {
user: UserSession;
};
type AppPropsWithLayout = AppProps<PageProps> & {
Component: NextPageWithLayout<PageProps>;
};
const MyApp: NextPage<AppPropsWithLayout> = ({ Component, pageProps }) => {
useCrispChat();
React.useEffect(() => {
@ -43,6 +53,8 @@ const MyApp: NextPage<AppProps> = ({ Component, pageProps }) => {
return <Maintenance />;
}
const getLayout = Component.getLayout ?? ((page) => page);
return (
<>
<DefaultSeo
@ -77,9 +89,7 @@ const MyApp: NextPage<AppProps> = ({ Component, pageProps }) => {
--font-noto: ${noto.style.fontFamily};
}
`}</style>
<ModalProvider>
<Component {...pageProps} />
</ModalProvider>
<ModalProvider>{getLayout(<Component {...pageProps} />)}</ModalProvider>
</>
);
};

View file

@ -1,23 +1,22 @@
import { GetServerSideProps, NextPage } from "next";
import { GetServerSideProps } from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import React from "react";
import FullPageLoader from "@/components/full-page-loader";
import StandardLayout from "@/components/layouts/standard-layout";
import { getStandardLayout } from "@/components/layouts/standard-layout";
import { ParticipantsProvider } from "@/components/participants-provider";
import { Poll } from "@/components/poll";
import { PollContextProvider } from "@/components/poll-context";
import { withSession } from "@/components/user-provider";
import { withSessionSsr } from "@/utils/auth";
import { trpcNext } from "@/utils/trpc";
import { withPageTranslations } from "@/utils/with-page-translations";
import { AdminControls } from "../../components/admin-control";
import ModalProvider from "../../components/modal/modal-provider";
import { NextPageWithLayout } from "../../types";
const PollPageLoader: NextPage = () => {
const Page: NextPageWithLayout = () => {
const { query } = useRouter();
const { t } = useTranslation("app");
const urlId = query.urlId as string;
@ -34,7 +33,6 @@ const PollPageLoader: NextPage = () => {
<meta name="robots" content="noindex,nofollow" />
</Head>
<ParticipantsProvider pollId={poll.id}>
<StandardLayout>
<PollContextProvider poll={poll} urlId={urlId} admin={true}>
<ModalProvider>
<div className="flex flex-col space-y-3 p-3 sm:space-y-4 sm:p-4">
@ -44,7 +42,6 @@ const PollPageLoader: NextPage = () => {
</div>
</ModalProvider>
</PollContextProvider>
</StandardLayout>
</ParticipantsProvider>
</>
);
@ -53,6 +50,8 @@ const PollPageLoader: NextPage = () => {
return <FullPageLoader>{t("loading")}</FullPageLoader>;
};
Page.getLayout = getStandardLayout;
export const getServerSideProps: GetServerSideProps = withSessionSsr(
withPageTranslations(["common", "app", "errors"]),
{
@ -64,4 +63,4 @@ export const getServerSideProps: GetServerSideProps = withSessionSsr(
},
);
export default withSession(PollPageLoader);
export default Page;

View file

@ -4,11 +4,12 @@ import { useTranslation } from "react-i18next";
import CreatePoll from "@/components/create-poll";
import { withSession } from "../components/user-provider";
import StandardLayout from "../components/layouts/standard-layout";
import { NextPageWithLayout } from "../types";
import { withSessionSsr } from "../utils/auth";
import { withPageTranslations } from "../utils/with-page-translations";
const Page = () => {
const Page: NextPageWithLayout = () => {
const { t } = useTranslation("app");
return (
<>
@ -20,7 +21,12 @@ const Page = () => {
</>
);
};
export default withSession(Page);
Page.getLayout = function getLayout(page) {
return <StandardLayout>{page}</StandardLayout>;
};
export default Page;
export const getServerSideProps: GetServerSideProps = withSessionSsr(
withPageTranslations(["common", "app"]),

View file

@ -1,4 +1,4 @@
import { GetServerSideProps, NextPage } from "next";
import { GetServerSideProps } from "next";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
@ -7,16 +7,16 @@ import { useTranslation } from "next-i18next";
import { ParticipantsProvider } from "@/components/participants-provider";
import { Poll } from "@/components/poll";
import { PollContextProvider } from "@/components/poll-context";
import { useUser, withSession } from "@/components/user-provider";
import { useUser } from "@/components/user-provider";
import { withSessionSsr } from "@/utils/auth";
import { trpcNext } from "@/utils/trpc";
import { withPageTranslations } from "@/utils/with-page-translations";
import { ParticipantLayout } from "../../components/layouts/participant-layout";
import StandardLayout from "../../components/layouts/standard-layout";
import ModalProvider from "../../components/modal/modal-provider";
import { DayjsProvider } from "../../utils/dayjs";
import { NextPageWithLayout } from "../../types";
const Page: NextPage = () => {
const Page: NextPageWithLayout = () => {
const { query } = useRouter();
const urlId = query.urlId as string;
@ -33,9 +33,7 @@ const Page: NextPage = () => {
<title>{poll.title}</title>
<meta name="robots" content="noindex,nofollow" />
</Head>
<DayjsProvider>
<ParticipantsProvider pollId={poll.id}>
<ParticipantLayout>
<PollContextProvider poll={poll} urlId={urlId} admin={false}>
<ModalProvider>
<div className="space-y-3 sm:space-y-4">
@ -51,9 +49,7 @@ const Page: NextPage = () => {
</div>
</ModalProvider>
</PollContextProvider>
</ParticipantLayout>
</ParticipantsProvider>
</DayjsProvider>
</>
);
}
@ -61,6 +57,10 @@ const Page: NextPage = () => {
return null;
};
Page.getLayout = function getLayout(page) {
return <StandardLayout>{page}</StandardLayout>;
};
export const getServerSideProps: GetServerSideProps = withSessionSsr(
withPageTranslations(["common", "app", "errors"]),
{
@ -72,4 +72,4 @@ export const getServerSideProps: GetServerSideProps = withSessionSsr(
},
);
export default withSession(Page);
export default Page;

View file

@ -1,20 +1,16 @@
import { NextPage } from "next";
import { withSessionSsr } from "@/utils/auth";
import StandardLayout from "../components/layouts/standard-layout";
import { getStandardLayout } from "../components/layouts/standard-layout";
import { Profile } from "../components/profile";
import { withSession } from "../components/user-provider";
import { NextPageWithLayout } from "../types";
import { withPageTranslations } from "../utils/with-page-translations";
const Page: NextPage = () => {
return (
<StandardLayout>
<Profile />
</StandardLayout>
);
const Page: NextPageWithLayout = () => {
return <Profile />;
};
Page.getLayout = getStandardLayout;
export const getServerSideProps = withSessionSsr(async (ctx) => {
if (ctx.req.session.user.isGuest !== false) {
return {
@ -27,4 +23,4 @@ export const getServerSideProps = withSessionSsr(async (ctx) => {
return withPageTranslations(["common", "app"])(ctx);
});
export default withSession(Page);
export default Page;

13
src/types.ts Normal file
View file

@ -0,0 +1,13 @@
import { NextPage } from "next";
import React from "react";
export type ReactTag = keyof JSX.IntrinsicElements;
export type PropsOf<TTag extends ReactTag> = TTag extends React.ElementType
? React.ComponentProps<TTag>
: never;
// eslint-disable-next-line @typescript-eslint/ban-types
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};