diff --git a/apps/web/app/(use-page-wrapper)/apps/[slug]/setup/page.tsx b/apps/web/app/(use-page-wrapper)/apps/[slug]/setup/page.tsx
index 6ac89e6455..4410b8cc71 100644
--- a/apps/web/app/(use-page-wrapper)/apps/[slug]/setup/page.tsx
+++ b/apps/web/app/(use-page-wrapper)/apps/[slug]/setup/page.tsx
@@ -32,4 +32,4 @@ const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
return ;
};
-export default ServerPage;
\ No newline at end of file
+export default ServerPage;
diff --git a/apps/web/modules/bookings/views/bookings-listing-view.tsx b/apps/web/modules/bookings/views/bookings-listing-view.tsx
index 17ae45d8bb..70d8458f56 100644
--- a/apps/web/modules/bookings/views/bookings-listing-view.tsx
+++ b/apps/web/modules/bookings/views/bookings-listing-view.tsx
@@ -7,7 +7,7 @@ import {
getSortedRowModel,
createColumnHelper,
} from "@tanstack/react-table";
-import { useMemo, useState } from "react";
+import { useMemo, useState, useEffect } from "react";
import type { z } from "zod";
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
@@ -95,12 +95,19 @@ type RowData =
};
function BookingsContent({ status }: BookingsProps) {
- const { data: filterQuery } = useFilterQuery();
+ const { data: filterQuery, pushItemToKey } = useFilterQuery();
const { t } = useLocale();
const user = useMeQuery().data;
const [isFiltersVisible, setIsFiltersVisible] = useState(false);
+ useEffect(() => {
+ if (user?.isTeamAdminOrOwner && !filterQuery.userIds?.length) {
+ setIsFiltersVisible(true);
+ pushItemToKey("userIds", user?.id);
+ }
+ }, [user, filterQuery.status]);
+
const query = trpc.viewer.bookings.get.useInfiniteQuery(
{
limit: 10,
diff --git a/apps/web/playwright/bookings-list.e2e.ts b/apps/web/playwright/bookings-list.e2e.ts
index 6ee5ff75e4..1b25d303de 100644
--- a/apps/web/playwright/bookings-list.e2e.ts
+++ b/apps/web/playwright/bookings-list.e2e.ts
@@ -1,10 +1,12 @@
import { expect } from "@playwright/test";
+import { prisma } from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/client";
+import { MembershipRole } from "@calcom/prisma/enums";
import type { Fixtures } from "./lib/fixtures";
import { test } from "./lib/fixtures";
-import { setupManagedEvent } from "./lib/testUtils";
+import { localize, setupManagedEvent } from "./lib/testUtils";
test.afterEach(({ users }) => users.deleteAll());
@@ -207,6 +209,95 @@ test.describe("Bookings", () => {
webhookReceiver.close();
});
});
+ test("Admin bookings filtered by default", async ({ page, users, bookings }) => {
+ const t = await localize("en");
+ const firstUser = await users.create(
+ { name: "First", email: "first@cal.com" },
+ {
+ hasTeam: true,
+ teamRole: MembershipRole.ADMIN,
+ }
+ );
+ const teamId = (await firstUser.getFirstTeamMembership()).teamId;
+ const secondUser = await users.create({ name: "Second", email: "second@cal.com" });
+ const thirdUser = await users.create({ name: "Third", email: "third@cal.com" });
+ // Add teammates to the team
+ await prisma.membership.createMany({
+ data: [
+ {
+ teamId: teamId,
+ userId: secondUser.id,
+ role: MembershipRole.MEMBER,
+ accepted: true,
+ },
+ {
+ teamId: teamId,
+ userId: thirdUser.id,
+ role: MembershipRole.MEMBER,
+ accepted: true,
+ },
+ ],
+ });
+
+ //Create a single booking for FirstUser(admin)
+ const firstUserBookingFixture = await createBooking({
+ title: "FirstUser as Organizer Meeting",
+ bookingsFixture: bookings,
+ relativeDate: 3,
+ organizer: firstUser,
+ organizerEventType: firstUser.eventTypes[0],
+ attendees: [
+ { name: "Second", email: secondUser.email, timeZone: "Europe/Berlin" },
+ { name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
+ ],
+ });
+ const firstUserBooking = await firstUserBookingFixture.self();
+
+ //Create 2 bookings for SecondUser
+ await createBooking({
+ title: "SecondUser as Organizer Meeting 1",
+ bookingsFixture: bookings,
+ organizer: secondUser,
+ relativeDate: 2,
+ organizerEventType: secondUser.eventTypes[0],
+ attendees: [
+ { name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
+ { name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
+ ],
+ });
+ await createBooking({
+ title: "SecondUser as Organizer Meeting 2",
+ bookingsFixture: bookings,
+ organizer: secondUser,
+ relativeDate: 4,
+ organizerEventType: secondUser.eventTypes[0],
+ attendees: [
+ { name: "First", email: firstUser.email, timeZone: "Europe/Berlin" },
+ { name: "Third", email: thirdUser.email, timeZone: "Europe/Berlin" },
+ ],
+ });
+
+ //admin login
+ await firstUser.apiLogin();
+ await Promise.all([
+ page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
+ page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url())),
+ page.goto(`/bookings/upcoming`),
+ page.waitForTimeout(10000),
+ page.waitForURL(`**\/upcoming?status=upcoming&userIds=${firstUser.id}`),
+ ]);
+
+ //expect only 1 booking (of admin) to be shown in list due to default filtering for admin
+ const upcomingBookingsTable = page.locator('[data-testid="upcoming-bookings"]');
+ const bookingListItems = upcomingBookingsTable.locator('[data-testid="booking-item"]');
+ const bookingListCount = await bookingListItems.count();
+ expect(bookingListCount).toBe(1);
+ const firstUpcomingBooking = bookingListItems.nth(0);
+ await expect(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ firstUpcomingBooking.locator(`text=${firstUserBooking!.title}`)
+ ).toBeVisible();
+ });
});
async function createBooking({
diff --git a/packages/features/bookings/components/FiltersContainer.tsx b/packages/features/bookings/components/FiltersContainer.tsx
index 373d61f54a..54fbf20b1d 100644
--- a/packages/features/bookings/components/FiltersContainer.tsx
+++ b/packages/features/bookings/components/FiltersContainer.tsx
@@ -35,6 +35,7 @@ export function FiltersContainer({ isFiltersVisible }: FiltersContainerProps) {