2023-03-27 08:27:10 +00:00
import type z from "zod" ;
import { SystemField } from "@calcom/features/bookings/lib/getBookingFields" ;
import type { bookingResponsesDbSchema } from "@calcom/features/bookings/lib/getBookingResponsesSchema" ;
2023-04-04 04:59:09 +00:00
import { getBookingWithResponses } from "@calcom/lib/getBooking" ;
import { eventTypeBookingFields } from "@calcom/prisma/zod-utils" ;
2023-03-27 08:27:10 +00:00
import type { CalendarEvent } from "@calcom/types/Calendar" ;
2023-04-04 04:59:09 +00:00
import type { EventType , Prisma } from ".prisma/client" ;
2023-03-27 08:27:10 +00:00
export const getCalEventResponses = ( {
bookingFields ,
2023-04-04 04:59:09 +00:00
booking ,
2023-03-27 08:27:10 +00:00
responses ,
} : {
// If the eventType has been deleted and a booking is Accepted later on, then bookingFields will be null and we can't know the label of fields. So, we should store the label as well in the DB
// Also, it is no longer straightforward to identify if a field is system field or not
2023-04-04 04:59:09 +00:00
bookingFields : z.infer < typeof eventTypeBookingFields > | EventType [ "bookingFields" ] | null ;
booking? : Prisma.BookingGetPayload < {
select : {
description : true ;
customInputs : true ;
attendees : {
select : {
email : true ;
name : true ;
} ;
} ;
location : true ;
responses : true ;
} ;
} > ;
responses? : z.infer < typeof bookingResponsesDbSchema > ;
2023-03-27 08:27:10 +00:00
} ) = > {
const calEventUserFieldsResponses = { } as NonNullable < CalendarEvent [ " userFieldsResponses " ] > ;
const calEventResponses = { } as NonNullable < CalendarEvent [ " responses " ] > ;
2023-04-04 04:59:09 +00:00
const parsedBookingFields = bookingFields ? eventTypeBookingFields . parse ( bookingFields ) : null ;
const backwardCompatibleResponses =
responses ? ? ( booking ? getBookingWithResponses ( booking ) . responses : null ) ;
if ( ! backwardCompatibleResponses ) throw new Error ( "Couldn't get responses" ) ;
2023-03-27 08:27:10 +00:00
2023-04-04 04:59:09 +00:00
if ( parsedBookingFields ) {
parsedBookingFields . forEach ( ( field ) = > {
2023-03-27 08:27:10 +00:00
const label = field . label || field . defaultLabel ;
if ( ! label ) {
throw new Error ( 'Missing label for booking field "' + field . name + '"' ) ;
}
2023-06-10 03:47:50 +00:00
// If the guests field is hidden (disableGuests is set on the event type) don't try and infer guests from attendees list
if ( field . name == "guests" && field . hidden ) {
backwardCompatibleResponses [ field . name ] = [ ] ;
}
2023-03-27 08:27:10 +00:00
if ( field . editable === "user" || field . editable === "user-readonly" ) {
calEventUserFieldsResponses [ field . name ] = {
label ,
2023-04-04 04:59:09 +00:00
value : backwardCompatibleResponses [ field . name ] ,
2023-03-27 08:27:10 +00:00
} ;
}
calEventResponses [ field . name ] = {
label ,
2023-04-04 04:59:09 +00:00
value : backwardCompatibleResponses [ field . name ] ,
2023-03-27 08:27:10 +00:00
} ;
} ) ;
} else {
// Alternative way to generate for a booking of whose eventType has been deleted
2023-04-04 04:59:09 +00:00
for ( const [ name , value ] of Object . entries ( backwardCompatibleResponses ) ) {
2023-03-27 08:27:10 +00:00
const isSystemField = SystemField . safeParse ( name ) ;
// Use name for Label because we don't have access to the label. This will not be needed once we start storing the label along with the response
const label = name ;
if ( ! isSystemField . success ) {
calEventUserFieldsResponses [ name ] = {
label ,
value ,
} ;
}
calEventResponses [ name ] = {
label ,
value ,
} ;
}
}
2023-04-04 04:59:09 +00:00
return { userFieldsResponses : calEventUserFieldsResponses , responses : calEventResponses } ;
2023-03-27 08:27:10 +00:00
} ;