/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import Avatar from "@components/Avatar"; import AvailableTimes from "@components/booking/AvailableTimes"; import DatePicker from "@components/booking/DatePicker"; import TimeOptions from "@components/booking/TimeOptions"; import { HeadSeo } from "@components/seo/head-seo"; import Theme from "@components/Theme"; import PoweredByCalendso from "@components/ui/PoweredByCalendso"; import { ChevronDownIcon, ChevronUpIcon, ClockIcon, GlobeIcon } from "@heroicons/react/solid"; import { asStringOrNull } from "@lib/asStringOrNull"; import { timeZone } from "@lib/clock"; import prisma from "@lib/prisma"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry"; import { inferSSRProps } from "@lib/types/inferSSRProps"; import { Availability } from "@prisma/client"; import * as Collapsible from "@radix-ui/react-collapsible"; import dayjs, { Dayjs } from "dayjs"; import { GetServerSidePropsContext } from "next"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; export default function Type(props: inferSSRProps) { // Get router variables const router = useRouter(); const { rescheduleUid } = router.query; const { isReady } = Theme(props.user.theme); const [selectedDate, setSelectedDate] = useState(() => { return props.date && dayjs(props.date).isValid() ? dayjs(props.date) : null; }); const [isTimeOptionsOpen, setIsTimeOptionsOpen] = useState(false); const [timeFormat, setTimeFormat] = useState("h:mma"); const telemetry = useTelemetry(); useEffect(() => { handleToggle24hClock(localStorage.getItem("timeOption.is24hClock") === "true"); telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.pageView, collectPageParameters())); }, [telemetry]); const changeDate = (date: Dayjs) => { telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.dateSelected, collectPageParameters())); setSelectedDate(date); }; useEffect(() => { if (!selectedDate) { return; } const formattedDate = selectedDate.utc().format("YYYY-MM-DD"); router.replace( { query: Object.assign( {}, { ...router.query, }, { date: formattedDate, } ), }, undefined, { shallow: true, } ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDate]); const handleSelectTimeZone = (selectedTimeZone: string): void => { if (selectedDate) { setSelectedDate(selectedDate.tz(selectedTimeZone)); } setIsTimeOptionsOpen(false); }; const handleToggle24hClock = (is24hClock: boolean) => { setTimeFormat(is24hClock ? "HH:mm" : "h:mma"); }; return ( <> {isReady && (
{/* mobile: details */}

{props.user.name}

{props.eventType.title}
{props.eventType.length} minutes

{props.eventType.description}

{props.user.name}

{props.eventType.title}

{props.eventType.length} minutes

{props.eventType.description}

{selectedDate && ( )}
{!props.user.hideBranding && }
)} ); function TimezoneDropdown() { return ( {timeZone()} {isTimeOptionsOpen ? ( ) : ( )} ); } } export const getServerSideProps = async (context: GetServerSidePropsContext) => { // get query params and typecast them to string // (would be even better to assert them instead of typecasting) const userParam = asStringOrNull(context.query.user); const typeParam = asStringOrNull(context.query.type); const dateParam = asStringOrNull(context.query.date); if (!userParam || !typeParam) { throw new Error(`File is not named [type]/[user]`); } const user = await prisma.user.findFirst({ where: { username: userParam.toLowerCase(), }, select: { id: true, username: true, name: true, email: true, bio: true, avatar: true, startTime: true, endTime: true, timeZone: true, weekStart: true, availability: true, hideBranding: true, theme: true, }, }); if (!user) { return { notFound: true, } as const; } const eventType = await prisma.eventType.findFirst({ where: { userId: user.id, slug: typeParam, }, select: { id: true, title: true, description: true, length: true, availability: true, timeZone: true, periodType: true, periodDays: true, periodStartDate: true, periodEndDate: true, periodCountCalendarDays: true, minimumBookingNotice: true, }, }); if (!eventType) { return { notFound: true, } as const; } const getWorkingHours = (providesAvailability: { availability: Availability[] }) => providesAvailability.availability && providesAvailability.availability.length ? providesAvailability.availability : null; const workingHours = getWorkingHours(eventType) || getWorkingHours(user) || [ { days: [0, 1, 2, 3, 4, 5, 6], startTime: user.startTime, endTime: user.endTime, }, ].filter((availability): boolean => typeof availability["days"] !== "undefined"); workingHours.sort((a, b) => a.startTime - b.startTime); const eventTypeObject = Object.assign({}, eventType, { periodStartDate: eventType.periodStartDate?.toString() ?? null, periodEndDate: eventType.periodEndDate?.toString() ?? null, }); return { props: { user, date: dateParam, eventType: eventTypeObject, workingHours, }, }; };