diff --git a/apps/web/lib/checkForEmptyAssignment.ts b/apps/web/lib/checkForEmptyAssignment.ts
new file mode 100644
index 0000000000..a2e5d5101c
--- /dev/null
+++ b/apps/web/lib/checkForEmptyAssignment.ts
@@ -0,0 +1,29 @@
+import type { EventTypeAssignedUsers, EventTypeHosts } from "~/event-types/views/event-types-single-view";
+
+// This function checks if EventType requires assignment.
+// returns true: if EventType requires assignment but there is no assignment yet done by the user.
+// returns false: for all other scenarios.
+export function checkForEmptyAssignment({
+ assignedUsers,
+ hosts,
+ isManagedEventType,
+ assignAllTeamMembers,
+}: {
+ assignedUsers: EventTypeAssignedUsers;
+ hosts: EventTypeHosts;
+ isManagedEventType: boolean;
+ assignAllTeamMembers: boolean;
+}): boolean {
+ // If Team-events have assignAllTeamMembers checked, return false as assignemnt is complete.
+ if (assignAllTeamMembers) {
+ return false;
+ }
+
+ // For managed eventtype check if assigned users are empty.
+ // For non-managed eventtype check if hosts are empty.
+ if (isManagedEventType ? assignedUsers.length === 0 : hosts.length === 0) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/apps/web/modules/event-types/views/event-types-single-view.tsx b/apps/web/modules/event-types/views/event-types-single-view.tsx
index 927227ab73..a6138db64b 100644
--- a/apps/web/modules/event-types/views/event-types-single-view.tsx
+++ b/apps/web/modules/event-types/views/event-types-single-view.tsx
@@ -26,6 +26,7 @@ import { HttpError } from "@calcom/lib/http-error";
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { validateBookerLayouts } from "@calcom/lib/validateBookerLayouts";
import type { Prisma } from "@calcom/prisma/client";
+import { SchedulingType } from "@calcom/prisma/enums";
import type { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { eventTypeBookingFields } from "@calcom/prisma/zod-utils";
import type { RouterOutputs } from "@calcom/trpc/react";
@@ -33,6 +34,7 @@ import { trpc } from "@calcom/trpc/react";
import { Form, showToast } from "@calcom/ui";
import type { AppProps } from "@lib/app-providers";
+import { checkForEmptyAssignment } from "@lib/checkForEmptyAssignment";
import { EventTypeSingleLayout } from "@components/eventtype/EventTypeSingleLayout";
@@ -144,6 +146,8 @@ const querySchema = z.object({
export type EventTypeSetupProps = RouterOutputs["viewer"]["eventTypes"]["get"];
export type EventTypeSetup = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"];
+export type EventTypeAssignedUsers = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]["children"];
+export type EventTypeHosts = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]["hosts"];
export const locationsResolver = (t: TFunction) => {
return z
@@ -400,40 +404,35 @@ const EventTypePage = (props: EventTypeSetupProps & { allActiveWorkflows?: Workf
formState: { isDirty: isFormDirty, dirtyFields },
} = formMethods;
- // useEffect(() => {
- // const handleRouteChange = (url: string) => {
- // const paths = url.split("/");
- //
- // // Check if event is managed event type - skip if there is assigned users
- // const assignedUsers = eventType.children;
- // const isManagedEventType = eventType.schedulingType === SchedulingType.MANAGED;
- // if (eventType.assignAllTeamMembers) {
- // return;
- // } else if (isManagedEventType && assignedUsers.length > 0) {
- // return;
- // }
- //
- // const hosts = eventType.hosts;
- // if (
- // !leaveWithoutAssigningHosts.current &&
- // !!team &&
- // (hosts.length === 0 || assignedUsers.length === 0) &&
- // (url === "/event-types" || paths[1] !== "event-types")
- // ) {
- // setIsOpenAssignmentWarnDialog(true);
- // setPendingRoute(url);
- // router.events.emit(
- // "routeChangeError",
- // new Error(`Aborted route change to ${url} because none was assigned to team event`)
- // );
- // throw "Aborted";
- // }
- // };
- // router.events.on("routeChangeStart", handleRouteChange);
- // return () => {
- // router.events.off("routeChangeStart", handleRouteChange);
- // };
- // }, [router]);
+ useEffect(() => {
+ const handleRouteChange = (url: string) => {
+ const paths = url.split("/");
+
+ if (
+ !!team &&
+ !leaveWithoutAssigningHosts.current &&
+ (url === "/event-types" || paths[1] !== "event-types") &&
+ checkForEmptyAssignment({
+ assignedUsers: eventType.children,
+ hosts: eventType.hosts,
+ assignAllTeamMembers: eventType.assignAllTeamMembers,
+ isManagedEventType: eventType.schedulingType === SchedulingType.MANAGED,
+ })
+ ) {
+ setIsOpenAssignmentWarnDialog(true);
+ setPendingRoute(url);
+ router.events.emit(
+ "routeChangeError",
+ new Error(`Aborted route change to ${url} because none was assigned to team event`)
+ );
+ throw "Aborted";
+ }
+ };
+ router.events.on("routeChangeStart", handleRouteChange);
+ return () => {
+ router.events.off("routeChangeStart", handleRouteChange);
+ };
+ }, [router, eventType.hosts, eventType.children, eventType.assignAllTeamMembers]);
const appsMetadata = formMethods.getValues("metadata")?.apps;
const availability = formMethods.watch("availability");
@@ -837,13 +836,13 @@ const EventTypePage = (props: EventTypeSetupProps & { allActiveWorkflows?: Workf
}}
/>
) : null}
- {/**/}
+
>
);
};
diff --git a/apps/web/test/lib/CheckForEmptyAssignment.test.ts b/apps/web/test/lib/CheckForEmptyAssignment.test.ts
new file mode 100644
index 0000000000..e8508e7089
--- /dev/null
+++ b/apps/web/test/lib/CheckForEmptyAssignment.test.ts
@@ -0,0 +1,102 @@
+import { describe, expect, it } from "vitest";
+
+import { checkForEmptyAssignment } from "../../lib/checkForEmptyAssignment";
+
+describe("Tests to Check if Event Types have empty Assignment", () => {
+ it("should return true if managed event type has no assigned users", () => {
+ expect(
+ checkForEmptyAssignment({
+ assignedUsers: [],
+ assignAllTeamMembers: false,
+ hosts: [{ userId: 101, isFixed: false, priority: 2 }],
+ isManagedEventType: true,
+ })
+ ).toBe(true);
+ });
+ it("should return true if non-managed event type has no hosts assigned", () => {
+ expect(
+ checkForEmptyAssignment({
+ assignedUsers: [
+ {
+ created: true,
+ owner: {
+ id: 101,
+ avatar: "avatar.svg",
+ email: "firstuser@cal.com",
+ membership: "OWNER",
+ name: "First user",
+ username: "firstuser",
+ profile: {
+ username: "firstuser",
+ upId: "usr-101",
+ id: null,
+ organization: null,
+ organizationId: null,
+ },
+ avatarUrl: null,
+ nonProfileUsername: null,
+ },
+ slug: "managedevent",
+ hidden: false,
+ },
+ ],
+ assignAllTeamMembers: false,
+ hosts: [],
+ isManagedEventType: false,
+ })
+ ).toBe(true);
+ });
+ it("should return false if assignAllTeamMembers is selected", () => {
+ expect(
+ checkForEmptyAssignment({
+ assignedUsers: [],
+ assignAllTeamMembers: true,
+ hosts: [],
+ isManagedEventType: false,
+ })
+ ).toBe(false);
+ });
+ it("should return false if non-managed event type has hosts assigned", () => {
+ expect(
+ checkForEmptyAssignment({
+ assignedUsers: [],
+ assignAllTeamMembers: false,
+ hosts: [{ userId: 101, isFixed: false, priority: 2 }],
+ isManagedEventType: false,
+ })
+ ).toBe(false);
+ });
+ it("should return false if managed event type has assigned users", () => {
+ expect(
+ checkForEmptyAssignment({
+ assignedUsers: [
+ {
+ created: true,
+ owner: {
+ id: 101,
+ avatar: "avatar.svg",
+ email: "firstuser@cal.com",
+ membership: "OWNER",
+ name: "First user",
+ username: "firstuser",
+ profile: {
+ username: "firstuser",
+ upId: "usr-101",
+ id: null,
+ organization: null,
+ organizationId: null,
+ },
+ avatarUrl: null,
+ nonProfileUsername: null,
+ },
+ slug: "managedevent",
+ hidden: false,
+ },
+ ],
+ assignAllTeamMembers: false,
+ hosts: [],
+ isManagedEventType: true,
+ })
+ ).toBe(false);
+ });
+});