cal.pub0.org/server/routers/viewer.tsx

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,
});
},
});