feat: adding custom field of type PHONE (#5623)
* feat: adding custom field of type PHONE Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in> * fix: null phone number bug and removed console log Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in> * fix: decrease iteration Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in> Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Omar López <zomars@me.com>
This commit is contained in:
parent
b789e58624
commit
916468b8cc
|
@ -299,6 +299,39 @@ const BookingPage = ({
|
|||
}
|
||||
|
||||
const bookEvent = (booking: BookingFormValues) => {
|
||||
const bookingCustomInputs = Object.keys(booking.customInputs || {}).map((inputId) => ({
|
||||
label: eventType.customInputs.find((input) => input.id === parseInt(inputId))?.label || "",
|
||||
value: booking.customInputs && booking.customInputs[inputId] ? booking.customInputs[inputId] : "",
|
||||
}));
|
||||
|
||||
// Checking if custom inputs of type Phone number are valid to display error message on UI
|
||||
if (eventType.customInputs.length) {
|
||||
let isErrorFound = false;
|
||||
eventType.customInputs.forEach((customInput) => {
|
||||
if (customInput.required && customInput.type === EventTypeCustomInputType.PHONE) {
|
||||
const input = bookingCustomInputs.find((i) => i.label === customInput.label);
|
||||
try {
|
||||
z.string({
|
||||
errorMap: () => ({
|
||||
message: `Missing ${customInput.type} customInput: '${customInput.label}'`,
|
||||
}),
|
||||
})
|
||||
.refine((val) => isValidPhoneNumber(val), {
|
||||
message: "Phone number is invalid",
|
||||
})
|
||||
.parse(input?.value);
|
||||
} catch (err) {
|
||||
isErrorFound = true;
|
||||
bookingForm.setError(`customInputs.${customInput.id}`, {
|
||||
type: "custom",
|
||||
message: "Invalid Phone number",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (isErrorFound) return;
|
||||
}
|
||||
|
||||
telemetry.event(
|
||||
top !== window ? telemetryEventTypes.embedBookingConfirmed : telemetryEventTypes.bookingConfirmed,
|
||||
{ isTeamBooking: document.URL.includes("team/") }
|
||||
|
@ -355,10 +388,7 @@ const BookingPage = ({
|
|||
attendeeAddress: booking.attendeeAddress,
|
||||
}),
|
||||
metadata,
|
||||
customInputs: Object.keys(booking.customInputs || {}).map((inputId) => ({
|
||||
label: eventType.customInputs.find((input) => input.id === parseInt(inputId))?.label || "",
|
||||
value: booking.customInputs && inputId in booking.customInputs ? booking.customInputs[inputId] : "",
|
||||
})),
|
||||
customInputs: bookingCustomInputs,
|
||||
hasHashedBookingLink,
|
||||
hashedLink,
|
||||
smsReminderNumber:
|
||||
|
@ -386,10 +416,7 @@ const BookingPage = ({
|
|||
attendeeAddress: booking.attendeeAddress,
|
||||
}),
|
||||
metadata,
|
||||
customInputs: Object.keys(booking.customInputs || {}).map((inputId) => ({
|
||||
label: eventType.customInputs.find((input) => input.id === parseInt(inputId))?.label || "",
|
||||
value: booking.customInputs && inputId in booking.customInputs ? booking.customInputs[inputId] : "",
|
||||
})),
|
||||
customInputs: bookingCustomInputs,
|
||||
hasHashedBookingLink,
|
||||
hashedLink,
|
||||
smsReminderNumber:
|
||||
|
@ -793,6 +820,23 @@ const BookingPage = ({
|
|||
</Group>
|
||||
</div>
|
||||
)}
|
||||
{input.type === EventTypeCustomInputType.PHONE && (
|
||||
<div>
|
||||
<PhoneInput<BookingFormValues>
|
||||
name={`customInputs.${input.id}`}
|
||||
control={bookingForm.control}
|
||||
placeholder={t("enter_phone_number")}
|
||||
id={`customInputs.${input.id}`}
|
||||
required={input.required}
|
||||
/>
|
||||
{bookingForm.formState.errors?.customInputs?.[input.id] && (
|
||||
<div className="mt-2 flex items-center text-sm text-red-700 ">
|
||||
<Icon.FiInfo className="mr-2 h-3 w-3" />
|
||||
<p>{t("invalid_number")}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{!eventType.disableGuests && guestToggle && (
|
||||
|
|
|
@ -40,6 +40,7 @@ const CustomInputTypeForm: FC<Props> = (props) => {
|
|||
value: EventTypeCustomInputType.RADIO,
|
||||
label: t("radio"),
|
||||
},
|
||||
{ value: EventTypeCustomInputType.PHONE, label: t("phone_number") },
|
||||
];
|
||||
|
||||
const { selectedCustomInput } = props;
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
WebhookTriggerEvents,
|
||||
} from "@prisma/client";
|
||||
import async from "async";
|
||||
import { isValidPhoneNumber } from "libphonenumber-js";
|
||||
import { cloneDeep } from "lodash";
|
||||
import type { NextApiRequest } from "next";
|
||||
import short from "short-uuid";
|
||||
|
@ -1095,6 +1096,16 @@ function handleCustomInputs(
|
|||
z.literal(true, {
|
||||
errorMap: () => ({ message: `Missing ${etcInput.type} customInput: '${etcInput.label}'` }),
|
||||
}).parse(input?.value);
|
||||
} else if (etcInput.type === "PHONE") {
|
||||
z.string({
|
||||
errorMap: () => ({
|
||||
message: `Missing ${etcInput.type} customInput: '${etcInput.label}'`,
|
||||
}),
|
||||
})
|
||||
.refine((val) => isValidPhoneNumber(val), {
|
||||
message: "Phone number is invalid",
|
||||
})
|
||||
.parse(input?.value);
|
||||
} else {
|
||||
// type: NUMBER are also passed as string
|
||||
z.string({
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"@hookform/resolvers": "^2.9.7",
|
||||
"@sendgrid/client": "^7.7.0",
|
||||
"@sendgrid/mail": "^7.6.2",
|
||||
"libphonenumber-js": "^1.10.12",
|
||||
"twilio": "^3.80.1",
|
||||
"zod": "^3.20.2"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterEnum
|
||||
ALTER TYPE "EventTypeCustomInputType" ADD VALUE 'phone';
|
|
@ -344,6 +344,7 @@ enum EventTypeCustomInputType {
|
|||
NUMBER @map("number")
|
||||
BOOL @map("bool")
|
||||
RADIO @map("radio")
|
||||
PHONE @map("phone")
|
||||
}
|
||||
|
||||
model EventTypeCustomInput {
|
||||
|
|
Loading…
Reference in New Issue
Block a user