From 5206fb4f88ef0b87759ccf28336a9bc3fee0892f Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Fri, 9 Jul 2021 22:59:21 +0000 Subject: [PATCH 1/2] Implemented theme through user preferences --- components/Theme.tsx | 19 ++++ pages/[user].tsx | 28 +++--- pages/[user]/[type].tsx | 6 +- pages/[user]/book.tsx | 32 +++--- pages/api/user/profile.ts | 24 +++-- pages/settings/profile.tsx | 97 +++++++++++++------ pages/success.tsx | 48 +++++---- .../migration.sql | 2 + prisma/schema.prisma | 1 + tailwind.config.js | 2 +- 10 files changed, 161 insertions(+), 98 deletions(-) create mode 100644 components/Theme.tsx create mode 100644 prisma/migrations/20210709231256_add_user_theme/migration.sql diff --git a/components/Theme.tsx b/components/Theme.tsx new file mode 100644 index 0000000000..78350999ee --- /dev/null +++ b/components/Theme.tsx @@ -0,0 +1,19 @@ +import {useEffect, useState} from "react"; + +const Theme = (theme?: string) => { + const [isReady, setIsReady] = useState(false); + useEffect( () => { + if (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches) { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.add(theme); + } + setIsReady(true); + }, []); + + return { + isReady + } +}; + +export default Theme; diff --git a/pages/[user].tsx b/pages/[user].tsx index bdb7872574..960e90a0f9 100644 --- a/pages/[user].tsx +++ b/pages/[user].tsx @@ -1,10 +1,14 @@ import { GetServerSideProps } from "next"; import Head from "next/head"; import Link from "next/link"; -import prisma from "../lib/prisma"; +import prisma, {whereAndSelect} from "@lib/prisma"; import Avatar from "../components/Avatar"; +import Theme from "@components/Theme"; export default function User(props): User { + + const { isReady } = Theme(props.user.theme); + const eventTypes = props.eventTypes.map((type) => (
  • )); - return ( + return isReady && (
    {props.user.name || props.user.username} | Calendso @@ -50,21 +54,13 @@ export default function User(props): User { } export const getServerSideProps: GetServerSideProps = async (context) => { - const user = await prisma.user.findFirst({ - where: { - username: context.query.user.toLowerCase(), - }, - select: { - id: true, - username: true, - email: true, - name: true, - bio: true, - avatar: true, - eventTypes: true, - }, - }); + const user = await whereAndSelect(prisma.user.findFirst, { + username: context.query.user.toLowerCase(), + }, [ + "id", "username", "email", "name", "bio", "avatar", "eventTypes", "theme" + ] + ); if (!user) { return { notFound: true, diff --git a/pages/[user]/[type].tsx b/pages/[user]/[type].tsx index 52e0773b31..d8ba07bf6c 100644 --- a/pages/[user]/[type].tsx +++ b/pages/[user]/[type].tsx @@ -13,12 +13,15 @@ import Avatar from "../../components/Avatar"; import { timeZone } from "../../lib/clock"; import DatePicker from "../../components/booking/DatePicker"; import PoweredByCalendso from "../../components/ui/PoweredByCalendso"; +import Theme from "@components/Theme"; export default function Type(props): Type { // Get router variables const router = useRouter(); const { rescheduleUid } = router.query; + const { isReady } = Theme(props.user.theme); + const [selectedDate, setSelectedDate] = useState(); const [isTimeOptionsOpen, setIsTimeOptionsOpen] = useState(false); const [timeFormat, setTimeFormat] = useState("h:mma"); @@ -44,7 +47,7 @@ export default function Type(props): Type { setTimeFormat(is24hClock ? "HH:mm" : "h:mma"); }; - return ( + return isReady && (
    @@ -174,6 +177,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { "weekStart", "availability", "hideBranding", + "theme", ] ); diff --git a/pages/[user]/book.tsx b/pages/[user]/book.tsx index ec348b69aa..fe305e2c85 100644 --- a/pages/[user]/book.tsx +++ b/pages/[user]/book.tsx @@ -2,7 +2,7 @@ import Head from "next/head"; import Link from "next/link"; import { useRouter } from "next/router"; import { CalendarIcon, ClockIcon, ExclamationIcon, LocationMarkerIcon } from "@heroicons/react/solid"; -import prisma from "../../lib/prisma"; +import prisma, {whereAndSelect} from "../../lib/prisma"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../../lib/telemetry"; import { useEffect, useState } from "react"; import dayjs from "dayjs"; @@ -14,6 +14,7 @@ import { LocationType } from "../../lib/location"; import Avatar from "../../components/Avatar"; import Button from "../../components/ui/Button"; import { EventTypeCustomInputType } from "../../lib/eventTypeInput"; +import Theme from "@components/Theme"; dayjs.extend(utc); dayjs.extend(timezone); @@ -32,7 +33,10 @@ export default function Book(props: any): JSX.Element { const [selectedLocation, setSelectedLocation] = useState<LocationType>( locations.length === 1 ? locations[0].type : "" ); + + const { isReady } = Theme(props.user.theme); const telemetry = useTelemetry(); + useEffect(() => { setPreferredTimeZone(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()); setIs24h(!!localStorage.getItem("timeOption.is24hClock")); @@ -137,7 +141,7 @@ export default function Book(props: any): JSX.Element { book(); }; - return ( + return isReady && ( <div> <Head> <title> @@ -366,19 +370,19 @@ export default function Book(props: any): JSX.Element { } export async function getServerSideProps(context) { - const user = await prisma.user.findFirst({ - where: { + + const user = await whereAndSelect(prisma.user.findFirst, { username: context.query.user, - }, - select: { - username: true, - name: true, - email: true, - bio: true, - avatar: true, - eventTypes: true, - }, - }); + }, [ + "username", + "name", + "email", + "bio", + "avatar", + "eventTypes", + "theme", + ] + ); const eventType = await prisma.eventType.findUnique({ where: { diff --git a/pages/api/user/profile.ts b/pages/api/user/profile.ts index dfb13315c2..0cfcab43d1 100644 --- a/pages/api/user/profile.ts +++ b/pages/api/user/profile.ts @@ -1,6 +1,6 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { getSession } from 'next-auth/client'; -import prisma from '../../../lib/prisma'; +import prisma, {whereAndSelect} from '@lib/prisma'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const session = await getSession({req: req}); @@ -11,15 +11,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) } // Get user - const user = await prisma.user.findUnique({ - where: { - email: session.user.email, + const user = await whereAndSelect(prisma.user.findUnique, { + id: session.user.id, }, - select: { - id: true, - password: true - } - }); + [ "id", "password" ] + ); if (!user) { res.status(404).json({message: 'User not found'}); return; } @@ -42,6 +38,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const timeZone = req.body.timeZone; const weekStart = req.body.weekStart; const hideBranding = req.body.hideBranding; + const theme = req.body.theme; const updateUser = await prisma.user.update({ where: { @@ -52,11 +49,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) name, avatar, bio: description, - timeZone: timeZone, - weekStart: weekStart, - hideBranding: hideBranding, + timeZone, + weekStart, + hideBranding, + theme, }, }); return res.status(200).json({message: 'Profile updated successfully'}); -} \ No newline at end of file +} diff --git a/pages/settings/profile.tsx b/pages/settings/profile.tsx index 8278a55cb9..e103b61cd5 100644 --- a/pages/settings/profile.tsx +++ b/pages/settings/profile.tsx @@ -1,12 +1,13 @@ import { GetServerSideProps } from "next"; import Head from "next/head"; -import { useRef, useState } from "react"; -import prisma from "../../lib/prisma"; +import {useEffect, useRef, useState} from "react"; +import prisma, {whereAndSelect} from "@lib/prisma"; import Modal from "../../components/Modal"; import Shell from "../../components/Shell"; import SettingsShell from "../../components/Settings"; import Avatar from "../../components/Avatar"; import { getSession } from "next-auth/client"; +import Select from "react-select"; import TimezoneSelect from "react-timezone-select"; import { UsernameInput } from "../../components/ui/UsernameInput"; import ErrorAlert from "../../components/ui/alerts/Error"; @@ -18,12 +19,23 @@ export default function Settings(props) { const descriptionRef = useRef<HTMLTextAreaElement>(); const avatarRef = useRef<HTMLInputElement>(); const hideBrandingRef = useRef<HTMLInputElement>(); + const [selectedTheme, setSelectedTheme] = useState({ value: "" }); const [selectedTimeZone, setSelectedTimeZone] = useState({ value: props.user.timeZone }); - const [selectedWeekStartDay, setSelectedWeekStartDay] = useState(props.user.weekStart || "Sunday"); + const [selectedWeekStartDay, setSelectedWeekStartDay] = useState({ value: "" }); const [hasErrors, setHasErrors] = useState(false); const [errorMessage, setErrorMessage] = useState(""); + const themeOptions = [ + {value: 'light', label: 'Light'}, + {value: 'dark', label: 'Dark'} + ]; + + useEffect( () => { + setSelectedTheme(props.user.theme ? themeOptions.find( (theme) => theme.value === props.user.theme ) : null); + setSelectedWeekStartDay({ value: props.user.weekStart, label: props.user.weekStart }); + }, []); + const closeSuccessModal = () => { setSuccessModalOpen(false); }; @@ -43,7 +55,7 @@ export default function Settings(props) { const enteredDescription = descriptionRef.current.value; const enteredAvatar = avatarRef.current.value; const enteredTimeZone = selectedTimeZone.value; - const enteredWeekStartDay = selectedWeekStartDay; + const enteredWeekStartDay = selectedWeekStartDay.value; const enteredHideBranding = hideBrandingRef.current.checked; // TODO: Add validation @@ -58,6 +70,7 @@ export default function Settings(props) { timeZone: enteredTimeZone, weekStart: enteredWeekStartDay, hideBranding: enteredHideBranding, + theme: selectedTheme ? selectedTheme.value : null, }), headers: { "Content-Type": "application/json", @@ -124,8 +137,8 @@ export default function Settings(props) { name="about" placeholder="A little something about yourself." rows={3} + defaultValue={props.user.bio} className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md"> - {props.user.bio} </textarea> </div> </div> @@ -147,14 +160,46 @@ export default function Settings(props) { First Day of Week </label> <div className="mt-1"> - <select + <Select id="weekStart" value={selectedWeekStartDay} - onChange={(e) => setSelectedWeekStartDay(e.target.value)} - className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md"> - <option value="Sunday">Sunday</option> - <option value="Monday">Monday</option> - </select> + onChange={setSelectedWeekStartDay} + className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" + options={[ + { value:'Sunday', label:'Sunday' }, + { value:'Monday', label:'Monday' } + ]} /> + </div> + </div> + <div> + <label htmlFor="theme" className="block text-sm font-medium text-gray-700"> + Single Theme + </label> + <div className="my-1"> + <Select + id="theme" + isDisabled={!selectedTheme} + defaultValue={selectedTheme || themeOptions[0]} + onChange={setSelectedTheme} + className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" + options={themeOptions} /> + </div> + <div className="relative flex items-start"> + <div className="flex items-center h-5"> + <input + id="theme-adjust-os" + name="theme-adjust-os" + type="checkbox" + onChange={(e) => setSelectedTheme(e.target.checked ? null : themeOptions[0])} + defaultChecked={!selectedTheme} + className="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-300 rounded" + /> + </div> + <div className="ml-3 text-sm"> + <label htmlFor="theme-adjust-os" className="font-medium text-gray-700"> + Automatically adjust theme based on invitee preferences + </label> + </div> </div> </div> <div> @@ -257,22 +302,20 @@ export const getServerSideProps: GetServerSideProps = async (context) => { return { redirect: { permanent: false, destination: "/auth/login" } }; } - const user = await prisma.user.findFirst({ - where: { - email: session.user.email, - }, - select: { - id: true, - username: true, - name: true, - email: true, - bio: true, - avatar: true, - timeZone: true, - weekStart: true, - hideBranding: true, - }, - }); + const user = await whereAndSelect(prisma.user.findFirst, { + id: session.user.id, + }, [ + "id", + "username", + "name", + "email", + "bio", + "avatar", + "timeZone", + "weekStart", + "hideBranding", + "theme" + ]); return { props: { user }, // will be passed to the page component as props diff --git a/pages/success.tsx b/pages/success.tsx index 286897b9e7..20d9e7c3a2 100644 --- a/pages/success.tsx +++ b/pages/success.tsx @@ -1,6 +1,6 @@ import Head from "next/head"; import Link from "next/link"; -import prisma from "../lib/prisma"; +import prisma, {whereAndSelect} from "../lib/prisma"; import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import { CheckIcon } from "@heroicons/react/outline"; @@ -11,6 +11,7 @@ import toArray from "dayjs/plugin/toArray"; import timezone from "dayjs/plugin/timezone"; import { createEvent } from "ics"; import { getEventName } from "../lib/event"; +import Theme from "@components/Theme"; dayjs.extend(utc); dayjs.extend(toArray); @@ -22,6 +23,7 @@ export default function Success(props) { const [is24h, setIs24h] = useState(false); const [date, setDate] = useState(dayjs.utc(router.query.date)); + const { isReady } = Theme(props.user.theme); useEffect(() => { setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess())); @@ -56,7 +58,7 @@ export default function Success(props) { return encodeURIComponent(event.value); } - return ( + return isReady && ( <div> <Head> <title>Booking Confirmed | {eventName} | Calendso @@ -212,32 +214,26 @@ export default function Success(props) { } export async function getServerSideProps(context) { - const user = await prisma.user.findFirst({ - where: { - username: context.query.user, - }, - select: { - username: true, - name: true, - bio: true, - avatar: true, - eventTypes: true, - hideBranding: true, - }, - }); - const eventType = await prisma.eventType.findUnique({ - where: { + const user = (context.query.user) ? await whereAndSelect(prisma.user.findFirst, { + username: context.query.user, + }, [ + "username", "name", "bio", "avatar", "eventTypes", "hideBranding", "theme" + ] + ) : null; + + if (!user) { + return { + notFound: true, + }; + } + + const eventType = await whereAndSelect(prisma.eventType.findUnique, { id: parseInt(context.query.type), - }, - select: { - id: true, - title: true, - description: true, - length: true, - eventName: true, - }, - }); + }, [ + "id", "title", "description", "length", "eventName" + ] + ); return { props: { diff --git a/prisma/migrations/20210709231256_add_user_theme/migration.sql b/prisma/migrations/20210709231256_add_user_theme/migration.sql new file mode 100644 index 0000000000..75875267e1 --- /dev/null +++ b/prisma/migrations/20210709231256_add_user_theme/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "theme" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ddaf7d8133..f083809617 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -50,6 +50,7 @@ model User { endTime Int @default(1440) bufferTime Int @default(0) hideBranding Boolean @default(false) + theme String? createdDate DateTime @default(now()) @map(name: "created") eventTypes EventType[] credentials Credential[] diff --git a/tailwind.config.js b/tailwind.config.js index 24bfaf0f7f..c14305a94e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,7 +1,7 @@ module.exports = { mode: "jit", purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"], - darkMode: "media", + darkMode: "class", theme: { extend: { colors: { From 4d7427ad914fd780fa64367484f58e020f6d99c0 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Sun, 11 Jul 2021 19:35:56 +0000 Subject: [PATCH 2/2] Fixes some linting + codacy issues --- components/Theme.tsx | 14 +- pages/[user].tsx | 65 +++--- pages/[user]/[type].tsx | 204 ++++++++--------- pages/[user]/book.tsx | 442 ++++++++++++++++++------------------- pages/api/user/profile.ts | 31 +-- pages/settings/profile.tsx | 46 ++-- pages/success.tsx | 317 +++++++++++++------------- 7 files changed, 563 insertions(+), 556 deletions(-) diff --git a/components/Theme.tsx b/components/Theme.tsx index 78350999ee..2c0dc1caad 100644 --- a/components/Theme.tsx +++ b/components/Theme.tsx @@ -1,8 +1,8 @@ -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; -const Theme = (theme?: string) => { +export default function Theme(theme?: string) { const [isReady, setIsReady] = useState(false); - useEffect( () => { + useEffect(() => { if (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches) { document.documentElement.classList.add("dark"); } else { @@ -12,8 +12,6 @@ const Theme = (theme?: string) => { }, []); return { - isReady - } -}; - -export default Theme; + isReady, + }; +} diff --git a/pages/[user].tsx b/pages/[user].tsx index 960e90a0f9..71c311cedf 100644 --- a/pages/[user].tsx +++ b/pages/[user].tsx @@ -1,12 +1,11 @@ import { GetServerSideProps } from "next"; import Head from "next/head"; import Link from "next/link"; -import prisma, {whereAndSelect} from "@lib/prisma"; +import prisma, { whereAndSelect } from "@lib/prisma"; import Avatar from "../components/Avatar"; import Theme from "@components/Theme"; export default function User(props): User { - const { isReady } = Theme(props.user.theme); const eventTypes = props.eventTypes.map((type) => ( @@ -24,42 +23,44 @@ export default function User(props): User { )); - return isReady && ( -
    - - {props.user.name || props.user.username} | Calendso - - + return ( + isReady && ( +
    + + {props.user.name || props.user.username} | Calendso + + -
    -
    - -

    - {props.user.name || props.user.username} -

    -

    {props.user.bio}

    -
    -
    -
      {eventTypes}
    - {eventTypes.length == 0 && ( -
    -

    Uh oh!

    -

    This user hasn't set up any event types yet.

    -
    - )} -
    -
    -
    +
    +
    + +

    + {props.user.name || props.user.username} +

    +

    {props.user.bio}

    +
    +
    +
      {eventTypes}
    + {eventTypes.length == 0 && ( +
    +

    Uh oh!

    +

    This user hasn't set up any event types yet.

    +
    + )} +
    +
    +
    + ) ); } export const getServerSideProps: GetServerSideProps = async (context) => { - - const user = await whereAndSelect(prisma.user.findFirst, { + const user = await whereAndSelect( + prisma.user.findFirst, + { username: context.query.user.toLowerCase(), - }, [ - "id", "username", "email", "name", "bio", "avatar", "eventTypes", "theme" - ] + }, + ["id", "username", "email", "name", "bio", "avatar", "eventTypes", "theme"] ); if (!user) { return { diff --git a/pages/[user]/[type].tsx b/pages/[user]/[type].tsx index d8ba07bf6c..ed5262aa33 100644 --- a/pages/[user]/[type].tsx +++ b/pages/[user]/[type].tsx @@ -47,113 +47,115 @@ export default function Type(props): Type { setTimeFormat(is24hClock ? "HH:mm" : "h:mma"); }; - return isReady && ( -
    - - - {rescheduleUid && "Reschedule"} {props.eventType.title} | {props.user.name || props.user.username} | - Calendso - - - + return ( + isReady && ( +
    + + + {rescheduleUid && "Reschedule"} {props.eventType.title} | {props.user.name || props.user.username}{" "} + | Calendso + + + - - - - - " + props.eventType.description - ).replace(/'/g, "%27") + - ".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" + - encodeURIComponent(props.user.avatar) - } - /> + + + + + " + props.eventType.description + ).replace(/'/g, "%27") + + ".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" + + encodeURIComponent(props.user.avatar) + } + /> - - - - - " + props.eventType.description - ).replace(/'/g, "%27") + - ".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" + - encodeURIComponent(props.user.avatar) - } - /> - -
    -
    -
    -
    - -

    {props.user.name}

    -

    - {props.eventType.title} -

    -

    - - {props.eventType.length} minutes -

    - - {isTimeOptionsOpen && ( - + + + + " + props.eventType.description + ).replace(/'/g, "%27") + + ".png?md=1&images=https%3A%2F%2Fcalendso.com%2Fcalendso-logo-white.svg&images=" + + encodeURIComponent(props.user.avatar) + } + /> + +
    +
    +
    +
    + +

    {props.user.name}

    +

    + {props.eventType.title} +

    +

    + + {props.eventType.length} minutes +

    + + {isTimeOptionsOpen && ( + + )} +

    {props.eventType.description}

    +
    + + {selectedDate && ( + )} -

    {props.eventType.description}

    - - {selectedDate && ( - - )}
    -
    - {!props.user.hideBranding && } -
    -
    + {!props.user.hideBranding && } + +
    + ) ); } diff --git a/pages/[user]/book.tsx b/pages/[user]/book.tsx index fe305e2c85..c03b86da9e 100644 --- a/pages/[user]/book.tsx +++ b/pages/[user]/book.tsx @@ -2,7 +2,7 @@ import Head from "next/head"; import Link from "next/link"; import { useRouter } from "next/router"; import { CalendarIcon, ClockIcon, ExclamationIcon, LocationMarkerIcon } from "@heroicons/react/solid"; -import prisma, {whereAndSelect} from "../../lib/prisma"; +import prisma, { whereAndSelect } from "../../lib/prisma"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "../../lib/telemetry"; import { useEffect, useState } from "react"; import dayjs from "dayjs"; @@ -141,247 +141,247 @@ export default function Book(props: any): JSX.Element { book(); }; - return isReady && ( -
    - - - {rescheduleUid ? "Reschedule" : "Confirm"} your {props.eventType.title} with{" "} - {props.user.name || props.user.username} | Calendso - - - + return ( + isReady && ( +
    + + + {rescheduleUid ? "Reschedule" : "Confirm"} your {props.eventType.title} with{" "} + {props.user.name || props.user.username} | Calendso + + + -
    -
    -
    -
    - -

    {props.user.name}

    -

    - {props.eventType.title} -

    -

    - - {props.eventType.length} minutes -

    - {selectedLocation === LocationType.InPerson && ( +
    +
    +
    +
    + +

    {props.user.name}

    +

    + {props.eventType.title} +

    - - {locationInfo(selectedLocation).address} + + {props.eventType.length} minutes

    - )} -

    - - {preferredTimeZone && - dayjs(date) - .tz(preferredTimeZone) - .format((is24h ? "H:mm" : "h:mma") + ", dddd DD MMMM YYYY")} -

    -

    {props.eventType.description}

    -
    -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    - {locations.length > 1 && ( -
    - Location - {locations.map((location) => ( - - ))} -
    + {selectedLocation === LocationType.InPerson && ( +

    + + {locationInfo(selectedLocation).address} +

    )} - {selectedLocation === LocationType.Phone && ( +

    + + {preferredTimeZone && + dayjs(date) + .tz(preferredTimeZone) + .format((is24h ? "H:mm" : "h:mma") + ", dddd DD MMMM YYYY")} +

    +

    {props.eventType.description}

    +
    +
    +
    -
    - )} - {props.eventType.customInputs && - props.eventType.customInputs - .sort((a, b) => a.id - b.id) - .map((input) => ( -
    - {input.type !== EventTypeCustomInputType.Bool && ( - - )} - {input.type === EventTypeCustomInputType.TextLong && ( - + className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md">
    @@ -166,9 +167,10 @@ export default function Settings(props) { onChange={setSelectedWeekStartDay} className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" options={[ - { value:'Sunday', label:'Sunday' }, - { value:'Monday', label:'Monday' } - ]} /> + { value: "Sunday", label: "Sunday" }, + { value: "Monday", label: "Monday" }, + ]} + />
    @@ -182,7 +184,8 @@ export default function Settings(props) { defaultValue={selectedTheme || themeOptions[0]} onChange={setSelectedTheme} className="shadow-sm focus:ring-blue-500 focus:border-blue-500 mt-1 block w-full sm:text-sm border-gray-300 rounded-md" - options={themeOptions} /> + options={themeOptions} + />
    @@ -302,20 +305,13 @@ export const getServerSideProps: GetServerSideProps = async (context) => { return { redirect: { permanent: false, destination: "/auth/login" } }; } - const user = await whereAndSelect(prisma.user.findFirst, { + const user = await whereAndSelect( + prisma.user.findFirst, + { id: session.user.id, - }, [ - "id", - "username", - "name", - "email", - "bio", - "avatar", - "timeZone", - "weekStart", - "hideBranding", - "theme" - ]); + }, + ["id", "username", "name", "email", "bio", "avatar", "timeZone", "weekStart", "hideBranding", "theme"] + ); return { props: { user }, // will be passed to the page component as props diff --git a/pages/success.tsx b/pages/success.tsx index 20d9e7c3a2..9b08377e3c 100644 --- a/pages/success.tsx +++ b/pages/success.tsx @@ -1,6 +1,6 @@ import Head from "next/head"; import Link from "next/link"; -import prisma, {whereAndSelect} from "../lib/prisma"; +import prisma, { whereAndSelect } from "../lib/prisma"; import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import { CheckIcon } from "@heroicons/react/outline"; @@ -33,7 +33,7 @@ export default function Success(props) { const eventName = getEventName(name, props.eventType.title, props.eventType.eventName); function eventLink(): string { - let optional = {}; + const optional = {}; if (location) { optional["location"] = location; } @@ -58,169 +58,173 @@ export default function Success(props) { return encodeURIComponent(event.value); } - return isReady && ( -
    - - Booking Confirmed | {eventName} | Calendso - - -
    -
    -
    -
    +
    + ) ); } export async function getServerSideProps(context) { - - const user = (context.query.user) ? await whereAndSelect(prisma.user.findFirst, { - username: context.query.user, - }, [ - "username", "name", "bio", "avatar", "eventTypes", "hideBranding", "theme" - ] - ) : null; + const user = context.query.user + ? await whereAndSelect( + prisma.user.findFirst, + { + username: context.query.user, + }, + ["username", "name", "bio", "avatar", "eventTypes", "hideBranding", "theme"] + ) + : null; if (!user) { return { @@ -228,11 +232,12 @@ export async function getServerSideProps(context) { }; } - const eventType = await whereAndSelect(prisma.eventType.findUnique, { + const eventType = await whereAndSelect( + prisma.eventType.findUnique, + { id: parseInt(context.query.type), - }, [ - "id", "title", "description", "length", "eventName" - ] + }, + ["id", "title", "description", "length", "eventName"] ); return {