diff --git a/apps/web/components/booking/BookingListItem.tsx b/apps/web/components/booking/BookingListItem.tsx index 906cf426a5..7819faa307 100644 --- a/apps/web/components/booking/BookingListItem.tsx +++ b/apps/web/components/booking/BookingListItem.tsx @@ -43,9 +43,13 @@ function BookingListItem(booking: BookingItemProps) { const [rejectionReason, setRejectionReason] = useState(""); const [rejectionDialogIsOpen, setRejectionDialogIsOpen] = useState(false); const mutation = trpc.viewer.bookings.confirm.useMutation({ - onSuccess: () => { - setRejectionDialogIsOpen(false); - showToast(t("booking_confirmation_success"), "success"); + onSuccess: (data) => { + if (data.status === BookingStatus.REJECTED) { + setRejectionDialogIsOpen(false); + showToast(t("booking_rejection_success"), "success"); + } else { + showToast(t("booking_confirmation_success"), "success"); + } utils.viewer.bookings.invalidate(); }, onError: () => { diff --git a/apps/web/pages/api/integrations/[...args].ts b/apps/web/pages/api/integrations/[...args].ts index 43e0a4046b..6335b51468 100644 --- a/apps/web/pages/api/integrations/[...args].ts +++ b/apps/web/pages/api/integrations/[...args].ts @@ -65,8 +65,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { await handler(req, res); } else { await defaultIntegrationAddHandler({ user: req.session?.user, ...handler }); - redirectUrl = handler.redirectUrl || getInstalledAppPath(handler); - res.json({ url: redirectUrl }); + redirectUrl = handler.redirect?.url || getInstalledAppPath(handler); + res.json({ url: redirectUrl, newTab: handler.redirect?.newTab }); } return res.status(200); } catch (error) { diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index c7eb6c3740..4dab52cae9 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1295,6 +1295,7 @@ "fetching_calendars_error": "There was a problem fetching your calendars. Please <1>try again or reach out to customer support.", "calendar_connection_fail": "Calendar connection failed", "booking_confirmation_success": "Booking confirmation succeeded", + "booking_rejection_success": "Booking rejection succeeded", "booking_confirmation_fail": "Booking confirmation failed", "we_wont_show_again": "We won't show this again", "couldnt_update_timezone": "We couldn't update the timezone", diff --git a/packages/app-store/_utils/useAddAppMutation.ts b/packages/app-store/_utils/useAddAppMutation.ts index b9ea8bbb69..5cdf68d60e 100644 --- a/packages/app-store/_utils/useAddAppMutation.ts +++ b/packages/app-store/_utils/useAddAppMutation.ts @@ -6,6 +6,14 @@ import { App } from "@calcom/types/App"; import getInstalledAppPath from "./getInstalledAppPath"; +function gotoUrl(url: string, newTab?: boolean) { + if (newTab) { + window.open(url, "_blank"); + return; + } + window.location.href = url; +} + function useAddAppMutation(_type: App["type"] | null, options?: Parameters[2]) { const mutation = useMutation< unknown, @@ -41,7 +49,7 @@ function useAddAppMutation(_type: App["type"] | null, options?: Parameters createDefaultInstallation({ appType, userId: user.id, slug, key: {} }), }; diff --git a/packages/app-store/pipedream/api/add.ts b/packages/app-store/pipedream/api/add.ts index dfcce1fa5e..8ecf1ce2a3 100644 --- a/packages/app-store/pipedream/api/add.ts +++ b/packages/app-store/pipedream/api/add.ts @@ -10,7 +10,10 @@ const handler: AppDeclarativeHandler = { slug: appConfig.slug, supportsMultipleInstalls: false, handlerType: "add", - redirectUrl: "https://pipedream.com/apps/cal-com", + redirect: { + newTab: true, + url: "https://pipedream.com/apps/cal-com", + }, createCredential: ({ appType, user, slug }) => createDefaultInstallation({ appType, userId: user.id, slug, key: {} }), }; diff --git a/packages/app-store/raycast/api/add.ts b/packages/app-store/raycast/api/add.ts index 9cbf5a12bb..93294b1c41 100644 --- a/packages/app-store/raycast/api/add.ts +++ b/packages/app-store/raycast/api/add.ts @@ -10,7 +10,9 @@ const handler: AppDeclarativeHandler = { variant: appConfig.variant, supportsMultipleInstalls: false, handlerType: "add", - redirectUrl: "raycast://extensions/eluce2/cal-com-share-meeting-links?source=webstore", + redirect: { + url: "raycast://extensions/eluce2/cal-com-share-meeting-links?source=webstore", + }, createCredential: ({ appType, user, slug }) => createDefaultInstallation({ appType, userId: user.id, slug, key: {} }), }; diff --git a/packages/app-store/typeform/api/add.ts b/packages/app-store/typeform/api/add.ts index 4bf80356c9..5ea6d24a58 100644 --- a/packages/app-store/typeform/api/add.ts +++ b/packages/app-store/typeform/api/add.ts @@ -10,7 +10,9 @@ const handler: AppDeclarativeHandler = { variant: appConfig.variant, supportsMultipleInstalls: false, handlerType: "add", - redirectUrl: "/apps/typeform/how-to-use", + redirect: { + url: "/apps/typeform/how-to-use", + }, createCredential: ({ appType, user, slug }) => createDefaultInstallation({ appType, userId: user.id, slug, key: {} }), }; diff --git a/packages/trpc/server/routers/viewer/bookings.tsx b/packages/trpc/server/routers/viewer/bookings.tsx index 41a325367b..f1abd3eecb 100644 --- a/packages/trpc/server/routers/viewer/bookings.tsx +++ b/packages/trpc/server/routers/viewer/bookings.tsx @@ -731,7 +731,7 @@ export const bookingsRouter = router({ }, }); - return { message: "Booking confirmed" }; + return { message: "Booking confirmed", status: BookingStatus.ACCEPTED }; } const attendeesListPromises = booking.attendees.map(async (attendee) => { return { @@ -985,6 +985,10 @@ export const bookingsRouter = router({ await sendDeclinedEmails(evt); } - return { message: "Booking " + confirmed ? "confirmed" : "rejected" }; + + const message = "Booking " + confirmed ? "confirmed" : "rejected"; + const status = confirmed ? BookingStatus.ACCEPTED : BookingStatus.REJECTED; + + return { message, status }; }), }); diff --git a/packages/types/AppHandler.d.ts b/packages/types/AppHandler.d.ts index 3c6a3987a6..bf8934092b 100644 --- a/packages/types/AppHandler.d.ts +++ b/packages/types/AppHandler.d.ts @@ -11,6 +11,9 @@ export type AppDeclarativeHandler = { handlerType: "add"; createCredential: (arg: { user: Session["user"]; appType: string; slug: string }) => Promise; supportsMultipleInstalls: boolean; - redirectUrl?: string; + redirect?: { + newTab?: boolean; + url: string; + }; }; export type AppHandler = AppDeclarativeHandler | NextApiHandler; diff --git a/packages/ui/v2/core/apps/AppCard.tsx b/packages/ui/v2/core/apps/AppCard.tsx index 7594f3571d..62151fd8dc 100644 --- a/packages/ui/v2/core/apps/AppCard.tsx +++ b/packages/ui/v2/core/apps/AppCard.tsx @@ -1,4 +1,5 @@ import type { Credential } from "@prisma/client"; +import { useRouter } from "next/router"; import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation"; import { InstallAppButton } from "@calcom/app-store/components"; @@ -15,8 +16,11 @@ interface AppCardProps { export default function AppCard({ app, credentials }: AppCardProps) { const { t } = useLocale(); + const router = useRouter(); const mutation = useAddAppMutation(null, { onSuccess: () => { + // Refresh SSR page content without actual reload + router.replace(router.asPath); showToast(t("app_successfully_installed"), "success"); }, onError: (error) => {