@blackcode_sa/metaestetics-api 1.6.3 → 1.6.5

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.
Files changed (40) hide show
  1. package/dist/admin/index.d.mts +439 -25
  2. package/dist/admin/index.d.ts +439 -25
  3. package/dist/admin/index.js +36107 -2493
  4. package/dist/admin/index.mjs +36093 -2461
  5. package/dist/backoffice/index.d.mts +254 -1
  6. package/dist/backoffice/index.d.ts +254 -1
  7. package/dist/backoffice/index.js +86 -12
  8. package/dist/backoffice/index.mjs +86 -13
  9. package/dist/index.d.mts +1434 -621
  10. package/dist/index.d.ts +1434 -621
  11. package/dist/index.js +1381 -970
  12. package/dist/index.mjs +1433 -1016
  13. package/package.json +1 -1
  14. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +321 -0
  15. package/src/admin/booking/booking.admin.ts +376 -3
  16. package/src/admin/index.ts +15 -1
  17. package/src/admin/notifications/notifications.admin.ts +1 -1
  18. package/src/admin/requirements/README.md +128 -0
  19. package/src/admin/requirements/patient-requirements.admin.service.ts +482 -0
  20. package/src/backoffice/types/product.types.ts +2 -0
  21. package/src/index.ts +16 -1
  22. package/src/services/appointment/appointment.service.ts +386 -250
  23. package/src/services/clinic/clinic-admin.service.ts +3 -0
  24. package/src/services/clinic/clinic-group.service.ts +8 -0
  25. package/src/services/documentation-templates/documentation-template.service.ts +24 -16
  26. package/src/services/documentation-templates/filled-document.service.ts +253 -136
  27. package/src/services/patient/patientRequirements.service.ts +285 -0
  28. package/src/services/procedure/procedure.service.ts +1 -0
  29. package/src/types/appointment/index.ts +136 -11
  30. package/src/types/documentation-templates/index.ts +34 -2
  31. package/src/types/notifications/README.md +77 -0
  32. package/src/types/notifications/index.ts +154 -27
  33. package/src/types/patient/patient-requirements.ts +81 -0
  34. package/src/types/procedure/index.ts +7 -0
  35. package/src/validations/appointment.schema.ts +298 -62
  36. package/src/validations/documentation-templates/template.schema.ts +55 -0
  37. package/src/validations/documentation-templates.schema.ts +9 -14
  38. package/src/validations/notification.schema.ts +3 -3
  39. package/src/validations/patient/patient-requirements.schema.ts +75 -0
  40. package/src/validations/procedure.schema.ts +3 -0
package/dist/index.js CHANGED
@@ -81,9 +81,13 @@ __export(index_exports, {
81
81
  PATIENT_LOCATION_INFO_COLLECTION: () => PATIENT_LOCATION_INFO_COLLECTION,
82
82
  PATIENT_MEDICAL_HISTORY_COLLECTION: () => PATIENT_MEDICAL_HISTORY_COLLECTION,
83
83
  PATIENT_MEDICAL_INFO_COLLECTION: () => PATIENT_MEDICAL_INFO_COLLECTION,
84
+ PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME: () => PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
84
85
  PATIENT_SENSITIVE_INFO_COLLECTION: () => PATIENT_SENSITIVE_INFO_COLLECTION,
85
86
  PRACTITIONERS_COLLECTION: () => PRACTITIONERS_COLLECTION,
86
87
  PROCEDURES_COLLECTION: () => PROCEDURES_COLLECTION,
88
+ PatientInstructionStatus: () => PatientInstructionStatus,
89
+ PatientRequirementOverallStatus: () => PatientRequirementOverallStatus,
90
+ PatientRequirementsService: () => PatientRequirementsService,
87
91
  PatientService: () => PatientService,
88
92
  PaymentStatus: () => PaymentStatus,
89
93
  PracticeType: () => PracticeType,
@@ -148,6 +152,7 @@ __export(index_exports, {
148
152
  createDefaultClinicGroupSchema: () => createDefaultClinicGroupSchema,
149
153
  createDocumentTemplateSchema: () => createDocumentTemplateSchema,
150
154
  createDraftPractitionerSchema: () => createDraftPractitionerSchema,
155
+ createFilledDocumentDataSchema: () => createFilledDocumentDataSchema,
151
156
  createPatientLocationInfoSchema: () => createPatientLocationInfoSchema,
152
157
  createPatientMedicalInfoSchema: () => createPatientMedicalInfoSchema,
153
158
  createPatientProfileSchema: () => createPatientProfileSchema,
@@ -163,6 +168,8 @@ __export(index_exports, {
163
168
  documentTemplateSchema: () => documentTemplateSchema,
164
169
  emailSchema: () => emailSchema,
165
170
  emergencyContactSchema: () => emergencyContactSchema,
171
+ filledDocumentSchema: () => filledDocumentSchema,
172
+ filledDocumentStatusSchema: () => filledDocumentStatusSchema,
166
173
  gamificationSchema: () => gamificationSchema,
167
174
  getFirebaseApp: () => getFirebaseApp,
168
175
  getFirebaseAuth: () => getFirebaseAuth,
@@ -212,6 +219,7 @@ __export(index_exports, {
212
219
  updateClinicSchema: () => updateClinicSchema,
213
220
  updateContraindicationSchema: () => updateContraindicationSchema,
214
221
  updateDocumentTemplateSchema: () => updateDocumentTemplateSchema,
222
+ updateFilledDocumentDataSchema: () => updateFilledDocumentDataSchema,
215
223
  updateMedicationSchema: () => updateMedicationSchema,
216
224
  updatePatientMedicalInfoSchema: () => updatePatientMedicalInfoSchema,
217
225
  updateVitalStatsSchema: () => updateVitalStatsSchema,
@@ -224,19 +232,20 @@ __export(index_exports, {
224
232
  module.exports = __toCommonJS(index_exports);
225
233
 
226
234
  // src/validations/appointment.schema.ts
227
- var import_zod = require("zod");
235
+ var import_zod2 = require("zod");
228
236
 
229
237
  // src/types/appointment/index.ts
230
238
  var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
231
- AppointmentStatus2["SCHEDULED"] = "scheduled";
239
+ AppointmentStatus2["PENDING"] = "pending";
232
240
  AppointmentStatus2["CONFIRMED"] = "confirmed";
233
241
  AppointmentStatus2["CHECKED_IN"] = "checked_in";
234
242
  AppointmentStatus2["IN_PROGRESS"] = "in_progress";
235
243
  AppointmentStatus2["COMPLETED"] = "completed";
236
244
  AppointmentStatus2["CANCELED_PATIENT"] = "canceled_patient";
245
+ AppointmentStatus2["CANCELED_PATIENT_RESCHEDULED"] = "canceled_patient_rescheduled";
237
246
  AppointmentStatus2["CANCELED_CLINIC"] = "canceled_clinic";
238
247
  AppointmentStatus2["NO_SHOW"] = "no_show";
239
- AppointmentStatus2["RESCHEDULED"] = "rescheduled";
248
+ AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
240
249
  return AppointmentStatus2;
241
250
  })(AppointmentStatus || {});
242
251
  var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
@@ -247,82 +256,444 @@ var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
247
256
  PaymentStatus3["NOT_APPLICABLE"] = "not_applicable";
248
257
  return PaymentStatus3;
249
258
  })(PaymentStatus || {});
259
+ var MediaType = /* @__PURE__ */ ((MediaType2) => {
260
+ MediaType2["BEFORE_PHOTO"] = "before_photo";
261
+ MediaType2["AFTER_PHOTO"] = "after_photo";
262
+ MediaType2["CONSENT_SCAN"] = "consent_scan";
263
+ MediaType2["OTHER_DOCUMENT"] = "other_document";
264
+ return MediaType2;
265
+ })(MediaType || {});
250
266
  var APPOINTMENTS_COLLECTION = "appointments";
251
267
 
268
+ // src/validations/documentation-templates/template.schema.ts
269
+ var import_zod = require("zod");
270
+
271
+ // src/types/documentation-templates/index.ts
272
+ var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
273
+ var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
274
+ var USER_FORMS_SUBCOLLECTION = "user-forms";
275
+ var DOCTOR_FORMS_SUBCOLLECTION = "doctor-forms";
276
+ var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
277
+ DocumentElementType2["HEADING"] = "heading";
278
+ DocumentElementType2["PARAGRAPH"] = "paragraph";
279
+ DocumentElementType2["LIST"] = "list";
280
+ DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
281
+ DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
282
+ DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
283
+ DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
284
+ DocumentElementType2["RATING_SCALE"] = "rating_scale";
285
+ DocumentElementType2["TEXT_INPUT"] = "text_input";
286
+ DocumentElementType2["DATE_PICKER"] = "date_picker";
287
+ DocumentElementType2["SIGNATURE"] = "signature";
288
+ DocumentElementType2["DITIGAL_SIGNATURE"] = "digital_signature";
289
+ DocumentElementType2["FILE_UPLOAD"] = "file_upload";
290
+ return DocumentElementType2;
291
+ })(DocumentElementType || {});
292
+ var ListType = /* @__PURE__ */ ((ListType2) => {
293
+ ListType2["ORDERED"] = "ordered";
294
+ ListType2["UNORDERED"] = "unordered";
295
+ return ListType2;
296
+ })(ListType || {});
297
+ var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
298
+ HeadingLevel2["H1"] = "h1";
299
+ HeadingLevel2["H2"] = "h2";
300
+ HeadingLevel2["H3"] = "h3";
301
+ HeadingLevel2["H4"] = "h4";
302
+ HeadingLevel2["H5"] = "h5";
303
+ HeadingLevel2["H6"] = "h6";
304
+ return HeadingLevel2;
305
+ })(HeadingLevel || {});
306
+ var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
307
+ DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
308
+ DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
309
+ DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
310
+ DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
311
+ DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
312
+ DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
313
+ DynamicVariable2["PROCEDURE_NAME"] = "[PROCEDURE_NAME]";
314
+ DynamicVariable2["PROCEDURE_DESCRIPTION"] = "[PROCEDURE_DESCRIPTION]";
315
+ DynamicVariable2["PROCEDURE_COST"] = "[PROCEDURE_COST]";
316
+ DynamicVariable2["PROCEDURE_DURATION"] = "[PROCEDURE_DURATION]";
317
+ DynamicVariable2["PROCEDURE_RISK"] = "[PROCEDURE_RISK]";
318
+ return DynamicVariable2;
319
+ })(DynamicVariable || {});
320
+ var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
321
+ FilledDocumentStatus2["DRAFT"] = "draft";
322
+ FilledDocumentStatus2["SKIPPED"] = "skipped";
323
+ FilledDocumentStatus2["PENDING"] = "pending";
324
+ FilledDocumentStatus2["COMPLETED"] = "completed";
325
+ FilledDocumentStatus2["SIGNED"] = "signed";
326
+ FilledDocumentStatus2["REJECTED"] = "rejected";
327
+ return FilledDocumentStatus2;
328
+ })(FilledDocumentStatus || {});
329
+
330
+ // src/validations/documentation-templates/template.schema.ts
331
+ var baseElementSchema = import_zod.z.object({
332
+ id: import_zod.z.string().optional(),
333
+ // Make id optional so we can omit it later
334
+ type: import_zod.z.nativeEnum(DocumentElementType),
335
+ required: import_zod.z.boolean().optional()
336
+ });
337
+ var headingElementSchema = baseElementSchema.extend({
338
+ type: import_zod.z.literal("heading" /* HEADING */),
339
+ text: import_zod.z.string().min(1).max(200),
340
+ level: import_zod.z.nativeEnum(HeadingLevel)
341
+ });
342
+ var paragraphElementSchema = baseElementSchema.extend({
343
+ type: import_zod.z.literal("paragraph" /* PARAGRAPH */),
344
+ text: import_zod.z.string().min(1).max(5e3)
345
+ });
346
+ var listElementSchema = baseElementSchema.extend({
347
+ type: import_zod.z.literal("list" /* LIST */),
348
+ items: import_zod.z.array(import_zod.z.string().min(1).max(500)).min(1).max(100),
349
+ listType: import_zod.z.nativeEnum(ListType)
350
+ });
351
+ var dynamicTextElementSchema = baseElementSchema.extend({
352
+ type: import_zod.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
353
+ text: import_zod.z.string().min(1).max(5e3)
354
+ });
355
+ var binaryChoiceElementSchema = baseElementSchema.extend({
356
+ type: import_zod.z.literal("binary_choice" /* BINARY_CHOICE */),
357
+ question: import_zod.z.string().min(1).max(500),
358
+ defaultValue: import_zod.z.boolean().optional()
359
+ });
360
+ var multipleChoiceElementSchema = baseElementSchema.extend({
361
+ type: import_zod.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
362
+ question: import_zod.z.string().min(1).max(500),
363
+ options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
364
+ defaultValues: import_zod.z.array(import_zod.z.string()).optional()
365
+ });
366
+ var singleChoiceElementSchema = baseElementSchema.extend({
367
+ type: import_zod.z.literal("single_choice" /* SINGLE_CHOICE */),
368
+ question: import_zod.z.string().min(1).max(500),
369
+ options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
370
+ defaultValue: import_zod.z.string().optional()
371
+ });
372
+ var ratingScaleElementSchema = baseElementSchema.extend({
373
+ type: import_zod.z.literal("rating_scale" /* RATING_SCALE */),
374
+ question: import_zod.z.string().min(1).max(500),
375
+ min: import_zod.z.number().int().min(0).max(10),
376
+ max: import_zod.z.number().int().min(1).max(10),
377
+ labels: import_zod.z.record(import_zod.z.string()).optional(),
378
+ defaultValue: import_zod.z.number().int().optional()
379
+ });
380
+ var textInputElementSchema = baseElementSchema.extend({
381
+ type: import_zod.z.literal("text_input" /* TEXT_INPUT */),
382
+ label: import_zod.z.string().min(1).max(200),
383
+ placeholder: import_zod.z.string().max(200).optional(),
384
+ multiline: import_zod.z.boolean().optional(),
385
+ defaultValue: import_zod.z.string().optional()
386
+ });
387
+ var datePickerElementSchema = baseElementSchema.extend({
388
+ type: import_zod.z.literal("date_picker" /* DATE_PICKER */),
389
+ label: import_zod.z.string().min(1).max(200),
390
+ defaultValue: import_zod.z.string().optional()
391
+ // ISO date string
392
+ });
393
+ var signatureElementSchema = baseElementSchema.extend({
394
+ type: import_zod.z.literal("signature" /* SIGNATURE */),
395
+ label: import_zod.z.string().min(1).max(200)
396
+ });
397
+ var digitalSignatureElementSchema = baseElementSchema.extend({
398
+ type: import_zod.z.literal("digital_signature" /* DITIGAL_SIGNATURE */),
399
+ // Matching your type enum
400
+ label: import_zod.z.string().min(1).max(200)
401
+ });
402
+ var fileUploadElementSchema = baseElementSchema.extend({
403
+ type: import_zod.z.literal("file_upload" /* FILE_UPLOAD */),
404
+ label: import_zod.z.string().min(1).max(200),
405
+ allowedFileTypes: import_zod.z.array(import_zod.z.string()).optional(),
406
+ maxFileSizeMB: import_zod.z.number().positive().optional()
407
+ });
408
+ var documentElementSchema = import_zod.z.discriminatedUnion("type", [
409
+ headingElementSchema,
410
+ paragraphElementSchema,
411
+ listElementSchema,
412
+ dynamicTextElementSchema,
413
+ binaryChoiceElementSchema,
414
+ multipleChoiceElementSchema,
415
+ singleChoiceElementSchema,
416
+ ratingScaleElementSchema,
417
+ textInputElementSchema,
418
+ datePickerElementSchema,
419
+ signatureElementSchema,
420
+ digitalSignatureElementSchema,
421
+ fileUploadElementSchema
422
+ ]);
423
+ var documentElementWithoutIdSchema = import_zod.z.discriminatedUnion("type", [
424
+ headingElementSchema.omit({ id: true }),
425
+ paragraphElementSchema.omit({ id: true }),
426
+ listElementSchema.omit({ id: true }),
427
+ dynamicTextElementSchema.omit({ id: true }),
428
+ binaryChoiceElementSchema.omit({ id: true }),
429
+ multipleChoiceElementSchema.omit({ id: true }),
430
+ singleChoiceElementSchema.omit({ id: true }),
431
+ ratingScaleElementSchema.omit({ id: true }),
432
+ textInputElementSchema.omit({ id: true }),
433
+ datePickerElementSchema.omit({ id: true }),
434
+ signatureElementSchema.omit({ id: true }),
435
+ digitalSignatureElementSchema.omit({ id: true }),
436
+ fileUploadElementSchema.omit({ id: true })
437
+ ]);
438
+ var createDocumentTemplateSchema = import_zod.z.object({
439
+ title: import_zod.z.string().min(1).max(200),
440
+ description: import_zod.z.string().max(1e3).optional(),
441
+ elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100),
442
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
443
+ isUserForm: import_zod.z.boolean().optional().default(false),
444
+ isRequired: import_zod.z.boolean().optional().default(false),
445
+ sortingOrder: import_zod.z.number().int().optional().default(0)
446
+ });
447
+ var updateDocumentTemplateSchema = import_zod.z.object({
448
+ title: import_zod.z.string().min(1).max(200).optional(),
449
+ description: import_zod.z.string().max(1e3).optional(),
450
+ elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
451
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
452
+ isActive: import_zod.z.boolean().optional(),
453
+ isUserForm: import_zod.z.boolean().optional(),
454
+ isRequired: import_zod.z.boolean().optional(),
455
+ sortingOrder: import_zod.z.number().int().optional()
456
+ });
457
+ var documentTemplateSchema = import_zod.z.object({
458
+ id: import_zod.z.string(),
459
+ title: import_zod.z.string().min(1).max(200),
460
+ description: import_zod.z.string().max(1e3).optional(),
461
+ createdAt: import_zod.z.number(),
462
+ updatedAt: import_zod.z.number(),
463
+ createdBy: import_zod.z.string(),
464
+ elements: import_zod.z.array(documentElementSchema),
465
+ tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
466
+ version: import_zod.z.number().int().positive(),
467
+ isActive: import_zod.z.boolean(),
468
+ isUserForm: import_zod.z.boolean().optional().default(false),
469
+ isRequired: import_zod.z.boolean().optional().default(false),
470
+ sortingOrder: import_zod.z.number().int().optional().default(0)
471
+ });
472
+ var filledDocumentStatusSchema = import_zod.z.nativeEnum(FilledDocumentStatus);
473
+ var filledDocumentSchema = import_zod.z.object({
474
+ id: import_zod.z.string(),
475
+ templateId: import_zod.z.string(),
476
+ templateVersion: import_zod.z.number(),
477
+ isUserForm: import_zod.z.boolean(),
478
+ procedureId: import_zod.z.string(),
479
+ appointmentId: import_zod.z.string(),
480
+ patientId: import_zod.z.string(),
481
+ practitionerId: import_zod.z.string(),
482
+ clinicId: import_zod.z.string(),
483
+ createdAt: import_zod.z.number(),
484
+ updatedAt: import_zod.z.number(),
485
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()),
486
+ status: filledDocumentStatusSchema
487
+ });
488
+ var createFilledDocumentDataSchema = import_zod.z.object({
489
+ templateId: import_zod.z.string(),
490
+ procedureId: import_zod.z.string(),
491
+ appointmentId: import_zod.z.string(),
492
+ patientId: import_zod.z.string(),
493
+ practitionerId: import_zod.z.string(),
494
+ clinicId: import_zod.z.string(),
495
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional().default({}),
496
+ status: filledDocumentStatusSchema.optional().default("draft" /* DRAFT */)
497
+ });
498
+ var updateFilledDocumentDataSchema = import_zod.z.object({
499
+ values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
500
+ status: filledDocumentStatusSchema.optional()
501
+ });
502
+
252
503
  // src/validations/appointment.schema.ts
253
- var createAppointmentSchema = import_zod.z.object({
254
- calendarEventId: import_zod.z.string().min(1, "Calendar event ID is required"),
255
- clinicBranchId: import_zod.z.string().min(1, "Clinic branch ID is required"),
256
- practitionerId: import_zod.z.string().min(1, "Practitioner ID is required"),
257
- patientId: import_zod.z.string().min(1, "Patient ID is required"),
258
- procedureId: import_zod.z.string().min(1, "Procedure ID is required"),
259
- appointmentStartTime: import_zod.z.any().refine(
260
- (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
261
- "Appointment start time must be a valid timestamp"
504
+ var MIN_STRING_LENGTH = 1;
505
+ var MAX_STRING_LENGTH = 1024;
506
+ var MAX_STRING_LENGTH_LONG = 4096;
507
+ var MAX_ARRAY_LENGTH = 100;
508
+ var appointmentStatusSchema = import_zod2.z.nativeEnum(AppointmentStatus);
509
+ var paymentStatusSchema = import_zod2.z.nativeEnum(PaymentStatus);
510
+ var mediaTypeSchema = import_zod2.z.nativeEnum(MediaType);
511
+ var appointmentMediaItemSchema = import_zod2.z.object({
512
+ id: import_zod2.z.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
513
+ type: mediaTypeSchema,
514
+ url: import_zod2.z.string().url("Media URL must be a valid URL"),
515
+ fileName: import_zod2.z.string().optional(),
516
+ uploadedAt: import_zod2.z.any().refine(
517
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
518
+ "uploadedAt must be a valid timestamp or Date object"
519
+ ),
520
+ uploadedBy: import_zod2.z.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
521
+ description: import_zod2.z.string().max(MAX_STRING_LENGTH, "Description too long").optional()
522
+ });
523
+ var procedureExtendedInfoSchema = import_zod2.z.object({
524
+ id: import_zod2.z.string().min(MIN_STRING_LENGTH),
525
+ name: import_zod2.z.string().min(MIN_STRING_LENGTH),
526
+ description: import_zod2.z.string(),
527
+ cost: import_zod2.z.number().min(0),
528
+ duration: import_zod2.z.number().min(0),
529
+ procedureFamily: import_zod2.z.any(),
530
+ procedureCategoryId: import_zod2.z.string(),
531
+ procedureCategoryName: import_zod2.z.string(),
532
+ procedureSubCategoryId: import_zod2.z.string(),
533
+ procedureSubCategoryName: import_zod2.z.string(),
534
+ procedureTechnologyId: import_zod2.z.string(),
535
+ procedureTechnologyName: import_zod2.z.string(),
536
+ procedureProductBrandId: import_zod2.z.string(),
537
+ procedureProductBrandName: import_zod2.z.string(),
538
+ procedureProductId: import_zod2.z.string(),
539
+ procedureProductName: import_zod2.z.string()
540
+ });
541
+ var linkedFormInfoSchema = import_zod2.z.object({
542
+ formId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form ID is required"),
543
+ templateId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Template ID is required"),
544
+ templateVersion: import_zod2.z.number().int().positive("Template version must be a positive integer"),
545
+ title: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form title is required"),
546
+ isUserForm: import_zod2.z.boolean(),
547
+ status: filledDocumentStatusSchema,
548
+ path: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form path is required"),
549
+ submittedAt: import_zod2.z.any().refine(
550
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
551
+ "submittedAt must be a valid timestamp or Date object"
552
+ ).optional(),
553
+ completedAt: import_zod2.z.any().refine(
554
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
555
+ "completedAt must be a valid timestamp or Date object"
556
+ ).optional()
557
+ });
558
+ var patientReviewInfoSchema = import_zod2.z.object({
559
+ reviewId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Review ID is required"),
560
+ rating: import_zod2.z.number().min(1).max(5, "Rating must be between 1 and 5"),
561
+ comment: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
562
+ reviewedAt: import_zod2.z.any().refine(
563
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
564
+ "reviewedAt must be a valid timestamp or Date object"
565
+ )
566
+ });
567
+ var finalizedDetailsSchema = import_zod2.z.object({
568
+ by: import_zod2.z.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
569
+ at: import_zod2.z.any().refine(
570
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
571
+ "Finalized at must be a valid timestamp or Date object"
572
+ ),
573
+ notes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
574
+ });
575
+ var createAppointmentSchema = import_zod2.z.object({
576
+ clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
577
+ practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
578
+ patientId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
579
+ procedureId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
580
+ appointmentStartTime: import_zod2.z.any().refine(
581
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
582
+ "Appointment start time must be a valid timestamp or Date object"
262
583
  ),
263
- appointmentEndTime: import_zod.z.any().refine(
264
- (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
265
- "Appointment end time must be a valid timestamp"
584
+ appointmentEndTime: import_zod2.z.any().refine(
585
+ (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
586
+ "Appointment end time must be a valid timestamp or Date object"
266
587
  ),
267
- cost: import_zod.z.number().min(0, "Cost must be a non-negative number"),
268
- currency: import_zod.z.string().min(1, "Currency is required"),
269
- patientNotes: import_zod.z.string().nullable().optional(),
270
- initialStatus: import_zod.z.nativeEnum(AppointmentStatus, {
271
- errorMap: () => ({ message: "Invalid appointment status" })
272
- }),
273
- initialPaymentStatus: import_zod.z.nativeEnum(PaymentStatus, {
274
- errorMap: () => ({ message: "Invalid payment status" })
275
- }).optional().default("unpaid" /* UNPAID */)
588
+ cost: import_zod2.z.number().min(0, "Cost must be a non-negative number"),
589
+ currency: import_zod2.z.string().min(1, "Currency is required"),
590
+ patientNotes: import_zod2.z.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
591
+ initialStatus: appointmentStatusSchema,
592
+ initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
593
+ }).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
594
+ message: "Appointment end time must be after start time",
595
+ path: ["appointmentEndTime"]
276
596
  });
277
- var updateAppointmentSchema = import_zod.z.object({
278
- status: import_zod.z.nativeEnum(AppointmentStatus, {
279
- errorMap: () => ({ message: "Invalid appointment status" })
280
- }).optional(),
281
- confirmationTime: import_zod.z.any().refine(
282
- (val) => val === null || val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
283
- "Confirmation time must be a valid timestamp or null"
597
+ var updateAppointmentSchema = import_zod2.z.object({
598
+ status: appointmentStatusSchema.optional(),
599
+ confirmationTime: import_zod2.z.any().optional().nullable(),
600
+ cancellationTime: import_zod2.z.any().optional().nullable(),
601
+ rescheduleTime: import_zod2.z.any().optional().nullable(),
602
+ procedureActualStartTime: import_zod2.z.any().optional().nullable(),
603
+ actualDurationMinutes: import_zod2.z.number().int().positive("Duration must be a positive integer").optional(),
604
+ cancellationReason: import_zod2.z.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
605
+ canceledBy: import_zod2.z.enum(["patient", "clinic", "practitioner", "system"]).optional(),
606
+ internalNotes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
607
+ patientNotes: import_zod2.z.any().optional().nullable(),
608
+ paymentStatus: paymentStatusSchema.optional(),
609
+ paymentTransactionId: import_zod2.z.any().optional().nullable(),
610
+ completedPreRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
611
+ completedPostRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
612
+ linkedFormIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
613
+ pendingUserFormsIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
614
+ appointmentStartTime: import_zod2.z.any().refine(
615
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
616
+ "Appointment start time must be a valid timestamp or Date object"
284
617
  ).optional(),
285
- actualDurationMinutes: import_zod.z.number().positive("Duration must be positive").optional(),
286
- cancellationReason: import_zod.z.string().nullable().optional(),
287
- canceledBy: import_zod.z.enum(["patient", "clinic", "practitioner", "system"]).optional(),
288
- internalNotes: import_zod.z.string().nullable().optional(),
289
- paymentStatus: import_zod.z.nativeEnum(PaymentStatus, {
290
- errorMap: () => ({ message: "Invalid payment status" })
291
- }).optional(),
292
- paymentTransactionId: import_zod.z.string().nullable().optional(),
293
- completedPreRequirements: import_zod.z.array(import_zod.z.string()).optional(),
294
- completedPostRequirements: import_zod.z.array(import_zod.z.string()).optional()
618
+ appointmentEndTime: import_zod2.z.any().refine(
619
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
620
+ "Appointment end time must be a valid timestamp or Date object"
621
+ ).optional(),
622
+ calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
623
+ cost: import_zod2.z.number().min(0).optional(),
624
+ clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
625
+ practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
626
+ linkedForms: import_zod2.z.union([import_zod2.z.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), import_zod2.z.any()]).optional(),
627
+ media: import_zod2.z.union([
628
+ import_zod2.z.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
629
+ import_zod2.z.any()
630
+ ]).optional(),
631
+ reviewInfo: import_zod2.z.union([patientReviewInfoSchema.nullable(), import_zod2.z.any()]).optional(),
632
+ finalizedDetails: import_zod2.z.union([finalizedDetailsSchema.nullable(), import_zod2.z.any()]).optional(),
633
+ isArchived: import_zod2.z.boolean().optional(),
634
+ updatedAt: import_zod2.z.any().optional()
295
635
  }).refine(
296
636
  (data) => {
297
- if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */) {
637
+ if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */ || data.status === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
298
638
  return !!data.cancellationReason && !!data.canceledBy;
299
639
  }
300
640
  return true;
301
641
  },
302
642
  {
303
- message: "Cancellation reason and canceled by must be provided when canceling an appointment",
643
+ message: "Cancellation reason and canceled by must be provided when canceling an appointment with patient or clinic origin.",
304
644
  path: ["status"]
305
645
  }
646
+ ).refine(
647
+ (data) => {
648
+ if (data.appointmentStartTime && data.appointmentEndTime) {
649
+ return data.appointmentEndTime > data.appointmentStartTime;
650
+ }
651
+ return true;
652
+ },
653
+ {
654
+ message: "Appointment end time must be after start time if both are provided",
655
+ path: ["appointmentEndTime"]
656
+ }
306
657
  );
307
- var searchAppointmentsSchema = import_zod.z.object({
308
- patientId: import_zod.z.string().optional(),
309
- practitionerId: import_zod.z.string().optional(),
310
- clinicBranchId: import_zod.z.string().optional(),
311
- startDate: import_zod.z.date().optional(),
312
- endDate: import_zod.z.date().optional(),
313
- status: import_zod.z.union([
314
- import_zod.z.nativeEnum(AppointmentStatus),
315
- import_zod.z.array(import_zod.z.nativeEnum(AppointmentStatus))
658
+ var searchAppointmentsSchema = import_zod2.z.object({
659
+ patientId: import_zod2.z.string().optional(),
660
+ practitionerId: import_zod2.z.string().optional(),
661
+ clinicBranchId: import_zod2.z.string().optional(),
662
+ startDate: import_zod2.z.any().refine(
663
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
664
+ "Start date must be a valid timestamp or Date object"
665
+ ).optional(),
666
+ endDate: import_zod2.z.any().refine(
667
+ (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
668
+ "End date must be a valid timestamp or Date object"
669
+ ).optional(),
670
+ status: import_zod2.z.union([
671
+ appointmentStatusSchema,
672
+ import_zod2.z.array(appointmentStatusSchema).nonempty()
316
673
  ]).optional(),
317
- limit: import_zod.z.number().positive().optional(),
318
- startAfter: import_zod.z.any().optional()
674
+ limit: import_zod2.z.number().positive().int().optional().default(20),
675
+ startAfter: import_zod2.z.any().optional()
319
676
  }).refine(
320
677
  (data) => {
321
- return !!(data.patientId || data.practitionerId || data.clinicBranchId);
678
+ if (!data.startDate && !data.endDate && !data.status) {
679
+ return !!(data.patientId || data.practitionerId || data.clinicBranchId);
680
+ }
681
+ return true;
682
+ },
683
+ {
684
+ message: "At least one of patientId, practitionerId, or clinicBranchId must be provided if no date or status filters are set.",
685
+ path: ["patientId"]
686
+ }
687
+ ).refine(
688
+ (data) => {
689
+ if (data.startDate && data.endDate) {
690
+ return data.endDate >= data.startDate;
691
+ }
692
+ return true;
322
693
  },
323
694
  {
324
- message: "At least one of patientId, practitionerId, or clinicBranchId must be provided",
325
- path: ["searchCriteria"]
695
+ message: "End date must be after or the same as start date",
696
+ path: ["endDate"]
326
697
  }
327
698
  );
328
699
 
@@ -371,54 +742,6 @@ var getFirebaseApp = async () => {
371
742
  var import_auth5 = require("firebase/auth");
372
743
  var import_firestore22 = require("firebase/firestore");
373
744
 
374
- // src/types/documentation-templates/index.ts
375
- var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
376
- var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
377
- var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
378
- DocumentElementType2["HEADING"] = "heading";
379
- DocumentElementType2["PARAGRAPH"] = "paragraph";
380
- DocumentElementType2["LIST"] = "list";
381
- DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
382
- DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
383
- DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
384
- DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
385
- DocumentElementType2["RATING_SCALE"] = "rating_scale";
386
- DocumentElementType2["TEXT_INPUT"] = "text_input";
387
- DocumentElementType2["DATE_PICKER"] = "date_picker";
388
- DocumentElementType2["SIGNATURE"] = "signature";
389
- DocumentElementType2["FILE_UPLOAD"] = "file_upload";
390
- return DocumentElementType2;
391
- })(DocumentElementType || {});
392
- var ListType = /* @__PURE__ */ ((ListType2) => {
393
- ListType2["ORDERED"] = "ordered";
394
- ListType2["UNORDERED"] = "unordered";
395
- return ListType2;
396
- })(ListType || {});
397
- var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
398
- HeadingLevel2["H1"] = "h1";
399
- HeadingLevel2["H2"] = "h2";
400
- HeadingLevel2["H3"] = "h3";
401
- HeadingLevel2["H4"] = "h4";
402
- HeadingLevel2["H5"] = "h5";
403
- HeadingLevel2["H6"] = "h6";
404
- return HeadingLevel2;
405
- })(HeadingLevel || {});
406
- var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
407
- DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
408
- DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
409
- DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
410
- DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
411
- DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
412
- DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
413
- return DynamicVariable2;
414
- })(DynamicVariable || {});
415
- var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
416
- FilledDocumentStatus2["DRAFT"] = "draft";
417
- FilledDocumentStatus2["COMPLETED"] = "completed";
418
- FilledDocumentStatus2["SIGNED"] = "signed";
419
- return FilledDocumentStatus2;
420
- })(FilledDocumentStatus || {});
421
-
422
745
  // src/types/calendar/index.ts
423
746
  var CalendarEventStatus = /* @__PURE__ */ ((CalendarEventStatus4) => {
424
747
  CalendarEventStatus4["PENDING"] = "pending";
@@ -465,136 +788,6 @@ var import_zod19 = require("zod");
465
788
 
466
789
  // src/validations/schemas.ts
467
790
  var import_zod3 = require("zod");
468
-
469
- // src/validations/documentation-templates/template.schema.ts
470
- var import_zod2 = require("zod");
471
- var baseElementSchema = import_zod2.z.object({
472
- id: import_zod2.z.string().optional(),
473
- // Make id optional so we can omit it later
474
- type: import_zod2.z.nativeEnum(DocumentElementType),
475
- required: import_zod2.z.boolean().optional()
476
- });
477
- var headingElementSchema = baseElementSchema.extend({
478
- type: import_zod2.z.literal("heading" /* HEADING */),
479
- text: import_zod2.z.string().min(1).max(200),
480
- level: import_zod2.z.nativeEnum(HeadingLevel)
481
- });
482
- var paragraphElementSchema = baseElementSchema.extend({
483
- type: import_zod2.z.literal("paragraph" /* PARAGRAPH */),
484
- text: import_zod2.z.string().min(1).max(5e3)
485
- });
486
- var listElementSchema = baseElementSchema.extend({
487
- type: import_zod2.z.literal("list" /* LIST */),
488
- items: import_zod2.z.array(import_zod2.z.string().min(1).max(500)).min(1).max(100),
489
- listType: import_zod2.z.nativeEnum(ListType)
490
- });
491
- var dynamicTextElementSchema = baseElementSchema.extend({
492
- type: import_zod2.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
493
- text: import_zod2.z.string().min(1).max(5e3)
494
- });
495
- var binaryChoiceElementSchema = baseElementSchema.extend({
496
- type: import_zod2.z.literal("binary_choice" /* BINARY_CHOICE */),
497
- question: import_zod2.z.string().min(1).max(500),
498
- defaultValue: import_zod2.z.boolean().optional()
499
- });
500
- var multipleChoiceElementSchema = baseElementSchema.extend({
501
- type: import_zod2.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
502
- question: import_zod2.z.string().min(1).max(500),
503
- options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
504
- defaultValues: import_zod2.z.array(import_zod2.z.string()).optional()
505
- });
506
- var singleChoiceElementSchema = baseElementSchema.extend({
507
- type: import_zod2.z.literal("single_choice" /* SINGLE_CHOICE */),
508
- question: import_zod2.z.string().min(1).max(500),
509
- options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
510
- defaultValue: import_zod2.z.string().optional()
511
- });
512
- var ratingScaleElementSchema = baseElementSchema.extend({
513
- type: import_zod2.z.literal("rating_scale" /* RATING_SCALE */),
514
- question: import_zod2.z.string().min(1).max(500),
515
- min: import_zod2.z.number().int().min(0).max(10),
516
- max: import_zod2.z.number().int().min(1).max(10),
517
- labels: import_zod2.z.record(import_zod2.z.string()).optional(),
518
- defaultValue: import_zod2.z.number().int().optional()
519
- });
520
- var textInputElementSchema = baseElementSchema.extend({
521
- type: import_zod2.z.literal("text_input" /* TEXT_INPUT */),
522
- label: import_zod2.z.string().min(1).max(200),
523
- placeholder: import_zod2.z.string().max(200).optional(),
524
- multiline: import_zod2.z.boolean().optional(),
525
- defaultValue: import_zod2.z.string().optional()
526
- });
527
- var datePickerElementSchema = baseElementSchema.extend({
528
- type: import_zod2.z.literal("date_picker" /* DATE_PICKER */),
529
- label: import_zod2.z.string().min(1).max(200),
530
- defaultValue: import_zod2.z.string().optional()
531
- // ISO date string
532
- });
533
- var signatureElementSchema = baseElementSchema.extend({
534
- type: import_zod2.z.literal("signature" /* SIGNATURE */),
535
- label: import_zod2.z.string().min(1).max(200)
536
- });
537
- var fileUploadElementSchema = baseElementSchema.extend({
538
- type: import_zod2.z.literal("file_upload" /* FILE_UPLOAD */),
539
- label: import_zod2.z.string().min(1).max(200),
540
- allowedFileTypes: import_zod2.z.array(import_zod2.z.string()).optional(),
541
- maxFileSizeMB: import_zod2.z.number().positive().optional()
542
- });
543
- var documentElementSchema = import_zod2.z.discriminatedUnion("type", [
544
- headingElementSchema,
545
- paragraphElementSchema,
546
- listElementSchema,
547
- dynamicTextElementSchema,
548
- binaryChoiceElementSchema,
549
- multipleChoiceElementSchema,
550
- singleChoiceElementSchema,
551
- ratingScaleElementSchema,
552
- textInputElementSchema,
553
- datePickerElementSchema,
554
- signatureElementSchema,
555
- fileUploadElementSchema
556
- ]);
557
- var documentElementWithoutIdSchema = import_zod2.z.discriminatedUnion("type", [
558
- headingElementSchema.omit({ id: true }),
559
- paragraphElementSchema.omit({ id: true }),
560
- listElementSchema.omit({ id: true }),
561
- dynamicTextElementSchema.omit({ id: true }),
562
- binaryChoiceElementSchema.omit({ id: true }),
563
- multipleChoiceElementSchema.omit({ id: true }),
564
- singleChoiceElementSchema.omit({ id: true }),
565
- ratingScaleElementSchema.omit({ id: true }),
566
- textInputElementSchema.omit({ id: true }),
567
- datePickerElementSchema.omit({ id: true }),
568
- signatureElementSchema.omit({ id: true }),
569
- fileUploadElementSchema.omit({ id: true })
570
- ]);
571
- var createDocumentTemplateSchema = import_zod2.z.object({
572
- title: import_zod2.z.string().min(1).max(200),
573
- description: import_zod2.z.string().max(1e3).optional(),
574
- elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100),
575
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional()
576
- });
577
- var updateDocumentTemplateSchema = import_zod2.z.object({
578
- title: import_zod2.z.string().min(1).max(200).optional(),
579
- description: import_zod2.z.string().max(1e3).optional(),
580
- elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
581
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
582
- isActive: import_zod2.z.boolean().optional()
583
- });
584
- var documentTemplateSchema = import_zod2.z.object({
585
- id: import_zod2.z.string(),
586
- title: import_zod2.z.string().min(1).max(200),
587
- description: import_zod2.z.string().max(1e3).optional(),
588
- createdAt: import_zod2.z.number(),
589
- updatedAt: import_zod2.z.number(),
590
- createdBy: import_zod2.z.string(),
591
- elements: import_zod2.z.array(documentElementSchema),
592
- tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
593
- version: import_zod2.z.number().int().positive(),
594
- isActive: import_zod2.z.boolean()
595
- });
596
-
597
- // src/validations/schemas.ts
598
791
  var emailSchema = import_zod3.z.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
599
792
  var passwordSchema = import_zod3.z.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
600
793
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\w\W]{8,}$/,
@@ -1607,9 +1800,9 @@ var addAllergyUtil = async (db, patientId, data, userRef) => {
1607
1800
  var updateAllergyUtil = async (db, patientId, data, userRef) => {
1608
1801
  const validatedData = updateAllergySchema.parse(data);
1609
1802
  const { allergyIndex, ...updateData } = validatedData;
1610
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1611
- if (!doc32.exists()) throw new Error("Medical info not found");
1612
- const medicalInfo = doc32.data();
1803
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1804
+ if (!doc33.exists()) throw new Error("Medical info not found");
1805
+ const medicalInfo = doc33.data();
1613
1806
  if (allergyIndex >= medicalInfo.allergies.length) {
1614
1807
  throw new Error("Invalid allergy index");
1615
1808
  }
@@ -1625,9 +1818,9 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
1625
1818
  });
1626
1819
  };
1627
1820
  var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1628
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1629
- if (!doc32.exists()) throw new Error("Medical info not found");
1630
- const medicalInfo = doc32.data();
1821
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1822
+ if (!doc33.exists()) throw new Error("Medical info not found");
1823
+ const medicalInfo = doc33.data();
1631
1824
  if (allergyIndex >= medicalInfo.allergies.length) {
1632
1825
  throw new Error("Invalid allergy index");
1633
1826
  }
@@ -1652,9 +1845,9 @@ var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
1652
1845
  var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1653
1846
  const validatedData = updateBlockingConditionSchema.parse(data);
1654
1847
  const { conditionIndex, ...updateData } = validatedData;
1655
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1656
- if (!doc32.exists()) throw new Error("Medical info not found");
1657
- const medicalInfo = doc32.data();
1848
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1849
+ if (!doc33.exists()) throw new Error("Medical info not found");
1850
+ const medicalInfo = doc33.data();
1658
1851
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1659
1852
  throw new Error("Invalid blocking condition index");
1660
1853
  }
@@ -1670,9 +1863,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1670
1863
  });
1671
1864
  };
1672
1865
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
1673
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1674
- if (!doc32.exists()) throw new Error("Medical info not found");
1675
- const medicalInfo = doc32.data();
1866
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1867
+ if (!doc33.exists()) throw new Error("Medical info not found");
1868
+ const medicalInfo = doc33.data();
1676
1869
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1677
1870
  throw new Error("Invalid blocking condition index");
1678
1871
  }
@@ -1697,9 +1890,9 @@ var addContraindicationUtil = async (db, patientId, data, userRef) => {
1697
1890
  var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1698
1891
  const validatedData = updateContraindicationSchema.parse(data);
1699
1892
  const { contraindicationIndex, ...updateData } = validatedData;
1700
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1701
- if (!doc32.exists()) throw new Error("Medical info not found");
1702
- const medicalInfo = doc32.data();
1893
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1894
+ if (!doc33.exists()) throw new Error("Medical info not found");
1895
+ const medicalInfo = doc33.data();
1703
1896
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1704
1897
  throw new Error("Invalid contraindication index");
1705
1898
  }
@@ -1715,9 +1908,9 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1715
1908
  });
1716
1909
  };
1717
1910
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
1718
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1719
- if (!doc32.exists()) throw new Error("Medical info not found");
1720
- const medicalInfo = doc32.data();
1911
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1912
+ if (!doc33.exists()) throw new Error("Medical info not found");
1913
+ const medicalInfo = doc33.data();
1721
1914
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1722
1915
  throw new Error("Invalid contraindication index");
1723
1916
  }
@@ -1742,9 +1935,9 @@ var addMedicationUtil = async (db, patientId, data, userRef) => {
1742
1935
  var updateMedicationUtil = async (db, patientId, data, userRef) => {
1743
1936
  const validatedData = updateMedicationSchema.parse(data);
1744
1937
  const { medicationIndex, ...updateData } = validatedData;
1745
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1746
- if (!doc32.exists()) throw new Error("Medical info not found");
1747
- const medicalInfo = doc32.data();
1938
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1939
+ if (!doc33.exists()) throw new Error("Medical info not found");
1940
+ const medicalInfo = doc33.data();
1748
1941
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1749
1942
  throw new Error("Invalid medication index");
1750
1943
  }
@@ -1760,9 +1953,9 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
1760
1953
  });
1761
1954
  };
1762
1955
  var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
1763
- const doc32 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1764
- if (!doc32.exists()) throw new Error("Medical info not found");
1765
- const medicalInfo = doc32.data();
1956
+ const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
1957
+ if (!doc33.exists()) throw new Error("Medical info not found");
1958
+ const medicalInfo = doc33.data();
1766
1959
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1767
1960
  throw new Error("Invalid medication index");
1768
1961
  }
@@ -2040,7 +2233,7 @@ var searchPatientsUtil = async (db, params, requester) => {
2040
2233
  try {
2041
2234
  const finalQuery = (0, import_firestore6.query)(patientsCollectionRef, ...constraints);
2042
2235
  const querySnapshot = await (0, import_firestore6.getDocs)(finalQuery);
2043
- const patients = querySnapshot.docs.map((doc32) => doc32.data());
2236
+ const patients = querySnapshot.docs.map((doc33) => doc33.data());
2044
2237
  console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
2045
2238
  return patients;
2046
2239
  } catch (error) {
@@ -2064,8 +2257,8 @@ var getAllPatientsUtil = async (db, options) => {
2064
2257
  }
2065
2258
  const patientsSnapshot = await (0, import_firestore6.getDocs)(q);
2066
2259
  const patients = [];
2067
- patientsSnapshot.forEach((doc32) => {
2068
- patients.push(doc32.data());
2260
+ patientsSnapshot.forEach((doc33) => {
2261
+ patients.push(doc33.data());
2069
2262
  });
2070
2263
  console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
2071
2264
  return patients;
@@ -2277,8 +2470,8 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
2277
2470
  }
2278
2471
  const patientsSnapshot = await (0, import_firestore9.getDocs)(q);
2279
2472
  const patients = [];
2280
- patientsSnapshot.forEach((doc32) => {
2281
- patients.push(doc32.data());
2473
+ patientsSnapshot.forEach((doc33) => {
2474
+ patients.push(doc33.data());
2282
2475
  });
2283
2476
  console.log(
2284
2477
  `[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
@@ -2366,8 +2559,8 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2366
2559
  }
2367
2560
  const patientsSnapshot = await (0, import_firestore10.getDocs)(q);
2368
2561
  const patients = [];
2369
- patientsSnapshot.forEach((doc32) => {
2370
- patients.push(doc32.data());
2562
+ patientsSnapshot.forEach((doc33) => {
2563
+ patients.push(doc33.data());
2371
2564
  });
2372
2565
  console.log(
2373
2566
  `[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
@@ -3480,7 +3673,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
3480
3673
  (0, import_firestore13.where)("clinicGroupId", "==", clinicGroupId)
3481
3674
  );
3482
3675
  const querySnapshot = await (0, import_firestore13.getDocs)(q);
3483
- return querySnapshot.docs.map((doc32) => doc32.data());
3676
+ return querySnapshot.docs.map((doc33) => doc33.data());
3484
3677
  }
3485
3678
  async function updateClinicAdmin(db, adminId, data) {
3486
3679
  const admin = await getClinicAdmin(db, adminId);
@@ -3741,6 +3934,8 @@ var ClinicAdminService = class extends BaseService {
3741
3934
  this.getClinicService()
3742
3935
  );
3743
3936
  }
3937
+ // TODO: Add more methods for clinic admins for managing permissions, editing profiles by the admin, or by the clinic group owner and so on
3938
+ // Generally refactor admin permissions and clinic group permissions and systems for admin management
3744
3939
  };
3745
3940
 
3746
3941
  // src/services/practitioner/practitioner.service.ts
@@ -4177,7 +4372,7 @@ var PractitionerService = class extends BaseService {
4177
4372
  (0, import_firestore15.where)("expiresAt", ">", import_firestore15.Timestamp.now())
4178
4373
  );
4179
4374
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4180
- return querySnapshot.docs.map((doc32) => doc32.data());
4375
+ return querySnapshot.docs.map((doc33) => doc33.data());
4181
4376
  }
4182
4377
  /**
4183
4378
  * Gets a token by its string value and validates it
@@ -4260,7 +4455,7 @@ var PractitionerService = class extends BaseService {
4260
4455
  (0, import_firestore15.where)("status", "==", "active" /* ACTIVE */)
4261
4456
  );
4262
4457
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4263
- return querySnapshot.docs.map((doc32) => doc32.data());
4458
+ return querySnapshot.docs.map((doc33) => doc33.data());
4264
4459
  }
4265
4460
  /**
4266
4461
  * Dohvata sve zdravstvene radnike za određenu kliniku
@@ -4272,7 +4467,7 @@ var PractitionerService = class extends BaseService {
4272
4467
  (0, import_firestore15.where)("isActive", "==", true)
4273
4468
  );
4274
4469
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4275
- return querySnapshot.docs.map((doc32) => doc32.data());
4470
+ return querySnapshot.docs.map((doc33) => doc33.data());
4276
4471
  }
4277
4472
  /**
4278
4473
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
@@ -4284,7 +4479,7 @@ var PractitionerService = class extends BaseService {
4284
4479
  (0, import_firestore15.where)("status", "==", "draft" /* DRAFT */)
4285
4480
  );
4286
4481
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4287
- return querySnapshot.docs.map((doc32) => doc32.data());
4482
+ return querySnapshot.docs.map((doc33) => doc33.data());
4288
4483
  }
4289
4484
  /**
4290
4485
  * Updates a practitioner
@@ -4466,7 +4661,7 @@ var PractitionerService = class extends BaseService {
4466
4661
  );
4467
4662
  const querySnapshot = await (0, import_firestore15.getDocs)(q);
4468
4663
  const practitioners = querySnapshot.docs.map(
4469
- (doc32) => doc32.data()
4664
+ (doc33) => doc33.data()
4470
4665
  );
4471
4666
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
4472
4667
  return {
@@ -4537,8 +4732,8 @@ var PractitionerService = class extends BaseService {
4537
4732
  console.log(
4538
4733
  `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
4539
4734
  );
4540
- let practitioners = querySnapshot.docs.map((doc32) => {
4541
- return { ...doc32.data(), id: doc32.id };
4735
+ let practitioners = querySnapshot.docs.map((doc33) => {
4736
+ return { ...doc33.data(), id: doc33.id };
4542
4737
  });
4543
4738
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
4544
4739
  if (filters.nameSearch && filters.nameSearch.trim() !== "") {
@@ -4792,7 +4987,7 @@ var UserService = class extends BaseService {
4792
4987
  ];
4793
4988
  const q = (0, import_firestore16.query)((0, import_firestore16.collection)(this.db, USERS_COLLECTION), ...constraints);
4794
4989
  const querySnapshot = await (0, import_firestore16.getDocs)(q);
4795
- const users = querySnapshot.docs.map((doc32) => doc32.data());
4990
+ const users = querySnapshot.docs.map((doc33) => doc33.data());
4796
4991
  return Promise.all(users.map((userData) => userSchema.parse(userData)));
4797
4992
  }
4798
4993
  /**
@@ -5156,7 +5351,7 @@ async function getAllActiveGroups(db) {
5156
5351
  (0, import_firestore17.where)("isActive", "==", true)
5157
5352
  );
5158
5353
  const querySnapshot = await (0, import_firestore17.getDocs)(q);
5159
- return querySnapshot.docs.map((doc32) => doc32.data());
5354
+ return querySnapshot.docs.map((doc33) => doc33.data());
5160
5355
  }
5161
5356
  async function updateClinicGroup(db, groupId, data, app) {
5162
5357
  console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
@@ -5528,6 +5723,11 @@ var ClinicGroupService = class extends BaseService {
5528
5723
  this.app
5529
5724
  );
5530
5725
  }
5726
+ // TODO: Add a method to get all admin tokens for a clinic group (not just active ones)
5727
+ // TODO: Refactor admin token methods not to add tokens to the clinicGroup document,
5728
+ // but to add them to a subcollection called adminTokens that belongs to a specific clinicGroup document
5729
+ // TODO: Add granular control over admin permissions, e.g. only allow admins to manage certain clinics to tokens directly
5730
+ // TODO: Generally refactor admin tokens and invites, also create cloud function to send invites and send updates when sombody uses the token
5531
5731
  };
5532
5732
 
5533
5733
  // src/services/clinic/clinic.service.ts
@@ -5554,7 +5754,7 @@ async function getClinicsByGroup(db, groupId) {
5554
5754
  (0, import_firestore18.where)("isActive", "==", true)
5555
5755
  );
5556
5756
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5557
- return querySnapshot.docs.map((doc32) => doc32.data());
5757
+ return querySnapshot.docs.map((doc33) => doc33.data());
5558
5758
  }
5559
5759
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
5560
5760
  console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
@@ -5748,7 +5948,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
5748
5948
  }
5749
5949
  const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
5750
5950
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5751
- return querySnapshot.docs.map((doc32) => doc32.data());
5951
+ return querySnapshot.docs.map((doc33) => doc33.data());
5752
5952
  }
5753
5953
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
5754
5954
  return getClinicsByAdmin(
@@ -5793,11 +5993,11 @@ async function getAllClinics(db, pagination, lastDoc) {
5793
5993
  }
5794
5994
  const clinicsSnapshot = await (0, import_firestore18.getDocs)(clinicsQuery);
5795
5995
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
5796
- const clinics = clinicsSnapshot.docs.map((doc32) => {
5797
- const data = doc32.data();
5996
+ const clinics = clinicsSnapshot.docs.map((doc33) => {
5997
+ const data = doc33.data();
5798
5998
  return {
5799
5999
  ...data,
5800
- id: doc32.id
6000
+ id: doc33.id
5801
6001
  };
5802
6002
  });
5803
6003
  return {
@@ -5824,8 +6024,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
5824
6024
  ];
5825
6025
  const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
5826
6026
  const querySnapshot = await (0, import_firestore18.getDocs)(q);
5827
- for (const doc32 of querySnapshot.docs) {
5828
- const clinic = doc32.data();
6027
+ for (const doc33 of querySnapshot.docs) {
6028
+ const clinic = doc33.data();
5829
6029
  const distance = (0, import_geofire_common4.distanceBetween)(
5830
6030
  [center.latitude, center.longitude],
5831
6031
  [clinic.location.latitude, clinic.location.longitude]
@@ -5942,8 +6142,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
5942
6142
  }
5943
6143
  const q = (0, import_firestore19.query)((0, import_firestore19.collection)(db, CLINICS_COLLECTION), ...constraints);
5944
6144
  const querySnapshot = await (0, import_firestore19.getDocs)(q);
5945
- for (const doc32 of querySnapshot.docs) {
5946
- const clinic = doc32.data();
6145
+ for (const doc33 of querySnapshot.docs) {
6146
+ const clinic = doc33.data();
5947
6147
  const distance = (0, import_geofire_common5.distanceBetween)(
5948
6148
  [center.latitude, center.longitude],
5949
6149
  [clinic.location.latitude, clinic.location.longitude]
@@ -6031,8 +6231,8 @@ async function getClinicsByFilters(db, filters) {
6031
6231
  console.log(
6032
6232
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
6033
6233
  );
6034
- for (const doc32 of querySnapshot.docs) {
6035
- const clinic = { ...doc32.data(), id: doc32.id };
6234
+ for (const doc33 of querySnapshot.docs) {
6235
+ const clinic = { ...doc33.data(), id: doc33.id };
6036
6236
  const distance = (0, import_geofire_common6.distanceBetween)(
6037
6237
  [center.latitude, center.longitude],
6038
6238
  [clinic.location.latitude, clinic.location.longitude]
@@ -6088,8 +6288,8 @@ async function getClinicsByFilters(db, filters) {
6088
6288
  console.log(
6089
6289
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
6090
6290
  );
6091
- const clinics = querySnapshot.docs.map((doc32) => {
6092
- return { ...doc32.data(), id: doc32.id };
6291
+ const clinics = querySnapshot.docs.map((doc33) => {
6292
+ return { ...doc33.data(), id: doc33.id };
6093
6293
  });
6094
6294
  let filteredClinics = clinics;
6095
6295
  if (filters.center) {
@@ -7301,17 +7501,28 @@ var import_firestore23 = require("firebase/firestore");
7301
7501
 
7302
7502
  // src/types/notifications/index.ts
7303
7503
  var NotificationType = /* @__PURE__ */ ((NotificationType3) => {
7304
- NotificationType3["PRE_REQUIREMENT"] = "preRequirement";
7305
- NotificationType3["POST_REQUIREMENT"] = "postRequirement";
7306
7504
  NotificationType3["APPOINTMENT_REMINDER"] = "appointmentReminder";
7307
- NotificationType3["APPOINTMENT_NOTIFICATION"] = "appointmentNotification";
7505
+ NotificationType3["APPOINTMENT_STATUS_CHANGE"] = "appointmentStatusChange";
7506
+ NotificationType3["APPOINTMENT_RESCHEDULED_PROPOSAL"] = "appointmentRescheduledProposal";
7507
+ NotificationType3["APPOINTMENT_CANCELLED"] = "appointmentCancelled";
7508
+ NotificationType3["REQUIREMENT_INSTRUCTION_DUE"] = "requirementInstructionDue";
7509
+ NotificationType3["FORM_REMINDER"] = "formReminder";
7510
+ NotificationType3["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
7511
+ NotificationType3["REVIEW_REQUEST"] = "reviewRequest";
7512
+ NotificationType3["PAYMENT_DUE"] = "paymentDue";
7513
+ NotificationType3["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
7514
+ NotificationType3["PAYMENT_FAILED"] = "paymentFailed";
7515
+ NotificationType3["GENERAL_MESSAGE"] = "generalMessage";
7516
+ NotificationType3["ACCOUNT_NOTIFICATION"] = "accountNotification";
7308
7517
  return NotificationType3;
7309
7518
  })(NotificationType || {});
7310
7519
  var NOTIFICATIONS_COLLECTION = "notifications";
7311
7520
  var NotificationStatus = /* @__PURE__ */ ((NotificationStatus2) => {
7312
7521
  NotificationStatus2["PENDING"] = "pending";
7522
+ NotificationStatus2["PROCESSING"] = "processing";
7313
7523
  NotificationStatus2["SENT"] = "sent";
7314
7524
  NotificationStatus2["FAILED"] = "failed";
7525
+ NotificationStatus2["DELIVERED"] = "delivered";
7315
7526
  NotificationStatus2["CANCELLED"] = "cancelled";
7316
7527
  NotificationStatus2["PARTIAL_SUCCESS"] = "partialSuccess";
7317
7528
  return NotificationStatus2;
@@ -7367,9 +7578,9 @@ var NotificationService = class extends BaseService {
7367
7578
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7368
7579
  );
7369
7580
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7370
- return querySnapshot.docs.map((doc32) => ({
7371
- id: doc32.id,
7372
- ...doc32.data()
7581
+ return querySnapshot.docs.map((doc33) => ({
7582
+ id: doc33.id,
7583
+ ...doc33.data()
7373
7584
  }));
7374
7585
  }
7375
7586
  /**
@@ -7383,9 +7594,9 @@ var NotificationService = class extends BaseService {
7383
7594
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7384
7595
  );
7385
7596
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7386
- return querySnapshot.docs.map((doc32) => ({
7387
- id: doc32.id,
7388
- ...doc32.data()
7597
+ return querySnapshot.docs.map((doc33) => ({
7598
+ id: doc33.id,
7599
+ ...doc33.data()
7389
7600
  }));
7390
7601
  }
7391
7602
  /**
@@ -7457,9 +7668,9 @@ var NotificationService = class extends BaseService {
7457
7668
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7458
7669
  );
7459
7670
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7460
- return querySnapshot.docs.map((doc32) => ({
7461
- id: doc32.id,
7462
- ...doc32.data()
7671
+ return querySnapshot.docs.map((doc33) => ({
7672
+ id: doc33.id,
7673
+ ...doc33.data()
7463
7674
  }));
7464
7675
  }
7465
7676
  /**
@@ -7472,9 +7683,9 @@ var NotificationService = class extends BaseService {
7472
7683
  (0, import_firestore23.orderBy)("notificationTime", "desc")
7473
7684
  );
7474
7685
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7475
- return querySnapshot.docs.map((doc32) => ({
7476
- id: doc32.id,
7477
- ...doc32.data()
7686
+ return querySnapshot.docs.map((doc33) => ({
7687
+ id: doc33.id,
7688
+ ...doc33.data()
7478
7689
  }));
7479
7690
  }
7480
7691
  };
@@ -7501,7 +7712,8 @@ var createProcedureSchema = import_zod20.z.object({
7501
7712
  duration: import_zod20.z.number().min(1).max(480),
7502
7713
  // Max 8 hours
7503
7714
  practitionerId: import_zod20.z.string().min(1),
7504
- clinicBranchId: import_zod20.z.string().min(1)
7715
+ clinicBranchId: import_zod20.z.string().min(1),
7716
+ photos: import_zod20.z.array(import_zod20.z.string()).optional()
7505
7717
  });
7506
7718
  var updateProcedureSchema = import_zod20.z.object({
7507
7719
  name: import_zod20.z.string().min(3).max(100).optional(),
@@ -7516,7 +7728,8 @@ var updateProcedureSchema = import_zod20.z.object({
7516
7728
  subcategoryId: import_zod20.z.string().optional(),
7517
7729
  technologyId: import_zod20.z.string().optional(),
7518
7730
  productId: import_zod20.z.string().optional(),
7519
- clinicBranchId: import_zod20.z.string().optional()
7731
+ clinicBranchId: import_zod20.z.string().optional(),
7732
+ photos: import_zod20.z.array(import_zod20.z.string()).optional()
7520
7733
  });
7521
7734
  var procedureSchema = createProcedureSchema.extend({
7522
7735
  id: import_zod20.z.string().min(1),
@@ -7530,6 +7743,8 @@ var procedureSchema = createProcedureSchema.extend({
7530
7743
  // We'll validate the full product object separately
7531
7744
  blockingConditions: import_zod20.z.array(import_zod20.z.any()),
7532
7745
  // We'll validate blocking conditions separately
7746
+ contraindications: import_zod20.z.array(import_zod20.z.any()),
7747
+ // We'll validate contraindications separately
7533
7748
  treatmentBenefits: import_zod20.z.array(import_zod20.z.any()),
7534
7749
  // We'll validate treatment benefits separately
7535
7750
  preRequirements: import_zod20.z.array(import_zod20.z.any()),
@@ -7634,6 +7849,7 @@ var ProcedureService = class extends BaseService {
7634
7849
  technology,
7635
7850
  product,
7636
7851
  blockingConditions: technology.blockingConditions,
7852
+ contraindications: technology.contraindications || [],
7637
7853
  treatmentBenefits: technology.benefits,
7638
7854
  preRequirements: technology.requirements.pre,
7639
7855
  postRequirements: technology.requirements.post,
@@ -7691,7 +7907,7 @@ var ProcedureService = class extends BaseService {
7691
7907
  (0, import_firestore24.where)("isActive", "==", true)
7692
7908
  );
7693
7909
  const snapshot = await (0, import_firestore24.getDocs)(q);
7694
- return snapshot.docs.map((doc32) => doc32.data());
7910
+ return snapshot.docs.map((doc33) => doc33.data());
7695
7911
  }
7696
7912
  /**
7697
7913
  * Gets all procedures for a practitioner
@@ -7705,7 +7921,7 @@ var ProcedureService = class extends BaseService {
7705
7921
  (0, import_firestore24.where)("isActive", "==", true)
7706
7922
  );
7707
7923
  const snapshot = await (0, import_firestore24.getDocs)(q);
7708
- return snapshot.docs.map((doc32) => doc32.data());
7924
+ return snapshot.docs.map((doc33) => doc33.data());
7709
7925
  }
7710
7926
  /**
7711
7927
  * Updates a procedure
@@ -7888,20 +8104,20 @@ var ProcedureService = class extends BaseService {
7888
8104
  const proceduresCollection = (0, import_firestore24.collection)(this.db, PROCEDURES_COLLECTION);
7889
8105
  let proceduresQuery = (0, import_firestore24.query)(proceduresCollection);
7890
8106
  if (pagination && pagination > 0) {
7891
- const { limit: limit11, startAfter: startAfter11 } = await import("firebase/firestore");
8107
+ const { limit: limit12, startAfter: startAfter12 } = await import("firebase/firestore");
7892
8108
  if (lastDoc) {
7893
8109
  proceduresQuery = (0, import_firestore24.query)(
7894
8110
  proceduresCollection,
7895
8111
  (0, import_firestore24.orderBy)("name"),
7896
8112
  // Use imported orderBy
7897
- startAfter11(lastDoc),
7898
- limit11(pagination)
8113
+ startAfter12(lastDoc),
8114
+ limit12(pagination)
7899
8115
  );
7900
8116
  } else {
7901
8117
  proceduresQuery = (0, import_firestore24.query)(
7902
8118
  proceduresCollection,
7903
8119
  (0, import_firestore24.orderBy)("name"),
7904
- limit11(pagination)
8120
+ limit12(pagination)
7905
8121
  );
7906
8122
  }
7907
8123
  } else {
@@ -7909,11 +8125,11 @@ var ProcedureService = class extends BaseService {
7909
8125
  }
7910
8126
  const proceduresSnapshot = await (0, import_firestore24.getDocs)(proceduresQuery);
7911
8127
  const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
7912
- const procedures = proceduresSnapshot.docs.map((doc32) => {
7913
- const data = doc32.data();
8128
+ const procedures = proceduresSnapshot.docs.map((doc33) => {
8129
+ const data = doc33.data();
7914
8130
  return {
7915
8131
  ...data,
7916
- id: doc32.id
8132
+ id: doc33.id
7917
8133
  // Ensure ID is present
7918
8134
  };
7919
8135
  });
@@ -7995,8 +8211,8 @@ var ProcedureService = class extends BaseService {
7995
8211
  console.log(
7996
8212
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
7997
8213
  );
7998
- for (const doc32 of querySnapshot.docs) {
7999
- const procedure = { ...doc32.data(), id: doc32.id };
8214
+ for (const doc33 of querySnapshot.docs) {
8215
+ const procedure = { ...doc33.data(), id: doc33.id };
8000
8216
  const distance = (0, import_geofire_common8.distanceBetween)(
8001
8217
  [center.latitude, center.longitude],
8002
8218
  [
@@ -8047,8 +8263,8 @@ var ProcedureService = class extends BaseService {
8047
8263
  console.log(
8048
8264
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
8049
8265
  );
8050
- const procedures = querySnapshot.docs.map((doc32) => {
8051
- return { ...doc32.data(), id: doc32.id };
8266
+ const procedures = querySnapshot.docs.map((doc33) => {
8267
+ return { ...doc33.data(), id: doc33.id };
8052
8268
  });
8053
8269
  if (filters.location) {
8054
8270
  const center = filters.location;
@@ -8188,7 +8404,10 @@ var DocumentationTemplateService = class extends BaseService {
8188
8404
  createdBy: userId,
8189
8405
  version: 1,
8190
8406
  isActive: true,
8191
- tags: validatedData.tags || []
8407
+ tags: validatedData.tags || [],
8408
+ isUserForm: validatedData.isUserForm || false,
8409
+ isRequired: validatedData.isRequired || false,
8410
+ sortingOrder: validatedData.sortingOrder || 0
8192
8411
  };
8193
8412
  const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
8194
8413
  await (0, import_firestore25.setDoc)(docRef, template);
@@ -8223,21 +8442,31 @@ var DocumentationTemplateService = class extends BaseService {
8223
8442
  if (validatedData.elements) {
8224
8443
  updatedElements = validatedData.elements.map((element) => ({
8225
8444
  ...element,
8226
- id: this.generateId()
8445
+ id: element.id || this.generateId()
8227
8446
  }));
8228
8447
  }
8229
- const updateData = {
8230
- ...validatedData,
8448
+ const updatePayload = {
8231
8449
  elements: updatedElements,
8232
8450
  updatedAt: Date.now(),
8233
8451
  version: template.version + 1
8234
8452
  };
8453
+ if (validatedData.title !== void 0)
8454
+ updatePayload.title = validatedData.title;
8455
+ if (validatedData.description !== void 0)
8456
+ updatePayload.description = validatedData.description;
8457
+ if (validatedData.isActive !== void 0)
8458
+ updatePayload.isActive = validatedData.isActive;
8459
+ if (validatedData.tags !== void 0)
8460
+ updatePayload.tags = validatedData.tags;
8461
+ if (validatedData.isUserForm !== void 0)
8462
+ updatePayload.isUserForm = validatedData.isUserForm;
8463
+ if (validatedData.isRequired !== void 0)
8464
+ updatePayload.isRequired = validatedData.isRequired;
8465
+ if (validatedData.sortingOrder !== void 0)
8466
+ updatePayload.sortingOrder = validatedData.sortingOrder;
8235
8467
  const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
8236
- await (0, import_firestore25.updateDoc)(docRef, updateData);
8237
- return {
8238
- ...template,
8239
- ...updateData
8240
- };
8468
+ await (0, import_firestore25.updateDoc)(docRef, updatePayload);
8469
+ return { ...template, ...updatePayload };
8241
8470
  }
8242
8471
  /**
8243
8472
  * Delete a document template
@@ -8266,9 +8495,9 @@ var DocumentationTemplateService = class extends BaseService {
8266
8495
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8267
8496
  const templates = [];
8268
8497
  let lastVisible = null;
8269
- querySnapshot.forEach((doc32) => {
8270
- templates.push(doc32.data());
8271
- lastVisible = doc32;
8498
+ querySnapshot.forEach((doc33) => {
8499
+ templates.push(doc33.data());
8500
+ lastVisible = doc33;
8272
8501
  });
8273
8502
  return {
8274
8503
  templates,
@@ -8296,9 +8525,9 @@ var DocumentationTemplateService = class extends BaseService {
8296
8525
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8297
8526
  const templates = [];
8298
8527
  let lastVisible = null;
8299
- querySnapshot.forEach((doc32) => {
8300
- templates.push(doc32.data());
8301
- lastVisible = doc32;
8528
+ querySnapshot.forEach((doc33) => {
8529
+ templates.push(doc33.data());
8530
+ lastVisible = doc33;
8302
8531
  });
8303
8532
  return {
8304
8533
  templates,
@@ -8325,9 +8554,9 @@ var DocumentationTemplateService = class extends BaseService {
8325
8554
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8326
8555
  const templates = [];
8327
8556
  let lastVisible = null;
8328
- querySnapshot.forEach((doc32) => {
8329
- templates.push(doc32.data());
8330
- lastVisible = doc32;
8557
+ querySnapshot.forEach((doc33) => {
8558
+ templates.push(doc33.data());
8559
+ lastVisible = doc33;
8331
8560
  });
8332
8561
  return {
8333
8562
  templates,
@@ -8341,50 +8570,80 @@ var import_firestore26 = require("firebase/firestore");
8341
8570
  var FilledDocumentService = class extends BaseService {
8342
8571
  constructor(...args) {
8343
8572
  super(...args);
8344
- this.collectionRef = (0, import_firestore26.collection)(
8345
- this.db,
8346
- FILLED_DOCUMENTS_COLLECTION
8347
- );
8348
8573
  this.templateService = new DocumentationTemplateService(...args);
8349
8574
  }
8575
+ getFormSubcollectionPath(isUserForm) {
8576
+ return isUserForm ? USER_FORMS_SUBCOLLECTION : DOCTOR_FORMS_SUBCOLLECTION;
8577
+ }
8350
8578
  /**
8351
- * Create a new filled document
8352
- * @param templateId - ID of the template to use
8353
- * @param patientId - ID of the patient
8354
- * @param practitionerId - ID of the practitioner
8355
- * @param clinicId - ID of the clinic
8356
- * @returns The created filled document
8579
+ * Create a new filled document within an appointment's subcollection.
8580
+ * @param templateId - ID of the template to use.
8581
+ * @param appointmentId - ID of the appointment this form belongs to.
8582
+ * @param procedureId - ID of the procedure associated with this form.
8583
+ * @param patientId - ID of the patient.
8584
+ * @param practitionerId - ID of the practitioner (can be system/generic if patient is filling).
8585
+ * @param clinicId - ID of the clinic.
8586
+ * @param initialValues - Optional initial values for the form elements.
8587
+ * @param initialStatus - Optional initial status for the form.
8588
+ * @returns The created filled document.
8357
8589
  */
8358
- async createFilledDocument(templateId, patientId, practitionerId, clinicId) {
8590
+ async createFilledDocumentForAppointment(templateId, appointmentId, procedureId, patientId, practitionerId, clinicId, initialValues = {}, initialStatus = "draft" /* DRAFT */) {
8359
8591
  const template = await this.templateService.getTemplateById(templateId);
8360
8592
  if (!template) {
8361
8593
  throw new Error(`Template with ID ${templateId} not found`);
8362
8594
  }
8363
8595
  const documentId3 = this.generateId();
8364
8596
  const now = Date.now();
8597
+ const isUserForm = template.isUserForm || false;
8598
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8365
8599
  const filledDocument = {
8366
8600
  id: documentId3,
8367
8601
  templateId,
8368
8602
  templateVersion: template.version,
8603
+ isUserForm,
8604
+ // Set based on template
8605
+ isRequired: template.isRequired || false,
8606
+ // Inherit isRequired from the template
8607
+ appointmentId,
8608
+ // NEW
8609
+ procedureId,
8610
+ // NEW
8369
8611
  patientId,
8370
8612
  practitionerId,
8371
8613
  clinicId,
8372
8614
  createdAt: now,
8373
8615
  updatedAt: now,
8374
- values: {},
8375
- status: "draft" /* DRAFT */
8616
+ values: initialValues,
8617
+ status: initialStatus
8376
8618
  };
8377
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8619
+ const docRef = (0, import_firestore26.doc)(
8620
+ this.db,
8621
+ APPOINTMENTS_COLLECTION,
8622
+ // Replaced "appointments"
8623
+ appointmentId,
8624
+ formSubcollection,
8625
+ documentId3
8626
+ );
8378
8627
  await (0, import_firestore26.setDoc)(docRef, filledDocument);
8379
8628
  return filledDocument;
8380
8629
  }
8381
8630
  /**
8382
- * Get a filled document by ID
8383
- * @param documentId - ID of the filled document to retrieve
8384
- * @returns The filled document or null if not found
8631
+ * Get a specific filled document from an appointment's subcollection.
8632
+ * @param appointmentId - ID of the appointment.
8633
+ * @param formId - ID of the filled document.
8634
+ * @param isUserForm - Boolean indicating if it's a user form or doctor form.
8635
+ * @returns The filled document or null if not found.
8385
8636
  */
8386
- async getFilledDocumentById(documentId3) {
8387
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8637
+ async getFilledDocumentFromAppointmentById(appointmentId, formId, isUserForm) {
8638
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8639
+ const docRef = (0, import_firestore26.doc)(
8640
+ this.db,
8641
+ APPOINTMENTS_COLLECTION,
8642
+ // Replaced "appointments"
8643
+ appointmentId,
8644
+ formSubcollection,
8645
+ formId
8646
+ );
8388
8647
  const docSnap = await (0, import_firestore26.getDoc)(docRef);
8389
8648
  if (!docSnap.exists()) {
8390
8649
  return null;
@@ -8392,178 +8651,183 @@ var FilledDocumentService = class extends BaseService {
8392
8651
  return docSnap.data();
8393
8652
  }
8394
8653
  /**
8395
- * Update values in a filled document
8396
- * @param documentId - ID of the filled document to update
8397
- * @param values - Updated values for elements
8398
- * @param status - Optional new status for the document
8399
- * @returns The updated filled document
8654
+ * Update values or status in a filled document within an appointment's subcollection.
8655
+ * @param appointmentId - ID of the appointment.
8656
+ * @param formId - ID of the filled document to update.
8657
+ * @param isUserForm - Boolean indicating if it's a user form or doctor form.
8658
+ * @param values - Updated values for elements.
8659
+ * @param status - Optional new status for the document.
8660
+ * @returns The updated filled document.
8400
8661
  */
8401
- async updateFilledDocument(documentId3, values, status) {
8402
- const filledDocument = await this.getFilledDocumentById(documentId3);
8403
- if (!filledDocument) {
8404
- throw new Error(`Filled document with ID ${documentId3} not found`);
8662
+ async updateFilledDocumentInAppointment(appointmentId, formId, isUserForm, values, status) {
8663
+ const formSubcollection = this.getFormSubcollectionPath(isUserForm);
8664
+ const docRef = (0, import_firestore26.doc)(
8665
+ this.db,
8666
+ APPOINTMENTS_COLLECTION,
8667
+ // Replaced "appointments"
8668
+ appointmentId,
8669
+ formSubcollection,
8670
+ formId
8671
+ );
8672
+ const existingDoc = await this.getFilledDocumentFromAppointmentById(
8673
+ appointmentId,
8674
+ formId,
8675
+ isUserForm
8676
+ );
8677
+ if (!existingDoc) {
8678
+ throw new Error(
8679
+ `Filled document with ID ${formId} not found in appointment ${appointmentId} ${formSubcollection}`
8680
+ );
8405
8681
  }
8406
- const updateData = {
8407
- values: {
8408
- ...filledDocument.values,
8409
- ...values
8410
- },
8682
+ const updatePayload = {
8411
8683
  updatedAt: Date.now()
8412
8684
  };
8685
+ if (values) {
8686
+ updatePayload.values = {
8687
+ ...existingDoc.values,
8688
+ ...values
8689
+ };
8690
+ }
8413
8691
  if (status) {
8414
- updateData.status = status;
8692
+ updatePayload.status = status;
8415
8693
  }
8416
- const docRef = (0, import_firestore26.doc)(this.collectionRef, documentId3);
8417
- await (0, import_firestore26.updateDoc)(docRef, updateData);
8418
- return {
8419
- ...filledDocument,
8420
- ...updateData
8421
- };
8694
+ if (Object.keys(updatePayload).length === 1 && "updatedAt" in updatePayload) {
8695
+ }
8696
+ await (0, import_firestore26.updateDoc)(docRef, updatePayload);
8697
+ return { ...existingDoc, ...updatePayload };
8422
8698
  }
8423
8699
  /**
8424
- * Get filled documents for a patient
8425
- * @param patientId - ID of the patient
8426
- * @param pageSize - Number of documents to retrieve
8427
- * @param lastDoc - Last document from previous page for pagination
8428
- * @returns Array of filled documents and the last document for pagination
8700
+ * Get all filled user forms for a specific appointment.
8701
+ * @param appointmentId ID of the appointment.
8702
+ * @param pageSize Number of documents to retrieve.
8703
+ * @param lastDoc Last document from previous page for pagination.
8429
8704
  */
8430
- async getFilledDocumentsByPatient(patientId, pageSize = 20, lastDoc) {
8705
+ async getFilledUserFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
8706
+ const subcollectionRef = (0, import_firestore26.collection)(
8707
+ this.db,
8708
+ APPOINTMENTS_COLLECTION,
8709
+ // Replaced "appointments"
8710
+ appointmentId,
8711
+ USER_FORMS_SUBCOLLECTION
8712
+ );
8431
8713
  let q = (0, import_firestore26.query)(
8432
- this.collectionRef,
8433
- (0, import_firestore26.where)("patientId", "==", patientId),
8714
+ subcollectionRef,
8434
8715
  (0, import_firestore26.orderBy)("updatedAt", "desc"),
8435
8716
  (0, import_firestore26.limit)(pageSize)
8436
8717
  );
8437
8718
  if (lastDoc) {
8438
8719
  q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8439
8720
  }
8440
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8441
- const documents = [];
8442
- let lastVisible = null;
8443
- querySnapshot.forEach((doc32) => {
8444
- documents.push(doc32.data());
8445
- lastVisible = doc32;
8446
- });
8447
- return {
8448
- documents,
8449
- lastDoc: lastVisible
8450
- };
8721
+ return this.executeQuery(q);
8451
8722
  }
8452
8723
  /**
8453
- * Get filled documents for a practitioner
8454
- * @param practitionerId - ID of the practitioner
8455
- * @param pageSize - Number of documents to retrieve
8456
- * @param lastDoc - Last document from previous page for pagination
8457
- * @returns Array of filled documents and the last document for pagination
8724
+ * Get all filled doctor forms for a specific appointment.
8725
+ * @param appointmentId ID of the appointment.
8726
+ * @param pageSize Number of documents to retrieve.
8727
+ * @param lastDoc Last document from previous page for pagination.
8458
8728
  */
8459
- async getFilledDocumentsByPractitioner(practitionerId, pageSize = 20, lastDoc) {
8729
+ async getFilledDoctorFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
8730
+ const subcollectionRef = (0, import_firestore26.collection)(
8731
+ this.db,
8732
+ APPOINTMENTS_COLLECTION,
8733
+ // Replaced "appointments"
8734
+ appointmentId,
8735
+ DOCTOR_FORMS_SUBCOLLECTION
8736
+ );
8460
8737
  let q = (0, import_firestore26.query)(
8461
- this.collectionRef,
8462
- (0, import_firestore26.where)("practitionerId", "==", practitionerId),
8738
+ subcollectionRef,
8463
8739
  (0, import_firestore26.orderBy)("updatedAt", "desc"),
8464
8740
  (0, import_firestore26.limit)(pageSize)
8465
8741
  );
8466
8742
  if (lastDoc) {
8467
8743
  q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8468
8744
  }
8745
+ return this.executeQuery(q);
8746
+ }
8747
+ // Helper to execute query and return documents + lastDoc
8748
+ async executeQuery(q) {
8469
8749
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8470
8750
  const documents = [];
8471
8751
  let lastVisible = null;
8472
- querySnapshot.forEach((doc32) => {
8473
- documents.push(doc32.data());
8474
- lastVisible = doc32;
8752
+ querySnapshot.forEach((doc33) => {
8753
+ documents.push(doc33.data());
8754
+ lastVisible = doc33;
8475
8755
  });
8476
8756
  return {
8477
8757
  documents,
8478
8758
  lastDoc: lastVisible
8479
8759
  };
8480
8760
  }
8761
+ // IMPORTANT: The following methods that query across all patients/practitioners/clinics
8762
+ // (e.g., getFilledDocumentsByPatient, getFilledDocumentsByPractitioner)
8763
+ // will NOT work correctly if FILLED_DOCUMENTS_COLLECTION is no longer a top-level collection
8764
+ // and data is only in appointment subcollections. You would need to use
8765
+ // Firestore Collection Group Queries for that, which require an index and a different query approach.
8766
+ // These methods are left here for now but would need significant rework or removal.
8481
8767
  /**
8482
- * Get filled documents for a clinic
8768
+ * Get filled documents for a patient (NEEDS REWORK for subcollections or Collection Group Query)
8769
+ * @param patientId - ID of the patient
8770
+ * @param pageSize - Number of documents to retrieve
8771
+ * @param lastDoc - Last document from previous page for pagination
8772
+ * @returns Array of filled documents and the last document for pagination
8773
+ */
8774
+ async getFilledDocumentsByPatient(patientId, pageSize = 20, lastDoc) {
8775
+ console.warn(
8776
+ "getFilledDocumentsByPatient needs rework for subcollection model or Collection Group Queries."
8777
+ );
8778
+ return { documents: [], lastDoc: null };
8779
+ }
8780
+ /**
8781
+ * Get filled documents for a practitioner (NEEDS REWORK for subcollections or Collection Group Query)
8782
+ * @param practitionerId - ID of the practitioner
8783
+ * @param pageSize - Number of documents to retrieve
8784
+ * @param lastDoc - Last document from previous page for pagination
8785
+ * @returns Array of filled documents and the last document for pagination
8786
+ */
8787
+ async getFilledDocumentsByPractitioner(practitionerId, pageSize = 20, lastDoc) {
8788
+ console.warn(
8789
+ "getFilledDocumentsByPractitioner needs rework for subcollection model or Collection Group Queries."
8790
+ );
8791
+ return { documents: [], lastDoc: null };
8792
+ }
8793
+ /**
8794
+ * Get filled documents for a clinic (NEEDS REWORK for subcollections or Collection Group Query)
8483
8795
  * @param clinicId - ID of the clinic
8484
8796
  * @param pageSize - Number of documents to retrieve
8485
8797
  * @param lastDoc - Last document from previous page for pagination
8486
8798
  * @returns Array of filled documents and the last document for pagination
8487
8799
  */
8488
8800
  async getFilledDocumentsByClinic(clinicId, pageSize = 20, lastDoc) {
8489
- let q = (0, import_firestore26.query)(
8490
- this.collectionRef,
8491
- (0, import_firestore26.where)("clinicId", "==", clinicId),
8492
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8493
- (0, import_firestore26.limit)(pageSize)
8801
+ console.warn(
8802
+ "getFilledDocumentsByClinic needs rework for subcollection model or Collection Group Queries."
8494
8803
  );
8495
- if (lastDoc) {
8496
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8497
- }
8498
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8499
- const documents = [];
8500
- let lastVisible = null;
8501
- querySnapshot.forEach((doc32) => {
8502
- documents.push(doc32.data());
8503
- lastVisible = doc32;
8504
- });
8505
- return {
8506
- documents,
8507
- lastDoc: lastVisible
8508
- };
8804
+ return { documents: [], lastDoc: null };
8509
8805
  }
8510
8806
  /**
8511
- * Get filled documents by template
8807
+ * Get filled documents by template (NEEDS REWORK for subcollections or Collection Group Query)
8512
8808
  * @param templateId - ID of the template
8513
8809
  * @param pageSize - Number of documents to retrieve
8514
8810
  * @param lastDoc - Last document from previous page for pagination
8515
8811
  * @returns Array of filled documents and the last document for pagination
8516
8812
  */
8517
8813
  async getFilledDocumentsByTemplate(templateId, pageSize = 20, lastDoc) {
8518
- let q = (0, import_firestore26.query)(
8519
- this.collectionRef,
8520
- (0, import_firestore26.where)("templateId", "==", templateId),
8521
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8522
- (0, import_firestore26.limit)(pageSize)
8814
+ console.warn(
8815
+ "getFilledDocumentsByTemplate needs rework for subcollection model or Collection Group Queries."
8523
8816
  );
8524
- if (lastDoc) {
8525
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8526
- }
8527
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8528
- const documents = [];
8529
- let lastVisible = null;
8530
- querySnapshot.forEach((doc32) => {
8531
- documents.push(doc32.data());
8532
- lastVisible = doc32;
8533
- });
8534
- return {
8535
- documents,
8536
- lastDoc: lastVisible
8537
- };
8817
+ return { documents: [], lastDoc: null };
8538
8818
  }
8539
8819
  /**
8540
- * Get filled documents by status
8820
+ * Get filled documents by status (NEEDS REWORK for subcollections or Collection Group Query)
8541
8821
  * @param status - Status to filter by
8542
8822
  * @param pageSize - Number of documents to retrieve
8543
8823
  * @param lastDoc - Last document from previous page for pagination
8544
8824
  * @returns Array of filled documents and the last document for pagination
8545
8825
  */
8546
8826
  async getFilledDocumentsByStatus(status, pageSize = 20, lastDoc) {
8547
- let q = (0, import_firestore26.query)(
8548
- this.collectionRef,
8549
- (0, import_firestore26.where)("status", "==", status),
8550
- (0, import_firestore26.orderBy)("updatedAt", "desc"),
8551
- (0, import_firestore26.limit)(pageSize)
8827
+ console.warn(
8828
+ "getFilledDocumentsByStatus needs rework for subcollection model or Collection Group Queries."
8552
8829
  );
8553
- if (lastDoc) {
8554
- q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
8555
- }
8556
- const querySnapshot = await (0, import_firestore26.getDocs)(q);
8557
- const documents = [];
8558
- let lastVisible = null;
8559
- querySnapshot.forEach((doc32) => {
8560
- documents.push(doc32.data());
8561
- lastVisible = doc32;
8562
- });
8563
- return {
8564
- documents,
8565
- lastDoc: lastVisible
8566
- };
8830
+ return { documents: [], lastDoc: null };
8567
8831
  }
8568
8832
  };
8569
8833
 
@@ -9055,7 +9319,7 @@ async function searchCalendarEventsUtil(db, params) {
9055
9319
  const finalQuery = (0, import_firestore33.query)(collectionRef, ...constraints);
9056
9320
  const querySnapshot = await (0, import_firestore33.getDocs)(finalQuery);
9057
9321
  const events = querySnapshot.docs.map(
9058
- (doc32) => ({ id: doc32.id, ...doc32.data() })
9322
+ (doc33) => ({ id: doc33.id, ...doc33.data() })
9059
9323
  );
9060
9324
  return events;
9061
9325
  } catch (error) {
@@ -9137,7 +9401,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
9137
9401
  );
9138
9402
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9139
9403
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9140
- return querySnapshot.docs.map((doc32) => doc32.data());
9404
+ return querySnapshot.docs.map((doc33) => doc33.data());
9141
9405
  }
9142
9406
  async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
9143
9407
  const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
@@ -9154,7 +9418,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
9154
9418
  );
9155
9419
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9156
9420
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9157
- return querySnapshot.docs.map((doc32) => doc32.data());
9421
+ return querySnapshot.docs.map((doc33) => doc33.data());
9158
9422
  }
9159
9423
  async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
9160
9424
  const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
@@ -9171,7 +9435,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
9171
9435
  );
9172
9436
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
9173
9437
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
9174
- return querySnapshot.docs.map((doc32) => doc32.data());
9438
+ return querySnapshot.docs.map((doc33) => doc33.data());
9175
9439
  }
9176
9440
  async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
9177
9441
  const calendarRef = getPractitionerSyncedCalendarDocRef(
@@ -10526,9 +10790,9 @@ var CalendarServiceV2 = class extends BaseService {
10526
10790
  (0, import_firestore37.where)("eventTime.start", "<=", import_firestore36.Timestamp.fromDate(endDate))
10527
10791
  );
10528
10792
  const eventsSnapshot = await (0, import_firestore37.getDocs)(q);
10529
- const events = eventsSnapshot.docs.map((doc32) => ({
10530
- id: doc32.id,
10531
- ...doc32.data()
10793
+ const events = eventsSnapshot.docs.map((doc33) => ({
10794
+ id: doc33.id,
10795
+ ...doc33.data()
10532
10796
  }));
10533
10797
  const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
10534
10798
  doctorId
@@ -11160,7 +11424,7 @@ var CalendarServiceV2 = class extends BaseService {
11160
11424
  ])
11161
11425
  );
11162
11426
  const querySnapshot = await (0, import_firestore37.getDocs)(q);
11163
- return querySnapshot.docs.map((doc32) => doc32.data());
11427
+ return querySnapshot.docs.map((doc33) => doc33.data());
11164
11428
  }
11165
11429
  /**
11166
11430
  * Calculates available time slots based on working hours, schedule and existing appointments
@@ -11427,7 +11691,7 @@ var ReviewService = class extends BaseService {
11427
11691
  (0, import_firestore38.where)("patientId", "==", patientId)
11428
11692
  );
11429
11693
  const snapshot = await (0, import_firestore38.getDocs)(q);
11430
- return snapshot.docs.map((doc32) => doc32.data());
11694
+ return snapshot.docs.map((doc33) => doc33.data());
11431
11695
  }
11432
11696
  /**
11433
11697
  * Gets all reviews for a specific clinic
@@ -11440,7 +11704,7 @@ var ReviewService = class extends BaseService {
11440
11704
  (0, import_firestore38.where)("clinicReview.clinicId", "==", clinicId)
11441
11705
  );
11442
11706
  const snapshot = await (0, import_firestore38.getDocs)(q);
11443
- return snapshot.docs.map((doc32) => doc32.data());
11707
+ return snapshot.docs.map((doc33) => doc33.data());
11444
11708
  }
11445
11709
  /**
11446
11710
  * Gets all reviews for a specific practitioner
@@ -11453,7 +11717,7 @@ var ReviewService = class extends BaseService {
11453
11717
  (0, import_firestore38.where)("practitionerReview.practitionerId", "==", practitionerId)
11454
11718
  );
11455
11719
  const snapshot = await (0, import_firestore38.getDocs)(q);
11456
- return snapshot.docs.map((doc32) => doc32.data());
11720
+ return snapshot.docs.map((doc33) => doc33.data());
11457
11721
  }
11458
11722
  /**
11459
11723
  * Gets all reviews for a specific procedure
@@ -11466,7 +11730,7 @@ var ReviewService = class extends BaseService {
11466
11730
  (0, import_firestore38.where)("procedureReview.procedureId", "==", procedureId)
11467
11731
  );
11468
11732
  const snapshot = await (0, import_firestore38.getDocs)(q);
11469
- return snapshot.docs.map((doc32) => doc32.data());
11733
+ return snapshot.docs.map((doc33) => doc33.data());
11470
11734
  }
11471
11735
  /**
11472
11736
  * Gets all reviews for a specific appointment
@@ -11904,166 +12168,6 @@ var import_firestore39 = require("firebase/firestore");
11904
12168
  var TECHNOLOGIES_COLLECTION = "technologies";
11905
12169
 
11906
12170
  // src/services/appointment/utils/appointment.utils.ts
11907
- async function fetchAggregatedInfoUtil(db, clinicId, practitionerId, patientId, procedureId) {
11908
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
11909
- try {
11910
- const [clinicDoc, practitionerDoc, patientDoc, procedureDoc] = await Promise.all([
11911
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, CLINICS_COLLECTION, clinicId)),
11912
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PRACTITIONERS_COLLECTION, practitionerId)),
11913
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PATIENTS_COLLECTION, patientId)),
11914
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PROCEDURES_COLLECTION, procedureId))
11915
- ]);
11916
- if (!clinicDoc.exists()) {
11917
- throw new Error(`Clinic with ID ${clinicId} not found`);
11918
- }
11919
- if (!practitionerDoc.exists()) {
11920
- throw new Error(`Practitioner with ID ${practitionerId} not found`);
11921
- }
11922
- if (!patientDoc.exists()) {
11923
- throw new Error(`Patient with ID ${patientId} not found`);
11924
- }
11925
- if (!procedureDoc.exists()) {
11926
- throw new Error(`Procedure with ID ${procedureId} not found`);
11927
- }
11928
- const clinicData = clinicDoc.data();
11929
- const practitionerData = practitionerDoc.data();
11930
- const patientData = patientDoc.data();
11931
- const procedureData = procedureDoc.data();
11932
- const clinicInfo = {
11933
- id: clinicId,
11934
- featuredPhoto: ((_a = clinicData.featuredPhotos) == null ? void 0 : _a[0]) || "",
11935
- name: clinicData.name,
11936
- description: clinicData.description || null,
11937
- location: clinicData.location,
11938
- contactInfo: clinicData.contactInfo
11939
- };
11940
- const practitionerInfo = {
11941
- id: practitionerId,
11942
- practitionerPhoto: ((_b = practitionerData.basicInfo) == null ? void 0 : _b.profileImageUrl) || null,
11943
- name: `${((_c = practitionerData.basicInfo) == null ? void 0 : _c.firstName) || ""} ${((_d = practitionerData.basicInfo) == null ? void 0 : _d.lastName) || ""}`.trim(),
11944
- email: ((_e = practitionerData.basicInfo) == null ? void 0 : _e.email) || "",
11945
- phone: ((_f = practitionerData.basicInfo) == null ? void 0 : _f.phoneNumber) || null,
11946
- certification: practitionerData.certification
11947
- };
11948
- const patientInfo = {
11949
- id: patientId,
11950
- fullName: patientData.displayName || "",
11951
- email: patientData.email || "",
11952
- phone: patientData.phoneNumber || null,
11953
- dateOfBirth: patientData.dateOfBirth || import_firestore39.Timestamp.now(),
11954
- gender: patientData.gender || "other"
11955
- };
11956
- const procedureInfo = {
11957
- id: procedureId,
11958
- name: procedureData.name,
11959
- description: procedureData.description,
11960
- photo: procedureData.photo || "",
11961
- family: procedureData.family,
11962
- categoryName: ((_g = procedureData.category) == null ? void 0 : _g.name) || "",
11963
- subcategoryName: ((_h = procedureData.subcategory) == null ? void 0 : _h.name) || "",
11964
- technologyName: ((_i = procedureData.technology) == null ? void 0 : _i.name) || "",
11965
- brandName: ((_j = procedureData.product) == null ? void 0 : _j.brand) || "",
11966
- productName: ((_k = procedureData.product) == null ? void 0 : _k.name) || "",
11967
- price: procedureData.price || 0,
11968
- pricingMeasure: procedureData.pricingMeasure,
11969
- currency: procedureData.currency,
11970
- duration: procedureData.duration || 0,
11971
- clinicId,
11972
- clinicName: clinicInfo.name,
11973
- practitionerId,
11974
- practitionerName: practitionerInfo.name
11975
- };
11976
- let technologyId = "";
11977
- if ((_l = procedureData.technology) == null ? void 0 : _l.id) {
11978
- technologyId = procedureData.technology.id;
11979
- }
11980
- let blockingConditions = [];
11981
- let contraindications = [];
11982
- let preProcedureRequirements = [];
11983
- let postProcedureRequirements = [];
11984
- if (technologyId) {
11985
- const technologyDoc = await (0, import_firestore39.getDoc)(
11986
- (0, import_firestore39.doc)(db, TECHNOLOGIES_COLLECTION, technologyId)
11987
- );
11988
- if (technologyDoc.exists()) {
11989
- const technologyData = technologyDoc.data();
11990
- blockingConditions = technologyData.blockingConditions || [];
11991
- contraindications = technologyData.contraindications || [];
11992
- preProcedureRequirements = ((_m = technologyData.requirements) == null ? void 0 : _m.pre) || [];
11993
- postProcedureRequirements = ((_n = technologyData.requirements) == null ? void 0 : _n.post) || [];
11994
- }
11995
- } else {
11996
- blockingConditions = procedureData.blockingConditions || [];
11997
- contraindications = procedureData.contraindications || [];
11998
- preProcedureRequirements = procedureData.preRequirements || [];
11999
- postProcedureRequirements = procedureData.postRequirements || [];
12000
- }
12001
- return {
12002
- clinicInfo,
12003
- practitionerInfo,
12004
- patientInfo,
12005
- procedureInfo,
12006
- blockingConditions,
12007
- contraindications,
12008
- preProcedureRequirements,
12009
- postProcedureRequirements
12010
- };
12011
- } catch (error) {
12012
- console.error("Error fetching aggregated info:", error);
12013
- throw error;
12014
- }
12015
- }
12016
- async function createAppointmentUtil2(db, data, aggregatedInfo, generateId2) {
12017
- try {
12018
- const appointmentId = generateId2();
12019
- const appointment = {
12020
- id: appointmentId,
12021
- calendarEventId: data.calendarEventId,
12022
- clinicBranchId: data.clinicBranchId,
12023
- clinicInfo: aggregatedInfo.clinicInfo,
12024
- practitionerId: data.practitionerId,
12025
- practitionerInfo: aggregatedInfo.practitionerInfo,
12026
- patientId: data.patientId,
12027
- patientInfo: aggregatedInfo.patientInfo,
12028
- procedureId: data.procedureId,
12029
- procedureInfo: aggregatedInfo.procedureInfo,
12030
- status: data.initialStatus,
12031
- bookingTime: import_firestore39.Timestamp.now(),
12032
- appointmentStartTime: data.appointmentStartTime,
12033
- appointmentEndTime: data.appointmentEndTime,
12034
- patientNotes: data.patientNotes || null,
12035
- cost: data.cost,
12036
- currency: data.currency,
12037
- paymentStatus: data.initialPaymentStatus || "unpaid" /* UNPAID */,
12038
- blockingConditions: aggregatedInfo.blockingConditions,
12039
- contraindications: aggregatedInfo.contraindications,
12040
- preProcedureRequirements: aggregatedInfo.preProcedureRequirements,
12041
- postProcedureRequirements: aggregatedInfo.postProcedureRequirements,
12042
- completedPreRequirements: [],
12043
- completedPostRequirements: [],
12044
- createdAt: (0, import_firestore39.serverTimestamp)(),
12045
- updatedAt: (0, import_firestore39.serverTimestamp)()
12046
- };
12047
- if (data.initialStatus === "confirmed" /* CONFIRMED */) {
12048
- appointment.confirmationTime = import_firestore39.Timestamp.now();
12049
- }
12050
- await (0, import_firestore39.setDoc)((0, import_firestore39.doc)(db, APPOINTMENTS_COLLECTION, appointmentId), appointment);
12051
- const calendarEventRef = (0, import_firestore39.doc)(db, CALENDAR_COLLECTION, data.calendarEventId);
12052
- await (0, import_firestore39.updateDoc)(calendarEventRef, {
12053
- appointmentId,
12054
- updatedAt: (0, import_firestore39.serverTimestamp)()
12055
- });
12056
- const now = import_firestore39.Timestamp.now();
12057
- return {
12058
- ...appointment,
12059
- createdAt: now,
12060
- updatedAt: now
12061
- };
12062
- } catch (error) {
12063
- console.error("Error creating appointment:", error);
12064
- throw error;
12065
- }
12066
- }
12067
12171
  async function updateAppointmentUtil2(db, appointmentId, data) {
12068
12172
  try {
12069
12173
  const appointmentRef = (0, import_firestore39.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
@@ -12165,7 +12269,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
12165
12269
  case "canceled_clinic" /* CANCELED_CLINIC */:
12166
12270
  calendarStatus = "canceled";
12167
12271
  break;
12168
- case "rescheduled" /* RESCHEDULED */:
12272
+ case AppointmentStatus.RESCHEDULED:
12169
12273
  calendarStatus = "rescheduled";
12170
12274
  break;
12171
12275
  case "completed" /* COMPLETED */:
@@ -12239,7 +12343,7 @@ async function searchAppointmentsUtil(db, params) {
12239
12343
  const q = (0, import_firestore39.query)((0, import_firestore39.collection)(db, APPOINTMENTS_COLLECTION), ...constraints);
12240
12344
  const querySnapshot = await (0, import_firestore39.getDocs)(q);
12241
12345
  const appointments = querySnapshot.docs.map(
12242
- (doc32) => doc32.data()
12346
+ (doc33) => doc33.data()
12243
12347
  );
12244
12348
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
12245
12349
  return { appointments, lastDoc };
@@ -12262,86 +12366,15 @@ var AppointmentService = class extends BaseService {
12262
12366
  * @param practitionerService Practitioner service instance
12263
12367
  * @param clinicService Clinic service instance
12264
12368
  */
12265
- constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService) {
12369
+ constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService, filledDocumentService) {
12266
12370
  super(db, auth, app);
12267
12371
  this.calendarService = calendarService;
12268
12372
  this.patientService = patientService;
12269
12373
  this.practitionerService = practitionerService;
12270
12374
  this.clinicService = clinicService;
12375
+ this.filledDocumentService = filledDocumentService;
12271
12376
  this.functions = (0, import_functions.getFunctions)(app, "europe-west6");
12272
12377
  }
12273
- /**
12274
- * Test method using the callable function version of getAvailableBookingSlots
12275
- * For development and testing purposes only - not for production use
12276
- *
12277
- * @param clinicId ID of the clinic
12278
- * @param practitionerId ID of the practitioner
12279
- * @param procedureId ID of the procedure
12280
- * @param startDate Start date of the time range to check
12281
- * @param endDate End date of the time range to check
12282
- * @returns Test result from the callable function
12283
- */
12284
- async testGetAvailableBookingSlots(clinicId, practitionerId, procedureId, startDate, endDate) {
12285
- try {
12286
- console.log(
12287
- `[APPOINTMENT_SERVICE] Testing callable function for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
12288
- );
12289
- const getAvailableBookingSlotsCallable = (0, import_functions.httpsCallable)(
12290
- this.functions,
12291
- "getAvailableBookingSlots"
12292
- );
12293
- const result = await getAvailableBookingSlotsCallable({
12294
- clinicId,
12295
- practitionerId,
12296
- procedureId,
12297
- timeframe: {
12298
- start: startDate.getTime(),
12299
- end: endDate.getTime()
12300
- }
12301
- });
12302
- console.log(
12303
- "[APPOINTMENT_SERVICE] Callable function test result:",
12304
- result.data
12305
- );
12306
- return result.data;
12307
- } catch (error) {
12308
- console.error(
12309
- "[APPOINTMENT_SERVICE] Error testing callable function:",
12310
- error
12311
- );
12312
- throw error;
12313
- }
12314
- }
12315
- /**
12316
- * Gets available booking slots for a specific clinic, practitioner, and procedure.
12317
- *
12318
- * @param clinicId ID of the clinic
12319
- * @param practitionerId ID of the practitioner
12320
- * @param procedureId ID of the procedure
12321
- * @param startDate Start date of the time range to check
12322
- * @param endDate End date of the time range to check
12323
- * @returns Array of available booking slots
12324
- */
12325
- async getAvailableBookingSlots(clinicId, practitionerId, procedureId, startDate, endDate) {
12326
- try {
12327
- console.log(
12328
- `[APPOINTMENT_SERVICE] Getting available booking slots for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
12329
- );
12330
- return this.getAvailableBookingSlotsHttp(
12331
- clinicId,
12332
- practitionerId,
12333
- procedureId,
12334
- startDate,
12335
- endDate
12336
- );
12337
- } catch (error) {
12338
- console.error(
12339
- "[APPOINTMENT_SERVICE] Error getting available booking slots:",
12340
- error
12341
- );
12342
- throw error;
12343
- }
12344
- }
12345
12378
  /**
12346
12379
  * Gets available booking slots for a specific clinic, practitioner, and procedure using HTTP request.
12347
12380
  * This is an alternative implementation using direct HTTP request instead of callable function.
@@ -12443,34 +12476,81 @@ var AppointmentService = class extends BaseService {
12443
12476
  }
12444
12477
  }
12445
12478
  /**
12446
- * Creates a new appointment.
12479
+ * Creates an appointment via the Cloud Function orchestrateAppointmentCreation
12447
12480
  *
12448
- * @param data Data needed to create the appointment
12481
+ * @param data - CreateAppointmentData object
12449
12482
  * @returns The created appointment
12450
12483
  */
12451
- async createAppointment(data) {
12484
+ async createAppointmentHttp(data) {
12452
12485
  try {
12453
- console.log("[APPOINTMENT_SERVICE] Creating appointment");
12454
- const validatedData = await createAppointmentSchema.parseAsync(data);
12455
- const aggregatedInfo = await fetchAggregatedInfoUtil(
12456
- this.db,
12457
- validatedData.clinicBranchId,
12458
- validatedData.practitionerId,
12459
- validatedData.patientId,
12460
- validatedData.procedureId
12486
+ console.log(
12487
+ "[APPOINTMENT_SERVICE] Creating appointment via cloud function"
12461
12488
  );
12462
- const appointment = await createAppointmentUtil2(
12463
- this.db,
12464
- validatedData,
12465
- aggregatedInfo,
12466
- this.generateId.bind(this)
12489
+ const currentUser = this.auth.currentUser;
12490
+ if (!currentUser) {
12491
+ throw new Error("User must be authenticated to create an appointment");
12492
+ }
12493
+ const idToken = await currentUser.getIdToken();
12494
+ const functionUrl = `https://europe-west6-metaestetics.cloudfunctions.net/bookingApi/orchestrateAppointmentCreation`;
12495
+ const requestData = {
12496
+ patientId: data.patientId,
12497
+ procedureId: data.procedureId,
12498
+ appointmentStartTime: data.appointmentStartTime.toMillis ? data.appointmentStartTime.toMillis() : new Date(data.appointmentStartTime).getTime(),
12499
+ appointmentEndTime: data.appointmentEndTime.toMillis ? data.appointmentEndTime.toMillis() : new Date(data.appointmentEndTime).getTime(),
12500
+ patientNotes: data.patientNotes || null
12501
+ };
12502
+ console.log(
12503
+ `[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
12467
12504
  );
12505
+ const response = await fetch(functionUrl, {
12506
+ method: "POST",
12507
+ mode: "cors",
12508
+ cache: "no-cache",
12509
+ credentials: "omit",
12510
+ headers: {
12511
+ "Content-Type": "application/json",
12512
+ Authorization: `Bearer ${idToken}`
12513
+ },
12514
+ redirect: "follow",
12515
+ referrerPolicy: "no-referrer",
12516
+ body: JSON.stringify(requestData)
12517
+ });
12468
12518
  console.log(
12469
- `[APPOINTMENT_SERVICE] Appointment created with ID: ${appointment.id}`
12519
+ `[APPOINTMENT_SERVICE] Received response ${response.status}: ${response.statusText}`
12470
12520
  );
12471
- return appointment;
12521
+ if (!response.ok) {
12522
+ const errorText = await response.text();
12523
+ console.error(
12524
+ `[APPOINTMENT_SERVICE] Error response details: ${errorText}`
12525
+ );
12526
+ throw new Error(
12527
+ `Failed to create appointment: ${response.status} ${response.statusText} - ${errorText}`
12528
+ );
12529
+ }
12530
+ const result = await response.json();
12531
+ if (!result.success) {
12532
+ throw new Error(result.error || "Failed to create appointment");
12533
+ }
12534
+ if (result.appointmentData) {
12535
+ console.log(
12536
+ `[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`
12537
+ );
12538
+ return result.appointmentData;
12539
+ }
12540
+ const createdAppointment = await this.getAppointmentById(
12541
+ result.appointmentId
12542
+ );
12543
+ if (!createdAppointment) {
12544
+ throw new Error(
12545
+ `Failed to retrieve created appointment with ID: ${result.appointmentId}`
12546
+ );
12547
+ }
12548
+ return createdAppointment;
12472
12549
  } catch (error) {
12473
- console.error("[APPOINTMENT_SERVICE] Error creating appointment:", error);
12550
+ console.error(
12551
+ "[APPOINTMENT_SERVICE] Error creating appointment via cloud function:",
12552
+ error
12553
+ );
12474
12554
  throw error;
12475
12555
  }
12476
12556
  }
@@ -12623,192 +12703,340 @@ var AppointmentService = class extends BaseService {
12623
12703
  *
12624
12704
  * @param appointmentId ID of the appointment
12625
12705
  * @param newStatus New status to set
12626
- * @param cancellationReason Required if canceling the appointment
12627
- * @param canceledBy Required if canceling the appointment
12706
+ * @param details Optional details for the status change
12628
12707
  * @returns The updated appointment
12629
12708
  */
12630
- async updateAppointmentStatus(appointmentId, newStatus, cancellationReason, canceledBy) {
12709
+ async updateAppointmentStatus(appointmentId, newStatus, details) {
12631
12710
  console.log(
12632
12711
  `[APPOINTMENT_SERVICE] Updating status of appointment ${appointmentId} to ${newStatus}`
12633
12712
  );
12634
- const updateData = { status: newStatus };
12635
- if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */) {
12636
- if (!cancellationReason) {
12637
- throw new Error(
12638
- "Cancellation reason is required when canceling an appointment"
12639
- );
12713
+ const updateData = {
12714
+ status: newStatus,
12715
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12716
+ };
12717
+ if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */ || newStatus === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
12718
+ if (!(details == null ? void 0 : details.cancellationReason)) {
12719
+ throw new Error("Cancellation reason is required when canceling.");
12640
12720
  }
12641
- if (!canceledBy) {
12642
- throw new Error(
12643
- "Canceled by is required when canceling an appointment"
12644
- );
12721
+ if (!(details == null ? void 0 : details.canceledBy)) {
12722
+ throw new Error("Canceled by is required when canceling.");
12645
12723
  }
12646
- updateData.cancellationReason = cancellationReason;
12647
- updateData.canceledBy = canceledBy;
12724
+ updateData.cancellationReason = details.cancellationReason;
12725
+ updateData.canceledBy = details.canceledBy;
12726
+ updateData.cancellationTime = import_firestore40.Timestamp.now();
12648
12727
  }
12649
12728
  if (newStatus === "confirmed" /* CONFIRMED */) {
12650
12729
  updateData.confirmationTime = import_firestore40.Timestamp.now();
12651
12730
  }
12731
+ if (newStatus === "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
12732
+ updateData.rescheduleTime = import_firestore40.Timestamp.now();
12733
+ }
12652
12734
  return this.updateAppointment(appointmentId, updateData);
12653
12735
  }
12654
12736
  /**
12655
- * Confirms an appointment.
12656
- *
12657
- * @param appointmentId ID of the appointment to confirm
12658
- * @returns The confirmed appointment
12737
+ * Confirms a PENDING appointment by an Admin/Clinic.
12659
12738
  */
12660
- async confirmAppointment(appointmentId) {
12739
+ async confirmAppointmentAdmin(appointmentId) {
12661
12740
  console.log(
12662
- `[APPOINTMENT_SERVICE] Confirming appointment: ${appointmentId}`
12741
+ `[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`
12663
12742
  );
12743
+ const appointment = await this.getAppointmentById(appointmentId);
12744
+ if (!appointment)
12745
+ throw new Error(`Appointment ${appointmentId} not found.`);
12746
+ if (appointment.status !== "pending" /* PENDING */) {
12747
+ throw new Error(
12748
+ `Appointment ${appointmentId} is not in PENDING state to be confirmed.`
12749
+ );
12750
+ }
12664
12751
  return this.updateAppointmentStatus(
12665
12752
  appointmentId,
12666
12753
  "confirmed" /* CONFIRMED */
12667
12754
  );
12668
12755
  }
12669
12756
  /**
12670
- * Cancels an appointment from the clinic side.
12671
- *
12672
- * @param appointmentId ID of the appointment to cancel
12673
- * @param reason Reason for cancellation
12674
- * @returns The canceled appointment
12757
+ * Cancels an appointment by the User (Patient).
12758
+ */
12759
+ async cancelAppointmentUser(appointmentId, reason) {
12760
+ console.log(
12761
+ `[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`
12762
+ );
12763
+ return this.updateAppointmentStatus(
12764
+ appointmentId,
12765
+ "canceled_patient" /* CANCELED_PATIENT */,
12766
+ {
12767
+ cancellationReason: reason,
12768
+ canceledBy: "patient"
12769
+ }
12770
+ );
12771
+ }
12772
+ /**
12773
+ * Cancels an appointment by an Admin/Clinic.
12675
12774
  */
12676
- async cancelAppointmentByClinic(appointmentId, reason) {
12775
+ async cancelAppointmentAdmin(appointmentId, reason) {
12677
12776
  console.log(
12678
- `[APPOINTMENT_SERVICE] Canceling appointment by clinic: ${appointmentId}`
12777
+ `[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`
12679
12778
  );
12680
12779
  return this.updateAppointmentStatus(
12681
12780
  appointmentId,
12682
12781
  "canceled_clinic" /* CANCELED_CLINIC */,
12683
- reason,
12684
- "clinic"
12782
+ {
12783
+ cancellationReason: reason,
12784
+ canceledBy: "clinic"
12785
+ }
12685
12786
  );
12686
12787
  }
12687
12788
  /**
12688
- * Cancels an appointment from the patient side.
12689
- *
12690
- * @param appointmentId ID of the appointment to cancel
12691
- * @param reason Reason for cancellation
12692
- * @returns The canceled appointment
12789
+ * Admin proposes to reschedule an appointment.
12790
+ * Sets status to RESCHEDULED_BY_CLINIC and updates times.
12791
+ */
12792
+ async rescheduleAppointmentAdmin(appointmentId, newStartTime, newEndTime) {
12793
+ console.log(
12794
+ `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
12795
+ );
12796
+ if (newEndTime.toMillis() <= newStartTime.toMillis()) {
12797
+ throw new Error("New end time must be after new start time.");
12798
+ }
12799
+ const updateData = {
12800
+ status: "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */,
12801
+ appointmentStartTime: newStartTime,
12802
+ appointmentEndTime: newEndTime,
12803
+ rescheduleTime: import_firestore40.Timestamp.now(),
12804
+ confirmationTime: null,
12805
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12806
+ };
12807
+ return this.updateAppointment(appointmentId, updateData);
12808
+ }
12809
+ /**
12810
+ * User confirms a reschedule proposed by the clinic.
12811
+ * Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
12693
12812
  */
12694
- async cancelAppointmentByPatient(appointmentId, reason) {
12813
+ async rescheduleAppointmentConfirmUser(appointmentId) {
12695
12814
  console.log(
12696
- `[APPOINTMENT_SERVICE] Canceling appointment by patient: ${appointmentId}`
12815
+ `[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`
12697
12816
  );
12817
+ const appointment = await this.getAppointmentById(appointmentId);
12818
+ if (!appointment)
12819
+ throw new Error(`Appointment ${appointmentId} not found.`);
12820
+ if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
12821
+ throw new Error(
12822
+ `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
12823
+ );
12824
+ }
12698
12825
  return this.updateAppointmentStatus(
12699
12826
  appointmentId,
12700
- "canceled_patient" /* CANCELED_PATIENT */,
12701
- reason,
12702
- "patient"
12827
+ "confirmed" /* CONFIRMED */
12703
12828
  );
12704
12829
  }
12705
12830
  /**
12706
- * Marks an appointment as checked in.
12707
- *
12708
- * @param appointmentId ID of the appointment
12709
- * @returns The updated appointment
12831
+ * User rejects a reschedule proposed by the clinic.
12832
+ * Status changes from RESCHEDULED_BY_CLINIC to CANCELED_PATIENT_RESCHEDULED.
12710
12833
  */
12711
- async checkInAppointment(appointmentId) {
12834
+ async rescheduleAppointmentRejectUser(appointmentId, reason) {
12712
12835
  console.log(
12713
- `[APPOINTMENT_SERVICE] Checking in appointment: ${appointmentId}`
12836
+ `[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`
12714
12837
  );
12838
+ const appointment = await this.getAppointmentById(appointmentId);
12839
+ if (!appointment)
12840
+ throw new Error(`Appointment ${appointmentId} not found.`);
12841
+ if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
12842
+ throw new Error(
12843
+ `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
12844
+ );
12845
+ }
12715
12846
  return this.updateAppointmentStatus(
12716
12847
  appointmentId,
12717
- "checked_in" /* CHECKED_IN */
12848
+ "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */,
12849
+ {
12850
+ cancellationReason: reason,
12851
+ canceledBy: "patient"
12852
+ }
12718
12853
  );
12719
12854
  }
12720
12855
  /**
12721
- * Marks an appointment as in progress.
12722
- *
12723
- * @param appointmentId ID of the appointment
12724
- * @returns The updated appointment
12856
+ * Admin checks in a patient for their appointment.
12857
+ * Requires all pending user forms to be completed.
12725
12858
  */
12726
- async startAppointment(appointmentId) {
12727
- console.log(`[APPOINTMENT_SERVICE] Starting appointment: ${appointmentId}`);
12859
+ async checkInPatientAdmin(appointmentId) {
12860
+ console.log(
12861
+ `[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`
12862
+ );
12863
+ const appointment = await this.getAppointmentById(appointmentId);
12864
+ if (!appointment)
12865
+ throw new Error(`Appointment ${appointmentId} not found.`);
12866
+ if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.length > 0) {
12867
+ throw new Error(
12868
+ `Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(
12869
+ ", "
12870
+ )}`
12871
+ );
12872
+ }
12873
+ if (appointment.status !== "confirmed" /* CONFIRMED */ && appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
12874
+ console.warn(
12875
+ `Checking in appointment ${appointmentId} with status ${appointment.status}. Ensure this is intended.`
12876
+ );
12877
+ }
12728
12878
  return this.updateAppointmentStatus(
12729
12879
  appointmentId,
12730
- "in_progress" /* IN_PROGRESS */
12880
+ "checked_in" /* CHECKED_IN */
12731
12881
  );
12732
12882
  }
12733
12883
  /**
12734
- * Marks an appointment as completed.
12735
- *
12736
- * @param appointmentId ID of the appointment
12737
- * @param actualDurationMinutes Actual duration of the appointment in minutes
12738
- * @returns The updated appointment
12884
+ * Doctor starts the appointment procedure.
12739
12885
  */
12740
- async completeAppointment(appointmentId, actualDurationMinutes) {
12886
+ async startAppointmentDoctor(appointmentId) {
12741
12887
  console.log(
12742
- `[APPOINTMENT_SERVICE] Completing appointment: ${appointmentId}`
12888
+ `[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`
12743
12889
  );
12890
+ const appointment = await this.getAppointmentById(appointmentId);
12891
+ if (!appointment)
12892
+ throw new Error(`Appointment ${appointmentId} not found.`);
12893
+ if (appointment.status !== "checked_in" /* CHECKED_IN */) {
12894
+ throw new Error(
12895
+ `Appointment ${appointmentId} must be CHECKED_IN to start.`
12896
+ );
12897
+ }
12898
+ const updateData = {
12899
+ status: "in_progress" /* IN_PROGRESS */,
12900
+ procedureActualStartTime: import_firestore40.Timestamp.now(),
12901
+ // Set actual start time
12902
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12903
+ };
12904
+ return this.updateAppointment(appointmentId, updateData);
12905
+ }
12906
+ /**
12907
+ * Doctor completes and finalizes the appointment.
12908
+ */
12909
+ async completeAppointmentDoctor(appointmentId, finalizationNotes, actualDurationMinutesInput) {
12910
+ console.log(
12911
+ `[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`
12912
+ );
12913
+ const currentUser = this.auth.currentUser;
12914
+ if (!currentUser)
12915
+ throw new Error("Authentication required to complete appointment.");
12916
+ const appointment = await this.getAppointmentById(appointmentId);
12917
+ if (!appointment)
12918
+ throw new Error(`Appointment ${appointmentId} not found.`);
12919
+ let calculatedDurationMinutes = actualDurationMinutesInput;
12920
+ const procedureCompletionTime = import_firestore40.Timestamp.now();
12921
+ if (calculatedDurationMinutes === void 0 && appointment.procedureActualStartTime) {
12922
+ const startTimeMillis = appointment.procedureActualStartTime.toMillis();
12923
+ const endTimeMillis = procedureCompletionTime.toMillis();
12924
+ if (endTimeMillis > startTimeMillis) {
12925
+ calculatedDurationMinutes = Math.round(
12926
+ (endTimeMillis - startTimeMillis) / 6e4
12927
+ );
12928
+ }
12929
+ }
12744
12930
  const updateData = {
12745
12931
  status: "completed" /* COMPLETED */,
12746
- actualDurationMinutes
12932
+ actualDurationMinutes: calculatedDurationMinutes,
12933
+ // Use calculated or provided duration
12934
+ finalizedDetails: {
12935
+ by: currentUser.uid,
12936
+ // This is used ID, not practitioner's profile ID (just so we know who completed the appointment)
12937
+ at: procedureCompletionTime,
12938
+ // Use consistent completion timestamp
12939
+ notes: finalizationNotes
12940
+ },
12941
+ // Optionally update appointmentEndTime to the actual completion time
12942
+ // appointmentEndTime: procedureCompletionTime,
12943
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12747
12944
  };
12748
12945
  return this.updateAppointment(appointmentId, updateData);
12749
12946
  }
12750
12947
  /**
12751
- * Marks an appointment as no-show.
12752
- *
12753
- * @param appointmentId ID of the appointment
12754
- * @returns The updated appointment
12948
+ * Admin marks an appointment as No-Show.
12755
12949
  */
12756
- async markNoShow(appointmentId) {
12950
+ async markNoShowAdmin(appointmentId) {
12757
12951
  console.log(
12758
- `[APPOINTMENT_SERVICE] Marking appointment as no-show: ${appointmentId}`
12952
+ `[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`
12759
12953
  );
12954
+ const appointment = await this.getAppointmentById(appointmentId);
12955
+ if (!appointment)
12956
+ throw new Error(`Appointment ${appointmentId} not found.`);
12957
+ if (import_firestore40.Timestamp.now().toMillis() < appointment.appointmentStartTime.toMillis()) {
12958
+ throw new Error("Cannot mark no-show before appointment start time.");
12959
+ }
12760
12960
  return this.updateAppointmentStatus(
12761
12961
  appointmentId,
12762
- "no_show" /* NO_SHOW */
12962
+ "no_show" /* NO_SHOW */,
12963
+ {
12964
+ cancellationReason: "Patient did not show up for the appointment.",
12965
+ canceledBy: "clinic"
12966
+ }
12763
12967
  );
12764
12968
  }
12765
12969
  /**
12766
- * Updates the payment status of an appointment.
12767
- *
12768
- * @param appointmentId ID of the appointment
12769
- * @param paymentStatus New payment status
12770
- * @param paymentTransactionId Optional transaction ID for the payment
12771
- * @returns The updated appointment
12970
+ * Adds a media item to an appointment.
12772
12971
  */
12773
- async updatePaymentStatus(appointmentId, paymentStatus, paymentTransactionId) {
12972
+ async addMediaToAppointment(appointmentId, mediaItemData) {
12774
12973
  console.log(
12775
- `[APPOINTMENT_SERVICE] Updating payment status of appointment ${appointmentId} to ${paymentStatus}`
12974
+ `[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`
12975
+ );
12976
+ const currentUser = this.auth.currentUser;
12977
+ if (!currentUser) throw new Error("Authentication required.");
12978
+ const newMediaItem = {
12979
+ ...mediaItemData,
12980
+ id: this.generateId(),
12981
+ uploadedAt: import_firestore40.Timestamp.now(),
12982
+ uploadedBy: currentUser.uid
12983
+ };
12984
+ const updateData = {
12985
+ media: (0, import_firestore40.arrayUnion)(newMediaItem),
12986
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12987
+ };
12988
+ return this.updateAppointment(appointmentId, updateData);
12989
+ }
12990
+ /**
12991
+ * Removes a media item from an appointment.
12992
+ */
12993
+ async removeMediaFromAppointment(appointmentId, mediaItemId) {
12994
+ console.log(
12995
+ `[APPOINTMENT_SERVICE] Removing media ${mediaItemId} from appointment ${appointmentId}`
12776
12996
  );
12997
+ const appointment = await this.getAppointmentById(appointmentId);
12998
+ if (!appointment || !appointment.media) {
12999
+ throw new Error("Appointment or media list not found.");
13000
+ }
13001
+ const mediaToRemove = appointment.media.find((m) => m.id === mediaItemId);
13002
+ if (!mediaToRemove) {
13003
+ throw new Error(`Media item ${mediaItemId} not found in appointment.`);
13004
+ }
12777
13005
  const updateData = {
12778
- paymentStatus,
12779
- paymentTransactionId: paymentTransactionId || null
13006
+ media: (0, import_firestore40.arrayRemove)(mediaToRemove),
13007
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12780
13008
  };
12781
13009
  return this.updateAppointment(appointmentId, updateData);
12782
13010
  }
12783
13011
  /**
12784
- * Marks pre-procedure requirements as completed.
12785
- *
12786
- * @param appointmentId ID of the appointment
12787
- * @param requirementIds IDs of the requirements to mark as completed
12788
- * @returns The updated appointment
13012
+ * Adds or updates review information for an appointment.
12789
13013
  */
12790
- async completePreRequirements(appointmentId, requirementIds) {
13014
+ async addReviewToAppointment(appointmentId, reviewData) {
12791
13015
  console.log(
12792
- `[APPOINTMENT_SERVICE] Marking pre-requirements as completed for appointment: ${appointmentId}`
13016
+ `[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`
12793
13017
  );
13018
+ const newReviewInfo = {
13019
+ ...reviewData,
13020
+ reviewId: this.generateId(),
13021
+ reviewedAt: import_firestore40.Timestamp.now()
13022
+ };
12794
13023
  const updateData = {
12795
- completedPreRequirements: requirementIds
13024
+ reviewInfo: newReviewInfo,
13025
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12796
13026
  };
12797
13027
  return this.updateAppointment(appointmentId, updateData);
12798
13028
  }
12799
13029
  /**
12800
- * Marks post-procedure requirements as completed.
12801
- *
12802
- * @param appointmentId ID of the appointment
12803
- * @param requirementIds IDs of the requirements to mark as completed
12804
- * @returns The updated appointment
13030
+ * Updates the payment status of an appointment.
12805
13031
  */
12806
- async completePostRequirements(appointmentId, requirementIds) {
13032
+ async updatePaymentStatus(appointmentId, paymentStatus, paymentTransactionId) {
12807
13033
  console.log(
12808
- `[APPOINTMENT_SERVICE] Marking post-requirements as completed for appointment: ${appointmentId}`
13034
+ `[APPOINTMENT_SERVICE] Updating payment status of appointment ${appointmentId} to ${paymentStatus}`
12809
13035
  );
12810
13036
  const updateData = {
12811
- completedPostRequirements: requirementIds
13037
+ paymentStatus,
13038
+ paymentTransactionId: paymentTransactionId || null,
13039
+ updatedAt: (0, import_firestore40.serverTimestamp)()
12812
13040
  };
12813
13041
  return this.updateAppointment(appointmentId, updateData);
12814
13042
  }
@@ -12828,29 +13056,204 @@ var AppointmentService = class extends BaseService {
12828
13056
  };
12829
13057
  return this.updateAppointment(appointmentId, updateData);
12830
13058
  }
13059
+ };
13060
+
13061
+ // src/services/patient/patientRequirements.service.ts
13062
+ var import_firestore41 = require("firebase/firestore");
13063
+
13064
+ // src/types/patient/patient-requirements.ts
13065
+ var PatientInstructionStatus = /* @__PURE__ */ ((PatientInstructionStatus2) => {
13066
+ PatientInstructionStatus2["PENDING_NOTIFICATION"] = "pendingNotification";
13067
+ PatientInstructionStatus2["ACTION_DUE"] = "actionDue";
13068
+ PatientInstructionStatus2["ACTION_TAKEN"] = "actionTaken";
13069
+ PatientInstructionStatus2["MISSED"] = "missed";
13070
+ PatientInstructionStatus2["CANCELLED"] = "cancelled";
13071
+ PatientInstructionStatus2["SKIPPED"] = "skipped";
13072
+ return PatientInstructionStatus2;
13073
+ })(PatientInstructionStatus || {});
13074
+ var PatientRequirementOverallStatus = /* @__PURE__ */ ((PatientRequirementOverallStatus2) => {
13075
+ PatientRequirementOverallStatus2["ACTIVE"] = "active";
13076
+ PatientRequirementOverallStatus2["ALL_INSTRUCTIONS_MET"] = "allInstructionsMet";
13077
+ PatientRequirementOverallStatus2["PARTIALLY_COMPLETED"] = "partiallyCompleted";
13078
+ PatientRequirementOverallStatus2["FAILED"] = "failed";
13079
+ PatientRequirementOverallStatus2["CANCELLED_APPOINTMENT"] = "cancelledAppointment";
13080
+ PatientRequirementOverallStatus2["SUPERSEDED_RESCHEDULE"] = "supersededReschedule";
13081
+ PatientRequirementOverallStatus2["FAILED_TO_PROCESS"] = "failedToProcess";
13082
+ return PatientRequirementOverallStatus2;
13083
+ })(PatientRequirementOverallStatus || {});
13084
+ var PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME = "patientRequirements";
13085
+
13086
+ // src/services/patient/patientRequirements.service.ts
13087
+ var PatientRequirementsService = class extends BaseService {
13088
+ constructor(db, auth, app) {
13089
+ super(db, auth, app);
13090
+ }
13091
+ getPatientRequirementsCollectionRef(patientId) {
13092
+ return (0, import_firestore41.collection)(
13093
+ this.db,
13094
+ `patients/${patientId}/${PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME}`
13095
+ );
13096
+ }
13097
+ getPatientRequirementDocRef(patientId, instanceId) {
13098
+ return (0, import_firestore41.doc)(
13099
+ this.getPatientRequirementsCollectionRef(patientId),
13100
+ instanceId
13101
+ );
13102
+ }
12831
13103
  /**
12832
- * Debug helper: Get the current user's ID token for testing purposes
12833
- * Use this token in Postman with Authorization: Bearer TOKEN
13104
+ * Gets a specific patient requirement instance by its ID.
13105
+ * @param patientId - The ID of the patient.
13106
+ * @param instanceId - The ID of the requirement instance.
13107
+ * @returns The patient requirement instance or null if not found.
12834
13108
  */
12835
- async getDebugToken() {
12836
- try {
12837
- const currentUser = this.auth.currentUser;
12838
- if (!currentUser) {
12839
- console.log("[APPOINTMENT_SERVICE] No user is signed in");
12840
- return null;
12841
- }
12842
- const idToken = await currentUser.getIdToken();
12843
- console.log("[APPOINTMENT_SERVICE] Debug token:", idToken);
12844
- return idToken;
12845
- } catch (error) {
12846
- console.error("[APPOINTMENT_SERVICE] Error getting debug token:", error);
13109
+ async getPatientRequirementInstance(patientId, instanceId) {
13110
+ const docRef = this.getPatientRequirementDocRef(patientId, instanceId);
13111
+ const docSnap = await (0, import_firestore41.getDoc)(docRef);
13112
+ if (!docSnap.exists()) {
12847
13113
  return null;
12848
13114
  }
13115
+ const data = docSnap.data();
13116
+ return { id: docSnap.id, ...data };
13117
+ }
13118
+ /**
13119
+ * Retrieves patient requirement instances based on specified filters.
13120
+ * This is a flexible query method.
13121
+ *
13122
+ * @param patientId - The ID of the patient.
13123
+ * @param filters - Optional filters for appointmentId, overall statuses, instruction statuses, and due timeframes.
13124
+ * @param pageLimit - Optional limit for pagination.
13125
+ * @param lastVisible - Optional last document snapshot for pagination.
13126
+ * @returns A promise resolving to an array of matching patient requirement instances and the last document snapshot.
13127
+ */
13128
+ async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
13129
+ const collRef = this.getPatientRequirementsCollectionRef(patientId);
13130
+ let q = (0, import_firestore41.query)(collRef, (0, import_firestore41.orderBy)("createdAt", "desc"));
13131
+ const queryConstraints = [];
13132
+ if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
13133
+ queryConstraints.push(
13134
+ (0, import_firestore41.where)("appointmentId", "==", filters.appointmentId)
13135
+ );
13136
+ }
13137
+ if ((filters == null ? void 0 : filters.statuses) && filters.statuses.length > 0) {
13138
+ queryConstraints.push((0, import_firestore41.where)("overallStatus", "in", filters.statuses));
13139
+ }
13140
+ if (lastVisible) {
13141
+ queryConstraints.push((0, import_firestore41.startAfter)(lastVisible));
13142
+ }
13143
+ queryConstraints.push((0, import_firestore41.limit)(pageLimit));
13144
+ q = (0, import_firestore41.query)(collRef, ...queryConstraints);
13145
+ const snapshot = await (0, import_firestore41.getDocs)(q);
13146
+ let requirements = snapshot.docs.map((docSnap) => {
13147
+ const data = docSnap.data();
13148
+ return { id: docSnap.id, ...data };
13149
+ });
13150
+ if ((filters == null ? void 0 : filters.instructionStatuses) && filters.instructionStatuses.length > 0) {
13151
+ requirements = requirements.filter(
13152
+ (req) => req.instructions.some(
13153
+ (instr) => filters.instructionStatuses.includes(instr.status)
13154
+ )
13155
+ );
13156
+ }
13157
+ if (filters == null ? void 0 : filters.dueBefore) {
13158
+ const dueBeforeMillis = filters.dueBefore.toMillis();
13159
+ requirements = requirements.filter(
13160
+ (req) => req.instructions.some(
13161
+ (instr) => instr.dueTime.toMillis() < dueBeforeMillis
13162
+ )
13163
+ );
13164
+ }
13165
+ if (filters == null ? void 0 : filters.dueAfter) {
13166
+ const dueAfterMillis = filters.dueAfter.toMillis();
13167
+ requirements = requirements.filter(
13168
+ (req) => req.instructions.some(
13169
+ (instr) => instr.dueTime.toMillis() > dueAfterMillis
13170
+ )
13171
+ );
13172
+ }
13173
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1] || null;
13174
+ return { requirements, lastDoc: newLastVisible };
13175
+ }
13176
+ /**
13177
+ * Marks a specific instruction within a PatientRequirementInstance as ACTION_TAKEN.
13178
+ * If all instructions are actioned, updates the overallStatus of the instance.
13179
+ *
13180
+ * @param patientId - The ID of the patient.
13181
+ * @param instanceId - The ID of the PatientRequirementInstance.
13182
+ * @param instructionId - The ID of the instruction to complete.
13183
+ * @returns The updated PatientRequirementInstance.
13184
+ * @throws Error if the instance or instruction is not found, or if the instruction is not in a completable state.
13185
+ */
13186
+ async completeInstruction(patientId, instanceId, instructionId) {
13187
+ const instanceRef = this.getPatientRequirementDocRef(patientId, instanceId);
13188
+ const instanceSnap = await (0, import_firestore41.getDoc)(instanceRef);
13189
+ if (!instanceSnap.exists()) {
13190
+ throw new Error(
13191
+ `PatientRequirementInstance ${instanceId} not found for patient ${patientId}.`
13192
+ );
13193
+ }
13194
+ const instanceData = instanceSnap.data();
13195
+ const instance = { id: instanceSnap.id, ...instanceData };
13196
+ const instructionIndex = instance.instructions.findIndex(
13197
+ (instr) => instr.instructionId === instructionId
13198
+ );
13199
+ if (instructionIndex === -1) {
13200
+ throw new Error(
13201
+ `Instruction ${instructionId} not found in instance ${instanceId}.`
13202
+ );
13203
+ }
13204
+ const instructionToUpdate = instance.instructions[instructionIndex];
13205
+ if (instructionToUpdate.status !== "pendingNotification" /* PENDING_NOTIFICATION */ && instructionToUpdate.status !== "actionDue" /* ACTION_DUE */ && instructionToUpdate.status !== "missed" /* MISSED */) {
13206
+ if (instructionToUpdate.status === "actionTaken" /* ACTION_TAKEN */) {
13207
+ console.warn(
13208
+ `Instruction ${instructionId} is already marked as ACTION_TAKEN.`
13209
+ );
13210
+ return instance;
13211
+ }
13212
+ throw new Error(
13213
+ `Instruction ${instructionId} is in status ${instructionToUpdate.status} and cannot be marked as completed.`
13214
+ );
13215
+ }
13216
+ const now = import_firestore41.Timestamp.now();
13217
+ const updatedInstructions = [...instance.instructions];
13218
+ updatedInstructions[instructionIndex] = {
13219
+ ...instructionToUpdate,
13220
+ status: "actionTaken" /* ACTION_TAKEN */,
13221
+ actionTakenAt: now,
13222
+ updatedAt: now
13223
+ };
13224
+ const allActionTaken = updatedInstructions.every(
13225
+ (instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
13226
+ );
13227
+ let newOverallStatus = instance.overallStatus;
13228
+ if (allActionTaken) {
13229
+ newOverallStatus = "allInstructionsMet" /* ALL_INSTRUCTIONS_MET */;
13230
+ } else if (updatedInstructions.some(
13231
+ (instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
13232
+ )) {
13233
+ newOverallStatus = "partiallyCompleted" /* PARTIALLY_COMPLETED */;
13234
+ }
13235
+ const updatePayload = {
13236
+ // Using a general type for updateDoc payload
13237
+ instructions: updatedInstructions,
13238
+ updatedAt: now
13239
+ };
13240
+ if (newOverallStatus !== instance.overallStatus) {
13241
+ updatePayload.overallStatus = newOverallStatus;
13242
+ }
13243
+ await (0, import_firestore41.updateDoc)(instanceRef, updatePayload);
13244
+ return {
13245
+ ...instance,
13246
+ instructions: updatedInstructions,
13247
+ updatedAt: now,
13248
+ overallStatus: newOverallStatus
13249
+ };
12849
13250
  }
13251
+ // Note: As per the request, full CRUD (create, direct update of instance, delete) is not part of this light service,
13252
+ // as those will be handled by Cloud Functions reacting to appointment lifecycle events.
12850
13253
  };
12851
13254
 
12852
13255
  // src/backoffice/services/brand.service.ts
12853
- var import_firestore41 = require("firebase/firestore");
13256
+ var import_firestore42 = require("firebase/firestore");
12854
13257
 
12855
13258
  // src/backoffice/types/brand.types.ts
12856
13259
  var BRANDS_COLLECTION = "brands";
@@ -12861,7 +13264,7 @@ var BrandService = class extends BaseService {
12861
13264
  * Gets reference to brands collection
12862
13265
  */
12863
13266
  getBrandsRef() {
12864
- return (0, import_firestore41.collection)(this.db, BRANDS_COLLECTION);
13267
+ return (0, import_firestore42.collection)(this.db, BRANDS_COLLECTION);
12865
13268
  }
12866
13269
  /**
12867
13270
  * Creates a new brand
@@ -12874,19 +13277,19 @@ var BrandService = class extends BaseService {
12874
13277
  updatedAt: now,
12875
13278
  isActive: true
12876
13279
  };
12877
- const docRef = await (0, import_firestore41.addDoc)(this.getBrandsRef(), newBrand);
13280
+ const docRef = await (0, import_firestore42.addDoc)(this.getBrandsRef(), newBrand);
12878
13281
  return { id: docRef.id, ...newBrand };
12879
13282
  }
12880
13283
  /**
12881
13284
  * Gets all active brands
12882
13285
  */
12883
13286
  async getAll() {
12884
- const q = (0, import_firestore41.query)(this.getBrandsRef(), (0, import_firestore41.where)("isActive", "==", true));
12885
- const snapshot = await (0, import_firestore41.getDocs)(q);
13287
+ const q = (0, import_firestore42.query)(this.getBrandsRef(), (0, import_firestore42.where)("isActive", "==", true));
13288
+ const snapshot = await (0, import_firestore42.getDocs)(q);
12886
13289
  return snapshot.docs.map(
12887
- (doc32) => ({
12888
- id: doc32.id,
12889
- ...doc32.data()
13290
+ (doc33) => ({
13291
+ id: doc33.id,
13292
+ ...doc33.data()
12890
13293
  })
12891
13294
  );
12892
13295
  }
@@ -12898,8 +13301,8 @@ var BrandService = class extends BaseService {
12898
13301
  ...brand,
12899
13302
  updatedAt: /* @__PURE__ */ new Date()
12900
13303
  };
12901
- const docRef = (0, import_firestore41.doc)(this.getBrandsRef(), brandId);
12902
- await (0, import_firestore41.updateDoc)(docRef, updateData);
13304
+ const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
13305
+ await (0, import_firestore42.updateDoc)(docRef, updateData);
12903
13306
  return this.getById(brandId);
12904
13307
  }
12905
13308
  /**
@@ -12914,8 +13317,8 @@ var BrandService = class extends BaseService {
12914
13317
  * Gets a brand by ID
12915
13318
  */
12916
13319
  async getById(brandId) {
12917
- const docRef = (0, import_firestore41.doc)(this.getBrandsRef(), brandId);
12918
- const docSnap = await (0, import_firestore41.getDoc)(docRef);
13320
+ const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
13321
+ const docSnap = await (0, import_firestore42.getDoc)(docRef);
12919
13322
  if (!docSnap.exists()) return null;
12920
13323
  return {
12921
13324
  id: docSnap.id,
@@ -12925,7 +13328,7 @@ var BrandService = class extends BaseService {
12925
13328
  };
12926
13329
 
12927
13330
  // src/backoffice/services/category.service.ts
12928
- var import_firestore42 = require("firebase/firestore");
13331
+ var import_firestore43 = require("firebase/firestore");
12929
13332
 
12930
13333
  // src/backoffice/types/category.types.ts
12931
13334
  var CATEGORIES_COLLECTION = "backoffice_categories";
@@ -12936,7 +13339,7 @@ var CategoryService = class extends BaseService {
12936
13339
  * Referenca na Firestore kolekciju kategorija
12937
13340
  */
12938
13341
  get categoriesRef() {
12939
- return (0, import_firestore42.collection)(this.db, CATEGORIES_COLLECTION);
13342
+ return (0, import_firestore43.collection)(this.db, CATEGORIES_COLLECTION);
12940
13343
  }
12941
13344
  /**
12942
13345
  * Kreira novu kategoriju u sistemu
@@ -12951,7 +13354,7 @@ var CategoryService = class extends BaseService {
12951
13354
  updatedAt: now,
12952
13355
  isActive: true
12953
13356
  };
12954
- const docRef = await (0, import_firestore42.addDoc)(this.categoriesRef, newCategory);
13357
+ const docRef = await (0, import_firestore43.addDoc)(this.categoriesRef, newCategory);
12955
13358
  return { id: docRef.id, ...newCategory };
12956
13359
  }
12957
13360
  /**
@@ -12959,12 +13362,12 @@ var CategoryService = class extends BaseService {
12959
13362
  * @returns Lista aktivnih kategorija
12960
13363
  */
12961
13364
  async getAll() {
12962
- const q = (0, import_firestore42.query)(this.categoriesRef, (0, import_firestore42.where)("isActive", "==", true));
12963
- const snapshot = await (0, import_firestore42.getDocs)(q);
13365
+ const q = (0, import_firestore43.query)(this.categoriesRef, (0, import_firestore43.where)("isActive", "==", true));
13366
+ const snapshot = await (0, import_firestore43.getDocs)(q);
12964
13367
  return snapshot.docs.map(
12965
- (doc32) => ({
12966
- id: doc32.id,
12967
- ...doc32.data()
13368
+ (doc33) => ({
13369
+ id: doc33.id,
13370
+ ...doc33.data()
12968
13371
  })
12969
13372
  );
12970
13373
  }
@@ -12974,16 +13377,16 @@ var CategoryService = class extends BaseService {
12974
13377
  * @returns Lista kategorija koje pripadaju traženoj familiji
12975
13378
  */
12976
13379
  async getAllByFamily(family) {
12977
- const q = (0, import_firestore42.query)(
13380
+ const q = (0, import_firestore43.query)(
12978
13381
  this.categoriesRef,
12979
- (0, import_firestore42.where)("family", "==", family),
12980
- (0, import_firestore42.where)("isActive", "==", true)
13382
+ (0, import_firestore43.where)("family", "==", family),
13383
+ (0, import_firestore43.where)("isActive", "==", true)
12981
13384
  );
12982
- const snapshot = await (0, import_firestore42.getDocs)(q);
13385
+ const snapshot = await (0, import_firestore43.getDocs)(q);
12983
13386
  return snapshot.docs.map(
12984
- (doc32) => ({
12985
- id: doc32.id,
12986
- ...doc32.data()
13387
+ (doc33) => ({
13388
+ id: doc33.id,
13389
+ ...doc33.data()
12987
13390
  })
12988
13391
  );
12989
13392
  }
@@ -12998,8 +13401,8 @@ var CategoryService = class extends BaseService {
12998
13401
  ...category,
12999
13402
  updatedAt: /* @__PURE__ */ new Date()
13000
13403
  };
13001
- const docRef = (0, import_firestore42.doc)(this.categoriesRef, id);
13002
- await (0, import_firestore42.updateDoc)(docRef, updateData);
13404
+ const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
13405
+ await (0, import_firestore43.updateDoc)(docRef, updateData);
13003
13406
  return this.getById(id);
13004
13407
  }
13005
13408
  /**
@@ -13015,8 +13418,8 @@ var CategoryService = class extends BaseService {
13015
13418
  * @returns Kategorija ili null ako ne postoji
13016
13419
  */
13017
13420
  async getById(id) {
13018
- const docRef = (0, import_firestore42.doc)(this.categoriesRef, id);
13019
- const docSnap = await (0, import_firestore42.getDoc)(docRef);
13421
+ const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
13422
+ const docSnap = await (0, import_firestore43.getDoc)(docRef);
13020
13423
  if (!docSnap.exists()) return null;
13021
13424
  return {
13022
13425
  id: docSnap.id,
@@ -13026,7 +13429,7 @@ var CategoryService = class extends BaseService {
13026
13429
  };
13027
13430
 
13028
13431
  // src/backoffice/services/subcategory.service.ts
13029
- var import_firestore43 = require("firebase/firestore");
13432
+ var import_firestore44 = require("firebase/firestore");
13030
13433
 
13031
13434
  // src/backoffice/types/subcategory.types.ts
13032
13435
  var SUBCATEGORIES_COLLECTION = "subcategories";
@@ -13038,7 +13441,7 @@ var SubcategoryService = class extends BaseService {
13038
13441
  * @param categoryId - ID roditeljske kategorije
13039
13442
  */
13040
13443
  getSubcategoriesRef(categoryId) {
13041
- return (0, import_firestore43.collection)(
13444
+ return (0, import_firestore44.collection)(
13042
13445
  this.db,
13043
13446
  CATEGORIES_COLLECTION,
13044
13447
  categoryId,
@@ -13060,7 +13463,7 @@ var SubcategoryService = class extends BaseService {
13060
13463
  updatedAt: now,
13061
13464
  isActive: true
13062
13465
  };
13063
- const docRef = await (0, import_firestore43.addDoc)(
13466
+ const docRef = await (0, import_firestore44.addDoc)(
13064
13467
  this.getSubcategoriesRef(categoryId),
13065
13468
  newSubcategory
13066
13469
  );
@@ -13072,15 +13475,15 @@ var SubcategoryService = class extends BaseService {
13072
13475
  * @returns Lista aktivnih podkategorija
13073
13476
  */
13074
13477
  async getAllByCategoryId(categoryId) {
13075
- const q = (0, import_firestore43.query)(
13478
+ const q = (0, import_firestore44.query)(
13076
13479
  this.getSubcategoriesRef(categoryId),
13077
- (0, import_firestore43.where)("isActive", "==", true)
13480
+ (0, import_firestore44.where)("isActive", "==", true)
13078
13481
  );
13079
- const snapshot = await (0, import_firestore43.getDocs)(q);
13482
+ const snapshot = await (0, import_firestore44.getDocs)(q);
13080
13483
  return snapshot.docs.map(
13081
- (doc32) => ({
13082
- id: doc32.id,
13083
- ...doc32.data()
13484
+ (doc33) => ({
13485
+ id: doc33.id,
13486
+ ...doc33.data()
13084
13487
  })
13085
13488
  );
13086
13489
  }
@@ -13096,8 +13499,8 @@ var SubcategoryService = class extends BaseService {
13096
13499
  ...subcategory,
13097
13500
  updatedAt: /* @__PURE__ */ new Date()
13098
13501
  };
13099
- const docRef = (0, import_firestore43.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13100
- await (0, import_firestore43.updateDoc)(docRef, updateData);
13502
+ const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13503
+ await (0, import_firestore44.updateDoc)(docRef, updateData);
13101
13504
  return this.getById(categoryId, subcategoryId);
13102
13505
  }
13103
13506
  /**
@@ -13115,8 +13518,8 @@ var SubcategoryService = class extends BaseService {
13115
13518
  * @returns Podkategorija ili null ako ne postoji
13116
13519
  */
13117
13520
  async getById(categoryId, subcategoryId) {
13118
- const docRef = (0, import_firestore43.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13119
- const docSnap = await (0, import_firestore43.getDoc)(docRef);
13521
+ const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
13522
+ const docSnap = await (0, import_firestore44.getDoc)(docRef);
13120
13523
  if (!docSnap.exists()) return null;
13121
13524
  return {
13122
13525
  id: docSnap.id,
@@ -13126,7 +13529,7 @@ var SubcategoryService = class extends BaseService {
13126
13529
  };
13127
13530
 
13128
13531
  // src/backoffice/services/technology.service.ts
13129
- var import_firestore44 = require("firebase/firestore");
13532
+ var import_firestore45 = require("firebase/firestore");
13130
13533
  var DEFAULT_CERTIFICATION_REQUIREMENT = {
13131
13534
  minimumLevel: "aesthetician" /* AESTHETICIAN */,
13132
13535
  requiredSpecialties: []
@@ -13136,7 +13539,7 @@ var TechnologyService = class extends BaseService {
13136
13539
  * Vraća referencu na Firestore kolekciju tehnologija
13137
13540
  */
13138
13541
  getTechnologiesRef() {
13139
- return (0, import_firestore44.collection)(this.db, TECHNOLOGIES_COLLECTION);
13542
+ return (0, import_firestore45.collection)(this.db, TECHNOLOGIES_COLLECTION);
13140
13543
  }
13141
13544
  /**
13142
13545
  * Kreira novu tehnologiju
@@ -13159,7 +13562,7 @@ var TechnologyService = class extends BaseService {
13159
13562
  benefits: technology.benefits || [],
13160
13563
  certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
13161
13564
  };
13162
- const docRef = await (0, import_firestore44.addDoc)(this.getTechnologiesRef(), newTechnology);
13565
+ const docRef = await (0, import_firestore45.addDoc)(this.getTechnologiesRef(), newTechnology);
13163
13566
  return { id: docRef.id, ...newTechnology };
13164
13567
  }
13165
13568
  /**
@@ -13167,12 +13570,12 @@ var TechnologyService = class extends BaseService {
13167
13570
  * @returns Lista aktivnih tehnologija
13168
13571
  */
13169
13572
  async getAll() {
13170
- const q = (0, import_firestore44.query)(this.getTechnologiesRef(), (0, import_firestore44.where)("isActive", "==", true));
13171
- const snapshot = await (0, import_firestore44.getDocs)(q);
13573
+ const q = (0, import_firestore45.query)(this.getTechnologiesRef(), (0, import_firestore45.where)("isActive", "==", true));
13574
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13172
13575
  return snapshot.docs.map(
13173
- (doc32) => ({
13174
- id: doc32.id,
13175
- ...doc32.data()
13576
+ (doc33) => ({
13577
+ id: doc33.id,
13578
+ ...doc33.data()
13176
13579
  })
13177
13580
  );
13178
13581
  }
@@ -13182,16 +13585,16 @@ var TechnologyService = class extends BaseService {
13182
13585
  * @returns Lista aktivnih tehnologija
13183
13586
  */
13184
13587
  async getAllByFamily(family) {
13185
- const q = (0, import_firestore44.query)(
13588
+ const q = (0, import_firestore45.query)(
13186
13589
  this.getTechnologiesRef(),
13187
- (0, import_firestore44.where)("isActive", "==", true),
13188
- (0, import_firestore44.where)("family", "==", family)
13590
+ (0, import_firestore45.where)("isActive", "==", true),
13591
+ (0, import_firestore45.where)("family", "==", family)
13189
13592
  );
13190
- const snapshot = await (0, import_firestore44.getDocs)(q);
13593
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13191
13594
  return snapshot.docs.map(
13192
- (doc32) => ({
13193
- id: doc32.id,
13194
- ...doc32.data()
13595
+ (doc33) => ({
13596
+ id: doc33.id,
13597
+ ...doc33.data()
13195
13598
  })
13196
13599
  );
13197
13600
  }
@@ -13201,16 +13604,16 @@ var TechnologyService = class extends BaseService {
13201
13604
  * @returns Lista aktivnih tehnologija
13202
13605
  */
13203
13606
  async getAllByCategoryId(categoryId) {
13204
- const q = (0, import_firestore44.query)(
13607
+ const q = (0, import_firestore45.query)(
13205
13608
  this.getTechnologiesRef(),
13206
- (0, import_firestore44.where)("isActive", "==", true),
13207
- (0, import_firestore44.where)("categoryId", "==", categoryId)
13609
+ (0, import_firestore45.where)("isActive", "==", true),
13610
+ (0, import_firestore45.where)("categoryId", "==", categoryId)
13208
13611
  );
13209
- const snapshot = await (0, import_firestore44.getDocs)(q);
13612
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13210
13613
  return snapshot.docs.map(
13211
- (doc32) => ({
13212
- id: doc32.id,
13213
- ...doc32.data()
13614
+ (doc33) => ({
13615
+ id: doc33.id,
13616
+ ...doc33.data()
13214
13617
  })
13215
13618
  );
13216
13619
  }
@@ -13220,16 +13623,16 @@ var TechnologyService = class extends BaseService {
13220
13623
  * @returns Lista aktivnih tehnologija
13221
13624
  */
13222
13625
  async getAllBySubcategoryId(subcategoryId) {
13223
- const q = (0, import_firestore44.query)(
13626
+ const q = (0, import_firestore45.query)(
13224
13627
  this.getTechnologiesRef(),
13225
- (0, import_firestore44.where)("isActive", "==", true),
13226
- (0, import_firestore44.where)("subcategoryId", "==", subcategoryId)
13628
+ (0, import_firestore45.where)("isActive", "==", true),
13629
+ (0, import_firestore45.where)("subcategoryId", "==", subcategoryId)
13227
13630
  );
13228
- const snapshot = await (0, import_firestore44.getDocs)(q);
13631
+ const snapshot = await (0, import_firestore45.getDocs)(q);
13229
13632
  return snapshot.docs.map(
13230
- (doc32) => ({
13231
- id: doc32.id,
13232
- ...doc32.data()
13633
+ (doc33) => ({
13634
+ id: doc33.id,
13635
+ ...doc33.data()
13233
13636
  })
13234
13637
  );
13235
13638
  }
@@ -13244,8 +13647,8 @@ var TechnologyService = class extends BaseService {
13244
13647
  ...technology,
13245
13648
  updatedAt: /* @__PURE__ */ new Date()
13246
13649
  };
13247
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13248
- await (0, import_firestore44.updateDoc)(docRef, updateData);
13650
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13651
+ await (0, import_firestore45.updateDoc)(docRef, updateData);
13249
13652
  return this.getById(technologyId);
13250
13653
  }
13251
13654
  /**
@@ -13263,8 +13666,8 @@ var TechnologyService = class extends BaseService {
13263
13666
  * @returns Tehnologija ili null ako ne postoji
13264
13667
  */
13265
13668
  async getById(technologyId) {
13266
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13267
- const docSnap = await (0, import_firestore44.getDoc)(docRef);
13669
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13670
+ const docSnap = await (0, import_firestore45.getDoc)(docRef);
13268
13671
  if (!docSnap.exists()) return null;
13269
13672
  return {
13270
13673
  id: docSnap.id,
@@ -13278,10 +13681,10 @@ var TechnologyService = class extends BaseService {
13278
13681
  * @returns Ažurirana tehnologija sa novim zahtevom
13279
13682
  */
13280
13683
  async addRequirement(technologyId, requirement) {
13281
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13684
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13282
13685
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
13283
- await (0, import_firestore44.updateDoc)(docRef, {
13284
- [requirementType]: (0, import_firestore44.arrayUnion)(requirement),
13686
+ await (0, import_firestore45.updateDoc)(docRef, {
13687
+ [requirementType]: (0, import_firestore45.arrayUnion)(requirement),
13285
13688
  updatedAt: /* @__PURE__ */ new Date()
13286
13689
  });
13287
13690
  return this.getById(technologyId);
@@ -13293,10 +13696,10 @@ var TechnologyService = class extends BaseService {
13293
13696
  * @returns Ažurirana tehnologija bez uklonjenog zahteva
13294
13697
  */
13295
13698
  async removeRequirement(technologyId, requirement) {
13296
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13699
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13297
13700
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
13298
- await (0, import_firestore44.updateDoc)(docRef, {
13299
- [requirementType]: (0, import_firestore44.arrayRemove)(requirement),
13701
+ await (0, import_firestore45.updateDoc)(docRef, {
13702
+ [requirementType]: (0, import_firestore45.arrayRemove)(requirement),
13300
13703
  updatedAt: /* @__PURE__ */ new Date()
13301
13704
  });
13302
13705
  return this.getById(technologyId);
@@ -13333,9 +13736,9 @@ var TechnologyService = class extends BaseService {
13333
13736
  * @returns Ažurirana tehnologija
13334
13737
  */
13335
13738
  async addBlockingCondition(technologyId, condition) {
13336
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13337
- await (0, import_firestore44.updateDoc)(docRef, {
13338
- blockingConditions: (0, import_firestore44.arrayUnion)(condition),
13739
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13740
+ await (0, import_firestore45.updateDoc)(docRef, {
13741
+ blockingConditions: (0, import_firestore45.arrayUnion)(condition),
13339
13742
  updatedAt: /* @__PURE__ */ new Date()
13340
13743
  });
13341
13744
  return this.getById(technologyId);
@@ -13347,9 +13750,9 @@ var TechnologyService = class extends BaseService {
13347
13750
  * @returns Ažurirana tehnologija
13348
13751
  */
13349
13752
  async removeBlockingCondition(technologyId, condition) {
13350
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13351
- await (0, import_firestore44.updateDoc)(docRef, {
13352
- blockingConditions: (0, import_firestore44.arrayRemove)(condition),
13753
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13754
+ await (0, import_firestore45.updateDoc)(docRef, {
13755
+ blockingConditions: (0, import_firestore45.arrayRemove)(condition),
13353
13756
  updatedAt: /* @__PURE__ */ new Date()
13354
13757
  });
13355
13758
  return this.getById(technologyId);
@@ -13361,9 +13764,9 @@ var TechnologyService = class extends BaseService {
13361
13764
  * @returns Ažurirana tehnologija
13362
13765
  */
13363
13766
  async addContraindication(technologyId, contraindication) {
13364
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13365
- await (0, import_firestore44.updateDoc)(docRef, {
13366
- contraindications: (0, import_firestore44.arrayUnion)(contraindication),
13767
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13768
+ await (0, import_firestore45.updateDoc)(docRef, {
13769
+ contraindications: (0, import_firestore45.arrayUnion)(contraindication),
13367
13770
  updatedAt: /* @__PURE__ */ new Date()
13368
13771
  });
13369
13772
  return this.getById(technologyId);
@@ -13375,9 +13778,9 @@ var TechnologyService = class extends BaseService {
13375
13778
  * @returns Ažurirana tehnologija
13376
13779
  */
13377
13780
  async removeContraindication(technologyId, contraindication) {
13378
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13379
- await (0, import_firestore44.updateDoc)(docRef, {
13380
- contraindications: (0, import_firestore44.arrayRemove)(contraindication),
13781
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13782
+ await (0, import_firestore45.updateDoc)(docRef, {
13783
+ contraindications: (0, import_firestore45.arrayRemove)(contraindication),
13381
13784
  updatedAt: /* @__PURE__ */ new Date()
13382
13785
  });
13383
13786
  return this.getById(technologyId);
@@ -13389,9 +13792,9 @@ var TechnologyService = class extends BaseService {
13389
13792
  * @returns Ažurirana tehnologija
13390
13793
  */
13391
13794
  async addBenefit(technologyId, benefit) {
13392
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13393
- await (0, import_firestore44.updateDoc)(docRef, {
13394
- benefits: (0, import_firestore44.arrayUnion)(benefit),
13795
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13796
+ await (0, import_firestore45.updateDoc)(docRef, {
13797
+ benefits: (0, import_firestore45.arrayUnion)(benefit),
13395
13798
  updatedAt: /* @__PURE__ */ new Date()
13396
13799
  });
13397
13800
  return this.getById(technologyId);
@@ -13403,9 +13806,9 @@ var TechnologyService = class extends BaseService {
13403
13806
  * @returns Ažurirana tehnologija
13404
13807
  */
13405
13808
  async removeBenefit(technologyId, benefit) {
13406
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13407
- await (0, import_firestore44.updateDoc)(docRef, {
13408
- benefits: (0, import_firestore44.arrayRemove)(benefit),
13809
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13810
+ await (0, import_firestore45.updateDoc)(docRef, {
13811
+ benefits: (0, import_firestore45.arrayRemove)(benefit),
13409
13812
  updatedAt: /* @__PURE__ */ new Date()
13410
13813
  });
13411
13814
  return this.getById(technologyId);
@@ -13444,8 +13847,8 @@ var TechnologyService = class extends BaseService {
13444
13847
  * @returns Ažurirana tehnologija
13445
13848
  */
13446
13849
  async updateCertificationRequirement(technologyId, certificationRequirement) {
13447
- const docRef = (0, import_firestore44.doc)(this.getTechnologiesRef(), technologyId);
13448
- await (0, import_firestore44.updateDoc)(docRef, {
13850
+ const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
13851
+ await (0, import_firestore45.updateDoc)(docRef, {
13449
13852
  certificationRequirement,
13450
13853
  updatedAt: /* @__PURE__ */ new Date()
13451
13854
  });
@@ -13545,7 +13948,7 @@ var TechnologyService = class extends BaseService {
13545
13948
  };
13546
13949
 
13547
13950
  // src/backoffice/services/product.service.ts
13548
- var import_firestore45 = require("firebase/firestore");
13951
+ var import_firestore46 = require("firebase/firestore");
13549
13952
 
13550
13953
  // src/backoffice/types/product.types.ts
13551
13954
  var PRODUCTS_COLLECTION = "products";
@@ -13558,7 +13961,7 @@ var ProductService = class extends BaseService {
13558
13961
  * @returns Firestore collection reference
13559
13962
  */
13560
13963
  getProductsRef(technologyId) {
13561
- return (0, import_firestore45.collection)(
13964
+ return (0, import_firestore46.collection)(
13562
13965
  this.db,
13563
13966
  TECHNOLOGIES_COLLECTION,
13564
13967
  technologyId,
@@ -13578,7 +13981,7 @@ var ProductService = class extends BaseService {
13578
13981
  updatedAt: now,
13579
13982
  isActive: true
13580
13983
  };
13581
- const productRef = await (0, import_firestore45.addDoc)(
13984
+ const productRef = await (0, import_firestore46.addDoc)(
13582
13985
  this.getProductsRef(technologyId),
13583
13986
  newProduct
13584
13987
  );
@@ -13588,15 +13991,15 @@ var ProductService = class extends BaseService {
13588
13991
  * Gets all products for a technology
13589
13992
  */
13590
13993
  async getAllByTechnology(technologyId) {
13591
- const q = (0, import_firestore45.query)(
13994
+ const q = (0, import_firestore46.query)(
13592
13995
  this.getProductsRef(technologyId),
13593
- (0, import_firestore45.where)("isActive", "==", true)
13996
+ (0, import_firestore46.where)("isActive", "==", true)
13594
13997
  );
13595
- const snapshot = await (0, import_firestore45.getDocs)(q);
13998
+ const snapshot = await (0, import_firestore46.getDocs)(q);
13596
13999
  return snapshot.docs.map(
13597
- (doc32) => ({
13598
- id: doc32.id,
13599
- ...doc32.data()
14000
+ (doc33) => ({
14001
+ id: doc33.id,
14002
+ ...doc33.data()
13600
14003
  })
13601
14004
  );
13602
14005
  }
@@ -13604,21 +14007,21 @@ var ProductService = class extends BaseService {
13604
14007
  * Gets all products for a brand by filtering through all technologies
13605
14008
  */
13606
14009
  async getAllByBrand(brandId) {
13607
- const allTechnologiesRef = (0, import_firestore45.collection)(this.db, TECHNOLOGIES_COLLECTION);
13608
- const technologiesSnapshot = await (0, import_firestore45.getDocs)(allTechnologiesRef);
14010
+ const allTechnologiesRef = (0, import_firestore46.collection)(this.db, TECHNOLOGIES_COLLECTION);
14011
+ const technologiesSnapshot = await (0, import_firestore46.getDocs)(allTechnologiesRef);
13609
14012
  const products = [];
13610
14013
  for (const techDoc of technologiesSnapshot.docs) {
13611
- const q = (0, import_firestore45.query)(
14014
+ const q = (0, import_firestore46.query)(
13612
14015
  this.getProductsRef(techDoc.id),
13613
- (0, import_firestore45.where)("brandId", "==", brandId),
13614
- (0, import_firestore45.where)("isActive", "==", true)
14016
+ (0, import_firestore46.where)("brandId", "==", brandId),
14017
+ (0, import_firestore46.where)("isActive", "==", true)
13615
14018
  );
13616
- const snapshot = await (0, import_firestore45.getDocs)(q);
14019
+ const snapshot = await (0, import_firestore46.getDocs)(q);
13617
14020
  products.push(
13618
14021
  ...snapshot.docs.map(
13619
- (doc32) => ({
13620
- id: doc32.id,
13621
- ...doc32.data()
14022
+ (doc33) => ({
14023
+ id: doc33.id,
14024
+ ...doc33.data()
13622
14025
  })
13623
14026
  )
13624
14027
  );
@@ -13633,8 +14036,8 @@ var ProductService = class extends BaseService {
13633
14036
  ...product,
13634
14037
  updatedAt: /* @__PURE__ */ new Date()
13635
14038
  };
13636
- const docRef = (0, import_firestore45.doc)(this.getProductsRef(technologyId), productId);
13637
- await (0, import_firestore45.updateDoc)(docRef, updateData);
14039
+ const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
14040
+ await (0, import_firestore46.updateDoc)(docRef, updateData);
13638
14041
  return this.getById(technologyId, productId);
13639
14042
  }
13640
14043
  /**
@@ -13649,8 +14052,8 @@ var ProductService = class extends BaseService {
13649
14052
  * Gets a product by ID
13650
14053
  */
13651
14054
  async getById(technologyId, productId) {
13652
- const docRef = (0, import_firestore45.doc)(this.getProductsRef(technologyId), productId);
13653
- const docSnap = await (0, import_firestore45.getDoc)(docRef);
14055
+ const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
14056
+ const docSnap = await (0, import_firestore46.getDoc)(docRef);
13654
14057
  if (!docSnap.exists()) return null;
13655
14058
  return {
13656
14059
  id: docSnap.id,
@@ -13679,14 +14082,14 @@ var baseNotificationSchema = import_zod24.z.object({
13679
14082
  userRole: import_zod24.z.nativeEnum(UserRole)
13680
14083
  });
13681
14084
  var preRequirementNotificationSchema = baseNotificationSchema.extend({
13682
- notificationType: import_zod24.z.literal("preRequirement" /* PRE_REQUIREMENT */),
14085
+ notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
13683
14086
  treatmentId: import_zod24.z.string(),
13684
14087
  requirements: import_zod24.z.array(import_zod24.z.string()),
13685
14088
  deadline: import_zod24.z.any()
13686
14089
  // Timestamp
13687
14090
  });
13688
14091
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
13689
- notificationType: import_zod24.z.literal("postRequirement" /* POST_REQUIREMENT */),
14092
+ notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
13690
14093
  treatmentId: import_zod24.z.string(),
13691
14094
  requirements: import_zod24.z.array(import_zod24.z.string()),
13692
14095
  deadline: import_zod24.z.any()
@@ -13701,7 +14104,7 @@ var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
13701
14104
  doctorName: import_zod24.z.string()
13702
14105
  });
13703
14106
  var appointmentNotificationSchema = baseNotificationSchema.extend({
13704
- notificationType: import_zod24.z.literal("appointmentNotification" /* APPOINTMENT_NOTIFICATION */),
14107
+ notificationType: import_zod24.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
13705
14108
  appointmentId: import_zod24.z.string(),
13706
14109
  appointmentStatus: import_zod24.z.string(),
13707
14110
  previousStatus: import_zod24.z.string(),
@@ -13798,9 +14201,13 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13798
14201
  PATIENT_LOCATION_INFO_COLLECTION,
13799
14202
  PATIENT_MEDICAL_HISTORY_COLLECTION,
13800
14203
  PATIENT_MEDICAL_INFO_COLLECTION,
14204
+ PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
13801
14205
  PATIENT_SENSITIVE_INFO_COLLECTION,
13802
14206
  PRACTITIONERS_COLLECTION,
13803
14207
  PROCEDURES_COLLECTION,
14208
+ PatientInstructionStatus,
14209
+ PatientRequirementOverallStatus,
14210
+ PatientRequirementsService,
13804
14211
  PatientService,
13805
14212
  PaymentStatus,
13806
14213
  PracticeType,
@@ -13865,6 +14272,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13865
14272
  createDefaultClinicGroupSchema,
13866
14273
  createDocumentTemplateSchema,
13867
14274
  createDraftPractitionerSchema,
14275
+ createFilledDocumentDataSchema,
13868
14276
  createPatientLocationInfoSchema,
13869
14277
  createPatientMedicalInfoSchema,
13870
14278
  createPatientProfileSchema,
@@ -13880,6 +14288,8 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13880
14288
  documentTemplateSchema,
13881
14289
  emailSchema,
13882
14290
  emergencyContactSchema,
14291
+ filledDocumentSchema,
14292
+ filledDocumentStatusSchema,
13883
14293
  gamificationSchema,
13884
14294
  getFirebaseApp,
13885
14295
  getFirebaseAuth,
@@ -13929,6 +14339,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
13929
14339
  updateClinicSchema,
13930
14340
  updateContraindicationSchema,
13931
14341
  updateDocumentTemplateSchema,
14342
+ updateFilledDocumentDataSchema,
13932
14343
  updateMedicationSchema,
13933
14344
  updatePatientMedicalInfoSchema,
13934
14345
  updateVitalStatsSchema,