refactor: add next-seo (#531)
* refactor: add next-seo * refactor: change naming of seo component
This commit is contained in:
parent
fc50821282
commit
a37411b8af
33 changed files with 290 additions and 298 deletions
|
@ -3,7 +3,7 @@ import React, { Fragment, useEffect, useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { signOut, useSession } from "next-auth/client";
|
import { signOut, useSession } from "next-auth/client";
|
||||||
import { Menu, Transition } from "@headlessui/react";
|
import { Menu, Transition } from "@headlessui/react";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
|
||||||
import { SelectorIcon } from "@heroicons/react/outline";
|
import { SelectorIcon } from "@heroicons/react/outline";
|
||||||
import {
|
import {
|
||||||
CalendarIcon,
|
CalendarIcon,
|
||||||
|
@ -20,6 +20,7 @@ import classNames from "@lib/classNames";
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
import Avatar from "@components/Avatar";
|
import Avatar from "@components/Avatar";
|
||||||
import { User } from "@prisma/client";
|
import { User } from "@prisma/client";
|
||||||
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
|
|
||||||
export default function Shell(props) {
|
export default function Shell(props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -70,8 +71,18 @@ export default function Shell(props) {
|
||||||
router.replace("/auth/login");
|
router.replace("/auth/login");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pageTitle = typeof props.heading === "string" ? props.heading : props.title;
|
||||||
|
|
||||||
return session ? (
|
return session ? (
|
||||||
<>
|
<>
|
||||||
|
<HeadSeo
|
||||||
|
title={pageTitle}
|
||||||
|
description={props.subtitle}
|
||||||
|
nextSeoProps={{
|
||||||
|
nofollow: true,
|
||||||
|
noindex: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div>
|
<div>
|
||||||
<Toaster position="bottom-right" />
|
<Toaster position="bottom-right" />
|
||||||
</div>
|
</div>
|
||||||
|
|
101
components/seo/head-seo.tsx
Normal file
101
components/seo/head-seo.tsx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import { NextSeo, NextSeoProps } from "next-seo";
|
||||||
|
import React from "react";
|
||||||
|
import { getBrowserInfo } from "@lib/core/browser/browser.utils";
|
||||||
|
import { getSeoImage, seoConfig } from "@lib/config/next-seo.config";
|
||||||
|
import merge from "lodash.merge";
|
||||||
|
|
||||||
|
export type HeadSeoProps = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
siteName?: string;
|
||||||
|
name?: string;
|
||||||
|
avatar?: string;
|
||||||
|
url?: string;
|
||||||
|
canonical?: string;
|
||||||
|
nextSeoProps?: NextSeoProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build full seo tags from title, desc, canonical and url
|
||||||
|
*/
|
||||||
|
const buildSeoMeta = (pageProps: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
image: string;
|
||||||
|
siteName?: string;
|
||||||
|
url?: string;
|
||||||
|
canonical?: string;
|
||||||
|
}): NextSeoProps => {
|
||||||
|
const { title, description, image, canonical, siteName = seoConfig.headSeo.siteName } = pageProps;
|
||||||
|
return {
|
||||||
|
title: title,
|
||||||
|
canonical: canonical,
|
||||||
|
openGraph: {
|
||||||
|
site_name: siteName,
|
||||||
|
type: "website",
|
||||||
|
title: title,
|
||||||
|
description: description,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: image,
|
||||||
|
//width: 1077,
|
||||||
|
//height: 565,
|
||||||
|
//alt: "Alt image"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
additionalMetaTags: [
|
||||||
|
{
|
||||||
|
property: "name",
|
||||||
|
content: title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: "description",
|
||||||
|
content: description,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "description",
|
||||||
|
content: description,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: "image",
|
||||||
|
content: image,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const constructImage = (name: string, avatar: string, description: string): string => {
|
||||||
|
return (
|
||||||
|
encodeURIComponent("Meet **" + name + "** <br>" + description).replace(/'/g, "%27") +
|
||||||
|
".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" +
|
||||||
|
encodeURIComponent(avatar)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HeadSeo: React.FC<HeadSeoProps & { children?: never }> = (props) => {
|
||||||
|
const defaultUrl = getBrowserInfo()?.url;
|
||||||
|
const image = getSeoImage("default");
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
name = null,
|
||||||
|
avatar = null,
|
||||||
|
siteName,
|
||||||
|
canonical = defaultUrl,
|
||||||
|
nextSeoProps = {},
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const pageTitle = title + " | Calendso";
|
||||||
|
let seoObject = buildSeoMeta({ title: pageTitle, image, description, canonical, siteName });
|
||||||
|
|
||||||
|
if (name && avatar) {
|
||||||
|
const pageImage = getSeoImage("ogImage") + constructImage(name, avatar, description);
|
||||||
|
seoObject = buildSeoMeta({ title: pageTitle, description, image: pageImage, canonical, siteName });
|
||||||
|
}
|
||||||
|
|
||||||
|
const seoProps: NextSeoProps = merge(nextSeoProps, seoObject);
|
||||||
|
|
||||||
|
return <NextSeo {...seoProps} />;
|
||||||
|
};
|
27
lib/config/next-seo.config.ts
Normal file
27
lib/config/next-seo.config.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { DefaultSeoProps } from "next-seo";
|
||||||
|
import { HeadSeoProps } from "@components/seo/head-seo";
|
||||||
|
|
||||||
|
const seoImages = {
|
||||||
|
default: "https://calendso.com/og-image.png",
|
||||||
|
ogImage: "https://og-image-one-pi.vercel.app/",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSeoImage = (key: keyof typeof seoImages): string => {
|
||||||
|
return seoImages[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const seoConfig: {
|
||||||
|
headSeo: Required<Pick<HeadSeoProps, "siteName">>;
|
||||||
|
defaultNextSeo: DefaultSeoProps;
|
||||||
|
} = {
|
||||||
|
headSeo: {
|
||||||
|
siteName: "Calendso",
|
||||||
|
},
|
||||||
|
defaultNextSeo: {
|
||||||
|
twitter: {
|
||||||
|
handle: "@calendso",
|
||||||
|
site: "@Calendso",
|
||||||
|
cardType: "summary_large_image",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
22
lib/core/browser/browser.utils.ts
Normal file
22
lib/core/browser/browser.utils.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
export const isBrowser = () => typeof window !== "undefined";
|
||||||
|
|
||||||
|
type BrowserInfo = {
|
||||||
|
url: string;
|
||||||
|
path: string;
|
||||||
|
referrer: string;
|
||||||
|
title: string;
|
||||||
|
query: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getBrowserInfo = (): Partial<BrowserInfo> => {
|
||||||
|
if (!isBrowser()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
url: window.document.location?.href ?? undefined,
|
||||||
|
path: window.document.location?.pathname ?? undefined,
|
||||||
|
referrer: window.document?.referrer ?? undefined,
|
||||||
|
title: window.document.title ?? undefined,
|
||||||
|
query: window.document.location?.search,
|
||||||
|
};
|
||||||
|
};
|
|
@ -42,6 +42,7 @@
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"next": "^10.2.3",
|
"next": "^10.2.3",
|
||||||
"next-auth": "^3.28.0",
|
"next-auth": "^3.28.0",
|
||||||
|
"next-seo": "^4.26.0",
|
||||||
"next-transpile-modules": "^8.0.0",
|
"next-transpile-modules": "^8.0.0",
|
||||||
"nodemailer": "^6.6.3",
|
"nodemailer": "^6.6.3",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { BookOpenIcon, CheckIcon, CodeIcon, DocumentTextIcon } from "@heroicons/
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{
|
{
|
||||||
|
@ -32,9 +32,14 @@ export default function Custom404() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>404: This page could not be found.</title>
|
title="404: This page could not be found."
|
||||||
</Head>
|
description="404: This page could not be found."
|
||||||
|
nextSeoProps={{
|
||||||
|
nofollow: true,
|
||||||
|
noindex: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div className="bg-white min-h-screen px-4">
|
<div className="bg-white min-h-screen px-4">
|
||||||
<main className="max-w-xl mx-auto pb-6 pt-16 sm:pt-24">
|
<main className="max-w-xl mx-auto pb-6 pt-16 sm:pt-24">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSideProps } from "next";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import prisma, { whereAndSelect } from "@lib/prisma";
|
import prisma, { whereAndSelect } from "@lib/prisma";
|
||||||
import Avatar from "@components/Avatar";
|
import Avatar from "@components/Avatar";
|
||||||
|
@ -48,59 +48,12 @@ export default function User(props): User {
|
||||||
));
|
));
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>{props.user.name || props.user.username} | Calendso</title>
|
title={props.user.name || props.user.username}
|
||||||
<link rel="icon" href="/favicon.ico" />
|
description={props.user.name || props.user.username}
|
||||||
|
name={props.user.name || props.user.username}
|
||||||
<meta name="title" content={"Meet " + (props.user.name || props.user.username) + " via Calendso"} />
|
avatar={props.user.avatar}
|
||||||
<meta name="description" content={"Book a time with " + (props.user.name || props.user.username)} />
|
|
||||||
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:url" content="https://calendso/" />
|
|
||||||
<meta
|
|
||||||
property="og:title"
|
|
||||||
content={"Meet " + (props.user.name || props.user.username) + " via Calendso"}
|
|
||||||
/>
|
/>
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content={"Book a time with " + (props.user.name || props.user.username)}
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="og:image"
|
|
||||||
content={
|
|
||||||
"https://og-image-one-pi.vercel.app/" +
|
|
||||||
encodeURIComponent("Meet **" + (props.user.name || props.user.username) + "** <br>").replace(
|
|
||||||
/'/g,
|
|
||||||
"%27"
|
|
||||||
) +
|
|
||||||
".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" +
|
|
||||||
encodeURIComponent(props.user.avatar)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
|
||||||
<meta property="twitter:url" content="https://calendso/" />
|
|
||||||
<meta
|
|
||||||
property="twitter:title"
|
|
||||||
content={"Meet " + (props.user.name || props.user.username) + " via Calendso"}
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="twitter:description"
|
|
||||||
content={"Book a time with " + (props.user.name || props.user.username)}
|
|
||||||
/>
|
|
||||||
<meta
|
|
||||||
property="twitter:image"
|
|
||||||
content={
|
|
||||||
"https://og-image-one-pi.vercel.app/" +
|
|
||||||
encodeURIComponent("Meet **" + (props.user.name || props.user.username) + "** <br>").replace(
|
|
||||||
/'/g,
|
|
||||||
"%27"
|
|
||||||
) +
|
|
||||||
".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" +
|
|
||||||
encodeURIComponent(props.user.avatar)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Head>
|
|
||||||
{isReady && (
|
{isReady && (
|
||||||
<div className="bg-neutral-50 dark:bg-black h-screen">
|
<div className="bg-neutral-50 dark:bg-black h-screen">
|
||||||
<main className="max-w-3xl mx-auto py-24 px-4">
|
<main className="max-w-3xl mx-auto py-24 px-4">
|
||||||
|
|
|
@ -6,16 +6,16 @@ import prisma from "@lib/prisma";
|
||||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||||
import dayjs, { Dayjs } from "dayjs";
|
import dayjs, { Dayjs } from "dayjs";
|
||||||
import { GetServerSidePropsContext, InferGetServerSidePropsType } from "next";
|
import { GetServerSidePropsContext, InferGetServerSidePropsType } from "next";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Avatar from "@components/Avatar";
|
import Avatar from "@components/Avatar";
|
||||||
import AvailableTimes from "../../components/booking/AvailableTimes";
|
import AvailableTimes from "@components/booking/AvailableTimes";
|
||||||
import DatePicker from "../../components/booking/DatePicker";
|
import DatePicker from "@components/booking/DatePicker";
|
||||||
import TimeOptions from "../../components/booking/TimeOptions";
|
import TimeOptions from "@components/booking/TimeOptions";
|
||||||
import PoweredByCalendso from "../../components/ui/PoweredByCalendso";
|
import PoweredByCalendso from "@components/ui/PoweredByCalendso";
|
||||||
import { timeZone } from "../../lib/clock";
|
import { timeZone } from "@lib/clock";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../../lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
|
||||||
import { asStringOrNull } from "@lib/asStringOrNull";
|
import { asStringOrNull } from "@lib/asStringOrNull";
|
||||||
|
|
||||||
export default function Type(props: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
export default function Type(props: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
|
@ -82,53 +82,14 @@ export default function Type(props: InferGetServerSidePropsType<typeof getServer
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>
|
title={`${rescheduleUid ? "Reschedule" : ""} ${props.eventType.title} | ${
|
||||||
{rescheduleUid && "Reschedule"} {props.eventType.title} | {props.user.name || props.user.username} |
|
props.user.name || props.user.username
|
||||||
Calendso
|
}`}
|
||||||
</title>
|
description={`${rescheduleUid ? "Reschedule" : ""} ${props.eventType.title}`}
|
||||||
<meta name="title" content={"Meet " + (props.user.name || props.user.username) + " via Calendso"} />
|
name={props.user.name || props.user.username}
|
||||||
<meta name="description" content={props.eventType.description} />
|
avatar={props.user.avatar}
|
||||||
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:url" content="https://calendso/" />
|
|
||||||
<meta
|
|
||||||
property="og:title"
|
|
||||||
content={"Meet " + (props.user.name || props.user.username) + " via Calendso"}
|
|
||||||
/>
|
/>
|
||||||
<meta property="og:description" content={props.eventType.description} />
|
|
||||||
<meta
|
|
||||||
property="og:image"
|
|
||||||
content={
|
|
||||||
"https://og-image-one-pi.vercel.app/" +
|
|
||||||
encodeURIComponent(
|
|
||||||
"Meet **" + (props.user.name || props.user.username) + "** <br>" + props.eventType.description
|
|
||||||
).replace(/'/g, "%27") +
|
|
||||||
".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" +
|
|
||||||
encodeURIComponent(props.user.avatar)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
|
||||||
<meta property="twitter:url" content="https://calendso/" />
|
|
||||||
<meta
|
|
||||||
property="twitter:title"
|
|
||||||
content={"Meet " + (props.user.name || props.user.username) + " via Calendso"}
|
|
||||||
/>
|
|
||||||
<meta property="twitter:description" content={props.eventType.description} />
|
|
||||||
<meta
|
|
||||||
property="twitter:image"
|
|
||||||
content={
|
|
||||||
"https://og-image-one-pi.vercel.app/" +
|
|
||||||
encodeURIComponent(
|
|
||||||
"Meet **" + (props.user.name || props.user.username) + "** <br>" + props.eventType.description
|
|
||||||
).replace(/'/g, "%27") +
|
|
||||||
".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" +
|
|
||||||
encodeURIComponent(props.user.avatar)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Head>
|
|
||||||
|
|
||||||
{isReady && (
|
{isReady && (
|
||||||
<div>
|
<div>
|
||||||
<main
|
<main
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { CalendarIcon, ClockIcon, ExclamationIcon, LocationMarkerIcon } from "@heroicons/react/solid";
|
import { CalendarIcon, ClockIcon, ExclamationIcon, LocationMarkerIcon } from "@heroicons/react/solid";
|
||||||
import prisma, { whereAndSelect } from "../../lib/prisma";
|
import prisma, { whereAndSelect } from "@lib/prisma";
|
||||||
import { EventTypeCustomInputType } from "@prisma/client";
|
import { EventTypeCustomInputType } from "@prisma/client";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../../lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import timezone from "dayjs/plugin/timezone";
|
import timezone from "dayjs/plugin/timezone";
|
||||||
import PhoneInput from "@components/ui/form/PhoneInput";
|
import PhoneInput from "@components/ui/form/PhoneInput";
|
||||||
import { LocationType } from "../../lib/location";
|
import { LocationType } from "@lib/location";
|
||||||
import Avatar from "@components/Avatar";
|
import Avatar from "@components/Avatar";
|
||||||
import { Button } from "@components/ui/Button";
|
import { Button } from "@components/ui/Button";
|
||||||
import Theme from "@components/Theme";
|
import Theme from "@components/Theme";
|
||||||
|
@ -150,13 +150,14 @@ export default function Book(props: any): JSX.Element {
|
||||||
return (
|
return (
|
||||||
isReady && (
|
isReady && (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>
|
title={`${rescheduleUid ? "Reschedule" : "Confirm"} your ${props.eventType.title} with ${
|
||||||
{rescheduleUid ? "Reschedule" : "Confirm"} your {props.eventType.title} with{" "}
|
props.user.name || props.user.username
|
||||||
{props.user.name || props.user.username} | Calendso
|
}`}
|
||||||
</title>
|
description={`${rescheduleUid ? "Reschedule" : "Confirm"} your ${props.eventType.title} with ${
|
||||||
<link rel="icon" href="/favicon.ico" />
|
props.user.name || props.user.username
|
||||||
</Head>
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
<main className="max-w-3xl mx-auto my-0 sm:my-24">
|
<main className="max-w-3xl mx-auto my-0 sm:my-24">
|
||||||
<div className="dark:bg-neutral-900 bg-white overflow-hidden border border-gray-200 dark:border-0 sm:rounded-sm">
|
<div className="dark:bg-neutral-900 bg-white overflow-hidden border border-gray-200 dark:border-0 sm:rounded-sm">
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
import AppProviders from "@lib/app-providers";
|
import AppProviders from "@lib/app-providers";
|
||||||
import type { AppProps as NextAppProps } from "next/app";
|
import type { AppProps as NextAppProps } from "next/app";
|
||||||
import Head from "next/head";
|
import { DefaultSeo } from "next-seo";
|
||||||
|
import { seoConfig } from "@lib/config/next-seo.config";
|
||||||
|
|
||||||
// Workaround for https://github.com/zeit/next.js/issues/8592
|
// Workaround for https://github.com/zeit/next.js/issues/8592
|
||||||
export type AppProps = NextAppProps & {
|
export type AppProps = NextAppProps & {
|
||||||
|
@ -12,9 +13,7 @@ export type AppProps = NextAppProps & {
|
||||||
function MyApp({ Component, pageProps, err }: AppProps) {
|
function MyApp({ Component, pageProps, err }: AppProps) {
|
||||||
return (
|
return (
|
||||||
<AppProviders>
|
<AppProviders>
|
||||||
<Head>
|
<DefaultSeo {...seoConfig.defaultNextSeo} />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
</Head>
|
|
||||||
<Component {...pageProps} err={err} />
|
<Component {...pageProps} err={err} />
|
||||||
</AppProviders>
|
</AppProviders>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { XIcon } from "@heroicons/react/outline";
|
import { XIcon } from "@heroicons/react/outline";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
export default function Error() {
|
export default function Error() {
|
||||||
|
@ -13,10 +13,7 @@ export default function Error() {
|
||||||
aria-labelledby="modal-title"
|
aria-labelledby="modal-title"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true">
|
aria-modal="true">
|
||||||
<Head>
|
<HeadSeo title="Error" description="Error" />
|
||||||
<title>{error} - Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
|
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
|
||||||
​
|
​
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { getCsrfToken } from "next-auth/client";
|
import { getCsrfToken } from "next-auth/client";
|
||||||
import prisma from "../../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Head from "next/head";
|
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import debounce from "lodash.debounce";
|
import debounce from "lodash.debounce";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
@ -122,10 +121,7 @@ export default function Page({ resetPasswordRequest, csrfToken }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||||
<Head>
|
<HeadSeo title="Reset Password" description="Change your password" />
|
||||||
<title>Reset Password</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
||||||
<div className="bg-white py-8 px-4 mx-2 shadow rounded-lg sm:px-10 space-y-6">
|
<div className="bg-white py-8 px-4 mx-2 shadow rounded-lg sm:px-10 space-y-6">
|
||||||
{isRequestExpired && <Expired />}
|
{isRequestExpired && <Expired />}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { getCsrfToken, getSession } from "next-auth/client";
|
import { getCsrfToken, getSession } from "next-auth/client";
|
||||||
|
@ -71,11 +71,7 @@ export default function ForgotPassword({ csrfToken }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
<div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||||
<Head>
|
<HeadSeo title="Forgot Password" description="Forgot Password" />
|
||||||
<title>Forgot Password</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
|
|
||||||
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
||||||
<div className="bg-white py-8 px-4 mx-2 shadow rounded-lg sm:px-10 space-y-6">
|
<div className="bg-white py-8 px-4 mx-2 shadow rounded-lg sm:px-10 space-y-6">
|
||||||
{success && <Success />}
|
{success && <Success />}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { getCsrfToken, getSession } from "next-auth/client";
|
import { getCsrfToken, getSession } from "next-auth/client";
|
||||||
|
|
||||||
export default function Login({ csrfToken }) {
|
export default function Login({ csrfToken }) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-neutral-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
<div className="min-h-screen bg-neutral-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
|
||||||
<Head>
|
<HeadSeo title="Login" description="Login" />
|
||||||
<title>Login</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
||||||
<img className="h-6 mx-auto" src="/calendso-logo-white-word.svg" alt="Calendso Logo" />
|
<img className="h-6 mx-auto" src="/calendso-logo-white-word.svg" alt="Calendso Logo" />
|
||||||
<h2 className="mt-6 text-center text-3xl font-bold text-neutral-900">Sign in to your account</h2>
|
<h2 className="mt-6 text-center text-3xl font-bold text-neutral-900">Sign in to your account</h2>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { CheckIcon } from "@heroicons/react/outline";
|
import { CheckIcon } from "@heroicons/react/outline";
|
||||||
|
|
||||||
|
@ -9,10 +9,7 @@ export default function Logout() {
|
||||||
aria-labelledby="modal-title"
|
aria-labelledby="modal-title"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true">
|
aria-modal="true">
|
||||||
<Head>
|
<HeadSeo title="Logged out" description="Logged out" />
|
||||||
<title>Logged out - Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
|
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
|
||||||
​
|
​
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { signIn } from "next-auth/client";
|
import { signIn } from "next-auth/client";
|
||||||
import ErrorAlert from "../../components/ui/alerts/Error";
|
import ErrorAlert from "@components/ui/alerts/Error";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { UsernameInput } from "../../components/ui/UsernameInput";
|
import { UsernameInput } from "@components/ui/UsernameInput";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
|
||||||
export default function Signup(props) {
|
export default function Signup(props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -54,10 +54,7 @@ export default function Signup(props) {
|
||||||
aria-labelledby="modal-title"
|
aria-labelledby="modal-title"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true">
|
aria-modal="true">
|
||||||
<Head>
|
<HeadSeo title="Sign up" description="Sign up" />
|
||||||
<title>Sign up</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
||||||
<h2 className="text-center text-3xl font-extrabold text-gray-900">Create your account</h2>
|
<h2 className="text-center text-3xl font-extrabold text-gray-900">Create your account</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import Head from "next/head";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
import Modal from "../../components/Modal";
|
import Modal from "@components/Modal";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
|
@ -115,15 +114,7 @@ export default function Availability(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<Shell heading="Availability" subtitle="Configure times when you are available for bookings.">
|
||||||
<title>Availability | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<Shell
|
|
||||||
heading="Availability"
|
|
||||||
subtitle="Configure times when you are available for bookings.
|
|
||||||
|
|
||||||
">
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="w-1/2 mr-2 bg-white border border-gray-200 rounded-sm">
|
<div className="w-1/2 mr-2 bg-white border border-gray-200 rounded-sm">
|
||||||
<div className="px-4 py-5 sm:p-6">
|
<div className="px-4 py-5 sm:p-6">
|
||||||
|
|
|
@ -4,9 +4,8 @@ import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSideProps } from "next";
|
||||||
import { getSession } from "next-auth/client";
|
import { getSession } from "next-auth/client";
|
||||||
import Head from "next/head";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
|
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
|
||||||
|
@ -52,10 +51,6 @@ export default function Troubleshoot({ user }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
|
||||||
<title>Troubleshoot | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<Shell
|
<Shell
|
||||||
heading="Troubleshoot"
|
heading="Troubleshoot"
|
||||||
subtitle="Understand why certain times are available and others are blocked.">
|
subtitle="Understand why certain times are available and others are blocked.">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Head from "next/head";
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../lib/prisma";
|
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
|
@ -36,10 +35,6 @@ export default function Bookings({ bookings }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
|
||||||
<title>Bookings | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<Shell heading="Bookings" subtitle="See upcoming and past events booked through your event type links.">
|
<Shell heading="Bookings" subtitle="See upcoming and past events booked through your event type links.">
|
||||||
<div className="-mx-4 sm:mx-auto flex flex-col">
|
<div className="-mx-4 sm:mx-auto flex flex-col">
|
||||||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||||
|
|
|
@ -4,11 +4,11 @@ import isBetween from "dayjs/plugin/isBetween";
|
||||||
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
|
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
|
||||||
import timezone from "dayjs/plugin/timezone";
|
import timezone from "dayjs/plugin/timezone";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../../lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
|
||||||
|
|
||||||
dayjs.extend(isSameOrBefore);
|
dayjs.extend(isSameOrBefore);
|
||||||
dayjs.extend(isBetween);
|
dayjs.extend(isBetween);
|
||||||
|
@ -55,13 +55,12 @@ export default function Type(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>
|
title={`Cancel ${props.booking && props.booking.title} | ${props.user.name || props.user.username}`}
|
||||||
Cancel {props.booking && `${props.booking.title} | ${props.user.name || props.user.username} `}|
|
description={`Cancel ${props.booking && props.booking.title} | ${
|
||||||
Calendso
|
props.user.name || props.user.username
|
||||||
</title>
|
}`}
|
||||||
<link rel="icon" href="/favicon.ico" />
|
/>
|
||||||
</Head>
|
|
||||||
<main className="max-w-3xl mx-auto my-24">
|
<main className="max-w-3xl mx-auto my-24">
|
||||||
<div className="fixed z-50 inset-0 overflow-y-auto">
|
<div className="fixed z-50 inset-0 overflow-y-auto">
|
||||||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "../../lib/prisma";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
@ -19,12 +19,10 @@ export default function Type(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>
|
title={`Cancelled ${props.title} | ${props.user.name || props.user.username}`}
|
||||||
Cancelled {props.title} | {props.user.name || props.user.username} | Calendso
|
description={`Cancelled ${props.title} | ${props.user.name || props.user.username}`}
|
||||||
</title>
|
/>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<main className="max-w-3xl mx-auto my-24">
|
<main className="max-w-3xl mx-auto my-24">
|
||||||
<div className="fixed z-50 inset-0 overflow-y-auto">
|
<div className="fixed z-50 inset-0 overflow-y-auto">
|
||||||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Head from "next/head";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Modal from "../../components/Modal";
|
import Modal from "@components/Modal";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import Select, { OptionBase } from "react-select";
|
import Select, { OptionBase } from "react-select";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
@ -331,11 +330,8 @@ const EventTypePage = (props: InferGetServerSidePropsType<typeof getServerSidePr
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
|
||||||
<title>{eventType.title} | Event Type | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<Shell
|
<Shell
|
||||||
|
title={`${eventType.title} | Event Type`}
|
||||||
heading={
|
heading={
|
||||||
<input
|
<input
|
||||||
ref={titleRef}
|
ref={titleRef}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
import classNames from "@lib/classNames";
|
import classNames from "@lib/classNames";
|
||||||
import showToast from "@lib/notification";
|
import showToast from "@lib/notification";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import Head from "next/head";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { Fragment, useRef } from "react";
|
import React, { Fragment, useRef } from "react";
|
||||||
|
@ -193,10 +192,6 @@ const EventTypesPage = (props: InferGetServerSidePropsType<typeof getServerSideP
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
|
||||||
<title>Event Types | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<Shell
|
<Shell
|
||||||
heading="Event Types"
|
heading="Event Types"
|
||||||
subtitle="Create events to share for people to book on your calendar."
|
subtitle="Create events to share for people to book on your calendar."
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Head from "next/head";
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../lib/prisma";
|
import { getIntegrationName, getIntegrationType } from "@lib/integrations";
|
||||||
import { getIntegrationName, getIntegrationType } from "../../lib/integrations";
|
import Shell from "@components/Shell";
|
||||||
import Shell from "../../components/Shell";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
|
@ -40,12 +39,9 @@ export default function Integration(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<Shell
|
||||||
<title>{getIntegrationName(props.integration.type)} App | Calendso</title>
|
heading={`${getIntegrationName(props.integration.type)} App`}
|
||||||
<link rel="icon" href="/favicon.ico" />
|
subtitle="Manage and delete this app.">
|
||||||
</Head>
|
|
||||||
|
|
||||||
<Shell heading={getIntegrationName(props.integration.type)} subtitle="Manage and delete this app.">
|
|
||||||
<div className="block sm:grid grid-cols-3 gap-4">
|
<div className="block sm:grid grid-cols-3 gap-4">
|
||||||
<div className="col-span-2 bg-white border border-gray-200 mb-6 overflow-hidden rounded-sm">
|
<div className="col-span-2 bg-white border border-gray-200 mb-6 overflow-hidden rounded-sm">
|
||||||
<div className="px-4 py-5 sm:px-6">
|
<div className="px-4 py-5 sm:px-6">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Head from "next/head";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
import { useEffect, useState, useRef, useCallback } from "react";
|
import { useEffect, useState, useRef, useCallback } from "react";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import { CheckCircleIcon, ChevronRightIcon, PlusIcon, XCircleIcon } from "@heroicons/react/solid";
|
import { CheckCircleIcon, ChevronRightIcon, PlusIcon, XCircleIcon } from "@heroicons/react/solid";
|
||||||
|
@ -270,11 +269,6 @@ export default function Home({ integrations }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
|
||||||
<title>App Store | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
|
|
||||||
<Shell heading="App Store" subtitle="Connect your favourite apps." CTA={<ConnectNewAppDialog />}>
|
<Shell heading="App Store" subtitle="Connect your favourite apps." CTA={<ConnectNewAppDialog />}>
|
||||||
<div className="bg-white border border-gray-200 overflow-hidden rounded-sm mb-8">
|
<div className="bg-white border border-gray-200 overflow-hidden rounded-sm mb-8">
|
||||||
{integrations.filter((ig) => ig.credential).length !== 0 ? (
|
{integrations.filter((ig) => ig.credential).length !== 0 ? (
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import Head from "next/head";
|
import Shell from "@components/Shell";
|
||||||
import Shell from "../../components/Shell";
|
import SettingsShell from "@components/Settings";
|
||||||
import SettingsShell from "../../components/Settings";
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../lib/prisma";
|
|
||||||
import { getSession } from "next-auth/client";
|
import { getSession } from "next-auth/client";
|
||||||
|
|
||||||
export default function Billing() {
|
export default function Billing() {
|
||||||
return (
|
return (
|
||||||
<Shell heading="Billing" subtitle="Manage your billing information and cancel your subscription.">
|
<Shell heading="Billing" subtitle="Manage your billing information and cancel your subscription.">
|
||||||
<Head>
|
|
||||||
<title>Billing | Calendso</title>
|
|
||||||
</Head>
|
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
<div className="py-6 lg:pb-8 lg:col-span-9">
|
<div className="py-6 lg:pb-8 lg:col-span-9">
|
||||||
<div className="my-6">
|
<div className="my-6">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Head from "next/head";
|
import prisma from "@lib/prisma";
|
||||||
import prisma from "../../lib/prisma";
|
import Shell from "@components/Shell";
|
||||||
import Shell from "../../components/Shell";
|
import SettingsShell from "@components/Settings";
|
||||||
import SettingsShell from "../../components/Settings";
|
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import Loader from "@components/Loader";
|
import Loader from "@components/Loader";
|
||||||
|
|
||||||
|
@ -15,10 +14,6 @@ export default function Embed(props) {
|
||||||
|
|
||||||
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.">
|
||||||
<Head>
|
|
||||||
<title>Embed | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
<div className="py-6 lg:pb-8 lg:col-span-9">
|
<div className="py-6 lg:pb-8 lg:col-span-9">
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import Head from "next/head";
|
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import prisma from "../../lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
import Modal from "../../components/Modal";
|
import Modal from "@components/Modal";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
import SettingsShell from "../../components/Settings";
|
import SettingsShell from "@components/Settings";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import Loader from "@components/Loader";
|
import Loader from "@components/Loader";
|
||||||
|
|
||||||
|
@ -45,11 +44,7 @@ export default function Settings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell heading="Password" subtitle="Change the password that you use to sign in to your account.">
|
<Shell heading="Change Password" subtitle="Change the password that you use to sign in to your account.">
|
||||||
<Head>
|
|
||||||
<title>Change Password | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
<form className="divide-y divide-gray-200 lg:col-span-9" onSubmit={changePasswordHandler}>
|
<form className="divide-y divide-gray-200 lg:col-span-9" onSubmit={changePasswordHandler}>
|
||||||
<div className="py-6 lg:pb-8">
|
<div className="py-6 lg:pb-8">
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSideProps } from "next";
|
||||||
import Head from "next/head";
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
import Modal from "../../components/Modal";
|
import Modal from "@components/Modal";
|
||||||
import Shell from "../../components/Shell";
|
import Shell from "@components/Shell";
|
||||||
import SettingsShell from "../../components/Settings";
|
import SettingsShell from "@components/Settings";
|
||||||
import Avatar from "@components/Avatar";
|
import Avatar from "@components/Avatar";
|
||||||
import { getSession } from "next-auth/client";
|
import { getSession } from "next-auth/client";
|
||||||
import Select from "react-select";
|
import Select from "react-select";
|
||||||
import TimezoneSelect from "react-timezone-select";
|
import TimezoneSelect from "react-timezone-select";
|
||||||
import { UsernameInput } from "../../components/ui/UsernameInput";
|
import { UsernameInput } from "@components/ui/UsernameInput";
|
||||||
import ErrorAlert from "../../components/ui/alerts/Error";
|
import ErrorAlert from "@components/ui/alerts/Error";
|
||||||
import ImageUploader from "../../components/ImageUploader";
|
import ImageUploader from "@components/ImageUploader";
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
|
||||||
const themeOptions = [
|
const themeOptions = [
|
||||||
|
@ -107,10 +106,6 @@ export default function Settings(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell heading="Profile" subtitle="Edit your profile information, which shows on your scheduling link.">
|
<Shell heading="Profile" subtitle="Edit your profile information, which shows on your scheduling link.">
|
||||||
<Head>
|
|
||||||
<title>Profile | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
<form className="divide-y divide-gray-200 lg:col-span-9" onSubmit={updateProfileHandler}>
|
<form className="divide-y divide-gray-200 lg:col-span-9" onSubmit={updateProfileHandler}>
|
||||||
{hasErrors && <ErrorAlert message={errorMessage} />}
|
{hasErrors && <ErrorAlert message={errorMessage} />}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSideProps } from "next";
|
||||||
import Head from "next/head";
|
import Shell from "@components/Shell";
|
||||||
import Shell from "../../components/Shell";
|
import SettingsShell from "@components/Settings";
|
||||||
import SettingsShell from "../../components/Settings";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import type { Session } from "next-auth";
|
import type { Session } from "next-auth";
|
||||||
import { getSession, useSession } from "next-auth/client";
|
import { getSession, useSession } from "next-auth/client";
|
||||||
import { UsersIcon } from "@heroicons/react/outline";
|
import { UsersIcon } from "@heroicons/react/outline";
|
||||||
import TeamList from "../../components/team/TeamList";
|
import TeamList from "@components/team/TeamList";
|
||||||
import TeamListItem from "../../components/team/TeamListItem";
|
import TeamListItem from "@components/team/TeamListItem";
|
||||||
import Loader from "@components/Loader";
|
import Loader from "@components/Loader";
|
||||||
|
|
||||||
export default function Teams() {
|
export default function Teams() {
|
||||||
|
@ -59,10 +58,6 @@ export default function Teams() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell heading="Teams" subtitle="Create and manage teams to use collaborative features.">
|
<Shell heading="Teams" subtitle="Create and manage teams to use collaborative features.">
|
||||||
<Head>
|
|
||||||
<title>Teams | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<SettingsShell>
|
<SettingsShell>
|
||||||
<div className="divide-y divide-gray-200 lg:col-span-9">
|
<div className="divide-y divide-gray-200 lg:col-span-9">
|
||||||
<div className="py-6 lg:pb-8">
|
<div className="py-6 lg:pb-8">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import prisma, { whereAndSelect } from "../lib/prisma";
|
import prisma, { whereAndSelect } from "@lib/prisma";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { CheckIcon } from "@heroicons/react/outline";
|
import { CheckIcon } from "@heroicons/react/outline";
|
||||||
|
@ -10,7 +10,7 @@ import utc from "dayjs/plugin/utc";
|
||||||
import toArray from "dayjs/plugin/toArray";
|
import toArray from "dayjs/plugin/toArray";
|
||||||
import timezone from "dayjs/plugin/timezone";
|
import timezone from "dayjs/plugin/timezone";
|
||||||
import { createEvent } from "ics";
|
import { createEvent } from "ics";
|
||||||
import { getEventName } from "../lib/event";
|
import { getEventName } from "@lib/event";
|
||||||
import Theme from "@components/Theme";
|
import Theme from "@components/Theme";
|
||||||
|
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
@ -61,13 +61,10 @@ export default function Success(props) {
|
||||||
return (
|
return (
|
||||||
isReady && (
|
isReady && (
|
||||||
<div className="bg-neutral-50 dark:bg-neutral-900 h-screen">
|
<div className="bg-neutral-50 dark:bg-neutral-900 h-screen">
|
||||||
<Head>
|
<HeadSeo
|
||||||
<title>
|
title={`Booking ${props.eventType.requiresConfirmation ? "Submitted" : "Confirmed"}`}
|
||||||
Booking {props.eventType.requiresConfirmation ? "Submitted" : "Confirmed"} | {eventName} |
|
description={`Booking ${props.eventType.requiresConfirmation ? "Submitted" : "Confirmed"}`}
|
||||||
Calendso
|
/>
|
||||||
</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
<main className="max-w-3xl mx-auto py-24">
|
<main className="max-w-3xl mx-auto py-24">
|
||||||
<div className="fixed z-50 inset-0 overflow-y-auto">
|
<div className="fixed z-50 inset-0 overflow-y-auto">
|
||||||
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { GetServerSideProps } from "next";
|
import { GetServerSideProps } from "next";
|
||||||
import Head from "next/head";
|
import { HeadSeo } from "@components/seo/head-seo";
|
||||||
|
|
||||||
import Theme from "@components/Theme";
|
import Theme from "@components/Theme";
|
||||||
import { getTeam } from "@lib/teams/getTeam";
|
import { getTeam } from "@lib/teams/getTeam";
|
||||||
import Team from "@components/team/screens/Team";
|
import Team from "@components/team/screens/Team";
|
||||||
|
@ -11,11 +10,7 @@ export default function Page(props) {
|
||||||
return (
|
return (
|
||||||
isReady && (
|
isReady && (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<HeadSeo title={props.team.name} description={props.team.name} />
|
||||||
<title>{props.team.name} | Calendso</title>
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
</Head>
|
|
||||||
|
|
||||||
<main className="mx-auto py-24 px-4">
|
<main className="mx-auto py-24 px-4">
|
||||||
<Team team={props.team} />
|
<Team team={props.team} />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -4216,6 +4216,10 @@ next-auth@^3.28.0:
|
||||||
preact-render-to-string "^5.1.14"
|
preact-render-to-string "^5.1.14"
|
||||||
querystring "^0.2.0"
|
querystring "^0.2.0"
|
||||||
|
|
||||||
|
next-seo@^4.26.0:
|
||||||
|
version "4.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-4.26.0.tgz#4218cfae5651fdc2e330dcdf1cc1b34ce199d41c"
|
||||||
|
|
||||||
next-transpile-modules@^8.0.0:
|
next-transpile-modules@^8.0.0:
|
||||||
version "8.0.0"
|
version "8.0.0"
|
||||||
resolved "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-8.0.0.tgz#56375cdc25ae5d23a834195f277fc2737b26cb97"
|
resolved "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-8.0.0.tgz#56375cdc25ae5d23a834195f277fc2737b26cb97"
|
||||||
|
|
Loading…
Reference in a new issue