diff --git a/apps/web/components/eventtype/AIEventController.tsx b/apps/web/components/eventtype/AIEventController.tsx
index 783161abb3..9d9b78c1bf 100644
--- a/apps/web/components/eventtype/AIEventController.tsx
+++ b/apps/web/components/eventtype/AIEventController.tsx
@@ -1,14 +1,18 @@
+import * as RadioGroup from "@radix-ui/react-radio-group";
import { useSession } from "next-auth/react";
import type { EventTypeSetup } from "pages/event-types/[type]";
-import { useState } from "react";
+import React, { useState } from "react";
import { useFormContext, Controller } from "react-hook-form";
import { z } from "zod";
+import { getTemplateFieldsSchema } from "@calcom/features/ee/cal-ai-phone/getTemplateFieldsSchema";
+import { TEMPLATES_FIELDS } from "@calcom/features/ee/cal-ai-phone/template-fields-map";
+import type { TemplateType } from "@calcom/features/ee/cal-ai-phone/zod-utils";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import type { FormValues } from "@calcom/features/eventtypes/lib/types";
+import { ComponentForField } from "@calcom/features/form-builder/FormBuilderField";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
-import { AIPhoneSettingSchema } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import {
Button,
@@ -17,9 +21,9 @@ import {
SettingsToggle,
Divider,
TextField,
- TextAreaField,
PhoneInput,
showToast,
+ Icon,
} from "@calcom/ui";
type AIEventControllerProps = {
@@ -85,10 +89,64 @@ export default function AIEventController({ eventType, isTeamEvent }: AIEventCon
);
}
+const ErrorMessage = ({ fieldName, message }: { fieldName: string; message: string }) => {
+ const { t } = useLocale();
+ return (
+
+
+
{t(message || "invalid_input")}
+
+ );
+};
+
+const TemplateFields = () => {
+ const { t } = useLocale();
+ const formMethods = useFormContext();
+ const { control, watch } = formMethods;
+
+ const templateType = watch("aiPhoneCallConfig.templateType");
+ const fields = TEMPLATES_FIELDS[templateType as TemplateType];
+
+ return (
+
+ {fields?.map((field) => (
+
+
{
+ const { variableName, ...restField } = field;
+ const variableInfo = !!variableName ? `: ${t("variable")} {{${variableName}}}` : "";
+ return (
+
+ {
+ onChange(val);
+ }}
+ />
+ {error?.message && }
+
+ );
+ }}
+ />
+
+ ))}
+
+ );
+};
+
const AISettings = ({ eventType }: { eventType: EventTypeSetup }) => {
const { t } = useLocale();
const formMethods = useFormContext();
+
const [calApiKey, setCalApiKey] = useState("");
const createCallMutation = trpc.viewer.organizations.createPhoneCall.useMutation({
@@ -98,43 +156,25 @@ const AISettings = ({ eventType }: { eventType: EventTypeSetup }) => {
}
},
onError: (err) => {
- showToast(t("something_went_wrong"), "error");
+ const message = err?.message ? err.message : t("something_went_wrong");
+ showToast(message, "error");
},
});
- // const [createModalOpen, setCreateModalOpen] = useState(false);
-
- // const NewPhoneButton = () => {
- // const { t } = useLocale();
- // return (
- //
- // );
- // };
-
- // v1 will require the user to log in to Retellai.com to create a phone number, and an agent and
- // authorize it with the Cal.com API key / OAuth
- // const retellAuthorized = true; // TODO: call retellAPI here
-
const handleSubmit = async () => {
try {
const values = formMethods.getValues("aiPhoneCallConfig");
+ const { templateType } = values;
- const data = await AIPhoneSettingSchema.parseAsync({
- generalPrompt: values.generalPrompt,
- beginMessage: values.beginMessage,
- enabled: values.enabled,
- guestName: values.guestName,
- guestEmail: values.guestEmail.trim().length ? values.guestEmail : undefined,
- guestCompany: values.guestCompany.trim().length ? values.guestCompany : undefined,
+ const schema = getTemplateFieldsSchema({ templateType });
+
+ const data = schema.parse({
+ ...values,
+ guestEmail: values.guestEmail && values.guestEmail.trim().length ? values.guestEmail : undefined,
+ guestCompany:
+ values.guestCompany && values.guestCompany.trim().length ? values.guestCompany : undefined,
+ guestName: values.guestName && values.guestName.trim().length ? values.guestName : undefined,
eventTypeId: eventType.id,
- numberToCall: values.numberToCall,
- yourPhoneNumber: values.yourPhoneNumber,
calApiKey,
});
@@ -144,6 +184,15 @@ const AISettings = ({ eventType }: { eventType: EventTypeSetup }) => {
const fieldName = err.issues?.[0]?.path?.[0];
const message = err.issues?.[0]?.message;
showToast(`Error on ${fieldName}: ${message} `, "error");
+
+ const issues = err.issues;
+ for (const issue of issues) {
+ const fieldName = `aiPhoneCallConfig.${issue.path[0]}` as unknown as keyof FormValues;
+ formMethods.setError(fieldName, {
+ type: "custom",
+ message: issue.message,
+ });
+ }
} else {
showToast(t("something_went_wrong"), "error");
}
@@ -157,68 +206,89 @@ const AISettings = ({ eventType }: { eventType: EventTypeSetup }) => {
{
+ render={({ field: { onChange, value, name }, fieldState: { error } }) => {
return (
- {
- onChange(val);
- }}
- />
+
+
{
+ onChange(val);
+ }}
+ />
+ {error?.message && }
+
);
}}
/>
+ <>
+ {
+ formMethods.setValue("aiPhoneCallConfig.templateType", val, { shouldDirty: true });
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
{
+ render={({ field: { onChange, value, name }, fieldState: { error } }) => {
return (
- {
- onChange(val);
- }}
- />
+
+
{
+ onChange(val);
+ }}
+ />
+ {error?.message && }
+
);
}}
/>
+
+
>
-
-
-
-
-
-
{
/>
- {
- formMethods.setValue("aiPhoneCallConfig.generalPrompt", e.target.value, { shouldDirty: true });
- }}
- />
-
- {
- formMethods.setValue("aiPhoneCallConfig.beginMessage", e.target.value, { shouldDirty: true });
- }}
- />