131 lines
3.8 KiB
TypeScript
131 lines
3.8 KiB
TypeScript
import { Prisma, BookingStatus } from "@prisma/client";
|
|
import { TRPCError } from "@trpc/server";
|
|
import { z } from "zod";
|
|
|
|
import { checkPremiumUsername } from "@ee/lib/core/checkPremiumUsername";
|
|
|
|
import { checkRegularUsername } from "@lib/core/checkRegularUsername";
|
|
import slugify from "@lib/slugify";
|
|
|
|
import { createProtectedRouter } from "../createRouter";
|
|
|
|
const checkUsername =
|
|
process.env.NEXT_PUBLIC_APP_URL === "https://cal.com" ? checkPremiumUsername : checkRegularUsername;
|
|
|
|
// routes only available to authenticated users
|
|
export const viewerRouter = createProtectedRouter()
|
|
.query("me", {
|
|
resolve({ ctx }) {
|
|
return ctx.user;
|
|
},
|
|
})
|
|
.query("bookings", {
|
|
input: z.object({
|
|
status: z.enum(["upcoming", "past", "cancelled"]).optional(),
|
|
}),
|
|
async resolve({ ctx, input }) {
|
|
const { prisma, user } = ctx;
|
|
const bookingListingByStatus = input.status || "upcoming";
|
|
const bookingListingFilters: Record<typeof bookingListingByStatus, Prisma.BookingWhereInput[]> = {
|
|
upcoming: [{ endTime: { gte: new Date() } }],
|
|
past: [{ endTime: { lte: new Date() } }],
|
|
cancelled: [{ status: { equals: BookingStatus.CANCELLED } }],
|
|
};
|
|
const bookingListingOrderby: Record<typeof bookingListingByStatus, Prisma.BookingOrderByInput> = {
|
|
upcoming: { startTime: "desc" },
|
|
past: { startTime: "asc" },
|
|
cancelled: { startTime: "asc" },
|
|
};
|
|
const passedBookingsFilter = bookingListingFilters[bookingListingByStatus];
|
|
const orderBy = bookingListingOrderby[bookingListingByStatus];
|
|
|
|
const bookingsQuery = await prisma.booking.findMany({
|
|
where: {
|
|
OR: [
|
|
{
|
|
userId: user.id,
|
|
},
|
|
{
|
|
attendees: {
|
|
some: {
|
|
email: user.email,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
AND: passedBookingsFilter,
|
|
},
|
|
select: {
|
|
uid: true,
|
|
title: true,
|
|
description: true,
|
|
attendees: true,
|
|
confirmed: true,
|
|
rejected: true,
|
|
id: true,
|
|
startTime: true,
|
|
endTime: true,
|
|
eventType: {
|
|
select: {
|
|
team: {
|
|
select: {
|
|
name: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
status: true,
|
|
},
|
|
orderBy,
|
|
});
|
|
|
|
const bookings = bookingsQuery.reverse().map((booking) => {
|
|
return {
|
|
...booking,
|
|
startTime: booking.startTime.toISOString(),
|
|
endTime: booking.endTime.toISOString(),
|
|
};
|
|
});
|
|
|
|
return bookings;
|
|
},
|
|
})
|
|
.mutation("updateProfile", {
|
|
input: z.object({
|
|
username: z.string().optional(),
|
|
name: z.string().optional(),
|
|
bio: z.string().optional(),
|
|
avatar: z.string().optional(),
|
|
timeZone: z.string().optional(),
|
|
weekStart: z.string().optional(),
|
|
hideBranding: z.boolean().optional(),
|
|
theme: z.string().optional(),
|
|
completedOnboarding: z.boolean().optional(),
|
|
locale: z.string().optional(),
|
|
}),
|
|
async resolve({ input, ctx }) {
|
|
const { user, prisma } = ctx;
|
|
const data: Prisma.UserUpdateInput = {
|
|
...input,
|
|
};
|
|
if (input.username) {
|
|
const username = slugify(input.username);
|
|
// Only validate if we're changing usernames
|
|
if (username !== user.username) {
|
|
data.username = username;
|
|
const response = await checkUsername(username);
|
|
if (!response.available) {
|
|
throw new TRPCError({ code: "BAD_REQUEST", message: response.message });
|
|
}
|
|
}
|
|
}
|
|
|
|
await prisma.user.update({
|
|
where: {
|
|
id: user.id,
|
|
},
|
|
data,
|
|
});
|
|
},
|
|
});
|