@blackcode_sa/metaestetics-api 1.6.4 → 1.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +236 -2
- package/dist/admin/index.d.ts +236 -2
- package/dist/admin/index.js +11251 -10447
- package/dist/admin/index.mjs +11251 -10447
- package/dist/backoffice/index.d.mts +2 -0
- package/dist/backoffice/index.d.ts +2 -0
- package/dist/index.d.mts +50 -77
- package/dist/index.d.ts +50 -77
- package/dist/index.js +77 -305
- package/dist/index.mjs +78 -306
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/README.md +128 -0
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1053 -0
- package/src/admin/booking/README.md +125 -0
- package/src/admin/booking/booking.admin.ts +638 -3
- package/src/admin/calendar/calendar.admin.service.ts +183 -0
- package/src/admin/documentation-templates/document-manager.admin.ts +131 -0
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +264 -0
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -0
- package/src/admin/mailing/base.mailing.service.ts +1 -1
- package/src/admin/mailing/index.ts +2 -0
- package/src/admin/notifications/notifications.admin.ts +397 -1
- package/src/backoffice/types/product.types.ts +2 -0
- package/src/services/appointment/appointment.service.ts +89 -182
- package/src/services/procedure/procedure.service.ts +1 -0
- package/src/types/appointment/index.ts +3 -1
- package/src/types/notifications/index.ts +4 -2
- package/src/types/procedure/index.ts +7 -0
- package/src/validations/appointment.schema.ts +2 -3
- package/src/validations/procedure.schema.ts +3 -0
|
@@ -93,100 +93,6 @@ export class AppointmentService extends BaseService {
|
|
|
93
93
|
this.functions = getFunctions(app, "europe-west6"); // Initialize Firebase Functions with the correct region
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/**
|
|
97
|
-
* Test method using the callable function version of getAvailableBookingSlots
|
|
98
|
-
* For development and testing purposes only - not for production use
|
|
99
|
-
*
|
|
100
|
-
* @param clinicId ID of the clinic
|
|
101
|
-
* @param practitionerId ID of the practitioner
|
|
102
|
-
* @param procedureId ID of the procedure
|
|
103
|
-
* @param startDate Start date of the time range to check
|
|
104
|
-
* @param endDate End date of the time range to check
|
|
105
|
-
* @returns Test result from the callable function
|
|
106
|
-
*/
|
|
107
|
-
async testGetAvailableBookingSlots(
|
|
108
|
-
clinicId: string,
|
|
109
|
-
practitionerId: string,
|
|
110
|
-
procedureId: string,
|
|
111
|
-
startDate: Date,
|
|
112
|
-
endDate: Date
|
|
113
|
-
): Promise<any> {
|
|
114
|
-
try {
|
|
115
|
-
console.log(
|
|
116
|
-
`[APPOINTMENT_SERVICE] Testing callable function for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
// Get the callable function
|
|
120
|
-
const getAvailableBookingSlotsCallable = httpsCallable(
|
|
121
|
-
this.functions,
|
|
122
|
-
"getAvailableBookingSlots"
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
// Call the function with the required parameters
|
|
126
|
-
const result = await getAvailableBookingSlotsCallable({
|
|
127
|
-
clinicId,
|
|
128
|
-
practitionerId,
|
|
129
|
-
procedureId,
|
|
130
|
-
timeframe: {
|
|
131
|
-
start: startDate.getTime(),
|
|
132
|
-
end: endDate.getTime(),
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
console.log(
|
|
137
|
-
"[APPOINTMENT_SERVICE] Callable function test result:",
|
|
138
|
-
result.data
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
return result.data;
|
|
142
|
-
} catch (error) {
|
|
143
|
-
console.error(
|
|
144
|
-
"[APPOINTMENT_SERVICE] Error testing callable function:",
|
|
145
|
-
error
|
|
146
|
-
);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Gets available booking slots for a specific clinic, practitioner, and procedure.
|
|
153
|
-
*
|
|
154
|
-
* @param clinicId ID of the clinic
|
|
155
|
-
* @param practitionerId ID of the practitioner
|
|
156
|
-
* @param procedureId ID of the procedure
|
|
157
|
-
* @param startDate Start date of the time range to check
|
|
158
|
-
* @param endDate End date of the time range to check
|
|
159
|
-
* @returns Array of available booking slots
|
|
160
|
-
*/
|
|
161
|
-
async getAvailableBookingSlots(
|
|
162
|
-
clinicId: string,
|
|
163
|
-
practitionerId: string,
|
|
164
|
-
procedureId: string,
|
|
165
|
-
startDate: Date,
|
|
166
|
-
endDate: Date
|
|
167
|
-
): Promise<AvailableSlot[]> {
|
|
168
|
-
try {
|
|
169
|
-
console.log(
|
|
170
|
-
`[APPOINTMENT_SERVICE] Getting available booking slots for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// Just call our HTTP implementation since the callable function isn't working in the browser
|
|
174
|
-
return this.getAvailableBookingSlotsHttp(
|
|
175
|
-
clinicId,
|
|
176
|
-
practitionerId,
|
|
177
|
-
procedureId,
|
|
178
|
-
startDate,
|
|
179
|
-
endDate
|
|
180
|
-
);
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.error(
|
|
183
|
-
"[APPOINTMENT_SERVICE] Error getting available booking slots:",
|
|
184
|
-
error
|
|
185
|
-
);
|
|
186
|
-
throw error;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
96
|
/**
|
|
191
97
|
* Gets available booking slots for a specific clinic, practitioner, and procedure using HTTP request.
|
|
192
98
|
* This is an alternative implementation using direct HTTP request instead of callable function.
|
|
@@ -328,42 +234,108 @@ export class AppointmentService extends BaseService {
|
|
|
328
234
|
}
|
|
329
235
|
|
|
330
236
|
/**
|
|
331
|
-
* Creates
|
|
237
|
+
* Creates an appointment via the Cloud Function orchestrateAppointmentCreation
|
|
332
238
|
*
|
|
333
|
-
* @param data
|
|
239
|
+
* @param data - CreateAppointmentData object
|
|
334
240
|
* @returns The created appointment
|
|
335
241
|
*/
|
|
336
|
-
async
|
|
242
|
+
async createAppointmentHttp(
|
|
243
|
+
data: CreateAppointmentData
|
|
244
|
+
): Promise<Appointment> {
|
|
337
245
|
try {
|
|
338
|
-
console.log(
|
|
246
|
+
console.log(
|
|
247
|
+
"[APPOINTMENT_SERVICE] Creating appointment via cloud function"
|
|
248
|
+
);
|
|
339
249
|
|
|
340
|
-
//
|
|
341
|
-
const
|
|
250
|
+
// Get the authenticated user's ID token
|
|
251
|
+
const currentUser = this.auth.currentUser;
|
|
252
|
+
if (!currentUser) {
|
|
253
|
+
throw new Error("User must be authenticated to create an appointment");
|
|
254
|
+
}
|
|
255
|
+
const idToken = await currentUser.getIdToken();
|
|
342
256
|
|
|
343
|
-
//
|
|
344
|
-
const
|
|
345
|
-
this.db,
|
|
346
|
-
validatedData.clinicBranchId,
|
|
347
|
-
validatedData.practitionerId,
|
|
348
|
-
validatedData.patientId,
|
|
349
|
-
validatedData.procedureId
|
|
350
|
-
);
|
|
257
|
+
// Construct the function URL for the Express app endpoint
|
|
258
|
+
const functionUrl = `https://europe-west6-metaestetics.cloudfunctions.net/bookingApi/orchestrateAppointmentCreation`;
|
|
351
259
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
260
|
+
// Prepare request data for the Cloud Function
|
|
261
|
+
// Map CreateAppointmentData to OrchestrateAppointmentCreationData format
|
|
262
|
+
const requestData = {
|
|
263
|
+
patientId: data.patientId,
|
|
264
|
+
procedureId: data.procedureId,
|
|
265
|
+
appointmentStartTime: data.appointmentStartTime.toMillis
|
|
266
|
+
? data.appointmentStartTime.toMillis()
|
|
267
|
+
: new Date(data.appointmentStartTime as any).getTime(),
|
|
268
|
+
appointmentEndTime: data.appointmentEndTime.toMillis
|
|
269
|
+
? data.appointmentEndTime.toMillis()
|
|
270
|
+
: new Date(data.appointmentEndTime as any).getTime(),
|
|
271
|
+
patientNotes: data.patientNotes || null,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
console.log(
|
|
275
|
+
`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
|
|
358
276
|
);
|
|
359
277
|
|
|
278
|
+
// Make the HTTP request with expanded CORS options for browser
|
|
279
|
+
const response = await fetch(functionUrl, {
|
|
280
|
+
method: "POST",
|
|
281
|
+
mode: "cors",
|
|
282
|
+
cache: "no-cache",
|
|
283
|
+
credentials: "omit",
|
|
284
|
+
headers: {
|
|
285
|
+
"Content-Type": "application/json",
|
|
286
|
+
Authorization: `Bearer ${idToken}`,
|
|
287
|
+
},
|
|
288
|
+
redirect: "follow",
|
|
289
|
+
referrerPolicy: "no-referrer",
|
|
290
|
+
body: JSON.stringify(requestData),
|
|
291
|
+
});
|
|
292
|
+
|
|
360
293
|
console.log(
|
|
361
|
-
`[APPOINTMENT_SERVICE]
|
|
294
|
+
`[APPOINTMENT_SERVICE] Received response ${response.status}: ${response.statusText}`
|
|
362
295
|
);
|
|
363
296
|
|
|
364
|
-
|
|
297
|
+
// Check if the request was successful
|
|
298
|
+
if (!response.ok) {
|
|
299
|
+
const errorText = await response.text();
|
|
300
|
+
console.error(
|
|
301
|
+
`[APPOINTMENT_SERVICE] Error response details: ${errorText}`
|
|
302
|
+
);
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Failed to create appointment: ${response.status} ${response.statusText} - ${errorText}`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Parse the response
|
|
309
|
+
const result = await response.json();
|
|
310
|
+
|
|
311
|
+
if (!result.success) {
|
|
312
|
+
throw new Error(result.error || "Failed to create appointment");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// If the backend returns the full appointment data
|
|
316
|
+
if (result.appointmentData) {
|
|
317
|
+
console.log(
|
|
318
|
+
`[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`
|
|
319
|
+
);
|
|
320
|
+
return result.appointmentData;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// If only the ID is returned, fetch the complete appointment
|
|
324
|
+
const createdAppointment = await this.getAppointmentById(
|
|
325
|
+
result.appointmentId
|
|
326
|
+
);
|
|
327
|
+
if (!createdAppointment) {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Failed to retrieve created appointment with ID: ${result.appointmentId}`
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return createdAppointment;
|
|
365
334
|
} catch (error) {
|
|
366
|
-
console.error(
|
|
335
|
+
console.error(
|
|
336
|
+
"[APPOINTMENT_SERVICE] Error creating appointment via cloud function:",
|
|
337
|
+
error
|
|
338
|
+
);
|
|
367
339
|
throw error;
|
|
368
340
|
}
|
|
369
341
|
}
|
|
@@ -1008,50 +980,6 @@ export class AppointmentService extends BaseService {
|
|
|
1008
980
|
return this.updateAppointment(appointmentId, updateData);
|
|
1009
981
|
}
|
|
1010
982
|
|
|
1011
|
-
/**
|
|
1012
|
-
* Marks pre-procedure requirements as completed.
|
|
1013
|
-
*
|
|
1014
|
-
* @param appointmentId ID of the appointment
|
|
1015
|
-
* @param requirementIds IDs of the requirements to mark as completed
|
|
1016
|
-
* @returns The updated appointment
|
|
1017
|
-
*/
|
|
1018
|
-
async completePreRequirements(
|
|
1019
|
-
appointmentId: string,
|
|
1020
|
-
requirementIds: string[]
|
|
1021
|
-
): Promise<Appointment> {
|
|
1022
|
-
console.log(
|
|
1023
|
-
`[APPOINTMENT_SERVICE] Marking pre-requirements as completed for appointment: ${appointmentId}`
|
|
1024
|
-
);
|
|
1025
|
-
|
|
1026
|
-
const updateData: UpdateAppointmentData = {
|
|
1027
|
-
completedPreRequirements: requirementIds,
|
|
1028
|
-
};
|
|
1029
|
-
|
|
1030
|
-
return this.updateAppointment(appointmentId, updateData);
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
/**
|
|
1034
|
-
* Marks post-procedure requirements as completed.
|
|
1035
|
-
*
|
|
1036
|
-
* @param appointmentId ID of the appointment
|
|
1037
|
-
* @param requirementIds IDs of the requirements to mark as completed
|
|
1038
|
-
* @returns The updated appointment
|
|
1039
|
-
*/
|
|
1040
|
-
async completePostRequirements(
|
|
1041
|
-
appointmentId: string,
|
|
1042
|
-
requirementIds: string[]
|
|
1043
|
-
): Promise<Appointment> {
|
|
1044
|
-
console.log(
|
|
1045
|
-
`[APPOINTMENT_SERVICE] Marking post-requirements as completed for appointment: ${appointmentId}`
|
|
1046
|
-
);
|
|
1047
|
-
|
|
1048
|
-
const updateData: UpdateAppointmentData = {
|
|
1049
|
-
completedPostRequirements: requirementIds,
|
|
1050
|
-
};
|
|
1051
|
-
|
|
1052
|
-
return this.updateAppointment(appointmentId, updateData);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
983
|
/**
|
|
1056
984
|
* Updates the internal notes of an appointment.
|
|
1057
985
|
*
|
|
@@ -1073,25 +1001,4 @@ export class AppointmentService extends BaseService {
|
|
|
1073
1001
|
|
|
1074
1002
|
return this.updateAppointment(appointmentId, updateData);
|
|
1075
1003
|
}
|
|
1076
|
-
|
|
1077
|
-
/**
|
|
1078
|
-
* Debug helper: Get the current user's ID token for testing purposes
|
|
1079
|
-
* Use this token in Postman with Authorization: Bearer TOKEN
|
|
1080
|
-
*/
|
|
1081
|
-
async getDebugToken(): Promise<string | null> {
|
|
1082
|
-
try {
|
|
1083
|
-
const currentUser = this.auth.currentUser;
|
|
1084
|
-
if (!currentUser) {
|
|
1085
|
-
console.log("[APPOINTMENT_SERVICE] No user is signed in");
|
|
1086
|
-
return null;
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
const idToken = await currentUser.getIdToken();
|
|
1090
|
-
console.log("[APPOINTMENT_SERVICE] Debug token:", idToken);
|
|
1091
|
-
return idToken;
|
|
1092
|
-
} catch (error) {
|
|
1093
|
-
console.error("[APPOINTMENT_SERVICE] Error getting debug token:", error);
|
|
1094
|
-
return null;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
1004
|
}
|
|
@@ -179,6 +179,7 @@ export class ProcedureService extends BaseService {
|
|
|
179
179
|
technology,
|
|
180
180
|
product,
|
|
181
181
|
blockingConditions: technology.blockingConditions,
|
|
182
|
+
contraindications: technology.contraindications || [],
|
|
182
183
|
treatmentBenefits: technology.benefits,
|
|
183
184
|
preRequirements: technology.requirements.pre,
|
|
184
185
|
postRequirements: technology.requirements.post,
|
|
@@ -93,6 +93,7 @@ export interface LinkedFormInfo {
|
|
|
93
93
|
templateVersion: number;
|
|
94
94
|
title: string; // For display, usually from DocumentTemplate.title
|
|
95
95
|
isUserForm: boolean;
|
|
96
|
+
isRequired?: boolean;
|
|
96
97
|
status: FilledDocumentStatus; // Status of the filled form (e.g., draft, completed, signed)
|
|
97
98
|
path: string; // Full Firestore path to the filled document (e.g., appointments/{aid}/user-forms/{fid})
|
|
98
99
|
submittedAt?: Timestamp;
|
|
@@ -178,6 +179,7 @@ export interface Appointment {
|
|
|
178
179
|
completedPostRequirements?: string[]; // IDs of completed post-requirements
|
|
179
180
|
|
|
180
181
|
/** NEW: Linked forms (consent, procedure-specific forms, etc.) */
|
|
182
|
+
linkedFormIds?: string[];
|
|
181
183
|
linkedForms?: LinkedFormInfo[];
|
|
182
184
|
pendingUserFormsIds?: string[]; // Determines if there are any user forms that are pending for this appointment, blocks the appointment from being checked in (only for user forms with isRequired = true)
|
|
183
185
|
|
|
@@ -210,7 +212,6 @@ export interface Appointment {
|
|
|
210
212
|
* Data needed to create a new Appointment
|
|
211
213
|
*/
|
|
212
214
|
export interface CreateAppointmentData {
|
|
213
|
-
calendarEventId: string;
|
|
214
215
|
clinicBranchId: string;
|
|
215
216
|
practitionerId: string;
|
|
216
217
|
patientId: string;
|
|
@@ -250,6 +251,7 @@ export interface UpdateAppointmentData {
|
|
|
250
251
|
practitionerId?: string; // If practitioner is changed
|
|
251
252
|
|
|
252
253
|
/** NEW: For updating linked forms - typically managed by dedicated methods */
|
|
254
|
+
linkedFormIds?: string[] | FieldValue;
|
|
253
255
|
linkedForms?: LinkedFormInfo[] | FieldValue;
|
|
254
256
|
|
|
255
257
|
/** NEW: For updating media items - typically managed by dedicated methods */
|
|
@@ -11,6 +11,8 @@ export enum NotificationType {
|
|
|
11
11
|
APPOINTMENT_CANCELLED = "appointmentCancelled", // When an appointment is cancelled
|
|
12
12
|
|
|
13
13
|
// --- Requirement-Driven Instructions ---
|
|
14
|
+
PRE_REQUIREMENT_INSTRUCTION_DUE = "preRequirementInstructionDue",
|
|
15
|
+
POST_REQUIREMENT_INSTRUCTION_DUE = "postRequirementInstructionDue",
|
|
14
16
|
REQUIREMENT_INSTRUCTION_DUE = "requirementInstructionDue", // For specific pre/post care instructions
|
|
15
17
|
|
|
16
18
|
// --- Form Related ---
|
|
@@ -106,7 +108,7 @@ export enum NotificationStatus {
|
|
|
106
108
|
* Notifikacija za pre-requirement
|
|
107
109
|
*/
|
|
108
110
|
export interface PreRequirementNotification extends BaseNotification {
|
|
109
|
-
notificationType: NotificationType.
|
|
111
|
+
notificationType: NotificationType.PRE_REQUIREMENT_INSTRUCTION_DUE;
|
|
110
112
|
/** ID tretmana za koji je vezan pre-requirement */
|
|
111
113
|
treatmentId: string;
|
|
112
114
|
/** Lista pre-requirements koji treba da se ispune */
|
|
@@ -119,7 +121,7 @@ export interface PreRequirementNotification extends BaseNotification {
|
|
|
119
121
|
* Notifikacija za post-requirement
|
|
120
122
|
*/
|
|
121
123
|
export interface PostRequirementNotification extends BaseNotification {
|
|
122
|
-
notificationType: NotificationType.
|
|
124
|
+
notificationType: NotificationType.POST_REQUIREMENT_INSTRUCTION_DUE;
|
|
123
125
|
/** ID tretmana za koji je vezan post-requirement */
|
|
124
126
|
treatmentId: string;
|
|
125
127
|
/** Lista post-requirements koji treba da se ispune */
|
|
@@ -16,6 +16,7 @@ import { ClinicInfo } from "../profile";
|
|
|
16
16
|
import { DoctorInfo } from "../clinic";
|
|
17
17
|
import { PRACTITIONERS_COLLECTION } from "../practitioner";
|
|
18
18
|
import { ProcedureReviewInfo } from "../reviews";
|
|
19
|
+
import type { Contraindication } from "../../backoffice/types/static/contraindication.types";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Procedure represents a specific medical procedure that can be performed by a practitioner in a clinic
|
|
@@ -26,6 +27,8 @@ export interface Procedure {
|
|
|
26
27
|
id: string;
|
|
27
28
|
/** Name of the procedure */
|
|
28
29
|
name: string;
|
|
30
|
+
/** Photos of the procedure */
|
|
31
|
+
photos?: string[];
|
|
29
32
|
/** Detailed description of the procedure */
|
|
30
33
|
description: string;
|
|
31
34
|
/** Family of procedures this belongs to (aesthetics/surgery) */
|
|
@@ -50,6 +53,8 @@ export interface Procedure {
|
|
|
50
53
|
blockingConditions: BlockingCondition[];
|
|
51
54
|
/** Treatment benefits of this procedure */
|
|
52
55
|
treatmentBenefits: TreatmentBenefit[];
|
|
56
|
+
/** Contraindications of this procedure */
|
|
57
|
+
contraindications: Contraindication[];
|
|
53
58
|
/** Pre-procedure requirements */
|
|
54
59
|
preRequirements: Requirement[];
|
|
55
60
|
/** Post-procedure requirements */
|
|
@@ -93,6 +98,7 @@ export interface CreateProcedureData {
|
|
|
93
98
|
duration: number;
|
|
94
99
|
practitionerId: string;
|
|
95
100
|
clinicBranchId: string;
|
|
101
|
+
photos?: string[];
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
/**
|
|
@@ -112,6 +118,7 @@ export interface UpdateProcedureData {
|
|
|
112
118
|
technologyId?: string;
|
|
113
119
|
productId?: string;
|
|
114
120
|
clinicBranchId?: string;
|
|
121
|
+
photos?: string[];
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
/**
|
|
@@ -70,6 +70,7 @@ export const linkedFormInfoSchema = z.object({
|
|
|
70
70
|
.positive("Template version must be a positive integer"),
|
|
71
71
|
title: z.string().min(MIN_STRING_LENGTH, "Form title is required"),
|
|
72
72
|
isUserForm: z.boolean(),
|
|
73
|
+
isRequired: z.boolean().optional(),
|
|
73
74
|
status: filledDocumentStatusSchema,
|
|
74
75
|
path: z.string().min(MIN_STRING_LENGTH, "Form path is required"),
|
|
75
76
|
submittedAt: z
|
|
@@ -138,9 +139,6 @@ export const finalizedDetailsSchema = z.object({
|
|
|
138
139
|
*/
|
|
139
140
|
export const createAppointmentSchema = z
|
|
140
141
|
.object({
|
|
141
|
-
calendarEventId: z
|
|
142
|
-
.string()
|
|
143
|
-
.min(MIN_STRING_LENGTH, "Calendar event ID is required"),
|
|
144
142
|
clinicBranchId: z
|
|
145
143
|
.string()
|
|
146
144
|
.min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
|
|
@@ -221,6 +219,7 @@ export const updateAppointmentSchema = z
|
|
|
221
219
|
completedPostRequirements: z
|
|
222
220
|
.union([z.array(z.string()), z.any()])
|
|
223
221
|
.optional(),
|
|
222
|
+
linkedFormIds: z.union([z.array(z.string()), z.any()]).optional(),
|
|
224
223
|
pendingUserFormsIds: z.union([z.array(z.string()), z.any()]).optional(),
|
|
225
224
|
appointmentStartTime: z
|
|
226
225
|
.any()
|
|
@@ -24,6 +24,7 @@ export const createProcedureSchema = z.object({
|
|
|
24
24
|
duration: z.number().min(1).max(480), // Max 8 hours
|
|
25
25
|
practitionerId: z.string().min(1),
|
|
26
26
|
clinicBranchId: z.string().min(1),
|
|
27
|
+
photos: z.array(z.string()).optional(),
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
/**
|
|
@@ -43,6 +44,7 @@ export const updateProcedureSchema = z.object({
|
|
|
43
44
|
technologyId: z.string().optional(),
|
|
44
45
|
productId: z.string().optional(),
|
|
45
46
|
clinicBranchId: z.string().optional(),
|
|
47
|
+
photos: z.array(z.string()).optional(),
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
/**
|
|
@@ -55,6 +57,7 @@ export const procedureSchema = createProcedureSchema.extend({
|
|
|
55
57
|
technology: z.any(), // We'll validate the full technology object separately
|
|
56
58
|
product: z.any(), // We'll validate the full product object separately
|
|
57
59
|
blockingConditions: z.array(z.any()), // We'll validate blocking conditions separately
|
|
60
|
+
contraindications: z.array(z.any()), // We'll validate contraindications separately
|
|
58
61
|
treatmentBenefits: z.array(z.any()), // We'll validate treatment benefits separately
|
|
59
62
|
preRequirements: z.array(z.any()), // We'll validate requirements separately
|
|
60
63
|
postRequirements: z.array(z.any()), // We'll validate requirements separately
|