feat: update event types for default availability change (#13964)

* feat: update event types for default availability change

* chore: add toast

---------

Co-authored-by: sean-brydon <sean@cal.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
Amit Sharma
2024-03-12 13:42:57 +00:00
committed by GitHub
co-authored by sean-brydon sean-brydon Udit Takkar
parent 1a645f3110
commit 9230b2d2ca
6 changed files with 111 additions and 13 deletions
+13 -2
View File
@@ -5,7 +5,7 @@ import { InstallAppButton } from "@calcom/app-store/components";
import { getEventLocationTypeFromApp, type EventLocationType } from "@calcom/app-store/locations";
import type { CredentialOwner } from "@calcom/app-store/types";
import { AppSetDefaultLinkDialog } from "@calcom/features/apps/components/AppSetDefaultLinkDialog";
import { BulkEditDefaultConferencingModal } from "@calcom/features/eventtypes/components/BulkEditDefaultConferencingModal";
import { BulkEditDefaultForEventsModal } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { AppCategories } from "@calcom/prisma/enums";
import { trpc, type RouterOutputs } from "@calcom/trpc";
@@ -154,6 +154,12 @@ export const AppList = ({ data, handleDisconnect, variant, listClassName }: AppL
});
const { t } = useLocale();
const updateLocationsMutation = trpc.viewer.eventTypes.bulkUpdateToDefaultLocation.useMutation({
onSuccess: () => {
utils.viewer.getUsersDefaultConferencingApp.invalidate();
setBulkUpdateModal(false);
},
});
return (
<>
<List className={listClassName}>
@@ -173,7 +179,12 @@ export const AppList = ({ data, handleDisconnect, variant, listClassName }: AppL
)}
{bulkUpdateModal && (
<BulkEditDefaultConferencingModal open={bulkUpdateModal} setOpen={setBulkUpdateModal} />
<BulkEditDefaultForEventsModal
bulkUpdateFunction={updateLocationsMutation.mutate}
open={bulkUpdateModal}
setOpen={setBulkUpdateModal}
isPending={updateLocationsMutation.isPending}
/>
)}
</>
);
+21 -1
View File
@@ -1,8 +1,9 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import Link from "next/link";
import { useRouter, usePathname } from "next/navigation";
import { useCallback } from "react";
import { useCallback, useState } from "react";
import { BulkEditDefaultForEventsModal } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal";
import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules";
import Shell from "@calcom/features/shell/Shell";
import { AvailabilitySliderTable } from "@calcom/features/timezone-buddy/components/AvailabilitySliderTable";
@@ -21,6 +22,7 @@ import SkeletonLoader from "@components/availability/SkeletonLoader";
export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availability"]["list"]) {
const { t } = useLocale();
const [bulkUpdateModal, setBulkUpdateModal] = useState(false);
const utils = trpc.useContext();
const meQuery = trpc.viewer.me.useQuery();
@@ -65,6 +67,7 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
}),
"success"
);
setBulkUpdateModal(true);
},
onError: (err) => {
if (err instanceof HttpError) {
@@ -74,6 +77,15 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
},
});
const bulkUpdateDefaultAvailabilityMutation =
trpc.viewer.availability.schedule.bulkUpdateToDefaultAvailability.useMutation({
onSuccess: () => {
utils.viewer.availability.list.invalidate();
setBulkUpdateModal(false);
showToast(t("success"), "success");
},
});
const duplicateMutation = trpc.viewer.availability.schedule.duplicate.useMutation({
onSuccess: async ({ schedule }) => {
await router.push(`/availability/${schedule.id}`);
@@ -129,6 +141,14 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
{t("add_a_redirect")}
</Link>
</div>
{bulkUpdateModal && (
<BulkEditDefaultForEventsModal
isPending={bulkUpdateDefaultAvailabilityMutation.isPending}
open={bulkUpdateModal}
setOpen={setBulkUpdateModal}
bulkUpdateFunction={bulkUpdateDefaultAvailabilityMutation.mutate}
/>
)}
</>
)}
</>
@@ -10,7 +10,12 @@ export const BulkUpdateEventSchema = z.object({
eventTypeIds: z.array(z.number()),
});
export function BulkEditDefaultConferencingModal(props: { open: boolean; setOpen: (open: boolean) => void }) {
export function BulkEditDefaultForEventsModal(props: {
open: boolean;
setOpen: (open: boolean) => void;
bulkUpdateFunction: ({ eventTypeIds }: { eventTypeIds: number[] }) => void;
isPending: boolean;
}) {
const { t } = useLocale();
const utils = trpc.useContext();
const { data, isFetching } = trpc.viewer.eventTypes.bulkEventFetch.useQuery();
@@ -21,13 +26,6 @@ export function BulkEditDefaultConferencingModal(props: { open: boolean; setOpen
},
});
const updateLocationsMutation = trpc.viewer.eventTypes.bulkUpdateToDefaultLocation.useMutation({
onSuccess: () => {
utils.viewer.getUsersDefaultConferencingApp.invalidate();
props.setOpen(false);
},
});
const eventTypesSelected = form.watch("eventTypeIds");
if (isFetching || !open || !data?.eventTypes) return null;
@@ -42,7 +40,7 @@ export function BulkEditDefaultConferencingModal(props: { open: boolean; setOpen
<Form
form={form}
handleSubmit={(values) => {
updateLocationsMutation.mutate(values);
props.bulkUpdateFunction(values);
}}>
<div className="flex flex-col space-y-2">
{data.eventTypes.length > 0 && (
@@ -81,7 +79,7 @@ export function BulkEditDefaultConferencingModal(props: { open: boolean; setOpen
utils.viewer.getUsersDefaultConferencingApp.invalidate();
}}
/>
<Button type="submit" color="primary" loading={updateLocationsMutation.isPending}>
<Button type="submit" color="primary" loading={props.isPending}>
{t("update")}
</Button>
</DialogFooter>
@@ -1,5 +1,6 @@
import authedProcedure from "../../../../procedures/authedProcedure";
import { router } from "../../../../trpc";
import { ZBulkUpdateToDefaultAvailabilityInputSchema } from "./bulkUpdateDefaultAvailability.schema";
import { ZCreateInputSchema } from "./create.schema";
import { ZDeleteInputSchema } from "./delete.schema";
import { ZScheduleDuplicateSchema } from "./duplicate.schema";
@@ -16,6 +17,7 @@ type ScheduleRouterHandlerCache = {
duplicate?: typeof import("./duplicate.handler").duplicateHandler;
getScheduleByUserId?: typeof import("./getScheduleByUserId.handler").getScheduleByUserIdHandler;
getScheduleByEventSlug?: typeof import("./getScheduleByEventTypeSlug.handler").getScheduleByEventSlugHandler;
bulkUpdateToDefaultAvailability?: typeof import("./bulkUpdateDefaultAvailability.handler").bulkUpdateToDefaultAvailabilityHandler;
};
const UNSTABLE_HANDLER_CACHE: ScheduleRouterHandlerCache = {};
@@ -137,4 +139,22 @@ export const scheduleRouter = router({
input,
});
}),
bulkUpdateToDefaultAvailability: authedProcedure
.input(ZBulkUpdateToDefaultAvailabilityInputSchema)
.mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.bulkUpdateToDefaultAvailability) {
UNSTABLE_HANDLER_CACHE.bulkUpdateToDefaultAvailability = await import(
"./bulkUpdateDefaultAvailability.handler"
).then((mod) => mod.bulkUpdateToDefaultAvailabilityHandler);
}
if (!UNSTABLE_HANDLER_CACHE.bulkUpdateToDefaultAvailability) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.bulkUpdateToDefaultAvailability({
ctx,
input,
});
}),
});
@@ -0,0 +1,40 @@
import { prisma } from "@calcom/prisma";
import { TRPCError } from "@trpc/server";
import type { TrpcSessionUser } from "../../../../trpc";
import type { TBulkUpdateToDefaultAvailabilityInputSchema } from "./bulkUpdateDefaultAvailability.schema";
type BulkUpdateToDefaultAvailabilityOptions = {
ctx: {
user: NonNullable<TrpcSessionUser>;
};
input: TBulkUpdateToDefaultAvailabilityInputSchema;
};
export const bulkUpdateToDefaultAvailabilityHandler = async ({
ctx,
input,
}: BulkUpdateToDefaultAvailabilityOptions) => {
const { eventTypeIds } = input;
const defaultScheduleId = ctx.user.defaultScheduleId;
if (!defaultScheduleId) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Default schedule not set",
});
}
return await prisma.eventType.updateMany({
where: {
id: {
in: eventTypeIds,
},
userId: ctx.user.id,
},
data: {
scheduleId: defaultScheduleId,
},
});
};
@@ -0,0 +1,9 @@
import { z } from "zod";
export const ZBulkUpdateToDefaultAvailabilityInputSchema = z.object({
eventTypeIds: z.array(z.number()),
});
export type TBulkUpdateToDefaultAvailabilityInputSchema = z.infer<
typeof ZBulkUpdateToDefaultAvailabilityInputSchema
>;