2021-08-27 12:35:20 +00:00
|
|
|
|
import { HeadSeo } from "@components/seo/head-seo";
|
2021-06-24 22:26:55 +00:00
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import { useRouter } from "next/router";
|
|
|
|
|
import { CalendarIcon, ClockIcon, ExclamationIcon, LocationMarkerIcon } from "@heroicons/react/solid";
|
2021-08-27 12:35:20 +00:00
|
|
|
|
import prisma, { whereAndSelect } from "@lib/prisma";
|
2021-08-14 17:03:50 +00:00
|
|
|
|
import { EventTypeCustomInputType } from "@prisma/client";
|
2021-08-27 12:35:20 +00:00
|
|
|
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
|
2021-06-24 22:26:55 +00:00
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
import dayjs from "dayjs";
|
|
|
|
|
import utc from "dayjs/plugin/utc";
|
|
|
|
|
import timezone from "dayjs/plugin/timezone";
|
2021-08-25 10:18:37 +00:00
|
|
|
|
import PhoneInput from "@components/ui/form/PhoneInput";
|
2021-08-27 12:35:20 +00:00
|
|
|
|
import { LocationType } from "@lib/location";
|
2021-08-22 13:16:42 +00:00
|
|
|
|
import Avatar from "@components/Avatar";
|
2021-08-24 08:38:37 +00:00
|
|
|
|
import { Button } from "@components/ui/Button";
|
2021-07-09 22:59:21 +00:00
|
|
|
|
import Theme from "@components/Theme";
|
2021-08-08 16:17:17 +00:00
|
|
|
|
import { ReactMultiEmail } from "react-multi-email";
|
2021-03-22 13:48:48 +00:00
|
|
|
|
|
2021-05-26 18:40:22 +00:00
|
|
|
|
dayjs.extend(utc);
|
|
|
|
|
dayjs.extend(timezone);
|
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
export default function Book(props: any): JSX.Element {
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const { date, user, rescheduleUid } = router.query;
|
2021-05-08 21:53:10 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const [is24h, setIs24h] = useState(false);
|
|
|
|
|
const [preferredTimeZone, setPreferredTimeZone] = useState("");
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [error, setError] = useState(false);
|
2021-08-04 10:39:43 +00:00
|
|
|
|
const [guestToggle, setGuestToggle] = useState(false);
|
|
|
|
|
const [guestEmails, setGuestEmails] = useState([]);
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const locations = props.eventType.locations || [];
|
2021-05-08 21:53:10 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const [selectedLocation, setSelectedLocation] = useState<LocationType>(
|
|
|
|
|
locations.length === 1 ? locations[0].type : ""
|
|
|
|
|
);
|
2021-07-09 22:59:21 +00:00
|
|
|
|
|
|
|
|
|
const { isReady } = Theme(props.user.theme);
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const telemetry = useTelemetry();
|
2021-07-09 22:59:21 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
setPreferredTimeZone(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess());
|
|
|
|
|
setIs24h(!!localStorage.getItem("timeOption.is24hClock"));
|
2021-05-26 18:40:22 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
telemetry.withJitsu((jitsu) => jitsu.track(telemetryEventTypes.timeSelected, collectPageParameters()));
|
|
|
|
|
});
|
2021-05-26 18:40:22 +00:00
|
|
|
|
|
2021-08-04 10:39:43 +00:00
|
|
|
|
function toggleGuestEmailInput() {
|
|
|
|
|
setGuestToggle(!guestToggle);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const locationInfo = (type: LocationType) => locations.find((location) => location.type === type);
|
2021-05-08 19:03:47 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
// TODO: Move to translations
|
|
|
|
|
const locationLabels = {
|
|
|
|
|
[LocationType.InPerson]: "In-person meeting",
|
|
|
|
|
[LocationType.Phone]: "Phone call",
|
|
|
|
|
[LocationType.GoogleMeet]: "Google Meet",
|
|
|
|
|
[LocationType.Zoom]: "Zoom Video",
|
|
|
|
|
};
|
2021-03-22 13:48:48 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const bookingHandler = (event) => {
|
|
|
|
|
const book = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
setError(false);
|
|
|
|
|
let notes = "";
|
|
|
|
|
if (props.eventType.customInputs) {
|
|
|
|
|
notes = props.eventType.customInputs
|
|
|
|
|
.map((input) => {
|
|
|
|
|
const data = event.target["custom_" + input.id];
|
|
|
|
|
if (data) {
|
2021-08-14 17:03:50 +00:00
|
|
|
|
if (input.type === EventTypeCustomInputType.BOOL) {
|
2021-08-03 10:45:19 +00:00
|
|
|
|
return input.label + "\n" + (data.checked ? "Yes" : "No");
|
2021-06-24 22:26:55 +00:00
|
|
|
|
} else {
|
|
|
|
|
return input.label + "\n" + data.value;
|
|
|
|
|
}
|
2021-06-21 15:56:14 +00:00
|
|
|
|
}
|
2021-06-24 22:26:55 +00:00
|
|
|
|
})
|
|
|
|
|
.join("\n\n");
|
|
|
|
|
}
|
|
|
|
|
if (!!notes && !!event.target.notes.value) {
|
|
|
|
|
notes += "\n\nAdditional notes:\n" + event.target.notes.value;
|
|
|
|
|
} else {
|
|
|
|
|
notes += event.target.notes.value;
|
|
|
|
|
}
|
2021-05-08 19:03:47 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const payload = {
|
|
|
|
|
start: dayjs(date).format(),
|
|
|
|
|
end: dayjs(date).add(props.eventType.length, "minute").format(),
|
|
|
|
|
name: event.target.name.value,
|
|
|
|
|
email: event.target.email.value,
|
|
|
|
|
notes: notes,
|
2021-08-04 10:39:43 +00:00
|
|
|
|
guests: guestEmails,
|
2021-06-24 22:26:55 +00:00
|
|
|
|
timeZone: preferredTimeZone,
|
|
|
|
|
eventTypeId: props.eventType.id,
|
|
|
|
|
rescheduleUid: rescheduleUid,
|
|
|
|
|
};
|
2021-06-20 18:32:30 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
if (selectedLocation) {
|
|
|
|
|
switch (selectedLocation) {
|
|
|
|
|
case LocationType.Phone:
|
|
|
|
|
payload["location"] = event.target.phone.value;
|
|
|
|
|
break;
|
2021-06-24 15:49:15 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
case LocationType.InPerson:
|
|
|
|
|
payload["location"] = locationInfo(selectedLocation).address;
|
|
|
|
|
break;
|
2021-06-24 15:49:15 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
// Catches all other location types, such as Google Meet, Zoom etc.
|
|
|
|
|
default:
|
|
|
|
|
payload["location"] = selectedLocation;
|
2021-05-08 21:53:10 +00:00
|
|
|
|
}
|
2021-06-24 22:26:55 +00:00
|
|
|
|
}
|
2021-05-08 19:03:47 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
telemetry.withJitsu((jitsu) =>
|
|
|
|
|
jitsu.track(telemetryEventTypes.bookingConfirmed, collectPageParameters())
|
|
|
|
|
);
|
2021-06-24 18:41:26 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
/*const res = await */ fetch("/api/book/" + user, {
|
|
|
|
|
body: JSON.stringify(payload),
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
method: "POST",
|
|
|
|
|
});
|
|
|
|
|
// TODO When the endpoint is fixed, change this to await the result again
|
|
|
|
|
//if (res.ok) {
|
|
|
|
|
let successUrl = `/success?date=${date}&type=${props.eventType.id}&user=${
|
|
|
|
|
props.user.username
|
|
|
|
|
}&reschedule=${!!rescheduleUid}&name=${payload.name}`;
|
|
|
|
|
if (payload["location"]) {
|
|
|
|
|
if (payload["location"].includes("integration")) {
|
|
|
|
|
successUrl += "&location=" + encodeURIComponent("Web conferencing details to follow.");
|
|
|
|
|
} else {
|
|
|
|
|
successUrl += "&location=" + encodeURIComponent(payload["location"]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-20 18:32:30 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
await router.push(successUrl);
|
|
|
|
|
/*} else {
|
2021-06-20 18:32:30 +00:00
|
|
|
|
setLoading(false);
|
|
|
|
|
setError(true);
|
2021-06-24 18:41:26 +00:00
|
|
|
|
}*/
|
2021-06-24 22:26:55 +00:00
|
|
|
|
};
|
2021-05-08 21:53:10 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
book();
|
|
|
|
|
};
|
2021-03-22 13:48:48 +00:00
|
|
|
|
|
2021-07-11 19:35:56 +00:00
|
|
|
|
return (
|
|
|
|
|
isReady && (
|
|
|
|
|
<div>
|
2021-08-27 12:35:20 +00:00
|
|
|
|
<HeadSeo
|
|
|
|
|
title={`${rescheduleUid ? "Reschedule" : "Confirm"} your ${props.eventType.title} with ${
|
|
|
|
|
props.user.name || props.user.username
|
|
|
|
|
}`}
|
|
|
|
|
description={`${rescheduleUid ? "Reschedule" : "Confirm"} your ${props.eventType.title} with ${
|
|
|
|
|
props.user.name || props.user.username
|
|
|
|
|
}`}
|
|
|
|
|
/>
|
2021-03-22 13:48:48 +00:00
|
|
|
|
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<main className="max-w-3xl mx-auto my-0 sm:my-24">
|
2021-08-08 16:17:17 +00:00
|
|
|
|
<div className="dark:bg-neutral-900 bg-white overflow-hidden border border-gray-200 dark:border-0 sm:rounded-sm">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<div className="sm:flex px-4 py-5 sm:p-4">
|
2021-08-08 16:17:17 +00:00
|
|
|
|
<div className="sm:w-1/2 sm:border-r sm:dark:border-black">
|
2021-08-22 13:16:42 +00:00
|
|
|
|
<Avatar
|
|
|
|
|
displayName={props.user.name}
|
|
|
|
|
imageSrc={props.user.avatar}
|
|
|
|
|
className="w-16 h-16 rounded-full mb-4"
|
|
|
|
|
/>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<h2 className="font-medium dark:text-gray-300 text-gray-500">{props.user.name}</h2>
|
|
|
|
|
<h1 className="text-3xl font-semibold dark:text-white text-gray-800 mb-4">
|
|
|
|
|
{props.eventType.title}
|
|
|
|
|
</h1>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
<p className="text-gray-500 mb-2">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<ClockIcon className="inline-block w-4 h-4 mr-1 -mt-1" />
|
|
|
|
|
{props.eventType.length} minutes
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</p>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{selectedLocation === LocationType.InPerson && (
|
2021-09-10 21:12:38 +00:00
|
|
|
|
<p className="text-gray-500 mb-2 break-words">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<LocationMarkerIcon className="inline-block w-4 h-4 mr-1 -mt-1" />
|
|
|
|
|
{locationInfo(selectedLocation).address}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
<p className="text-green-500 mb-4">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<CalendarIcon className="inline-block w-4 h-4 mr-1 -mt-1" />
|
|
|
|
|
{preferredTimeZone &&
|
|
|
|
|
dayjs(date)
|
|
|
|
|
.tz(preferredTimeZone)
|
|
|
|
|
.format((is24h ? "H:mm" : "h:mma") + ", dddd DD MMMM YYYY")}
|
|
|
|
|
</p>
|
|
|
|
|
<p className="dark:text-white text-gray-600 mb-8">{props.eventType.description}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="sm:w-1/2 sm:pl-8 sm:pr-4">
|
|
|
|
|
<form onSubmit={bookingHandler}>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
<div className="mb-4">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<label htmlFor="name" className="block text-sm font-medium dark:text-white text-gray-700">
|
|
|
|
|
Your name
|
|
|
|
|
</label>
|
|
|
|
|
<div className="mt-1">
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
name="name"
|
|
|
|
|
id="name"
|
|
|
|
|
required
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
placeholder="John Doe"
|
|
|
|
|
defaultValue={props.booking ? props.booking.attendees[0].name : ""}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div className="mb-4">
|
2021-07-07 19:58:18 +00:00
|
|
|
|
<label
|
2021-07-11 19:35:56 +00:00
|
|
|
|
htmlFor="email"
|
2021-07-07 19:58:18 +00:00
|
|
|
|
className="block text-sm font-medium dark:text-white text-gray-700">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
Email address
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</label>
|
|
|
|
|
<div className="mt-1">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<input
|
|
|
|
|
type="email"
|
|
|
|
|
name="email"
|
|
|
|
|
id="email"
|
2021-06-24 22:26:55 +00:00
|
|
|
|
required
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
placeholder="you@example.com"
|
|
|
|
|
defaultValue={props.booking ? props.booking.attendees[0].email : ""}
|
2021-06-24 22:26:55 +00:00
|
|
|
|
/>
|
2021-03-22 13:48:48 +00:00
|
|
|
|
</div>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</div>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{locations.length > 1 && (
|
|
|
|
|
<div className="mb-4">
|
2021-07-22 12:16:21 +00:00
|
|
|
|
<span className="block text-sm font-medium dark:text-white text-gray-700">
|
|
|
|
|
Location
|
|
|
|
|
</span>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{locations.map((location) => (
|
|
|
|
|
<label key={location.type} className="block">
|
2021-06-24 22:26:55 +00:00
|
|
|
|
<input
|
2021-07-11 19:35:56 +00:00
|
|
|
|
type="radio"
|
|
|
|
|
required
|
|
|
|
|
onChange={(e) => setSelectedLocation(e.target.value)}
|
2021-08-20 12:11:08 +00:00
|
|
|
|
className="location focus:ring-black h-4 w-4 text-black border-gray-300 mr-2"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
name="location"
|
|
|
|
|
value={location.type}
|
|
|
|
|
checked={selectedLocation === location.type}
|
2021-06-24 22:26:55 +00:00
|
|
|
|
/>
|
2021-07-22 12:16:21 +00:00
|
|
|
|
<span className="text-sm ml-2 dark:text-gray-500">
|
|
|
|
|
{locationLabels[location.type]}
|
|
|
|
|
</span>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
</label>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{selectedLocation === LocationType.Phone && (
|
|
|
|
|
<div className="mb-4">
|
|
|
|
|
<label
|
|
|
|
|
htmlFor="phone"
|
|
|
|
|
className="block text-sm font-medium dark:text-white text-gray-700">
|
2021-08-25 10:18:37 +00:00
|
|
|
|
Phone number
|
2021-07-11 19:35:56 +00:00
|
|
|
|
</label>
|
|
|
|
|
<div className="mt-1">
|
2021-08-25 10:18:37 +00:00
|
|
|
|
<PhoneInput name="phone" placeholder="Enter phone number" id="phone" required />
|
2021-07-11 19:35:56 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{props.eventType.customInputs &&
|
|
|
|
|
props.eventType.customInputs
|
|
|
|
|
.sort((a, b) => a.id - b.id)
|
|
|
|
|
.map((input) => (
|
|
|
|
|
<div className="mb-4" key={"input-" + input.label.toLowerCase}>
|
2021-08-14 17:03:50 +00:00
|
|
|
|
{input.type !== EventTypeCustomInputType.BOOL && (
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<label
|
2021-08-20 12:11:08 +00:00
|
|
|
|
htmlFor={"custom_" + input.id}
|
2021-07-26 20:08:53 +00:00
|
|
|
|
className="block text-sm font-medium text-gray-700 dark:text-white mb-1">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{input.label}
|
|
|
|
|
</label>
|
|
|
|
|
)}
|
2021-08-14 17:03:50 +00:00
|
|
|
|
{input.type === EventTypeCustomInputType.TEXTLONG && (
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<textarea
|
|
|
|
|
name={"custom_" + input.id}
|
|
|
|
|
id={"custom_" + input.id}
|
|
|
|
|
required={input.required}
|
|
|
|
|
rows={3}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-08-22 13:06:26 +00:00
|
|
|
|
placeholder={input.placeholder}
|
2021-07-11 19:35:56 +00:00
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-08-14 17:03:50 +00:00
|
|
|
|
{input.type === EventTypeCustomInputType.TEXT && (
|
2021-06-24 22:26:55 +00:00
|
|
|
|
<input
|
2021-07-11 19:35:56 +00:00
|
|
|
|
type="text"
|
2021-06-24 22:26:55 +00:00
|
|
|
|
name={"custom_" + input.id}
|
|
|
|
|
id={"custom_" + input.id}
|
2021-07-11 19:35:56 +00:00
|
|
|
|
required={input.required}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-08-22 13:06:26 +00:00
|
|
|
|
placeholder={input.placeholder}
|
2021-06-24 22:26:55 +00:00
|
|
|
|
/>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
)}
|
2021-08-14 17:03:50 +00:00
|
|
|
|
{input.type === EventTypeCustomInputType.NUMBER && (
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
name={"custom_" + input.id}
|
|
|
|
|
id={"custom_" + input.id}
|
|
|
|
|
required={input.required}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
placeholder=""
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-08-14 17:03:50 +00:00
|
|
|
|
{input.type === EventTypeCustomInputType.BOOL && (
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<div className="flex items-center h-5">
|
|
|
|
|
<input
|
|
|
|
|
type="checkbox"
|
|
|
|
|
name={"custom_" + input.id}
|
|
|
|
|
id={"custom_" + input.id}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="focus:ring-black h-4 w-4 text-black border-gray-300 rounded mr-2"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
placeholder=""
|
|
|
|
|
/>
|
|
|
|
|
<label
|
2021-08-20 12:11:08 +00:00
|
|
|
|
htmlFor={"custom_" + input.id}
|
|
|
|
|
className="block text-sm font-medium text-gray-700 dark:text-white mb-1">
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{input.label}
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
2021-08-04 10:39:43 +00:00
|
|
|
|
<div className="mb-4">
|
2021-08-08 21:44:11 +00:00
|
|
|
|
{!guestToggle && (
|
|
|
|
|
<label
|
|
|
|
|
onClick={toggleGuestEmailInput}
|
|
|
|
|
htmlFor="guests"
|
|
|
|
|
className="block text-sm font-medium dark:text-white text-blue-500 mb-1 hover:cursor-pointer">
|
|
|
|
|
+ Additional Guests
|
|
|
|
|
</label>
|
|
|
|
|
)}
|
|
|
|
|
{guestToggle && (
|
|
|
|
|
<div>
|
2021-08-04 10:39:43 +00:00
|
|
|
|
<label
|
|
|
|
|
htmlFor="guests"
|
2021-08-08 21:44:11 +00:00
|
|
|
|
className="block text-sm font-medium dark:text-white text-gray-700 mb-1">
|
2021-08-05 04:33:08 +00:00
|
|
|
|
Guests
|
2021-08-08 21:44:11 +00:00
|
|
|
|
</label>
|
|
|
|
|
<ReactMultiEmail
|
2021-08-05 04:33:08 +00:00
|
|
|
|
placeholder="guest@example.com"
|
|
|
|
|
emails={guestEmails}
|
|
|
|
|
onChange={(_emails: string[]) => {
|
|
|
|
|
setGuestEmails(_emails);
|
|
|
|
|
}}
|
2021-08-08 21:44:11 +00:00
|
|
|
|
getLabel={(email: string, index: number, removeEmail: (index: number) => void) => {
|
2021-08-05 04:33:08 +00:00
|
|
|
|
return (
|
|
|
|
|
<div data-tag key={index}>
|
|
|
|
|
{email}
|
|
|
|
|
<span data-tag-handle onClick={() => removeEmail(index)}>
|
|
|
|
|
×
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}}
|
2021-08-08 21:44:11 +00:00
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
<div className="mb-4">
|
|
|
|
|
<label
|
|
|
|
|
htmlFor="notes"
|
|
|
|
|
className="block text-sm font-medium dark:text-white text-gray-700 mb-1">
|
|
|
|
|
Additional notes
|
|
|
|
|
</label>
|
|
|
|
|
<textarea
|
|
|
|
|
name="notes"
|
|
|
|
|
id="notes"
|
|
|
|
|
rows={3}
|
2021-08-08 16:17:17 +00:00
|
|
|
|
className="shadow-sm dark:bg-black dark:text-white dark:border-gray-900 focus:ring-black focus:border-black block w-full sm:text-sm border-gray-300 rounded-md"
|
2021-07-11 19:35:56 +00:00
|
|
|
|
placeholder="Please share anything that will help prepare for our meeting."
|
|
|
|
|
defaultValue={props.booking ? props.booking.description : ""}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-start">
|
2021-08-08 16:17:17 +00:00
|
|
|
|
{/* TODO: add styling props to <Button variant="" color="" /> and get rid of btn-primary */}
|
|
|
|
|
<Button type="submit" loading={loading}>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
{rescheduleUid ? "Reschedule" : "Confirm"}
|
|
|
|
|
</Button>
|
|
|
|
|
<Link
|
|
|
|
|
href={
|
|
|
|
|
"/" +
|
|
|
|
|
props.user.username +
|
|
|
|
|
"/" +
|
|
|
|
|
props.eventType.slug +
|
|
|
|
|
(rescheduleUid ? "?rescheduleUid=" + rescheduleUid : "")
|
|
|
|
|
}>
|
2021-08-08 16:17:17 +00:00
|
|
|
|
<a className="ml-2 text-sm dark:text-white p-2">Cancel</a>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
{error && (
|
|
|
|
|
<div className="bg-yellow-50 border-l-4 border-yellow-400 p-4 mt-2">
|
|
|
|
|
<div className="flex">
|
|
|
|
|
<div className="flex-shrink-0">
|
|
|
|
|
<ExclamationIcon className="h-5 w-5 text-yellow-400" aria-hidden="true" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="ml-3">
|
|
|
|
|
<p className="text-sm text-yellow-700">
|
|
|
|
|
Could not {rescheduleUid ? "reschedule" : "book"} the meeting. Please try again or{" "}
|
|
|
|
|
<a
|
|
|
|
|
href={"mailto:" + props.user.email}
|
|
|
|
|
className="font-medium underline text-yellow-700 hover:text-yellow-600">
|
|
|
|
|
Contact {props.user.name} via e-mail
|
|
|
|
|
</a>
|
|
|
|
|
</p>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
)}
|
|
|
|
|
</div>
|
2021-06-24 22:26:55 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-07-11 19:35:56 +00:00
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2021-06-24 22:26:55 +00:00
|
|
|
|
);
|
2021-03-22 13:48:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getServerSideProps(context) {
|
2021-07-11 19:35:56 +00:00
|
|
|
|
const user = await whereAndSelect(
|
|
|
|
|
prisma.user.findFirst,
|
|
|
|
|
{
|
2021-06-24 22:26:55 +00:00
|
|
|
|
username: context.query.user,
|
2021-07-11 19:35:56 +00:00
|
|
|
|
},
|
2021-07-15 14:10:26 +00:00
|
|
|
|
["username", "name", "email", "bio", "avatar", "theme"]
|
2021-07-09 22:59:21 +00:00
|
|
|
|
);
|
2021-03-22 13:48:48 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
const eventType = await prisma.eventType.findUnique({
|
|
|
|
|
where: {
|
|
|
|
|
id: parseInt(context.query.type),
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
id: true,
|
|
|
|
|
title: true,
|
|
|
|
|
slug: true,
|
|
|
|
|
description: true,
|
|
|
|
|
length: true,
|
|
|
|
|
locations: true,
|
|
|
|
|
customInputs: true,
|
2021-07-15 14:10:26 +00:00
|
|
|
|
periodType: true,
|
|
|
|
|
periodDays: true,
|
|
|
|
|
periodStartDate: true,
|
|
|
|
|
periodEndDate: true,
|
|
|
|
|
periodCountCalendarDays: true,
|
2021-06-24 22:26:55 +00:00
|
|
|
|
},
|
|
|
|
|
});
|
2021-06-09 18:28:39 +00:00
|
|
|
|
|
2021-08-08 16:17:17 +00:00
|
|
|
|
const eventTypeObject = [eventType].map((e) => {
|
|
|
|
|
return {
|
|
|
|
|
...e,
|
|
|
|
|
periodStartDate: e.periodStartDate?.toString() ?? null,
|
|
|
|
|
periodEndDate: e.periodEndDate?.toString() ?? null,
|
|
|
|
|
};
|
2021-08-04 10:39:43 +00:00
|
|
|
|
})[0];
|
2021-07-15 14:10:26 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
let booking = null;
|
2021-06-09 18:28:39 +00:00
|
|
|
|
|
2021-06-24 22:26:55 +00:00
|
|
|
|
if (context.query.rescheduleUid) {
|
|
|
|
|
booking = await prisma.booking.findFirst({
|
|
|
|
|
where: {
|
|
|
|
|
uid: context.query.rescheduleUid,
|
|
|
|
|
},
|
|
|
|
|
select: {
|
|
|
|
|
description: true,
|
|
|
|
|
attendees: {
|
|
|
|
|
select: {
|
|
|
|
|
email: true,
|
|
|
|
|
name: true,
|
|
|
|
|
},
|
2021-03-22 13:48:48 +00:00
|
|
|
|
},
|
2021-06-24 22:26:55 +00:00
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
props: {
|
|
|
|
|
user,
|
2021-07-15 14:10:26 +00:00
|
|
|
|
eventType: eventTypeObject,
|
2021-06-24 22:26:55 +00:00
|
|
|
|
booking,
|
|
|
|
|
},
|
|
|
|
|
};
|
2021-06-15 15:26:16 +00:00
|
|
|
|
}
|