This commit is contained in:
sean-brydon 2022-12-14 22:33:27 +00:00
parent b66cd09e0d
commit 140cd3f349
5 changed files with 66 additions and 18 deletions

View File

@ -6,6 +6,7 @@ import { z } from "zod";
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
import BookingLayout from "@calcom/features/bookings/layout/BookingLayout";
import { useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterInputs, RouterOutputs, trpc } from "@calcom/trpc/react";
import { Alert, Button, EmptyScreen, Icon } from "@calcom/ui";
@ -42,12 +43,19 @@ const querySchema = z.object({
});
export default function Bookings() {
const { data: filterQuery } = useFilterQuery();
const router = useRouter();
const { status } = router.isReady ? querySchema.parse(router.query) : { status: "upcoming" as const };
const { t } = useLocale();
const query = trpc.viewer.bookings.get.useInfiniteQuery(
{ status, limit: 10 },
{
limit: 10,
filters: {
...filterQuery,
status: filterQuery.status ?? status,
},
},
{
// first render has status `undefined`
enabled: router.isReady,

View File

@ -21,26 +21,27 @@ export const queryStringArray = z.preprocess((a) => z.string().parse(a).split(",
const filterSingleSchema = z.object({
teamIds: z.number().positive().optional(),
status: z.string().optional(), // Not used right now but could be implemented when/if we move status to a filter
userIds: z.number().positive().optional(),
status: z.enum(["upcoming", "recurring", "past", "cancelled", "unconfirmed"]),
eventTypeIds: z.number().positive().optional(),
});
const filterQuerySchema = z.object({
export const filterQuerySchema = z.object({
teamIds: queryNumberArray.optional(),
status: queryStringArray.optional(), // Not used right now but could be implemented when/if we move status to a filter
userIds: queryNumberArray.optional(),
status: z.enum(["upcoming", "recurring", "past", "cancelled", "unconfirmed"]),
eventTypeIds: queryNumberArray.optional(),
});
type FilterQuerySchema = z.infer<typeof filterQuerySchema>;
type Keys = keyof FilterQuerySchema;
type KeysWithoutStatus = Exclude<Keys, "status">;
export function useFilterQuery() {
const router = useRouter();
const data = filterQuerySchema.parse(router.query);
const push = (key: Required<Keys>, item: string | number) => {
const push = (key: KeysWithoutStatus, item: string | number) => {
const newData = data;
const search = new URLSearchParams();
const keyData = data[key] ?? [];
@ -48,7 +49,7 @@ export function useFilterQuery() {
const itemParsed = filterSingleSchema.shape[key].parse(item);
if (!itemParsed) return;
const itemWithArray = [...keyData, itemParsed] as string[] & number[];
const itemWithArray = [...keyData, itemParsed] as number[];
newData[key] = itemWithArray;
@ -58,10 +59,11 @@ export function useFilterQuery() {
}
});
router.push({ query: search.toString() }, undefined, { shallow: true });
console.log(newData);
router.replace({ query: search.toString() }, undefined, { shallow: true });
};
const pop = (key: Required<Keys>, item: string | number) => {
const pop = (key: KeysWithoutStatus, item: string | number) => {
// Pop item from array
const newData = data;
const search = new URLSearchParams();
@ -78,10 +80,10 @@ export function useFilterQuery() {
search.append(key, value.toString());
}
});
router.push({ query: search.toString() }, undefined, { shallow: true });
router.replace({ query: search.toString() }, undefined, { shallow: true });
};
const set = (key: Required<Keys>, item: string | number) => {
const set = (key: KeysWithoutStatus, item: string | number) => {
// Set item to array
const newData = data;
const search = new URLSearchParams();
@ -95,10 +97,10 @@ export function useFilterQuery() {
search.append(key, value.toString());
}
});
router.push({ query: search.toString() }, undefined, { shallow: true });
router.replace({ query: search.toString() }, undefined);
};
const clear = (schemaKey: Required<Keys>) => {
const clear = (schemaKey: KeysWithoutStatus) => {
// Clear item from array
const newData = data;
const search = new URLSearchParams();
@ -110,8 +112,18 @@ export function useFilterQuery() {
}
});
search.delete(schemaKey);
router.push({ query: search.toString() }, undefined, { shallow: true });
router.replace({ query: search.toString() }, undefined);
};
return { data, push, pop, set, clear };
const dataAsSearchString = () => {
const search = new URLSearchParams();
Object.entries(data).forEach(([key, value]) => {
if (value) {
search.append(key, value.toString());
}
});
return search.toString();
};
return { data, push, pop, set, clear, dataAsSearchString };
}

View File

@ -28,6 +28,7 @@ import {
sendRequestRescheduleEmail,
sendScheduledEmails,
} from "@calcom/emails";
import { filterQuerySchema } from "@calcom/features/bookings/lib/useFilterQuery";
import { scheduleWorkflowReminders } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
import sendPayload, { EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
@ -103,7 +104,7 @@ export const bookingsRouter = router({
get: authedProcedure
.input(
z.object({
status: z.enum(["upcoming", "recurring", "past", "cancelled", "unconfirmed"]),
filters: filterQuerySchema,
limit: z.number().min(1).max(100).nullish(),
cursor: z.number().nullish(), // <-- "cursor" needs to exist when using useInfiniteQuery, but can be any type
})
@ -114,7 +115,7 @@ export const bookingsRouter = router({
const take = input.limit ?? 10;
const skip = input.cursor ?? 0;
const { prisma, user } = ctx;
const bookingListingByStatus = input.status;
const bookingListingByStatus = input.filters.status;
const bookingListingFilters: Record<typeof bookingListingByStatus, Prisma.BookingWhereInput> = {
upcoming: {
endTime: { gte: new Date() },
@ -175,7 +176,31 @@ export const bookingsRouter = router({
cancelled: { startTime: "desc" },
unconfirmed: { startTime: "asc" },
};
const passedBookingsFilter = bookingListingFilters[bookingListingByStatus];
// TODO: Fix record typing
const bookingWhereInputFilters: Record<string, Prisma.BookingWhereInput> = {
teamIds: {
AND: [
{
eventType: {
team: {
id: {
in: input.filters?.teamIds,
},
},
},
},
],
},
};
const filtersCombined: Prisma.BookingWhereInput[] =
input.filters &&
Object.keys(input.filters).map((key) => {
return bookingWhereInputFilters[key];
});
const passedBookingsStatusFilter = bookingListingFilters[bookingListingByStatus];
const orderBy = bookingListingOrderby[bookingListingByStatus];
const bookingsQuery = await prisma.booking.findMany({
@ -204,7 +229,7 @@ export const bookingsRouter = router({
},
},
],
AND: [passedBookingsFilter],
AND: [passedBookingsStatusFilter],
},
select: {
...bookingMinimalSelect,

View File

@ -1,4 +1,5 @@
import superjson from "superjson";
import { ZodError } from "zod";
import { initTRPC, TRPCError } from "@trpc/server";

View File

@ -1,3 +1,5 @@
import { useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
import HorizontalTabItem, { HorizontalTabItemProps } from "./HorizontalTabItem";
export { HorizontalTabItem };