WIP bookings page ui changes, created api endpoint
This commit is contained in:
parent
77266535e5
commit
8b92475097
|
@ -4,12 +4,13 @@ import dayjs from "dayjs";
|
|||
import { useState } from "react";
|
||||
import { useMutation } from "react-query";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import Button from "@calcom/ui/Button";
|
||||
import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog";
|
||||
import { TextArea } from "@calcom/ui/form/fields";
|
||||
|
||||
import { HttpError } from "@lib/core/http/error";
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
import * as fetch from "@lib/core/http/fetch-wrapper";
|
||||
import { inferQueryOutput, trpc } from "@lib/trpc";
|
||||
|
||||
import { useMeQuery } from "@components/Shell";
|
||||
|
@ -17,6 +18,69 @@ import TableActions, { ActionType } from "@components/ui/TableActions";
|
|||
|
||||
type BookingItem = inferQueryOutput<"viewer.bookings">["bookings"][number];
|
||||
|
||||
interface IRescheduleDialog {
|
||||
isOpenDialog: boolean;
|
||||
setIsOpenDialog: () => void;
|
||||
bookingUId: string;
|
||||
}
|
||||
|
||||
const RescheduleDialog = (props: IRescheduleDialog) => {
|
||||
const { t } = useLocale();
|
||||
const { isOpenDialog, setIsOpenDialog, bookingUId: bookingId } = props;
|
||||
const [rescheduleReason, setRescheduleReason] = useState("");
|
||||
|
||||
const rescheduleApi = async () => {
|
||||
await fetch.post(`${process.env.BASE_URL}/api/reschedule`, { bookingId, rescheduleReason });
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpenDialog} onOpenChange={setIsOpenDialog}>
|
||||
<DialogContent>
|
||||
<DialogClose asChild>
|
||||
<div className="fixed top-1 right-1 flex h-8 w-8 justify-center rounded-full hover:bg-gray-200">
|
||||
<XIcon className="w-4" />
|
||||
</div>
|
||||
</DialogClose>
|
||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||
<div className="flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]">
|
||||
<ClockIcon className="m-auto h-6 w-6"></ClockIcon>
|
||||
</div>
|
||||
<div className="px-4 pt-1">
|
||||
<DialogHeader title={"Send reschedule request"} />
|
||||
|
||||
<p className="-mt-8 text-sm text-gray-500">
|
||||
This will cancel the scheduled meeting, notify the scheduler and ask them to pick a new time.
|
||||
</p>
|
||||
<p className="mt-6 mb-2 text-sm font-bold text-black">
|
||||
Reason for reschedule request
|
||||
<span className="font-normal text-gray-500"> (Optional)</span>
|
||||
</p>
|
||||
<TextArea
|
||||
name={t("rejection_reason")}
|
||||
value={rescheduleReason}
|
||||
onChange={(e) => setRescheduleReason(e.target.value)}
|
||||
className="mb-5 sm:mb-6"
|
||||
/>
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose>
|
||||
<Button color="secondary">{t("cancel")}</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
// disabled={mutation.isLoading}
|
||||
onClick={() => {
|
||||
// mutation.mutate(false);
|
||||
}}>
|
||||
Send reschedule request
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
function BookingListItem(booking: BookingItem) {
|
||||
// Get user so we can determine 12/24 hour format preferences
|
||||
const query = useMeQuery();
|
||||
|
@ -80,15 +144,29 @@ function BookingListItem(booking: BookingItem) {
|
|||
{
|
||||
id: "reschedule",
|
||||
label: t("reschedule"),
|
||||
href: `/reschedule/${booking.uid}`,
|
||||
icon: ClockIcon,
|
||||
actions: [
|
||||
{
|
||||
id: "edit",
|
||||
// @TODO: add translate
|
||||
label: "Edit booking",
|
||||
href: "",
|
||||
},
|
||||
{
|
||||
id: "reschedule_request",
|
||||
// @TODO: add translate
|
||||
label: "Reschedule booking",
|
||||
onClick: () => setIsOpenRescheduleDialog(true),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const startTime = dayjs(booking.startTime).format(isUpcoming ? "ddd, D MMM" : "D MMMM YYYY");
|
||||
|
||||
const [isOpenRescheduleDialog, setIsOpenRescheduleDialog] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<RescheduleDialog isOpenDialog={isOpenRescheduleDialog} setIsOpenDialog={setIsOpenRescheduleDialog} />
|
||||
<Dialog open={rejectionDialogIsOpen} onOpenChange={setRejectionDialogIsOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader title={t("rejection_reason_title")} />
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { DotsHorizontalIcon } from "@heroicons/react/solid";
|
||||
import React, { FC } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import Button from "@calcom/ui/Button";
|
||||
import Dropdown, { DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@calcom/ui/Dropdown";
|
||||
|
||||
|
@ -9,56 +8,72 @@ import { SVGComponent } from "@lib/types/SVGComponent";
|
|||
|
||||
export type ActionType = {
|
||||
id: string;
|
||||
icon: SVGComponent;
|
||||
icon?: SVGComponent;
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
color?: "primary" | "secondary";
|
||||
} & ({ href?: never; onClick: () => any } | { href: string; onClick?: never });
|
||||
} & ({ href?: never; onClick: () => any } | { href?: string; onClick?: never }) & { actions?: ActionType[] };
|
||||
|
||||
interface Props {
|
||||
actions: ActionType[];
|
||||
}
|
||||
|
||||
const DropdownActions = ({ actions, actionTrigger }: { actions: ActionType[]; actionTrigger?: any }) => {
|
||||
return (
|
||||
<Dropdown>
|
||||
{!actionTrigger ? (
|
||||
<DropdownMenuTrigger className="h-[38px] w-[38px] cursor-pointer rounded-sm border border-transparent text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
|
||||
<DotsHorizontalIcon className="h-5 w-5 group-hover:text-gray-800" />
|
||||
</DropdownMenuTrigger>
|
||||
) : (
|
||||
<DropdownMenuTrigger asChild>{actionTrigger}</DropdownMenuTrigger>
|
||||
)}
|
||||
<DropdownMenuContent portalled>
|
||||
{actions.map((action) => (
|
||||
<DropdownMenuItem key={action.id} className="focus-visible:outline-none">
|
||||
<Button
|
||||
type="button"
|
||||
size="lg"
|
||||
color="minimal"
|
||||
className="w-full rounded-none font-normal"
|
||||
href={action.href}
|
||||
StartIcon={action.icon}
|
||||
onClick={action.onClick}>
|
||||
{action.label}
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
const TableActions: FC<Props> = ({ actions }) => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<>
|
||||
<div className="hidden space-x-2 rtl:space-x-reverse lg:block">
|
||||
{actions.map((action) => (
|
||||
<Button
|
||||
key={action.id}
|
||||
data-testid={action.id}
|
||||
href={action.href}
|
||||
onClick={action.onClick}
|
||||
StartIcon={action.icon}
|
||||
disabled={action.disabled}
|
||||
color={action.color || "secondary"}>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
{actions.map((action) => {
|
||||
const button = (
|
||||
<Button
|
||||
key={action.id}
|
||||
data-testid={action.id}
|
||||
href={action.href}
|
||||
onClick={action.onClick}
|
||||
StartIcon={action.icon}
|
||||
disabled={action.disabled}
|
||||
color={action.color || "secondary"}>
|
||||
{action.label}
|
||||
</Button>
|
||||
);
|
||||
if (!action.actions) {
|
||||
return button;
|
||||
}
|
||||
|
||||
return <DropdownActions key={action.id} actions={action.actions} actionTrigger={button} />;
|
||||
})}
|
||||
</div>
|
||||
<div className="inline-block text-left lg:hidden">
|
||||
<Dropdown>
|
||||
<DropdownMenuTrigger className="h-[38px] w-[38px] cursor-pointer rounded-sm border border-transparent text-neutral-500 hover:border-gray-300 hover:text-neutral-900">
|
||||
<DotsHorizontalIcon className="h-5 w-5 group-hover:text-gray-800" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent portalled>
|
||||
{actions.map((action) => (
|
||||
<DropdownMenuItem key={action.id}>
|
||||
<Button
|
||||
type="button"
|
||||
size="lg"
|
||||
color="minimal"
|
||||
className="w-full rounded-none font-normal"
|
||||
href={action.href}
|
||||
StartIcon={action.icon}
|
||||
onClick={action.onClick}>
|
||||
{action.label}
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</Dropdown>
|
||||
<DropdownActions actions={actions} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -14,6 +14,8 @@ import OrganizerScheduledEmail from "@lib/emails/templates/organizer-scheduled-e
|
|||
import TeamInviteEmail, { TeamInvite } from "@lib/emails/templates/team-invite-email";
|
||||
import { CalendarEvent, Person } from "@lib/integrations/calendar/interfaces/Calendar";
|
||||
|
||||
import OrganizerRequestRescheduledEmail from "./templates/organizer-request-reschedule-email";
|
||||
|
||||
export const sendScheduledEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
|
@ -207,3 +209,14 @@ export const sendTeamInviteEmail = async (teamInviteEvent: TeamInvite) => {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const sendRescheduleEmail = async (calEvent: CalendarEvent) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const rescheduleEmail = new OrganizerRequestRescheduledEmail(calEvent);
|
||||
resolve(rescheduleEmail.sendEmail());
|
||||
} catch (e) {
|
||||
reject(console.error("RescheduleEmail.sendEmail failed", e));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import timezone from "dayjs/plugin/timezone";
|
||||
import toArray from "dayjs/plugin/toArray";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
|
||||
import { getCancelLink } from "@lib/CalEventParser";
|
||||
|
||||
import {
|
||||
emailHead,
|
||||
emailSchedulingBodyHeader,
|
||||
emailBodyLogo,
|
||||
emailScheduledBodyHeaderContent,
|
||||
emailSchedulingBodyDivider,
|
||||
} from "./common";
|
||||
import OrganizerScheduledEmail from "./organizer-scheduled-email";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(localizedFormat);
|
||||
dayjs.extend(toArray);
|
||||
|
||||
export default class OrganizerRequestRescheduledEmail extends OrganizerScheduledEmail {
|
||||
protected getNodeMailerPayload(): Record<string, unknown> {
|
||||
const toAddresses = [this.calEvent.organizer.email];
|
||||
if (this.calEvent.team) {
|
||||
this.calEvent.team.members.forEach((member) => {
|
||||
const memberAttendee = this.calEvent.attendees.find((attendee) => attendee.name === member);
|
||||
if (memberAttendee) {
|
||||
toAddresses.push(memberAttendee.email);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
icalEvent: {
|
||||
filename: "event.ics",
|
||||
content: this.getiCalEventAsString(),
|
||||
},
|
||||
from: `Cal.com <${this.getMailerOptions().from}>`,
|
||||
to: toAddresses.join(","),
|
||||
subject: `${this.calEvent.organizer.language.translate("rescheduled_event_type_subject", {
|
||||
eventType: this.calEvent.type,
|
||||
name: this.calEvent.attendees[0].name,
|
||||
date: `${this.getOrganizerStart().format("h:mma")} - ${this.getOrganizerEnd().format(
|
||||
"h:mma"
|
||||
)}, ${this.calEvent.organizer.language.translate(
|
||||
this.getOrganizerStart().format("dddd").toLowerCase()
|
||||
)}, ${this.calEvent.organizer.language.translate(
|
||||
this.getOrganizerStart().format("MMMM").toLowerCase()
|
||||
)} ${this.getOrganizerStart().format("D")}, ${this.getOrganizerStart().format("YYYY")}`,
|
||||
})}`,
|
||||
html: this.getHtmlBody(),
|
||||
text: this.getTextBody(),
|
||||
};
|
||||
}
|
||||
|
||||
protected getTextBody(): string {
|
||||
return `
|
||||
${this.calEvent.organizer.language.translate("event_has_been_rescheduled")}
|
||||
${this.calEvent.organizer.language.translate("emailed_you_and_any_other_attendees")}
|
||||
${this.getWhat()}
|
||||
${this.getWhen()}
|
||||
${this.getLocation()}
|
||||
${this.getAdditionalNotes()}
|
||||
${this.calEvent.organizer.language.translate("need_to_reschedule_or_cancel")}
|
||||
${getCancelLink(this.calEvent)}
|
||||
`.replace(/(<([^>]+)>)/gi, "");
|
||||
}
|
||||
|
||||
protected getHtmlBody(): string {
|
||||
const headerContent = this.calEvent.organizer.language.translate("rescheduled_event_type_subject", {
|
||||
eventType: this.calEvent.type,
|
||||
name: this.calEvent.attendees[0].name,
|
||||
date: `${this.getOrganizerStart().format("h:mma")} - ${this.getOrganizerEnd().format(
|
||||
"h:mma"
|
||||
)}, ${this.calEvent.organizer.language.translate(
|
||||
this.getOrganizerStart().format("dddd").toLowerCase()
|
||||
)}, ${this.calEvent.organizer.language.translate(
|
||||
this.getOrganizerStart().format("MMMM").toLowerCase()
|
||||
)} ${this.getOrganizerStart().format("D")}, ${this.getOrganizerStart().format("YYYY")}`,
|
||||
});
|
||||
|
||||
return `
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
${emailHead(headerContent)}
|
||||
<body style="word-spacing:normal;background-color:#F5F5F5;">
|
||||
<div style="background-color:#F5F5F5;">
|
||||
${emailSchedulingBodyHeader("calendarCircle")}
|
||||
${emailScheduledBodyHeaderContent(
|
||||
this.calEvent.organizer.language.translate("event_has_been_rescheduled"),
|
||||
this.calEvent.organizer.language.translate("emailed_you_and_any_other_attendees")
|
||||
)}
|
||||
${emailSchedulingBodyDivider()}
|
||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#FFFFFF" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="background:#FFFFFF;background-color:#FFFFFF;margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#FFFFFF;background-color:#FFFFFF;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="border-left:1px solid #E1E1E1;border-right:1px solid #E1E1E1;direction:ltr;font-size:0px;padding:0px;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:598px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Roboto, Helvetica, sans-serif;font-size:16px;font-weight:500;line-height:1;text-align:left;color:#3E3E3E;">
|
||||
${this.getWhat()}
|
||||
${this.getWhen()}
|
||||
${this.getWho()}
|
||||
${this.getLocation()}
|
||||
${this.getAdditionalNotes()}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
${emailSchedulingBodyDivider()}
|
||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#FFFFFF" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="background:#FFFFFF;background-color:#FFFFFF;margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#FFFFFF;background-color:#FFFFFF;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="border-bottom:1px solid #E1E1E1;border-left:1px solid #E1E1E1;border-right:1px solid #E1E1E1;direction:ltr;font-size:0px;padding:0px;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:598px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Roboto, Helvetica, sans-serif;font-size:16px;font-weight:500;line-height:0px;text-align:left;color:#3E3E3E;">
|
||||
${this.getManageLink()}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
${emailBodyLogo()}
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import { BookingStatus } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
import type { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
|
||||
import { z, ZodError } from "zod";
|
||||
|
||||
import prisma from "@lib/prisma";
|
||||
|
||||
const rescheduleSchema = z.object({
|
||||
bookingId: z.string(),
|
||||
rescheduleReason: z.string().optional(),
|
||||
});
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { bookingId, rescheduleReason: cancellationReason } = req.body;
|
||||
try {
|
||||
const bookingToReschedule = await prisma.booking.findFirst({
|
||||
where: {
|
||||
uid: bookingId,
|
||||
NOT: {
|
||||
// status: BookingStatus.CANCELLED,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (bookingToReschedule) {
|
||||
await prisma.booking.update({
|
||||
where: {
|
||||
id: bookingToReschedule.id,
|
||||
},
|
||||
data: {
|
||||
cancellationReason,
|
||||
updatedAt: dayjs().toISOString(),
|
||||
status: BookingStatus.CANCELLED,
|
||||
rescheduled: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log({ bookingToReschedule });
|
||||
|
||||
return res.status(200).json(bookingToReschedule);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// throw new Error(error?.message);
|
||||
}
|
||||
// Change it to cancelled and update reschedule sent field
|
||||
|
||||
// Send email about rescheduling
|
||||
return res.status(204);
|
||||
};
|
||||
|
||||
function validate(handler: NextApiHandler) {
|
||||
return async (req, res) => {
|
||||
if (req.method === "POST") {
|
||||
try {
|
||||
rescheduleSchema.parse(req.body);
|
||||
} catch (error) {
|
||||
if (error instanceof ZodError && error?.name === "ZodError") {
|
||||
return res.status(400).json(error?.issues);
|
||||
}
|
||||
return res.status(402);
|
||||
}
|
||||
} else {
|
||||
return res.status(405);
|
||||
}
|
||||
await handler(req, res);
|
||||
};
|
||||
}
|
||||
|
||||
export default validate(handler);
|
|
@ -2,11 +2,11 @@ import { CalendarIcon } from "@heroicons/react/outline";
|
|||
import { useRouter } from "next/router";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Alert } from "@calcom/ui/Alert";
|
||||
import Button from "@calcom/ui/Button";
|
||||
|
||||
import { useInViewObserver } from "@lib/hooks/useInViewObserver";
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
import { inferQueryInput, trpc } from "@lib/trpc";
|
||||
|
||||
import BookingsShell from "@components/BookingsShell";
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Booking" ADD COLUMN "fromReschedule" TEXT,
|
||||
ADD COLUMN "rescheduled" BOOLEAN;
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "Booking.uid_unique" RENAME TO "Booking_uid_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "DailyEventReference_bookingId_unique" RENAME TO "DailyEventReference_bookingId_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "DestinationCalendar.bookingId_unique" RENAME TO "DestinationCalendar_bookingId_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "DestinationCalendar.eventTypeId_unique" RENAME TO "DestinationCalendar_eventTypeId_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "DestinationCalendar.userId_unique" RENAME TO "DestinationCalendar_userId_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "EventType.userId_slug_unique" RENAME TO "EventType_userId_slug_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "Payment.externalId_unique" RENAME TO "Payment_externalId_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "Payment.uid_unique" RENAME TO "Payment_uid_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "Team.slug_unique" RENAME TO "Team_slug_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "VerificationRequest.identifier_token_unique" RENAME TO "VerificationRequest_identifier_token_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "VerificationRequest.token_unique" RENAME TO "VerificationRequest_token_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "Webhook.id_unique" RENAME TO "Webhook_id_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "users.email_unique" RENAME TO "users_email_key";
|
||||
|
||||
-- RenameIndex
|
||||
ALTER INDEX "users.username_unique" RENAME TO "users_username_key";
|
|
@ -253,6 +253,8 @@ model Booking {
|
|||
destinationCalendar DestinationCalendar?
|
||||
cancellationReason String?
|
||||
rejectionReason String?
|
||||
rescheduled Boolean?
|
||||
fromReschedule String?
|
||||
}
|
||||
|
||||
model Schedule {
|
||||
|
|
Loading…
Reference in New Issue
Block a user