CAL-473 Fixes client-side routing for authed pages (#763)
This commit is contained in:
parent
d3d6778c60
commit
420daec147
14 changed files with 62 additions and 53 deletions
|
@ -1,18 +1,26 @@
|
||||||
import { Provider } from "next-auth/client";
|
import { Provider } from "next-auth/client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { QueryClient, QueryClientProvider } from "react-query";
|
import { HydrateProps, QueryClient, QueryClientProvider } from "react-query";
|
||||||
import { Hydrate } from "react-query/hydration";
|
import { Hydrate } from "react-query/hydration";
|
||||||
|
|
||||||
|
import { Session } from "@lib/auth";
|
||||||
import { createTelemetryClient, TelemetryProvider } from "@lib/telemetry";
|
import { createTelemetryClient, TelemetryProvider } from "@lib/telemetry";
|
||||||
|
|
||||||
export const queryClient = new QueryClient();
|
export const queryClient = new QueryClient();
|
||||||
|
|
||||||
const AppProviders: React.FC = (props, pageProps) => {
|
type AppProviderProps = {
|
||||||
|
pageProps: {
|
||||||
|
session?: Session;
|
||||||
|
dehydratedState?: HydrateProps;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppProviders: React.FC<AppProviderProps> = ({ pageProps, children }) => {
|
||||||
return (
|
return (
|
||||||
<TelemetryProvider value={createTelemetryClient()}>
|
<TelemetryProvider value={createTelemetryClient()}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<Hydrate state={pageProps.dehydratedState}>
|
<Hydrate state={pageProps.dehydratedState}>
|
||||||
<Provider session={pageProps.session}>{props.children}</Provider>
|
<Provider session={pageProps.session}>{children}</Provider>
|
||||||
</Hydrate>
|
</Hydrate>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</TelemetryProvider>
|
</TelemetryProvider>
|
||||||
|
|
|
@ -15,7 +15,7 @@ export type AppProps = NextAppProps & {
|
||||||
|
|
||||||
function MyApp({ Component, pageProps, err }: AppProps) {
|
function MyApp({ Component, pageProps, err }: AppProps) {
|
||||||
return (
|
return (
|
||||||
<AppProviders>
|
<AppProviders pageProps={pageProps}>
|
||||||
<DefaultSeo {...seoConfig.defaultNextSeo} />
|
<DefaultSeo {...seoConfig.defaultNextSeo} />
|
||||||
<Component {...pageProps} err={err} />
|
<Component {...pageProps} err={err} />
|
||||||
</AppProviders>
|
</AppProviders>
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { asStringOrNull } from "@lib/asStringOrNull";
|
||||||
import { getBusyCalendarTimes } from "@lib/calendarClient";
|
import { getBusyCalendarTimes } from "@lib/calendarClient";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
|
||||||
|
import { Prisma } from ".prisma/client";
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const user = asStringOrNull(req.query.user);
|
const user = asStringOrNull(req.query.user);
|
||||||
const dateFrom = dayjs(asStringOrNull(req.query.dateFrom));
|
const dateFrom = dayjs(asStringOrNull(req.query.dateFrom));
|
||||||
|
@ -32,19 +34,24 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventType = await prisma.eventType.findUnique({
|
const getEventType = (id: number) =>
|
||||||
where: { id: eventTypeId },
|
prisma.eventType.findUnique({
|
||||||
select: {
|
where: { id },
|
||||||
timeZone: true,
|
select: {
|
||||||
availability: {
|
timeZone: true,
|
||||||
select: {
|
availability: {
|
||||||
startTime: true,
|
select: {
|
||||||
endTime: true,
|
startTime: true,
|
||||||
days: true,
|
endTime: true,
|
||||||
|
days: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
type EventType = Prisma.PromiseReturnType<typeof getEventType>;
|
||||||
|
let eventType: EventType | null = null;
|
||||||
|
if (eventTypeId) eventType = await getEventType(eventTypeId);
|
||||||
|
|
||||||
if (!rawUser) throw new Error("No user found");
|
if (!rawUser) throw new Error("No user found");
|
||||||
|
|
||||||
|
|
|
@ -339,6 +339,6 @@ export async function getServerSideProps(context) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
props: { user, types }, // will be passed to the page component as props
|
props: { session, user, types },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSidePropsContext } from "next";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
|
|
||||||
import Loader from "@components/Loader";
|
import Loader from "@components/Loader";
|
||||||
import Shell from "@components/Shell";
|
import Shell from "@components/Shell";
|
||||||
|
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
|
||||||
export default function Troubleshoot({ user }) {
|
export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSideProps>) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [availability, setAvailability] = useState([]);
|
const [availability, setAvailability] = useState([]);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
const [selectedDate] = useState(dayjs());
|
||||||
const [selectedDate, setSelectedDate] = useState(dayjs());
|
|
||||||
|
|
||||||
function convertMinsToHrsMins(mins) {
|
function convertMinsToHrsMins(mins: number) {
|
||||||
let h = Math.floor(mins / 60);
|
let h = Math.floor(mins / 60);
|
||||||
let m = mins % 60;
|
let m = mins % 60;
|
||||||
h = h < 10 ? "0" + h : h;
|
h = h < 10 ? "0" + h : h;
|
||||||
|
@ -97,9 +96,9 @@ export default function Troubleshoot({ user }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||||
const session = await getSession(context);
|
const session = await getSession(context);
|
||||||
if (!session) {
|
if (!session?.user?.id) {
|
||||||
return { redirect: { permanent: false, destination: "/auth/login" } };
|
return { redirect: { permanent: false, destination: "/auth/login" } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +113,9 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!user) return { redirect: { permanent: false, destination: "/auth/login" } };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { user },
|
props: { session, user },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -346,5 +346,5 @@ export async function getServerSideProps(context) {
|
||||||
return { ...booking, startTime: booking.startTime.toISOString(), endTime: booking.endTime.toISOString() };
|
return { ...booking, startTime: booking.startTime.toISOString(), endTime: booking.endTime.toISOString() };
|
||||||
});
|
});
|
||||||
|
|
||||||
return { props: { bookings } };
|
return { props: { session, bookings } };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1350,6 +1350,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
session,
|
||||||
localeProp: locale,
|
localeProp: locale,
|
||||||
eventType: eventTypeObject,
|
eventType: eventTypeObject,
|
||||||
locationOptions,
|
locationOptions,
|
||||||
|
|
|
@ -475,7 +475,7 @@ const CreateNewEventDialog = ({
|
||||||
<div className="mt-1">
|
<div className="mt-1">
|
||||||
<div className="flex rounded-sm shadow-sm">
|
<div className="flex rounded-sm shadow-sm">
|
||||||
<span className="inline-flex items-center px-3 text-gray-500 border border-r-0 border-gray-300 rounded-l-md bg-gray-50 sm:text-sm">
|
<span className="inline-flex items-center px-3 text-gray-500 border border-r-0 border-gray-300 rounded-l-md bg-gray-50 sm:text-sm">
|
||||||
{location.hostname}/{router.query.eventPage || profiles[0].slug}/
|
{process.env.NEXT_PUBLIC_APP_URL}/{router.query.eventPage || profiles[0].slug}/
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
ref={slugRef}
|
ref={slugRef}
|
||||||
|
@ -723,6 +723,7 @@ export async function getServerSideProps(context) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
session,
|
||||||
localeProp: locale,
|
localeProp: locale,
|
||||||
canAddEvents,
|
canAddEvents,
|
||||||
user: userObj,
|
user: userObj,
|
||||||
|
|
|
@ -98,6 +98,6 @@ export async function getServerSideProps(context) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
props: { integration }, // will be passed to the page component as props
|
props: { session, integration },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -495,6 +495,6 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
const integrations = getIntegrations(credentials);
|
const integrations = getIntegrations(credentials);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { integrations },
|
props: { session, integrations },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,6 @@ export async function getServerSideProps(context) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { user }, // will be passed to the page component as props
|
props: { session, user },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
|
import { GetServerSidePropsContext } from "next";
|
||||||
import { useSession } from "next-auth/client";
|
import { useSession } from "next-auth/client";
|
||||||
|
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
|
|
||||||
import Loader from "@components/Loader";
|
import Loader from "@components/Loader";
|
||||||
import SettingsShell from "@components/Settings";
|
import SettingsShell from "@components/Settings";
|
||||||
import Shell from "@components/Shell";
|
import Shell from "@components/Shell";
|
||||||
|
|
||||||
export default function Embed(props) {
|
export default function Embed(props: inferSSRProps<typeof getServerSideProps>) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
const [, loading] = useSession();
|
||||||
const [session, loading] = useSession();
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const iframeTemplate = `<iframe src="${process.env.NEXT_PUBLIC_APP_URL}/${props.user?.username}" frameborder="0" allowfullscreen></iframe>`;
|
||||||
|
const htmlTemplate = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Schedule a meeting</title><style>body {margin: 0;}iframe {height: calc(100vh - 4px);width: calc(100vw - 4px);box-sizing: border-box;}</style></head><body>${iframeTemplate}</body></html>`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell heading="Embed" subtitle="Integrate with your website using our embed options.">
|
<Shell heading="Embed" subtitle="Integrate with your website using our embed options.">
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
|
@ -33,13 +37,7 @@ export default function Embed(props) {
|
||||||
id="iframe"
|
id="iframe"
|
||||||
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
|
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
|
||||||
placeholder="Loading..."
|
placeholder="Loading..."
|
||||||
defaultValue={
|
defaultValue={iframeTemplate}
|
||||||
'<iframe src="' +
|
|
||||||
props.BASE_URL +
|
|
||||||
"/" +
|
|
||||||
session.user.username +
|
|
||||||
'" frameborder="0" allowfullscreen></iframe>'
|
|
||||||
}
|
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,13 +51,7 @@ export default function Embed(props) {
|
||||||
id="fullscreen"
|
id="fullscreen"
|
||||||
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
|
className="h-32 shadow-sm focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-sm"
|
||||||
placeholder="Loading..."
|
placeholder="Loading..."
|
||||||
defaultValue={
|
defaultValue={htmlTemplate}
|
||||||
'<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Schedule a meeting</title><style>body {margin: 0;}iframe {height: calc(100vh - 4px);width: calc(100vw - 4px);box-sizing: border-box;}</style></head><body><iframe src="' +
|
|
||||||
props.BASE_URL +
|
|
||||||
"/" +
|
|
||||||
session.user.username +
|
|
||||||
'" frameborder="0" allowfullscreen></iframe></body></html>'
|
|
||||||
}
|
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,9 +72,9 @@ export default function Embed(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getServerSideProps(context) {
|
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
const session = await getSession(context);
|
const session = await getSession(context);
|
||||||
if (!session) {
|
if (!session?.user?.email) {
|
||||||
return { redirect: { permanent: false, destination: "/auth/login" } };
|
return { redirect: { permanent: false, destination: "/auth/login" } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +94,7 @@ export async function getServerSideProps(context) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BASE_URL = process.env.BASE_URL;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { user, BASE_URL }, // will be passed to the page component as props
|
props: { session, user },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -433,6 +433,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
session,
|
||||||
localeProp: locale,
|
localeProp: locale,
|
||||||
localeOptions,
|
localeOptions,
|
||||||
localeLabels,
|
localeLabels,
|
||||||
|
|
|
@ -46,6 +46,6 @@ export async function getServerSideProps(context) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: { user }, // will be passed to the page component as props
|
props: { session, user },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue