Skip to content

Commit

Permalink
feat: virtual queues tab in insights (#18260)
Browse files Browse the repository at this point in the history
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: sean-brydon <sean@cal.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
  • Loading branch information
6 people authored and nizzyabi committed Dec 26, 2024
1 parent 4810649 commit a3b21ee
Show file tree
Hide file tree
Showing 39 changed files with 538 additions and 195 deletions.
17 changes: 17 additions & 0 deletions apps/web/app/insights/virtual-queues/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { withAppDirSsr } from "app/WithAppDirSsr";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";

import { getServerSideProps } from "@lib/insights/getServerSideProps";

import InsightsVirtualQueuesPage from "~/insights/insights-virtual-queues-view";

export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("insights"),
(t) => t("insights_subtitle")
);

const getData = withAppDirSsr(getServerSideProps);

export default WithLayout({ getLayout: null, getData, Page: InsightsVirtualQueuesPage });
22 changes: 14 additions & 8 deletions apps/web/modules/apps/installation/[[...step]]/step-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { Team } from "@calcom/prisma/client";
import type { eventTypeBookingFields } from "@calcom/prisma/zod-utils";
import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/prisma/zod-utils";
import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import type { AppMeta } from "@calcom/types/App";
Expand Down Expand Up @@ -243,15 +244,20 @@ const OnboardingPage = ({
const promises = group.eventTypes
.filter((eventType) => eventType.selected)
.map((value: TEventType) => {
// Prevent two payment apps to be enabled
// Ok to cast type here because this metadata will be updated as the event type metadata
if (
checkForMultiplePaymentApps(value.metadata as z.infer<typeof EventTypeMetaDataSchema>)
)
throw new Error(t("event_setup_multiple_payment_apps_error"));
if (value.metadata?.apps?.stripe?.paymentOption === "HOLD" && value.seatsPerTimeSlot) {
throw new Error(t("seats_and_no_show_fee_error"));
if (value.metadata) {
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(value.metadata);
// Prevent two payment apps to be enabled
// Ok to cast type here because this metadata will be updated as the event type metadata
if (checkForMultiplePaymentApps(metadata))
throw new Error(t("event_setup_multiple_payment_apps_error"));
if (
value.metadata?.apps?.stripe?.paymentOption === "HOLD" &&
value.seatsPerTimeSlot
) {
throw new Error(t("seats_and_no_show_fee_error"));
}
}

let updateObject: TUpdateObject = { id: value.id };
if (isConferencing) {
updateObject = {
Expand Down
16 changes: 13 additions & 3 deletions apps/web/modules/bookings/views/bookings-single-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat";
import { localStorage } from "@calcom/lib/webstorage";
import { BookingStatus, SchedulingType } from "@calcom/prisma/enums";
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
import { bookingMetadataSchema, eventTypeMetaDataSchemaWithTypedApps } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import {
Alert,
Expand All @@ -61,6 +61,7 @@ import {
showToast,
EmptyScreen,
Icon,
HeadSeo,
} from "@calcom/ui";
import CancelBooking from "@calcom/web/components/booking/CancelBooking";
import EventReservationSchema from "@calcom/web/components/schemas/EventReservationSchema";
Expand Down Expand Up @@ -229,7 +230,13 @@ export default function Success(props: PageProps) {
t,
};

const giphyAppData = getEventTypeAppData(eventType, "giphy");
const giphyAppData = getEventTypeAppData(
{
...eventType,
metadata: eventTypeMetaDataSchemaWithTypedApps.parse(eventType.metadata),
},
"giphy"
);
const giphyImage = giphyAppData?.thankYouPage;
const isRoundRobin = eventType.schedulingType === SchedulingType.ROUND_ROBIN;

Expand Down Expand Up @@ -433,7 +440,10 @@ export default function Success(props: PageProps) {
</Link>
</div>
)}
<BookingPageTagManager eventType={eventType} />
<HeadSeo origin={getOrgFullOrigin(orgSlug)} title={title} description={title} />
<BookingPageTagManager
eventType={{ ...eventType, metadata: eventTypeMetaDataSchemaWithTypedApps.parse(eventType.metadata) }}
/>
<main className={classNames(shouldAlignCentrally ? "mx-auto" : "", isEmbed ? "" : "max-w-3xl")}>
<div className={classNames("overflow-y-auto", isEmbed ? "" : "z-50 ")}>
<div
Expand Down
49 changes: 49 additions & 0 deletions apps/web/modules/insights/insights-virtual-queues-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use client";

import { useState } from "react";

import { TestForm } from "@calcom/app-store/routing-forms/components/SingleForm";
import type { RoutingForm } from "@calcom/app-store/routing-forms/types/types";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc";
import { Label, Select } from "@calcom/ui";

import InsightsLayout from "./layout";

export default function InsightsVirtualQueuesPage() {
const { t } = useLocale();
const { data: routingForms, isLoading: isRoutingFormsLoading } =
trpc.viewer.insights.getUserRelevantTeamRoutingForms.useQuery();

const [selectedForm, setSelectedForm] = useState<RoutingForm | undefined>(
routingForms && routingForms.length > 0 ? routingForms[0] : undefined
);

if (routingForms && !selectedForm && routingForms.length > 0) {
setSelectedForm(routingForms[0]);
}

return (
<InsightsLayout>
<Label>{t("routing_form")}</Label>
<Select
placeholder="Select project"
options={routingForms?.map((form) => ({ label: form.name, value: form.id })) ?? []}
isLoading={isRoutingFormsLoading}
className="w-60"
onChange={(e) => {
if (e && routingForms) {
const form = routingForms.find((form) => form.id === e.value);
setSelectedForm(form);
}
}}
value={selectedForm ? { label: selectedForm.name, value: selectedForm.id } : undefined}
/>
<div className="mt-10">
{selectedForm ? <TestForm form={selectedForm} showAllData={false} /> : <></>}
</div>
</InsightsLayout>
);

return <></>;
}
3 changes: 3 additions & 0 deletions apps/web/modules/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ vi.mock("@calcom/prisma/zod-utils", () => ({
EventTypeMetaDataSchema: {
parse: vi.fn(),
},
eventTypeMetaDataSchemaWithTypedApps: {
parse: vi.fn(),
},
bookingMetadataSchema: {
parse: vi.fn(),
},
Expand Down
10 changes: 5 additions & 5 deletions apps/web/playwright/integrations-stripe.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type Prisma from "@prisma/client";

import prisma from "@calcom/prisma";
import { SchedulingType } from "@calcom/prisma/enums";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/prisma/zod-utils";

import { test, todo } from "./lib/fixtures";
import type { Fixtures } from "./lib/fixtures";
Expand Down Expand Up @@ -51,7 +51,7 @@ test.describe("Stripe integration skip true", () => {
},
});

const metadata = EventTypeMetaDataSchema.parse(eventTypeMetadata?.metadata);
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(eventTypeMetadata?.metadata);

const stripeAppMetadata = metadata?.apps?.stripe;

Expand Down Expand Up @@ -93,7 +93,7 @@ test.describe("Stripe integration skip true", () => {
},
});

const metadata = EventTypeMetaDataSchema.parse(eventTypeMetadata?.metadata);
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(eventTypeMetadata?.metadata);

const stripeAppMetadata = metadata?.apps?.stripe;

Expand Down Expand Up @@ -291,7 +291,7 @@ test.describe("Stripe integration with the new app install flow skip false", ()
});

for (const eventTypeMetadata of eventTypeMetadatas) {
const metadata = EventTypeMetaDataSchema.parse(eventTypeMetadata?.metadata);
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(eventTypeMetadata?.metadata);
const stripeAppMetadata = metadata?.apps?.stripe;
expect(stripeAppMetadata).toHaveProperty("credentialId");
expect(typeof stripeAppMetadata?.credentialId).toBe("number");
Expand Down Expand Up @@ -328,7 +328,7 @@ test.describe("Stripe integration with the new app install flow skip false", ()
},
});

const metadata = EventTypeMetaDataSchema.parse(eventTypeMetadata?.metadata);
const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(eventTypeMetadata?.metadata);

const stripeAppMetadata = metadata?.apps?.stripe;

Expand Down
7 changes: 7 additions & 0 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -2895,5 +2895,12 @@
"reassigned": "Reassigned",
"rerouted": "Rerouted",
"salesforce_assigned": "Salesforce assignment",
"router_position": "Router Position",
"show_matching_hosts": "Show matching hosts",
"no_active_queues": "No active queues for this input",
"weight": "Weight",
"calibration": "Calibration",
"shortfall": "Shortfall",
"routing_form": "Routing Form",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
6 changes: 4 additions & 2 deletions packages/app-store/_utils/getEventTypeAppData.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { z } from "zod";

import type { BookerEvent } from "@calcom/features/bookings/types";
import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import type { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/prisma/zod-utils";

export type EventTypeApps = NonNullable<NonNullable<z.infer<typeof EventTypeMetaDataSchema>>["apps"]>;
export type EventTypeApps = NonNullable<
NonNullable<z.infer<typeof eventTypeMetaDataSchemaWithTypedApps>>["apps"]
>;
export type EventTypeAppsList = keyof EventTypeApps;

export const getEventTypeAppData = <T extends EventTypeAppsList>(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type z from "zod";

import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import type { eventTypeAppMetadataOptionalSchema } from "@calcom/prisma/zod-utils";

import type { appDataSchemas } from "../../apps.schemas.generated";

Expand All @@ -11,7 +11,12 @@ import type { appDataSchemas } from "../../apps.schemas.generated";
* @returns boolean
*/
const checkForMultiplePaymentApps = (
metadata: z.infer<typeof EventTypeMetaDataSchema>,
metadata:
| {
apps?: z.infer<typeof eventTypeAppMetadataOptionalSchema>;
}
| null
| undefined,
inclusive = false
) => {
let enabledPaymentApps = 0;
Expand Down
Loading

0 comments on commit a3b21ee

Please sign in to comment.