@blackcode_sa/metaestetics-api 1.11.3 → 1.12.1

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 (53) hide show
  1. package/dist/admin/index.d.mts +378 -334
  2. package/dist/admin/index.d.ts +378 -334
  3. package/dist/backoffice/index.d.mts +1198 -430
  4. package/dist/backoffice/index.d.ts +1198 -430
  5. package/dist/backoffice/index.js +1128 -245
  6. package/dist/backoffice/index.mjs +1119 -209
  7. package/dist/index.d.mts +4478 -4031
  8. package/dist/index.d.ts +4478 -4031
  9. package/dist/index.js +1974 -757
  10. package/dist/index.mjs +1735 -490
  11. package/package.json +1 -1
  12. package/src/backoffice/expo-safe/index.ts +4 -0
  13. package/src/backoffice/services/README.md +40 -0
  14. package/src/backoffice/services/brand.service.ts +85 -6
  15. package/src/backoffice/services/category.service.ts +92 -10
  16. package/src/backoffice/services/constants.service.ts +308 -0
  17. package/src/backoffice/services/documentation-template.service.ts +56 -2
  18. package/src/backoffice/services/index.ts +1 -0
  19. package/src/backoffice/services/product.service.ts +126 -5
  20. package/src/backoffice/services/requirement.service.ts +13 -0
  21. package/src/backoffice/services/subcategory.service.ts +184 -13
  22. package/src/backoffice/services/technology.service.ts +344 -129
  23. package/src/backoffice/types/admin-constants.types.ts +69 -0
  24. package/src/backoffice/types/brand.types.ts +1 -0
  25. package/src/backoffice/types/index.ts +2 -0
  26. package/src/backoffice/types/procedure-product.types.ts +38 -0
  27. package/src/backoffice/types/product.types.ts +31 -4
  28. package/src/backoffice/types/static/contraindication.types.ts +1 -0
  29. package/src/backoffice/types/static/treatment-benefit.types.ts +1 -0
  30. package/src/backoffice/types/technology.types.ts +113 -4
  31. package/src/backoffice/validations/schemas.ts +35 -9
  32. package/src/services/appointment/appointment.service.ts +0 -5
  33. package/src/services/appointment/utils/appointment.utils.ts +124 -113
  34. package/src/services/base.service.ts +10 -3
  35. package/src/services/documentation-templates/documentation-template.service.ts +116 -0
  36. package/src/services/media/media.service.ts +2 -2
  37. package/src/services/practitioner/practitioner.service.ts +201 -83
  38. package/src/services/procedure/README.md +76 -1
  39. package/src/services/procedure/procedure.service.ts +538 -235
  40. package/src/types/appointment/index.ts +2 -3
  41. package/src/types/clinic/index.ts +1 -6
  42. package/src/types/patient/medical-info.types.ts +3 -3
  43. package/src/types/procedure/index.ts +39 -20
  44. package/src/validations/clinic.schema.ts +1 -6
  45. package/src/validations/patient/medical-info.schema.ts +7 -2
  46. package/src/validations/procedure-product.schema.ts +41 -0
  47. package/src/validations/procedure.schema.ts +59 -8
  48. package/src/backoffice/services/__tests__/brand.service.test.ts +0 -196
  49. package/src/backoffice/services/__tests__/category.service.test.ts +0 -201
  50. package/src/backoffice/services/__tests__/product.service.test.ts +0 -358
  51. package/src/backoffice/services/__tests__/requirement.service.test.ts +0 -226
  52. package/src/backoffice/services/__tests__/subcategory.service.test.ts +0 -181
  53. package/src/backoffice/services/__tests__/technology.service.test.ts +0 -1097
package/dist/index.js CHANGED
@@ -56,6 +56,7 @@ __export(index_exports, {
56
56
  ClinicPhotoTag: () => ClinicPhotoTag,
57
57
  ClinicService: () => ClinicService,
58
58
  ClinicTag: () => ClinicTag,
59
+ ConstantsService: () => ConstantsService,
59
60
  Contraindication: () => Contraindication,
60
61
  CosmeticAllergySubtype: () => CosmeticAllergySubtype,
61
62
  Currency: () => Currency,
@@ -145,11 +146,13 @@ var import_functions = require("firebase/functions");
145
146
  // src/services/base.service.ts
146
147
  var import_storage = require("firebase/storage");
147
148
  var BaseService = class {
148
- constructor(db, auth, app) {
149
+ constructor(db, auth, app, storage) {
149
150
  this.db = db;
150
151
  this.auth = auth;
151
152
  this.app = app;
152
- this.storage = (0, import_storage.getStorage)(app);
153
+ if (app) {
154
+ this.storage = storage || (0, import_storage.getStorage)(app);
155
+ }
153
156
  }
154
157
  /**
155
158
  * Generiše jedinstveni ID za dokumente
@@ -181,13 +184,13 @@ var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
181
184
  AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
182
185
  return AppointmentStatus2;
183
186
  })(AppointmentStatus || {});
184
- var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
185
- PaymentStatus3["UNPAID"] = "unpaid";
186
- PaymentStatus3["PAID"] = "paid";
187
- PaymentStatus3["PARTIALLY_PAID"] = "partially_paid";
188
- PaymentStatus3["REFUNDED"] = "refunded";
189
- PaymentStatus3["NOT_APPLICABLE"] = "not_applicable";
190
- return PaymentStatus3;
187
+ var PaymentStatus = /* @__PURE__ */ ((PaymentStatus4) => {
188
+ PaymentStatus4["UNPAID"] = "unpaid";
189
+ PaymentStatus4["PAID"] = "paid";
190
+ PaymentStatus4["PARTIALLY_PAID"] = "partially_paid";
191
+ PaymentStatus4["REFUNDED"] = "refunded";
192
+ PaymentStatus4["NOT_APPLICABLE"] = "not_applicable";
193
+ return PaymentStatus4;
191
194
  })(PaymentStatus || {});
192
195
  var MediaType = /* @__PURE__ */ ((MediaType2) => {
193
196
  MediaType2["BEFORE_PHOTO"] = "before_photo";
@@ -933,44 +936,48 @@ async function updateAppointmentUtil(db, appointmentId, data) {
933
936
  const validPreReqIds = currentAppointment.preProcedureRequirements.map(
934
937
  (req) => req.id
935
938
  );
936
- const invalidPreReqIds = data.completedPreRequirements.filter(
937
- (id) => !validPreReqIds.includes(id)
938
- );
939
- if (invalidPreReqIds.length > 0) {
940
- throw new Error(
941
- `Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
939
+ if (Array.isArray(data.completedPreRequirements)) {
940
+ const invalidPreReqIds = data.completedPreRequirements.filter(
941
+ (id) => !validPreReqIds.includes(id)
942
942
  );
943
+ if (invalidPreReqIds.length > 0) {
944
+ throw new Error(
945
+ `Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
946
+ );
947
+ }
948
+ completedPreRequirements = [
949
+ .../* @__PURE__ */ new Set([
950
+ ...completedPreRequirements,
951
+ ...data.completedPreRequirements
952
+ ])
953
+ ];
943
954
  }
944
- completedPreRequirements = [
945
- .../* @__PURE__ */ new Set([
946
- ...completedPreRequirements,
947
- ...data.completedPreRequirements
948
- ])
949
- ];
950
955
  }
951
956
  if (data.completedPostRequirements) {
952
957
  const validPostReqIds = currentAppointment.postProcedureRequirements.map(
953
958
  (req) => req.id
954
959
  );
955
- const invalidPostReqIds = data.completedPostRequirements.filter(
956
- (id) => !validPostReqIds.includes(id)
957
- );
958
- if (invalidPostReqIds.length > 0) {
959
- throw new Error(
960
- `Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
960
+ if (Array.isArray(data.completedPostRequirements)) {
961
+ const invalidPostReqIds = data.completedPostRequirements.filter(
962
+ (id) => !validPostReqIds.includes(id)
961
963
  );
964
+ if (invalidPostReqIds.length > 0) {
965
+ throw new Error(
966
+ `Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
967
+ );
968
+ }
969
+ completedPostRequirements = [
970
+ .../* @__PURE__ */ new Set([
971
+ ...completedPostRequirements,
972
+ ...data.completedPostRequirements
973
+ ])
974
+ ];
962
975
  }
963
- completedPostRequirements = [
964
- .../* @__PURE__ */ new Set([
965
- ...completedPostRequirements,
966
- ...data.completedPostRequirements
967
- ])
968
- ];
969
976
  }
970
977
  const updateData = {
971
978
  ...data,
972
- completedPreRequirements,
973
- completedPostRequirements,
979
+ completedPreRequirements: Array.isArray(data.completedPreRequirements) ? completedPreRequirements : data.completedPreRequirements,
980
+ completedPostRequirements: Array.isArray(data.completedPostRequirements) ? completedPostRequirements : data.completedPostRequirements,
974
981
  updatedAt: (0, import_firestore.serverTimestamp)()
975
982
  };
976
983
  Object.keys(updateData).forEach((key) => {
@@ -1020,7 +1027,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
1020
1027
  case "canceled_clinic" /* CANCELED_CLINIC */:
1021
1028
  calendarStatus = "canceled";
1022
1029
  break;
1023
- case AppointmentStatus.RESCHEDULED:
1030
+ case "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */:
1024
1031
  calendarStatus = "rescheduled";
1025
1032
  break;
1026
1033
  case "completed" /* COMPLETED */:
@@ -1094,7 +1101,7 @@ async function searchAppointmentsUtil(db, params) {
1094
1101
  const q = (0, import_firestore.query)((0, import_firestore.collection)(db, APPOINTMENTS_COLLECTION), ...constraints);
1095
1102
  const querySnapshot = await (0, import_firestore.getDocs)(q);
1096
1103
  const appointments = querySnapshot.docs.map(
1097
- (doc37) => doc37.data()
1104
+ (doc38) => doc38.data()
1098
1105
  );
1099
1106
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1100
1107
  return { appointments, lastDoc };
@@ -1901,7 +1908,7 @@ var AppointmentService = class extends BaseService {
1901
1908
  );
1902
1909
  const querySnapshot = await (0, import_firestore2.getDocs)(q);
1903
1910
  const appointments = querySnapshot.docs.map(
1904
- (doc37) => doc37.data()
1911
+ (doc38) => doc38.data()
1905
1912
  );
1906
1913
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1907
1914
  console.log(
@@ -1974,7 +1981,7 @@ var AppointmentService = class extends BaseService {
1974
1981
  );
1975
1982
  const querySnapshot = await (0, import_firestore2.getDocs)(q);
1976
1983
  const appointments = querySnapshot.docs.map(
1977
- (doc37) => doc37.data()
1984
+ (doc38) => doc38.data()
1978
1985
  );
1979
1986
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1980
1987
  console.log(
@@ -2470,8 +2477,8 @@ var MediaAccessLevel = /* @__PURE__ */ ((MediaAccessLevel2) => {
2470
2477
  })(MediaAccessLevel || {});
2471
2478
  var MEDIA_METADATA_COLLECTION = "media_metadata";
2472
2479
  var MediaService = class extends BaseService {
2473
- constructor(db, auth, app) {
2474
- super(db, auth, app);
2480
+ constructor(...args) {
2481
+ super(...args);
2475
2482
  }
2476
2483
  /**
2477
2484
  * Upload a media file, store its metadata, and return the metadata including the URL.
@@ -2731,7 +2738,7 @@ var MediaService = class extends BaseService {
2731
2738
  try {
2732
2739
  const querySnapshot = await (0, import_firestore4.getDocs)(finalQuery);
2733
2740
  const mediaList = querySnapshot.docs.map(
2734
- (doc37) => doc37.data()
2741
+ (doc38) => doc38.data()
2735
2742
  );
2736
2743
  console.log(`[MediaService] Found ${mediaList.length} media items.`);
2737
2744
  return mediaList;
@@ -2785,8 +2792,8 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2785
2792
  }
2786
2793
  const patientsSnapshot = await (0, import_firestore5.getDocs)(q);
2787
2794
  const patients = [];
2788
- patientsSnapshot.forEach((doc37) => {
2789
- patients.push(doc37.data());
2795
+ patientsSnapshot.forEach((doc38) => {
2796
+ patients.push(doc38.data());
2790
2797
  });
2791
2798
  console.log(
2792
2799
  `[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
@@ -2836,23 +2843,6 @@ var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
2836
2843
  return BlockingCondition2;
2837
2844
  })(BlockingCondition || {});
2838
2845
 
2839
- // src/backoffice/types/static/contraindication.types.ts
2840
- var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
2841
- Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
2842
- Contraindication2["RECENT_TANNING"] = "recent_tanning";
2843
- Contraindication2["RECENT_BOTOX"] = "recent_botox";
2844
- Contraindication2["RECENT_FILLERS"] = "recent_fillers";
2845
- Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
2846
- Contraindication2["MEDICATIONS"] = "medications";
2847
- Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
2848
- Contraindication2["RECENT_LASER"] = "recent_laser";
2849
- Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
2850
- Contraindication2["OPEN_WOUNDS"] = "open_wounds";
2851
- Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
2852
- Contraindication2["COLD_SORES"] = "cold_sores";
2853
- return Contraindication2;
2854
- })(Contraindication || {});
2855
-
2856
2846
  // src/validations/common.schema.ts
2857
2847
  var import_zod5 = require("zod");
2858
2848
  var import_firestore6 = require("firebase/firestore");
@@ -2907,8 +2897,13 @@ var blockingConditionSchema = import_zod6.z.object({
2907
2897
  notes: import_zod6.z.string().optional().nullable(),
2908
2898
  isActive: import_zod6.z.boolean()
2909
2899
  });
2900
+ var contraindicationDynamicSchema = import_zod6.z.object({
2901
+ id: import_zod6.z.string(),
2902
+ name: import_zod6.z.string(),
2903
+ description: import_zod6.z.string().optional()
2904
+ });
2910
2905
  var contraindicationSchema = import_zod6.z.object({
2911
- condition: import_zod6.z.nativeEnum(Contraindication),
2906
+ condition: contraindicationDynamicSchema,
2912
2907
  lastOccurrence: timestampSchema,
2913
2908
  frequency: import_zod6.z.enum(["rare", "occasional", "frequent"]),
2914
2909
  notes: import_zod6.z.string().optional().nullable(),
@@ -3139,8 +3134,8 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
3139
3134
  }
3140
3135
  const patientsSnapshot = await (0, import_firestore8.getDocs)(q);
3141
3136
  const patients = [];
3142
- patientsSnapshot.forEach((doc37) => {
3143
- patients.push(doc37.data());
3137
+ patientsSnapshot.forEach((doc38) => {
3138
+ patients.push(doc38.data());
3144
3139
  });
3145
3140
  console.log(
3146
3141
  `[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
@@ -3907,7 +3902,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
3907
3902
  (0, import_firestore10.where)("clinicGroupId", "==", clinicGroupId)
3908
3903
  );
3909
3904
  const querySnapshot = await (0, import_firestore10.getDocs)(q);
3910
- return querySnapshot.docs.map((doc37) => doc37.data());
3905
+ return querySnapshot.docs.map((doc38) => doc38.data());
3911
3906
  }
3912
3907
  async function updateClinicAdmin(db, adminId, data) {
3913
3908
  const admin = await getClinicAdmin(db, adminId);
@@ -4570,9 +4565,9 @@ var updateAllergyUtil = async (db, patientId, data, requesterId, requesterRoles)
4570
4565
  };
4571
4566
  var removeAllergyUtil = async (db, patientId, allergyIndex, requesterId, requesterRoles) => {
4572
4567
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4573
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4574
- if (!doc37.exists()) throw new Error("Medical info not found");
4575
- const medicalInfo = doc37.data();
4568
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4569
+ if (!doc38.exists()) throw new Error("Medical info not found");
4570
+ const medicalInfo = doc38.data();
4576
4571
  if (allergyIndex >= medicalInfo.allergies.length) {
4577
4572
  throw new Error("Invalid allergy index");
4578
4573
  }
@@ -4599,9 +4594,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, requesterId, reque
4599
4594
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4600
4595
  const validatedData = updateBlockingConditionSchema.parse(data);
4601
4596
  const { conditionIndex, ...updateData } = validatedData;
4602
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4603
- if (!doc37.exists()) throw new Error("Medical info not found");
4604
- const medicalInfo = doc37.data();
4597
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4598
+ if (!doc38.exists()) throw new Error("Medical info not found");
4599
+ const medicalInfo = doc38.data();
4605
4600
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
4606
4601
  throw new Error("Invalid blocking condition index");
4607
4602
  }
@@ -4618,9 +4613,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, requesterId, reque
4618
4613
  };
4619
4614
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, requesterId, requesterRoles) => {
4620
4615
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4621
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4622
- if (!doc37.exists()) throw new Error("Medical info not found");
4623
- const medicalInfo = doc37.data();
4616
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4617
+ if (!doc38.exists()) throw new Error("Medical info not found");
4618
+ const medicalInfo = doc38.data();
4624
4619
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
4625
4620
  throw new Error("Invalid blocking condition index");
4626
4621
  }
@@ -4647,9 +4642,9 @@ var updateContraindicationUtil = async (db, patientId, data, requesterId, reques
4647
4642
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4648
4643
  const validatedData = updateContraindicationSchema.parse(data);
4649
4644
  const { contraindicationIndex, ...updateData } = validatedData;
4650
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4651
- if (!doc37.exists()) throw new Error("Medical info not found");
4652
- const medicalInfo = doc37.data();
4645
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4646
+ if (!doc38.exists()) throw new Error("Medical info not found");
4647
+ const medicalInfo = doc38.data();
4653
4648
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
4654
4649
  throw new Error("Invalid contraindication index");
4655
4650
  }
@@ -4666,9 +4661,9 @@ var updateContraindicationUtil = async (db, patientId, data, requesterId, reques
4666
4661
  };
4667
4662
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, requesterId, requesterRoles) => {
4668
4663
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4669
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4670
- if (!doc37.exists()) throw new Error("Medical info not found");
4671
- const medicalInfo = doc37.data();
4664
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4665
+ if (!doc38.exists()) throw new Error("Medical info not found");
4666
+ const medicalInfo = doc38.data();
4672
4667
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
4673
4668
  throw new Error("Invalid contraindication index");
4674
4669
  }
@@ -4695,9 +4690,9 @@ var updateMedicationUtil = async (db, patientId, data, requesterId, requesterRol
4695
4690
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4696
4691
  const validatedData = updateMedicationSchema.parse(data);
4697
4692
  const { medicationIndex, ...updateData } = validatedData;
4698
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4699
- if (!doc37.exists()) throw new Error("Medical info not found");
4700
- const medicalInfo = doc37.data();
4693
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4694
+ if (!doc38.exists()) throw new Error("Medical info not found");
4695
+ const medicalInfo = doc38.data();
4701
4696
  if (medicationIndex >= medicalInfo.currentMedications.length) {
4702
4697
  throw new Error("Invalid medication index");
4703
4698
  }
@@ -4714,9 +4709,9 @@ var updateMedicationUtil = async (db, patientId, data, requesterId, requesterRol
4714
4709
  };
4715
4710
  var removeMedicationUtil = async (db, patientId, medicationIndex, requesterId, requesterRoles) => {
4716
4711
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4717
- const doc37 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4718
- if (!doc37.exists()) throw new Error("Medical info not found");
4719
- const medicalInfo = doc37.data();
4712
+ const doc38 = await (0, import_firestore15.getDoc)(getMedicalInfoDocRef(db, patientId));
4713
+ if (!doc38.exists()) throw new Error("Medical info not found");
4714
+ const medicalInfo = doc38.data();
4720
4715
  if (medicationIndex >= medicalInfo.currentMedications.length) {
4721
4716
  throw new Error("Invalid medication index");
4722
4717
  }
@@ -5003,7 +4998,7 @@ var searchPatientsUtil = async (db, params, requester) => {
5003
4998
  const finalQuery = (0, import_firestore16.query)(patientsCollectionRef, ...constraints);
5004
4999
  const querySnapshot = await (0, import_firestore16.getDocs)(finalQuery);
5005
5000
  const patients = querySnapshot.docs.map(
5006
- (doc37) => doc37.data()
5001
+ (doc38) => doc38.data()
5007
5002
  );
5008
5003
  console.log(
5009
5004
  `[searchPatientsUtil] Found ${patients.length} patients matching criteria.`
@@ -5035,8 +5030,8 @@ var getAllPatientsUtil = async (db, options) => {
5035
5030
  }
5036
5031
  const patientsSnapshot = await (0, import_firestore16.getDocs)(q);
5037
5032
  const patients = [];
5038
- patientsSnapshot.forEach((doc37) => {
5039
- patients.push(doc37.data());
5033
+ patientsSnapshot.forEach((doc38) => {
5034
+ patients.push(doc38.data());
5040
5035
  });
5041
5036
  console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
5042
5037
  return patients;
@@ -5158,7 +5153,7 @@ var getActiveInviteTokensByClinicUtil = async (db, clinicId) => {
5158
5153
  if (querySnapshot.empty) {
5159
5154
  return [];
5160
5155
  }
5161
- return querySnapshot.docs.map((doc37) => doc37.data());
5156
+ return querySnapshot.docs.map((doc38) => doc38.data());
5162
5157
  };
5163
5158
  var getActiveInviteTokensByPatientUtil = async (db, patientId) => {
5164
5159
  const tokensRef = (0, import_firestore17.collection)(
@@ -5176,7 +5171,7 @@ var getActiveInviteTokensByPatientUtil = async (db, patientId) => {
5176
5171
  if (querySnapshot.empty) {
5177
5172
  return [];
5178
5173
  }
5179
- return querySnapshot.docs.map((doc37) => doc37.data());
5174
+ return querySnapshot.docs.map((doc38) => doc38.data());
5180
5175
  };
5181
5176
 
5182
5177
  // src/services/patient/patient.service.ts
@@ -6448,7 +6443,7 @@ var PractitionerService = class extends BaseService {
6448
6443
  (0, import_firestore21.where)("expiresAt", ">", import_firestore21.Timestamp.now())
6449
6444
  );
6450
6445
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6451
- return querySnapshot.docs.map((doc37) => doc37.data());
6446
+ return querySnapshot.docs.map((doc38) => doc38.data());
6452
6447
  }
6453
6448
  /**
6454
6449
  * Gets a token by its string value and validates it
@@ -6558,7 +6553,7 @@ var PractitionerService = class extends BaseService {
6558
6553
  (0, import_firestore21.where)("status", "==", "active" /* ACTIVE */)
6559
6554
  );
6560
6555
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6561
- return querySnapshot.docs.map((doc37) => doc37.data());
6556
+ return querySnapshot.docs.map((doc38) => doc38.data());
6562
6557
  }
6563
6558
  /**
6564
6559
  * Dohvata sve zdravstvene radnike za određenu kliniku
@@ -6570,7 +6565,7 @@ var PractitionerService = class extends BaseService {
6570
6565
  (0, import_firestore21.where)("isActive", "==", true)
6571
6566
  );
6572
6567
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6573
- return querySnapshot.docs.map((doc37) => doc37.data());
6568
+ return querySnapshot.docs.map((doc38) => doc38.data());
6574
6569
  }
6575
6570
  /**
6576
6571
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
@@ -6582,7 +6577,7 @@ var PractitionerService = class extends BaseService {
6582
6577
  (0, import_firestore21.where)("status", "==", "draft" /* DRAFT */)
6583
6578
  );
6584
6579
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6585
- return querySnapshot.docs.map((doc37) => doc37.data());
6580
+ return querySnapshot.docs.map((doc38) => doc38.data());
6586
6581
  }
6587
6582
  /**
6588
6583
  * Updates a practitioner
@@ -6600,7 +6595,9 @@ var PractitionerService = class extends BaseService {
6600
6595
  throw new Error(`Practitioner ${practitionerId} not found`);
6601
6596
  }
6602
6597
  const currentPractitioner = practitionerDoc.data();
6603
- let processedData = { ...validData };
6598
+ let processedData = {
6599
+ ...validData
6600
+ };
6604
6601
  if (validData.basicInfo) {
6605
6602
  processedData.basicInfo = await this.processBasicInfo(
6606
6603
  validData.basicInfo,
@@ -6797,7 +6794,7 @@ var PractitionerService = class extends BaseService {
6797
6794
  );
6798
6795
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6799
6796
  const practitioners = querySnapshot.docs.map(
6800
- (doc37) => doc37.data()
6797
+ (doc38) => doc38.data()
6801
6798
  );
6802
6799
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6803
6800
  return {
@@ -6834,7 +6831,9 @@ var PractitionerService = class extends BaseService {
6834
6831
  */
6835
6832
  async getPractitionersByFilters(filters) {
6836
6833
  try {
6837
- console.log("[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies");
6834
+ console.log(
6835
+ "[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies"
6836
+ );
6838
6837
  if (filters.location && filters.radiusInKm) {
6839
6838
  console.log("[PRACTITIONER_SERVICE] Executing geo query:", {
6840
6839
  location: filters.location,
@@ -6842,14 +6841,19 @@ var PractitionerService = class extends BaseService {
6842
6841
  serviceName: "PractitionerService"
6843
6842
  });
6844
6843
  if (!filters.location.latitude || !filters.location.longitude) {
6845
- console.warn("[PRACTITIONER_SERVICE] Invalid location data:", filters.location);
6844
+ console.warn(
6845
+ "[PRACTITIONER_SERVICE] Invalid location data:",
6846
+ filters.location
6847
+ );
6846
6848
  filters.location = void 0;
6847
6849
  filters.radiusInKm = void 0;
6848
6850
  }
6849
6851
  }
6850
6852
  if (filters.nameSearch && filters.nameSearch.trim()) {
6851
6853
  try {
6852
- console.log("[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search");
6854
+ console.log(
6855
+ "[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search"
6856
+ );
6853
6857
  const searchTerm = filters.nameSearch.trim().toLowerCase();
6854
6858
  const constraints = [];
6855
6859
  if (!filters.includeDraftPractitioners) {
@@ -6869,11 +6873,18 @@ var PractitionerService = class extends BaseService {
6869
6873
  }
6870
6874
  }
6871
6875
  constraints.push((0, import_firestore21.limit)(filters.pagination || 10));
6872
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6876
+ const q = (0, import_firestore21.query)(
6877
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6878
+ ...constraints
6879
+ );
6873
6880
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6874
- const practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6881
+ const practitioners = querySnapshot.docs.map(
6882
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6883
+ );
6875
6884
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6876
- console.log(`[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`);
6885
+ console.log(
6886
+ `[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`
6887
+ );
6877
6888
  if (practitioners.length < (filters.pagination || 10)) {
6878
6889
  return { practitioners, lastDoc: null };
6879
6890
  }
@@ -6883,7 +6894,9 @@ var PractitionerService = class extends BaseService {
6883
6894
  }
6884
6895
  }
6885
6896
  try {
6886
- console.log("[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering");
6897
+ console.log(
6898
+ "[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering"
6899
+ );
6887
6900
  const constraints = [];
6888
6901
  if (!filters.includeDraftPractitioners) {
6889
6902
  constraints.push((0, import_firestore21.where)("status", "==", "active" /* ACTIVE */));
@@ -6892,14 +6905,22 @@ var PractitionerService = class extends BaseService {
6892
6905
  if (filters.certifications && filters.certifications.length > 0) {
6893
6906
  const certificationsToMatch = filters.certifications;
6894
6907
  constraints.push(
6895
- (0, import_firestore21.where)("certification.specialties", "array-contains-any", certificationsToMatch)
6908
+ (0, import_firestore21.where)(
6909
+ "certification.specialties",
6910
+ "array-contains-any",
6911
+ certificationsToMatch
6912
+ )
6896
6913
  );
6897
6914
  }
6898
6915
  if (filters.minRating !== void 0) {
6899
- constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", ">=", filters.minRating));
6916
+ constraints.push(
6917
+ (0, import_firestore21.where)("reviewInfo.averageRating", ">=", filters.minRating)
6918
+ );
6900
6919
  }
6901
6920
  if (filters.maxRating !== void 0) {
6902
- constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", "<=", filters.maxRating));
6921
+ constraints.push(
6922
+ (0, import_firestore21.where)("reviewInfo.averageRating", "<=", filters.maxRating)
6923
+ );
6903
6924
  }
6904
6925
  constraints.push((0, import_firestore21.orderBy)("createdAt", "desc"));
6905
6926
  if (filters.location && filters.radiusInKm) {
@@ -6916,9 +6937,14 @@ var PractitionerService = class extends BaseService {
6916
6937
  }
6917
6938
  constraints.push((0, import_firestore21.limit)(filters.pagination || 10));
6918
6939
  }
6919
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6940
+ const q = (0, import_firestore21.query)(
6941
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6942
+ ...constraints
6943
+ );
6920
6944
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6921
- let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6945
+ let practitioners = querySnapshot.docs.map(
6946
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6947
+ );
6922
6948
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6923
6949
  const location = filters.location;
6924
6950
  const radiusInKm = filters.radiusInKm;
@@ -6937,7 +6963,9 @@ var PractitionerService = class extends BaseService {
6937
6963
  }
6938
6964
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6939
6965
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6940
- console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
6966
+ console.log(
6967
+ `[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`
6968
+ );
6941
6969
  if (practitioners.length < (filters.pagination || 10)) {
6942
6970
  return { practitioners, lastDoc: null };
6943
6971
  }
@@ -6946,18 +6974,27 @@ var PractitionerService = class extends BaseService {
6946
6974
  console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
6947
6975
  }
6948
6976
  try {
6949
- console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
6977
+ console.log(
6978
+ "[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback"
6979
+ );
6950
6980
  const constraints = [
6951
6981
  (0, import_firestore21.where)("isActive", "==", true),
6952
6982
  (0, import_firestore21.orderBy)("createdAt", "desc"),
6953
6983
  (0, import_firestore21.limit)(filters.pagination || 10)
6954
6984
  ];
6955
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6985
+ const q = (0, import_firestore21.query)(
6986
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6987
+ ...constraints
6988
+ );
6956
6989
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6957
- let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6990
+ let practitioners = querySnapshot.docs.map(
6991
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6992
+ );
6958
6993
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6959
6994
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6960
- console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
6995
+ console.log(
6996
+ `[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`
6997
+ );
6961
6998
  if (practitioners.length < (filters.pagination || 10)) {
6962
6999
  return { practitioners, lastDoc: null };
6963
7000
  }
@@ -6966,19 +7003,28 @@ var PractitionerService = class extends BaseService {
6966
7003
  console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
6967
7004
  }
6968
7005
  try {
6969
- console.log("[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback");
7006
+ console.log(
7007
+ "[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback"
7008
+ );
6970
7009
  const constraints = [
6971
7010
  (0, import_firestore21.where)("isActive", "==", true),
6972
7011
  (0, import_firestore21.where)("status", "==", "active" /* ACTIVE */),
6973
7012
  (0, import_firestore21.orderBy)("createdAt", "desc"),
6974
7013
  (0, import_firestore21.limit)(filters.pagination || 10)
6975
7014
  ];
6976
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7015
+ const q = (0, import_firestore21.query)(
7016
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
7017
+ ...constraints
7018
+ );
6977
7019
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6978
- let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
7020
+ let practitioners = querySnapshot.docs.map(
7021
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
7022
+ );
6979
7023
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6980
7024
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6981
- console.log(`[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`);
7025
+ console.log(
7026
+ `[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`
7027
+ );
6982
7028
  if (practitioners.length < (filters.pagination || 10)) {
6983
7029
  return { practitioners, lastDoc: null };
6984
7030
  }
@@ -6986,10 +7032,15 @@ var PractitionerService = class extends BaseService {
6986
7032
  } catch (error) {
6987
7033
  console.log("[PRACTITIONER_SERVICE] Strategy 4 failed:", error);
6988
7034
  }
6989
- console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
7035
+ console.log(
7036
+ "[PRACTITIONER_SERVICE] All strategies failed, returning empty result"
7037
+ );
6990
7038
  return { practitioners: [], lastDoc: null };
6991
7039
  } catch (error) {
6992
- console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
7040
+ console.error(
7041
+ "[PRACTITIONER_SERVICE] Error filtering practitioners:",
7042
+ error
7043
+ );
6993
7044
  return { practitioners: [], lastDoc: null };
6994
7045
  }
6995
7046
  }
@@ -7009,63 +7060,93 @@ var PractitionerService = class extends BaseService {
7009
7060
  const fullNameLower = practitioner.fullNameLower || "";
7010
7061
  return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
7011
7062
  });
7012
- console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`);
7063
+ console.log(
7064
+ `[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`
7065
+ );
7013
7066
  }
7014
7067
  if (filters.certifications && filters.certifications.length > 0) {
7015
7068
  const certificationsToMatch = filters.certifications;
7016
7069
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7017
7070
  var _a;
7018
7071
  const practitionerCerts = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7019
- return certificationsToMatch.some((cert) => practitionerCerts.includes(cert));
7072
+ return certificationsToMatch.some(
7073
+ (cert) => practitionerCerts.includes(cert)
7074
+ );
7020
7075
  });
7021
- console.log(`[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`);
7076
+ console.log(
7077
+ `[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`
7078
+ );
7022
7079
  }
7023
7080
  if (filters.specialties && filters.specialties.length > 0) {
7024
7081
  const specialtiesToMatch = filters.specialties;
7025
7082
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7026
7083
  var _a;
7027
7084
  const practitionerSpecs = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7028
- return specialtiesToMatch.some((spec) => practitionerSpecs.includes(spec));
7085
+ return specialtiesToMatch.some(
7086
+ (spec) => practitionerSpecs.includes(spec)
7087
+ );
7029
7088
  });
7030
- console.log(`[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`);
7089
+ console.log(
7090
+ `[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`
7091
+ );
7031
7092
  }
7032
7093
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
7033
7094
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7034
7095
  var _a;
7035
7096
  const rating = ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
7036
- if (filters.minRating !== void 0 && rating < filters.minRating) return false;
7037
- if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
7097
+ if (filters.minRating !== void 0 && rating < filters.minRating)
7098
+ return false;
7099
+ if (filters.maxRating !== void 0 && rating > filters.maxRating)
7100
+ return false;
7038
7101
  return true;
7039
7102
  });
7040
- console.log(`[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`);
7103
+ console.log(
7104
+ `[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`
7105
+ );
7041
7106
  }
7042
7107
  if (filters.procedureFamily) {
7043
7108
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7044
7109
  const proceduresInfo = practitioner.proceduresInfo || [];
7045
- return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
7110
+ return proceduresInfo.some(
7111
+ (proc) => proc.family === filters.procedureFamily
7112
+ );
7046
7113
  });
7047
- console.log(`[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`);
7114
+ console.log(
7115
+ `[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`
7116
+ );
7048
7117
  }
7049
7118
  if (filters.procedureCategory) {
7050
7119
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7051
7120
  const proceduresInfo = practitioner.proceduresInfo || [];
7052
- return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
7121
+ return proceduresInfo.some(
7122
+ (proc) => proc.categoryName === filters.procedureCategory
7123
+ );
7053
7124
  });
7054
- console.log(`[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`);
7125
+ console.log(
7126
+ `[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`
7127
+ );
7055
7128
  }
7056
7129
  if (filters.procedureSubcategory) {
7057
7130
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7058
7131
  const proceduresInfo = practitioner.proceduresInfo || [];
7059
- return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
7132
+ return proceduresInfo.some(
7133
+ (proc) => proc.subcategoryName === filters.procedureSubcategory
7134
+ );
7060
7135
  });
7061
- console.log(`[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`);
7136
+ console.log(
7137
+ `[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`
7138
+ );
7062
7139
  }
7063
7140
  if (filters.procedureTechnology) {
7064
7141
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7065
7142
  const proceduresInfo = practitioner.proceduresInfo || [];
7066
- return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
7143
+ return proceduresInfo.some(
7144
+ (proc) => proc.technologyName === filters.procedureTechnology
7145
+ );
7067
7146
  });
7068
- console.log(`[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`);
7147
+ console.log(
7148
+ `[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`
7149
+ );
7069
7150
  }
7070
7151
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
7071
7152
  const location = filters.location;
@@ -7081,7 +7162,9 @@ var PractitionerService = class extends BaseService {
7081
7162
  return distanceInKm <= radiusInKm;
7082
7163
  });
7083
7164
  });
7084
- console.log(`[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`);
7165
+ console.log(
7166
+ `[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`
7167
+ );
7085
7168
  }
7086
7169
  return filteredPractitioners;
7087
7170
  }
@@ -7146,6 +7229,15 @@ var PractitionerService = class extends BaseService {
7146
7229
  price: 0,
7147
7230
  currency: "EUR" /* EUR */,
7148
7231
  pricingMeasure: "per_session" /* PER_SESSION */,
7232
+ productsMetadata: [
7233
+ {
7234
+ productId: "free-consultation-product",
7235
+ price: 0,
7236
+ currency: "EUR" /* EUR */,
7237
+ pricingMeasure: "per_session" /* PER_SESSION */,
7238
+ isDefault: true
7239
+ }
7240
+ ],
7149
7241
  duration: 30,
7150
7242
  // 30 minutes consultation
7151
7243
  practitionerId,
@@ -7490,7 +7582,7 @@ var UserService = class extends BaseService {
7490
7582
  ];
7491
7583
  const q = (0, import_firestore22.query)((0, import_firestore22.collection)(this.db, USERS_COLLECTION), ...constraints);
7492
7584
  const querySnapshot = await (0, import_firestore22.getDocs)(q);
7493
- const users = querySnapshot.docs.map((doc37) => doc37.data());
7585
+ const users = querySnapshot.docs.map((doc38) => doc38.data());
7494
7586
  return users.map((userData) => userSchema.parse(userData));
7495
7587
  }
7496
7588
  /**
@@ -7854,7 +7946,7 @@ async function getAllActiveGroups(db) {
7854
7946
  (0, import_firestore23.where)("isActive", "==", true)
7855
7947
  );
7856
7948
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
7857
- return querySnapshot.docs.map((doc37) => doc37.data());
7949
+ return querySnapshot.docs.map((doc38) => doc38.data());
7858
7950
  }
7859
7951
  async function updateClinicGroup(db, groupId, data, app) {
7860
7952
  console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
@@ -8295,7 +8387,7 @@ async function getClinicsByGroup(db, groupId) {
8295
8387
  (0, import_firestore24.where)("isActive", "==", true)
8296
8388
  );
8297
8389
  const querySnapshot = await (0, import_firestore24.getDocs)(q);
8298
- return querySnapshot.docs.map((doc37) => doc37.data());
8390
+ return querySnapshot.docs.map((doc38) => doc38.data());
8299
8391
  }
8300
8392
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
8301
8393
  console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
@@ -8489,7 +8581,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
8489
8581
  }
8490
8582
  const q = (0, import_firestore24.query)((0, import_firestore24.collection)(db, CLINICS_COLLECTION), ...constraints);
8491
8583
  const querySnapshot = await (0, import_firestore24.getDocs)(q);
8492
- return querySnapshot.docs.map((doc37) => doc37.data());
8584
+ return querySnapshot.docs.map((doc38) => doc38.data());
8493
8585
  }
8494
8586
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
8495
8587
  return getClinicsByAdmin(
@@ -8534,11 +8626,11 @@ async function getAllClinics(db, pagination, lastDoc) {
8534
8626
  }
8535
8627
  const clinicsSnapshot = await (0, import_firestore24.getDocs)(clinicsQuery);
8536
8628
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
8537
- const clinics = clinicsSnapshot.docs.map((doc37) => {
8538
- const data = doc37.data();
8629
+ const clinics = clinicsSnapshot.docs.map((doc38) => {
8630
+ const data = doc38.data();
8539
8631
  return {
8540
8632
  ...data,
8541
- id: doc37.id
8633
+ id: doc38.id
8542
8634
  };
8543
8635
  });
8544
8636
  return {
@@ -8565,8 +8657,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
8565
8657
  ];
8566
8658
  const q = (0, import_firestore24.query)((0, import_firestore24.collection)(db, CLINICS_COLLECTION), ...constraints);
8567
8659
  const querySnapshot = await (0, import_firestore24.getDocs)(q);
8568
- for (const doc37 of querySnapshot.docs) {
8569
- const clinic = doc37.data();
8660
+ for (const doc38 of querySnapshot.docs) {
8661
+ const clinic = doc38.data();
8570
8662
  const distance = (0, import_geofire_common4.distanceBetween)(
8571
8663
  [center.latitude, center.longitude],
8572
8664
  [clinic.location.latitude, clinic.location.longitude]
@@ -8683,8 +8775,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
8683
8775
  }
8684
8776
  const q = (0, import_firestore25.query)((0, import_firestore25.collection)(db, CLINICS_COLLECTION), ...constraints);
8685
8777
  const querySnapshot = await (0, import_firestore25.getDocs)(q);
8686
- for (const doc37 of querySnapshot.docs) {
8687
- const clinic = doc37.data();
8778
+ for (const doc38 of querySnapshot.docs) {
8779
+ const clinic = doc38.data();
8688
8780
  const distance = (0, import_geofire_common5.distanceBetween)(
8689
8781
  [center.latitude, center.longitude],
8690
8782
  [clinic.location.latitude, clinic.location.longitude]
@@ -8805,7 +8897,7 @@ async function getClinicsByFilters(db, filters) {
8805
8897
  constraints.push((0, import_firestore26.limit)(filters.pagination || 5));
8806
8898
  const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
8807
8899
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8808
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8900
+ let clinics = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
8809
8901
  clinics = applyInMemoryFilters(clinics, filters);
8810
8902
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8811
8903
  console.log(`[CLINIC_SERVICE] Strategy 1 success: ${clinics.length} clinics`);
@@ -8837,7 +8929,7 @@ async function getClinicsByFilters(db, filters) {
8837
8929
  constraints.push((0, import_firestore26.limit)(filters.pagination || 5));
8838
8930
  const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
8839
8931
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8840
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8932
+ let clinics = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
8841
8933
  clinics = applyInMemoryFilters(clinics, filters);
8842
8934
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8843
8935
  console.log(`[CLINIC_SERVICE] Strategy 2 success: ${clinics.length} clinics`);
@@ -8867,7 +8959,7 @@ async function getClinicsByFilters(db, filters) {
8867
8959
  constraints.push((0, import_firestore26.limit)(filters.pagination || 5));
8868
8960
  const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
8869
8961
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8870
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8962
+ let clinics = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
8871
8963
  clinics = applyInMemoryFilters(clinics, filters);
8872
8964
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8873
8965
  console.log(`[CLINIC_SERVICE] Strategy 3 success: ${clinics.length} clinics`);
@@ -8887,7 +8979,7 @@ async function getClinicsByFilters(db, filters) {
8887
8979
  ];
8888
8980
  const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
8889
8981
  const querySnapshot = await (0, import_firestore26.getDocs)(q);
8890
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8982
+ let clinics = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
8891
8983
  clinics = applyInMemoryFilters(clinics, filters);
8892
8984
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8893
8985
  console.log(`[CLINIC_SERVICE] Strategy 4 success: ${clinics.length} clinics`);
@@ -9463,11 +9555,11 @@ var ClinicService = class extends BaseService {
9463
9555
  async getClinicsForMap() {
9464
9556
  const clinicsRef = (0, import_firestore27.collection)(this.db, CLINICS_COLLECTION);
9465
9557
  const snapshot = await (0, import_firestore27.getDocs)(clinicsRef);
9466
- const clinicsForMap = snapshot.docs.map((doc37) => {
9558
+ const clinicsForMap = snapshot.docs.map((doc38) => {
9467
9559
  var _a, _b, _c;
9468
- const data = doc37.data();
9560
+ const data = doc38.data();
9469
9561
  return {
9470
- id: doc37.id,
9562
+ id: doc38.id,
9471
9563
  name: data.name,
9472
9564
  address: ((_a = data.location) == null ? void 0 : _a.address) || "",
9473
9565
  latitude: (_b = data.location) == null ? void 0 : _b.latitude,
@@ -10628,7 +10720,7 @@ async function updatePractitionerCalendarEventUtil(db, practitionerId, eventId,
10628
10720
  }
10629
10721
 
10630
10722
  // src/services/calendar/utils/appointment.utils.ts
10631
- async function createAppointmentUtil2(db, clinicId, practitionerId, patientId, eventData, generateId2) {
10723
+ async function createAppointmentUtil(db, clinicId, practitionerId, patientId, eventData, generateId2) {
10632
10724
  const eventId = generateId2();
10633
10725
  const autoConfirm = await checkAutoConfirmAppointmentsUtil(db, clinicId);
10634
10726
  const initialStatus = autoConfirm ? "confirmed" /* CONFIRMED */ : "pending" /* PENDING */;
@@ -10762,7 +10854,7 @@ async function searchCalendarEventsUtil(db, params) {
10762
10854
  const finalQuery = (0, import_firestore33.query)(collectionRef, ...constraints);
10763
10855
  const querySnapshot = await (0, import_firestore33.getDocs)(finalQuery);
10764
10856
  const events = querySnapshot.docs.map(
10765
- (doc37) => ({ id: doc37.id, ...doc37.data() })
10857
+ (doc38) => ({ id: doc38.id, ...doc38.data() })
10766
10858
  );
10767
10859
  return events;
10768
10860
  } catch (error) {
@@ -10844,7 +10936,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
10844
10936
  );
10845
10937
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
10846
10938
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
10847
- return querySnapshot.docs.map((doc37) => doc37.data());
10939
+ return querySnapshot.docs.map((doc38) => doc38.data());
10848
10940
  }
10849
10941
  async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
10850
10942
  const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
@@ -10861,7 +10953,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
10861
10953
  );
10862
10954
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
10863
10955
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
10864
- return querySnapshot.docs.map((doc37) => doc37.data());
10956
+ return querySnapshot.docs.map((doc38) => doc38.data());
10865
10957
  }
10866
10958
  async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
10867
10959
  const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
@@ -10878,7 +10970,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
10878
10970
  );
10879
10971
  const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
10880
10972
  const querySnapshot = await (0, import_firestore34.getDocs)(q);
10881
- return querySnapshot.docs.map((doc37) => doc37.data());
10973
+ return querySnapshot.docs.map((doc38) => doc38.data());
10882
10974
  }
10883
10975
  async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
10884
10976
  const calendarRef = getPractitionerSyncedCalendarDocRef(
@@ -11946,7 +12038,7 @@ var CalendarServiceV2 = class extends BaseService {
11946
12038
  syncStatus: "internal" /* INTERNAL */,
11947
12039
  eventType: "appointment" /* APPOINTMENT */
11948
12040
  };
11949
- const appointment = await createAppointmentUtil2(
12041
+ const appointment = await createAppointmentUtil(
11950
12042
  this.db,
11951
12043
  params.clinicId,
11952
12044
  params.doctorId,
@@ -12233,9 +12325,9 @@ var CalendarServiceV2 = class extends BaseService {
12233
12325
  (0, import_firestore37.where)("eventTime.start", "<=", import_firestore36.Timestamp.fromDate(endDate))
12234
12326
  );
12235
12327
  const eventsSnapshot = await (0, import_firestore37.getDocs)(q);
12236
- const events = eventsSnapshot.docs.map((doc37) => ({
12237
- id: doc37.id,
12238
- ...doc37.data()
12328
+ const events = eventsSnapshot.docs.map((doc38) => ({
12329
+ id: doc38.id,
12330
+ ...doc38.data()
12239
12331
  }));
12240
12332
  const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
12241
12333
  doctorId
@@ -12869,7 +12961,7 @@ var CalendarServiceV2 = class extends BaseService {
12869
12961
  ])
12870
12962
  );
12871
12963
  const querySnapshot = await (0, import_firestore37.getDocs)(q);
12872
- return querySnapshot.docs.map((doc37) => doc37.data());
12964
+ return querySnapshot.docs.map((doc38) => doc38.data());
12873
12965
  }
12874
12966
  /**
12875
12967
  * Calculates available time slots based on working hours, schedule and existing appointments
@@ -13400,7 +13492,7 @@ var PractitionerInviteService = class extends BaseService {
13400
13492
  ...constraints
13401
13493
  );
13402
13494
  const querySnapshot = await (0, import_firestore40.getDocs)(q);
13403
- return querySnapshot.docs.map((doc37) => doc37.data());
13495
+ return querySnapshot.docs.map((doc38) => doc38.data());
13404
13496
  } catch (error) {
13405
13497
  console.error(
13406
13498
  "[PractitionerInviteService] Error getting doctor invites:",
@@ -13429,7 +13521,7 @@ var PractitionerInviteService = class extends BaseService {
13429
13521
  ...constraints
13430
13522
  );
13431
13523
  const querySnapshot = await (0, import_firestore40.getDocs)(q);
13432
- return querySnapshot.docs.map((doc37) => doc37.data());
13524
+ return querySnapshot.docs.map((doc38) => doc38.data());
13433
13525
  } catch (error) {
13434
13526
  console.error(
13435
13527
  "[PractitionerInviteService] Error getting clinic invites:",
@@ -13585,7 +13677,7 @@ var PractitionerInviteService = class extends BaseService {
13585
13677
  );
13586
13678
  const querySnapshot = await (0, import_firestore40.getDocs)(q);
13587
13679
  let invites = querySnapshot.docs.map(
13588
- (doc37) => doc37.data()
13680
+ (doc38) => doc38.data()
13589
13681
  );
13590
13682
  if (filters.fromDate) {
13591
13683
  invites = invites.filter(
@@ -13688,9 +13780,10 @@ var PractitionerInviteService = class extends BaseService {
13688
13780
 
13689
13781
  // src/services/documentation-templates/documentation-template.service.ts
13690
13782
  var import_firestore41 = require("firebase/firestore");
13783
+ var import_firestore42 = require("firebase/firestore");
13691
13784
  var DocumentationTemplateService = class extends BaseService {
13692
- constructor() {
13693
- super(...arguments);
13785
+ constructor(...args) {
13786
+ super(...args);
13694
13787
  this.collectionRef = (0, import_firestore41.collection)(
13695
13788
  this.db,
13696
13789
  DOCUMENTATION_TEMPLATES_COLLECTION
@@ -13842,8 +13935,8 @@ var DocumentationTemplateService = class extends BaseService {
13842
13935
  const q = (0, import_firestore41.query)(versionsCollectionRef, (0, import_firestore41.orderBy)("version", "desc"));
13843
13936
  const querySnapshot = await (0, import_firestore41.getDocs)(q);
13844
13937
  const versions = [];
13845
- querySnapshot.forEach((doc37) => {
13846
- versions.push(doc37.data());
13938
+ querySnapshot.forEach((doc38) => {
13939
+ versions.push(doc38.data());
13847
13940
  });
13848
13941
  return versions;
13849
13942
  }
@@ -13874,15 +13967,97 @@ var DocumentationTemplateService = class extends BaseService {
13874
13967
  const querySnapshot = await (0, import_firestore41.getDocs)(q);
13875
13968
  const templates = [];
13876
13969
  let lastVisible = null;
13877
- querySnapshot.forEach((doc37) => {
13878
- templates.push(doc37.data());
13879
- lastVisible = doc37;
13970
+ querySnapshot.forEach((doc38) => {
13971
+ templates.push(doc38.data());
13972
+ lastVisible = doc38;
13973
+ });
13974
+ return {
13975
+ templates,
13976
+ lastDoc: lastVisible
13977
+ };
13978
+ }
13979
+ /**
13980
+ * Get all active templates with optional filters and pagination.
13981
+ * @param options - Options for filtering and pagination.
13982
+ * @returns A promise that resolves to the templates and the last visible document.
13983
+ */
13984
+ async getTemplates(options) {
13985
+ const {
13986
+ pageSize = 20,
13987
+ lastDoc,
13988
+ isUserForm,
13989
+ isRequired,
13990
+ sortingOrder
13991
+ } = options;
13992
+ const constraints = [
13993
+ (0, import_firestore41.where)("isActive", "==", true),
13994
+ (0, import_firestore41.orderBy)("sortingOrder", "asc"),
13995
+ (0, import_firestore41.orderBy)("title", "asc"),
13996
+ (0, import_firestore41.limit)(pageSize)
13997
+ ];
13998
+ if (isUserForm !== void 0) {
13999
+ constraints.push((0, import_firestore41.where)("isUserForm", "==", isUserForm));
14000
+ }
14001
+ if (isRequired !== void 0) {
14002
+ constraints.push((0, import_firestore41.where)("isRequired", "==", isRequired));
14003
+ }
14004
+ if (sortingOrder !== void 0) {
14005
+ constraints.push((0, import_firestore41.where)("sortingOrder", "==", sortingOrder));
14006
+ }
14007
+ if (lastDoc) {
14008
+ constraints.push((0, import_firestore41.startAfter)(lastDoc));
14009
+ }
14010
+ const q = (0, import_firestore41.query)(this.collectionRef, ...constraints.filter((c) => c));
14011
+ const querySnapshot = await (0, import_firestore41.getDocs)(q);
14012
+ const templates = [];
14013
+ let lastVisible = null;
14014
+ querySnapshot.forEach((doc38) => {
14015
+ templates.push(doc38.data());
14016
+ lastVisible = doc38;
13880
14017
  });
13881
14018
  return {
13882
14019
  templates,
13883
14020
  lastDoc: lastVisible
13884
14021
  };
13885
14022
  }
14023
+ /**
14024
+ * Get the total count of active templates with optional filters.
14025
+ * @param options - Options for filtering.
14026
+ * @returns A promise that resolves to the total count of templates.
14027
+ */
14028
+ async getTemplatesCount(options) {
14029
+ const { isUserForm, isRequired, sortingOrder } = options;
14030
+ const constraints = [(0, import_firestore41.where)("isActive", "==", true)];
14031
+ if (isUserForm !== void 0) {
14032
+ constraints.push((0, import_firestore41.where)("isUserForm", "==", isUserForm));
14033
+ }
14034
+ if (isRequired !== void 0) {
14035
+ constraints.push((0, import_firestore41.where)("isRequired", "==", isRequired));
14036
+ }
14037
+ if (sortingOrder !== void 0) {
14038
+ constraints.push((0, import_firestore41.where)("sortingOrder", "==", sortingOrder));
14039
+ }
14040
+ const q = (0, import_firestore41.query)(this.collectionRef, ...constraints.filter((c) => c));
14041
+ const snapshot = await (0, import_firestore42.getCountFromServer)(q);
14042
+ return snapshot.data().count;
14043
+ }
14044
+ /**
14045
+ * Get all active templates without pagination for filtering purposes.
14046
+ * @returns A promise that resolves to an array of all active templates.
14047
+ */
14048
+ async getAllActiveTemplates() {
14049
+ const q = (0, import_firestore41.query)(
14050
+ this.collectionRef,
14051
+ (0, import_firestore41.where)("isActive", "==", true),
14052
+ (0, import_firestore41.orderBy)("title", "asc")
14053
+ );
14054
+ const querySnapshot = await (0, import_firestore41.getDocs)(q);
14055
+ const templates = [];
14056
+ querySnapshot.forEach((doc38) => {
14057
+ templates.push(doc38.data());
14058
+ });
14059
+ return templates;
14060
+ }
13886
14061
  /**
13887
14062
  * Get templates by tags
13888
14063
  * @param tags - Tags to filter by
@@ -13904,9 +14079,9 @@ var DocumentationTemplateService = class extends BaseService {
13904
14079
  const querySnapshot = await (0, import_firestore41.getDocs)(q);
13905
14080
  const templates = [];
13906
14081
  let lastVisible = null;
13907
- querySnapshot.forEach((doc37) => {
13908
- templates.push(doc37.data());
13909
- lastVisible = doc37;
14082
+ querySnapshot.forEach((doc38) => {
14083
+ templates.push(doc38.data());
14084
+ lastVisible = doc38;
13910
14085
  });
13911
14086
  return {
13912
14087
  templates,
@@ -13933,9 +14108,9 @@ var DocumentationTemplateService = class extends BaseService {
13933
14108
  const querySnapshot = await (0, import_firestore41.getDocs)(q);
13934
14109
  const templates = [];
13935
14110
  let lastVisible = null;
13936
- querySnapshot.forEach((doc37) => {
13937
- templates.push(doc37.data());
13938
- lastVisible = doc37;
14111
+ querySnapshot.forEach((doc38) => {
14112
+ templates.push(doc38.data());
14113
+ lastVisible = doc38;
13939
14114
  });
13940
14115
  return {
13941
14116
  templates,
@@ -13961,15 +14136,15 @@ var DocumentationTemplateService = class extends BaseService {
13961
14136
  }
13962
14137
  const querySnapshot = await (0, import_firestore41.getDocs)(q);
13963
14138
  const templates = [];
13964
- querySnapshot.forEach((doc37) => {
13965
- templates.push(doc37.data());
14139
+ querySnapshot.forEach((doc38) => {
14140
+ templates.push(doc38.data());
13966
14141
  });
13967
14142
  return templates;
13968
14143
  }
13969
14144
  };
13970
14145
 
13971
14146
  // src/services/documentation-templates/filled-document.service.ts
13972
- var import_firestore42 = require("firebase/firestore");
14147
+ var import_firestore43 = require("firebase/firestore");
13973
14148
  var FilledDocumentService = class extends BaseService {
13974
14149
  constructor(...args) {
13975
14150
  super(...args);
@@ -14024,7 +14199,7 @@ var FilledDocumentService = class extends BaseService {
14024
14199
  values: initialValues,
14025
14200
  status: initialStatus
14026
14201
  };
14027
- const docRef = (0, import_firestore42.doc)(
14202
+ const docRef = (0, import_firestore43.doc)(
14028
14203
  this.db,
14029
14204
  APPOINTMENTS_COLLECTION,
14030
14205
  // Replaced "appointments"
@@ -14032,7 +14207,7 @@ var FilledDocumentService = class extends BaseService {
14032
14207
  formSubcollection,
14033
14208
  documentId3
14034
14209
  );
14035
- await (0, import_firestore42.setDoc)(docRef, filledDocument);
14210
+ await (0, import_firestore43.setDoc)(docRef, filledDocument);
14036
14211
  return filledDocument;
14037
14212
  }
14038
14213
  /**
@@ -14044,7 +14219,7 @@ var FilledDocumentService = class extends BaseService {
14044
14219
  */
14045
14220
  async getFilledDocumentFromAppointmentById(appointmentId, formId, isUserForm) {
14046
14221
  const formSubcollection = this.getFormSubcollectionPath(isUserForm);
14047
- const docRef = (0, import_firestore42.doc)(
14222
+ const docRef = (0, import_firestore43.doc)(
14048
14223
  this.db,
14049
14224
  APPOINTMENTS_COLLECTION,
14050
14225
  // Replaced "appointments"
@@ -14052,7 +14227,7 @@ var FilledDocumentService = class extends BaseService {
14052
14227
  formSubcollection,
14053
14228
  formId
14054
14229
  );
14055
- const docSnap = await (0, import_firestore42.getDoc)(docRef);
14230
+ const docSnap = await (0, import_firestore43.getDoc)(docRef);
14056
14231
  if (!docSnap.exists()) {
14057
14232
  return null;
14058
14233
  }
@@ -14069,7 +14244,7 @@ var FilledDocumentService = class extends BaseService {
14069
14244
  */
14070
14245
  async updateFilledDocumentInAppointment(appointmentId, formId, isUserForm, values, status) {
14071
14246
  const formSubcollection = this.getFormSubcollectionPath(isUserForm);
14072
- const docRef = (0, import_firestore42.doc)(
14247
+ const docRef = (0, import_firestore43.doc)(
14073
14248
  this.db,
14074
14249
  APPOINTMENTS_COLLECTION,
14075
14250
  // Replaced "appointments"
@@ -14101,7 +14276,7 @@ var FilledDocumentService = class extends BaseService {
14101
14276
  }
14102
14277
  if (Object.keys(updatePayload).length === 1 && "updatedAt" in updatePayload) {
14103
14278
  }
14104
- await (0, import_firestore42.updateDoc)(docRef, updatePayload);
14279
+ await (0, import_firestore43.updateDoc)(docRef, updatePayload);
14105
14280
  return { ...existingDoc, ...updatePayload };
14106
14281
  }
14107
14282
  /**
@@ -14111,20 +14286,20 @@ var FilledDocumentService = class extends BaseService {
14111
14286
  * @param lastDoc Last document from previous page for pagination.
14112
14287
  */
14113
14288
  async getFilledUserFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
14114
- const subcollectionRef = (0, import_firestore42.collection)(
14289
+ const subcollectionRef = (0, import_firestore43.collection)(
14115
14290
  this.db,
14116
14291
  APPOINTMENTS_COLLECTION,
14117
14292
  // Replaced "appointments"
14118
14293
  appointmentId,
14119
14294
  USER_FORMS_SUBCOLLECTION
14120
14295
  );
14121
- let q = (0, import_firestore42.query)(
14296
+ let q = (0, import_firestore43.query)(
14122
14297
  subcollectionRef,
14123
- (0, import_firestore42.orderBy)("updatedAt", "desc"),
14124
- (0, import_firestore42.limit)(pageSize)
14298
+ (0, import_firestore43.orderBy)("updatedAt", "desc"),
14299
+ (0, import_firestore43.limit)(pageSize)
14125
14300
  );
14126
14301
  if (lastDoc) {
14127
- q = (0, import_firestore42.query)(q, (0, import_firestore42.startAfter)(lastDoc));
14302
+ q = (0, import_firestore43.query)(q, (0, import_firestore43.startAfter)(lastDoc));
14128
14303
  }
14129
14304
  return this.executeQuery(q);
14130
14305
  }
@@ -14135,31 +14310,31 @@ var FilledDocumentService = class extends BaseService {
14135
14310
  * @param lastDoc Last document from previous page for pagination.
14136
14311
  */
14137
14312
  async getFilledDoctorFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
14138
- const subcollectionRef = (0, import_firestore42.collection)(
14313
+ const subcollectionRef = (0, import_firestore43.collection)(
14139
14314
  this.db,
14140
14315
  APPOINTMENTS_COLLECTION,
14141
14316
  // Replaced "appointments"
14142
14317
  appointmentId,
14143
14318
  DOCTOR_FORMS_SUBCOLLECTION
14144
14319
  );
14145
- let q = (0, import_firestore42.query)(
14320
+ let q = (0, import_firestore43.query)(
14146
14321
  subcollectionRef,
14147
- (0, import_firestore42.orderBy)("updatedAt", "desc"),
14148
- (0, import_firestore42.limit)(pageSize)
14322
+ (0, import_firestore43.orderBy)("updatedAt", "desc"),
14323
+ (0, import_firestore43.limit)(pageSize)
14149
14324
  );
14150
14325
  if (lastDoc) {
14151
- q = (0, import_firestore42.query)(q, (0, import_firestore42.startAfter)(lastDoc));
14326
+ q = (0, import_firestore43.query)(q, (0, import_firestore43.startAfter)(lastDoc));
14152
14327
  }
14153
14328
  return this.executeQuery(q);
14154
14329
  }
14155
14330
  // Helper to execute query and return documents + lastDoc
14156
14331
  async executeQuery(q) {
14157
- const querySnapshot = await (0, import_firestore42.getDocs)(q);
14332
+ const querySnapshot = await (0, import_firestore43.getDocs)(q);
14158
14333
  const documents = [];
14159
14334
  let lastVisible = null;
14160
- querySnapshot.forEach((doc37) => {
14161
- documents.push(doc37.data());
14162
- lastVisible = doc37;
14335
+ querySnapshot.forEach((doc38) => {
14336
+ documents.push(doc38.data());
14337
+ lastVisible = doc38;
14163
14338
  });
14164
14339
  return {
14165
14340
  documents,
@@ -14318,14 +14493,14 @@ var FilledDocumentService = class extends BaseService {
14318
14493
  };
14319
14494
 
14320
14495
  // src/services/notifications/notification.service.ts
14321
- var import_firestore43 = require("firebase/firestore");
14496
+ var import_firestore44 = require("firebase/firestore");
14322
14497
  var NotificationService = class extends BaseService {
14323
14498
  /**
14324
14499
  * Kreira novu notifikaciju
14325
14500
  */
14326
14501
  async createNotification(notification) {
14327
- const notificationsRef = (0, import_firestore43.collection)(this.db, NOTIFICATIONS_COLLECTION);
14328
- const now = import_firestore43.Timestamp.now();
14502
+ const notificationsRef = (0, import_firestore44.collection)(this.db, NOTIFICATIONS_COLLECTION);
14503
+ const now = import_firestore44.Timestamp.now();
14329
14504
  const notificationData = {
14330
14505
  ...notification,
14331
14506
  createdAt: now,
@@ -14334,7 +14509,7 @@ var NotificationService = class extends BaseService {
14334
14509
  isRead: false,
14335
14510
  userRole: notification.userRole || "patient" /* PATIENT */
14336
14511
  };
14337
- const docRef = await (0, import_firestore43.addDoc)(notificationsRef, notificationData);
14512
+ const docRef = await (0, import_firestore44.addDoc)(notificationsRef, notificationData);
14338
14513
  return {
14339
14514
  ...notificationData,
14340
14515
  id: docRef.id
@@ -14344,12 +14519,12 @@ var NotificationService = class extends BaseService {
14344
14519
  * Dohvata notifikaciju po ID-u
14345
14520
  */
14346
14521
  async getNotification(notificationId) {
14347
- const notificationRef = (0, import_firestore43.doc)(
14522
+ const notificationRef = (0, import_firestore44.doc)(
14348
14523
  this.db,
14349
14524
  NOTIFICATIONS_COLLECTION,
14350
14525
  notificationId
14351
14526
  );
14352
- const notificationDoc = await (0, import_firestore43.getDoc)(notificationRef);
14527
+ const notificationDoc = await (0, import_firestore44.getDoc)(notificationRef);
14353
14528
  if (!notificationDoc.exists()) {
14354
14529
  return null;
14355
14530
  }
@@ -14362,45 +14537,45 @@ var NotificationService = class extends BaseService {
14362
14537
  * Dohvata sve notifikacije za korisnika
14363
14538
  */
14364
14539
  async getUserNotifications(userId) {
14365
- const q = (0, import_firestore43.query)(
14366
- (0, import_firestore43.collection)(this.db, NOTIFICATIONS_COLLECTION),
14367
- (0, import_firestore43.where)("userId", "==", userId),
14368
- (0, import_firestore43.orderBy)("notificationTime", "desc")
14369
- );
14370
- const querySnapshot = await (0, import_firestore43.getDocs)(q);
14371
- return querySnapshot.docs.map((doc37) => ({
14372
- id: doc37.id,
14373
- ...doc37.data()
14540
+ const q = (0, import_firestore44.query)(
14541
+ (0, import_firestore44.collection)(this.db, NOTIFICATIONS_COLLECTION),
14542
+ (0, import_firestore44.where)("userId", "==", userId),
14543
+ (0, import_firestore44.orderBy)("notificationTime", "desc")
14544
+ );
14545
+ const querySnapshot = await (0, import_firestore44.getDocs)(q);
14546
+ return querySnapshot.docs.map((doc38) => ({
14547
+ id: doc38.id,
14548
+ ...doc38.data()
14374
14549
  }));
14375
14550
  }
14376
14551
  /**
14377
14552
  * Dohvata nepročitane notifikacije za korisnika
14378
14553
  */
14379
14554
  async getUnreadNotifications(userId) {
14380
- const q = (0, import_firestore43.query)(
14381
- (0, import_firestore43.collection)(this.db, NOTIFICATIONS_COLLECTION),
14382
- (0, import_firestore43.where)("userId", "==", userId),
14383
- (0, import_firestore43.where)("isRead", "==", false),
14384
- (0, import_firestore43.orderBy)("notificationTime", "desc")
14385
- );
14386
- const querySnapshot = await (0, import_firestore43.getDocs)(q);
14387
- return querySnapshot.docs.map((doc37) => ({
14388
- id: doc37.id,
14389
- ...doc37.data()
14555
+ const q = (0, import_firestore44.query)(
14556
+ (0, import_firestore44.collection)(this.db, NOTIFICATIONS_COLLECTION),
14557
+ (0, import_firestore44.where)("userId", "==", userId),
14558
+ (0, import_firestore44.where)("isRead", "==", false),
14559
+ (0, import_firestore44.orderBy)("notificationTime", "desc")
14560
+ );
14561
+ const querySnapshot = await (0, import_firestore44.getDocs)(q);
14562
+ return querySnapshot.docs.map((doc38) => ({
14563
+ id: doc38.id,
14564
+ ...doc38.data()
14390
14565
  }));
14391
14566
  }
14392
14567
  /**
14393
14568
  * Označava notifikaciju kao pročitanu
14394
14569
  */
14395
14570
  async markAsRead(notificationId) {
14396
- const notificationRef = (0, import_firestore43.doc)(
14571
+ const notificationRef = (0, import_firestore44.doc)(
14397
14572
  this.db,
14398
14573
  NOTIFICATIONS_COLLECTION,
14399
14574
  notificationId
14400
14575
  );
14401
- await (0, import_firestore43.updateDoc)(notificationRef, {
14576
+ await (0, import_firestore44.updateDoc)(notificationRef, {
14402
14577
  isRead: true,
14403
- updatedAt: import_firestore43.Timestamp.now()
14578
+ updatedAt: import_firestore44.Timestamp.now()
14404
14579
  });
14405
14580
  }
14406
14581
  /**
@@ -14408,16 +14583,16 @@ var NotificationService = class extends BaseService {
14408
14583
  */
14409
14584
  async markAllAsRead(userId) {
14410
14585
  const notifications = await this.getUnreadNotifications(userId);
14411
- const batch = (0, import_firestore43.writeBatch)(this.db);
14586
+ const batch = (0, import_firestore44.writeBatch)(this.db);
14412
14587
  notifications.forEach((notification) => {
14413
- const notificationRef = (0, import_firestore43.doc)(
14588
+ const notificationRef = (0, import_firestore44.doc)(
14414
14589
  this.db,
14415
14590
  NOTIFICATIONS_COLLECTION,
14416
14591
  notification.id
14417
14592
  );
14418
14593
  batch.update(notificationRef, {
14419
14594
  isRead: true,
14420
- updatedAt: import_firestore43.Timestamp.now()
14595
+ updatedAt: import_firestore44.Timestamp.now()
14421
14596
  });
14422
14597
  });
14423
14598
  await batch.commit();
@@ -14426,74 +14601,74 @@ var NotificationService = class extends BaseService {
14426
14601
  * Ažurira status notifikacije
14427
14602
  */
14428
14603
  async updateNotificationStatus(notificationId, status) {
14429
- const notificationRef = (0, import_firestore43.doc)(
14604
+ const notificationRef = (0, import_firestore44.doc)(
14430
14605
  this.db,
14431
14606
  NOTIFICATIONS_COLLECTION,
14432
14607
  notificationId
14433
14608
  );
14434
- await (0, import_firestore43.updateDoc)(notificationRef, {
14609
+ await (0, import_firestore44.updateDoc)(notificationRef, {
14435
14610
  status,
14436
- updatedAt: import_firestore43.Timestamp.now()
14611
+ updatedAt: import_firestore44.Timestamp.now()
14437
14612
  });
14438
14613
  }
14439
14614
  /**
14440
14615
  * Briše notifikaciju
14441
14616
  */
14442
14617
  async deleteNotification(notificationId) {
14443
- const notificationRef = (0, import_firestore43.doc)(
14618
+ const notificationRef = (0, import_firestore44.doc)(
14444
14619
  this.db,
14445
14620
  NOTIFICATIONS_COLLECTION,
14446
14621
  notificationId
14447
14622
  );
14448
- await (0, import_firestore43.deleteDoc)(notificationRef);
14623
+ await (0, import_firestore44.deleteDoc)(notificationRef);
14449
14624
  }
14450
14625
  /**
14451
14626
  * Dohvata notifikacije po tipu
14452
14627
  */
14453
14628
  async getNotificationsByType(userId, type) {
14454
- const q = (0, import_firestore43.query)(
14455
- (0, import_firestore43.collection)(this.db, NOTIFICATIONS_COLLECTION),
14456
- (0, import_firestore43.where)("userId", "==", userId),
14457
- (0, import_firestore43.where)("notificationType", "==", type),
14458
- (0, import_firestore43.orderBy)("notificationTime", "desc")
14459
- );
14460
- const querySnapshot = await (0, import_firestore43.getDocs)(q);
14461
- return querySnapshot.docs.map((doc37) => ({
14462
- id: doc37.id,
14463
- ...doc37.data()
14629
+ const q = (0, import_firestore44.query)(
14630
+ (0, import_firestore44.collection)(this.db, NOTIFICATIONS_COLLECTION),
14631
+ (0, import_firestore44.where)("userId", "==", userId),
14632
+ (0, import_firestore44.where)("notificationType", "==", type),
14633
+ (0, import_firestore44.orderBy)("notificationTime", "desc")
14634
+ );
14635
+ const querySnapshot = await (0, import_firestore44.getDocs)(q);
14636
+ return querySnapshot.docs.map((doc38) => ({
14637
+ id: doc38.id,
14638
+ ...doc38.data()
14464
14639
  }));
14465
14640
  }
14466
14641
  /**
14467
14642
  * Dohvata notifikacije za određeni termin
14468
14643
  */
14469
14644
  async getAppointmentNotifications(appointmentId) {
14470
- const q = (0, import_firestore43.query)(
14471
- (0, import_firestore43.collection)(this.db, NOTIFICATIONS_COLLECTION),
14472
- (0, import_firestore43.where)("appointmentId", "==", appointmentId),
14473
- (0, import_firestore43.orderBy)("notificationTime", "desc")
14474
- );
14475
- const querySnapshot = await (0, import_firestore43.getDocs)(q);
14476
- return querySnapshot.docs.map((doc37) => ({
14477
- id: doc37.id,
14478
- ...doc37.data()
14645
+ const q = (0, import_firestore44.query)(
14646
+ (0, import_firestore44.collection)(this.db, NOTIFICATIONS_COLLECTION),
14647
+ (0, import_firestore44.where)("appointmentId", "==", appointmentId),
14648
+ (0, import_firestore44.orderBy)("notificationTime", "desc")
14649
+ );
14650
+ const querySnapshot = await (0, import_firestore44.getDocs)(q);
14651
+ return querySnapshot.docs.map((doc38) => ({
14652
+ id: doc38.id,
14653
+ ...doc38.data()
14479
14654
  }));
14480
14655
  }
14481
14656
  };
14482
14657
 
14483
14658
  // src/services/patient/patientRequirements.service.ts
14484
- var import_firestore44 = require("firebase/firestore");
14659
+ var import_firestore45 = require("firebase/firestore");
14485
14660
  var PatientRequirementsService = class extends BaseService {
14486
14661
  constructor(db, auth, app) {
14487
14662
  super(db, auth, app);
14488
14663
  }
14489
14664
  getPatientRequirementsCollectionRef(patientId) {
14490
- return (0, import_firestore44.collection)(
14665
+ return (0, import_firestore45.collection)(
14491
14666
  this.db,
14492
14667
  `patients/${patientId}/${PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME}`
14493
14668
  );
14494
14669
  }
14495
14670
  getPatientRequirementDocRef(patientId, instanceId) {
14496
- return (0, import_firestore44.doc)(
14671
+ return (0, import_firestore45.doc)(
14497
14672
  this.getPatientRequirementsCollectionRef(patientId),
14498
14673
  instanceId
14499
14674
  );
@@ -14506,7 +14681,7 @@ var PatientRequirementsService = class extends BaseService {
14506
14681
  */
14507
14682
  async getPatientRequirementInstance(patientId, instanceId) {
14508
14683
  const docRef = this.getPatientRequirementDocRef(patientId, instanceId);
14509
- const docSnap = await (0, import_firestore44.getDoc)(docRef);
14684
+ const docSnap = await (0, import_firestore45.getDoc)(docRef);
14510
14685
  if (!docSnap.exists()) {
14511
14686
  return null;
14512
14687
  }
@@ -14525,22 +14700,22 @@ var PatientRequirementsService = class extends BaseService {
14525
14700
  */
14526
14701
  async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
14527
14702
  const collRef = this.getPatientRequirementsCollectionRef(patientId);
14528
- let q = (0, import_firestore44.query)(collRef, (0, import_firestore44.orderBy)("createdAt", "desc"));
14703
+ let q = (0, import_firestore45.query)(collRef, (0, import_firestore45.orderBy)("createdAt", "desc"));
14529
14704
  const queryConstraints = [];
14530
14705
  if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
14531
14706
  queryConstraints.push(
14532
- (0, import_firestore44.where)("appointmentId", "==", filters.appointmentId)
14707
+ (0, import_firestore45.where)("appointmentId", "==", filters.appointmentId)
14533
14708
  );
14534
14709
  }
14535
14710
  if ((filters == null ? void 0 : filters.statuses) && filters.statuses.length > 0) {
14536
- queryConstraints.push((0, import_firestore44.where)("overallStatus", "in", filters.statuses));
14711
+ queryConstraints.push((0, import_firestore45.where)("overallStatus", "in", filters.statuses));
14537
14712
  }
14538
14713
  if (lastVisible) {
14539
- queryConstraints.push((0, import_firestore44.startAfter)(lastVisible));
14714
+ queryConstraints.push((0, import_firestore45.startAfter)(lastVisible));
14540
14715
  }
14541
- queryConstraints.push((0, import_firestore44.limit)(pageLimit));
14542
- q = (0, import_firestore44.query)(collRef, ...queryConstraints);
14543
- const snapshot = await (0, import_firestore44.getDocs)(q);
14716
+ queryConstraints.push((0, import_firestore45.limit)(pageLimit));
14717
+ q = (0, import_firestore45.query)(collRef, ...queryConstraints);
14718
+ const snapshot = await (0, import_firestore45.getDocs)(q);
14544
14719
  let requirements = snapshot.docs.map((docSnap) => {
14545
14720
  const data = docSnap.data();
14546
14721
  return { id: docSnap.id, ...data };
@@ -14583,7 +14758,7 @@ var PatientRequirementsService = class extends BaseService {
14583
14758
  */
14584
14759
  async completeInstruction(patientId, instanceId, instructionId) {
14585
14760
  const instanceRef = this.getPatientRequirementDocRef(patientId, instanceId);
14586
- const instanceSnap = await (0, import_firestore44.getDoc)(instanceRef);
14761
+ const instanceSnap = await (0, import_firestore45.getDoc)(instanceRef);
14587
14762
  if (!instanceSnap.exists()) {
14588
14763
  throw new Error(
14589
14764
  `PatientRequirementInstance ${instanceId} not found for patient ${patientId}.`
@@ -14611,7 +14786,7 @@ var PatientRequirementsService = class extends BaseService {
14611
14786
  `Instruction ${instructionId} is in status ${instructionToUpdate.status} and cannot be marked as completed.`
14612
14787
  );
14613
14788
  }
14614
- const now = import_firestore44.Timestamp.now();
14789
+ const now = import_firestore45.Timestamp.now();
14615
14790
  const updatedInstructions = [...instance.instructions];
14616
14791
  updatedInstructions[instructionIndex] = {
14617
14792
  ...instructionToUpdate,
@@ -14638,7 +14813,7 @@ var PatientRequirementsService = class extends BaseService {
14638
14813
  if (newOverallStatus !== instance.overallStatus) {
14639
14814
  updatePayload.overallStatus = newOverallStatus;
14640
14815
  }
14641
- await (0, import_firestore44.updateDoc)(instanceRef, updatePayload);
14816
+ await (0, import_firestore45.updateDoc)(instanceRef, updatePayload);
14642
14817
  return {
14643
14818
  ...instance,
14644
14819
  instructions: updatedInstructions,
@@ -14651,70 +14826,144 @@ var PatientRequirementsService = class extends BaseService {
14651
14826
  };
14652
14827
 
14653
14828
  // src/services/procedure/procedure.service.ts
14654
- var import_firestore45 = require("firebase/firestore");
14829
+ var import_firestore46 = require("firebase/firestore");
14655
14830
 
14656
14831
  // src/validations/procedure.schema.ts
14832
+ var import_zod25 = require("zod");
14833
+
14834
+ // src/validations/procedure-product.schema.ts
14657
14835
  var import_zod24 = require("zod");
14658
- var createProcedureSchema = import_zod24.z.object({
14659
- name: import_zod24.z.string().min(1).max(200),
14660
- // Optional: service will derive from name if not provided by client
14661
- nameLower: import_zod24.z.string().min(1).max(200).optional(),
14662
- description: import_zod24.z.string().min(1).max(2e3),
14663
- family: import_zod24.z.nativeEnum(ProcedureFamily),
14664
- categoryId: import_zod24.z.string().min(1),
14665
- subcategoryId: import_zod24.z.string().min(1),
14666
- technologyId: import_zod24.z.string().min(1),
14667
- productId: import_zod24.z.string().min(1),
14668
- price: import_zod24.z.number().min(0),
14836
+ var procedureProductDataSchema = import_zod24.z.object({
14837
+ /**
14838
+ * The ID of the product. Must be a non-empty string.
14839
+ * @validation
14840
+ */
14841
+ productId: import_zod24.z.string().min(1, "Product ID is required"),
14842
+ /**
14843
+ * The price of the product. Must be a non-negative number.
14844
+ * @validation
14845
+ */
14846
+ price: import_zod24.z.number().min(0, "Price must be a non-negative number"),
14847
+ /**
14848
+ * The currency for the price. Must be one of the values from the Currency enum.
14849
+ * @validation
14850
+ */
14669
14851
  currency: import_zod24.z.nativeEnum(Currency),
14852
+ /**
14853
+ * The pricing measure for the product. Must be one of the values from the PricingMeasure enum.
14854
+ * @validation
14855
+ */
14670
14856
  pricingMeasure: import_zod24.z.nativeEnum(PricingMeasure),
14671
- duration: import_zod24.z.number().min(1).max(480),
14857
+ /**
14858
+ * Whether this is the default product for the procedure.
14859
+ * @validation
14860
+ */
14861
+ isDefault: import_zod24.z.boolean().optional()
14862
+ });
14863
+
14864
+ // src/validations/procedure.schema.ts
14865
+ var storedProcedureProductSchema = import_zod25.z.object({
14866
+ /**
14867
+ * The full product object used in the procedure.
14868
+ */
14869
+ product: import_zod25.z.any(),
14870
+ // We'll validate the full product object separately
14871
+ /**
14872
+ * The price of the procedure when using this specific product.
14873
+ */
14874
+ price: import_zod25.z.number().min(0, "Price must be a non-negative number"),
14875
+ /**
14876
+ * The currency for the price of this product.
14877
+ */
14878
+ currency: import_zod25.z.nativeEnum(Currency),
14879
+ /**
14880
+ * How the price is measured (e.g., per ml, per zone).
14881
+ */
14882
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14883
+ /**
14884
+ * Whether this is the default product for the procedure.
14885
+ */
14886
+ isDefault: import_zod25.z.boolean().optional()
14887
+ });
14888
+ var createProcedureSchema = import_zod25.z.object({
14889
+ name: import_zod25.z.string().min(1).max(200),
14890
+ // Optional: service will derive from name if not provided by client
14891
+ nameLower: import_zod25.z.string().min(1).max(200).optional(),
14892
+ description: import_zod25.z.string().min(1).max(2e3),
14893
+ family: import_zod25.z.nativeEnum(ProcedureFamily),
14894
+ categoryId: import_zod25.z.string().min(1),
14895
+ subcategoryId: import_zod25.z.string().min(1),
14896
+ technologyId: import_zod25.z.string().min(1),
14897
+ productId: import_zod25.z.string().min(1),
14898
+ price: import_zod25.z.number().min(0),
14899
+ currency: import_zod25.z.nativeEnum(Currency),
14900
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14901
+ productsMetadata: import_zod25.z.array(procedureProductDataSchema).min(1),
14902
+ duration: import_zod25.z.number().min(1).max(480),
14672
14903
  // Max 8 hours
14673
- practitionerId: import_zod24.z.string().min(1),
14674
- clinicBranchId: import_zod24.z.string().min(1),
14675
- photos: import_zod24.z.array(mediaResourceSchema).optional()
14904
+ practitionerId: import_zod25.z.string().min(1),
14905
+ clinicBranchId: import_zod25.z.string().min(1),
14906
+ photos: import_zod25.z.array(mediaResourceSchema).optional()
14676
14907
  });
14677
- var updateProcedureSchema = import_zod24.z.object({
14678
- name: import_zod24.z.string().min(3).max(100).optional(),
14679
- nameLower: import_zod24.z.string().min(1).max(200).optional(),
14680
- description: import_zod24.z.string().min(3).max(1e3).optional(),
14681
- price: import_zod24.z.number().min(0).optional(),
14682
- currency: import_zod24.z.nativeEnum(Currency).optional(),
14683
- pricingMeasure: import_zod24.z.nativeEnum(PricingMeasure).optional(),
14684
- duration: import_zod24.z.number().min(0).optional(),
14685
- isActive: import_zod24.z.boolean().optional(),
14686
- practitionerId: import_zod24.z.string().optional(),
14687
- categoryId: import_zod24.z.string().optional(),
14688
- subcategoryId: import_zod24.z.string().optional(),
14689
- technologyId: import_zod24.z.string().optional(),
14690
- productId: import_zod24.z.string().optional(),
14691
- clinicBranchId: import_zod24.z.string().optional(),
14692
- photos: import_zod24.z.array(mediaResourceSchema).optional()
14908
+ var updateProcedureSchema = import_zod25.z.object({
14909
+ name: import_zod25.z.string().min(3).max(100).optional(),
14910
+ nameLower: import_zod25.z.string().min(1).max(200).optional(),
14911
+ description: import_zod25.z.string().min(3).max(1e3).optional(),
14912
+ price: import_zod25.z.number().min(0).optional(),
14913
+ currency: import_zod25.z.nativeEnum(Currency).optional(),
14914
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure).optional(),
14915
+ productsMetadata: import_zod25.z.array(procedureProductDataSchema).min(1).optional(),
14916
+ duration: import_zod25.z.number().min(0).optional(),
14917
+ isActive: import_zod25.z.boolean().optional(),
14918
+ practitionerId: import_zod25.z.string().optional(),
14919
+ categoryId: import_zod25.z.string().optional(),
14920
+ subcategoryId: import_zod25.z.string().optional(),
14921
+ technologyId: import_zod25.z.string().optional(),
14922
+ productId: import_zod25.z.string().optional(),
14923
+ clinicBranchId: import_zod25.z.string().optional(),
14924
+ photos: import_zod25.z.array(mediaResourceSchema).optional()
14693
14925
  });
14694
- var procedureSchema = createProcedureSchema.extend({
14695
- id: import_zod24.z.string().min(1),
14696
- nameLower: import_zod24.z.string().min(1).max(200),
14697
- category: import_zod24.z.any(),
14926
+ var procedureSchema = import_zod25.z.object({
14927
+ id: import_zod25.z.string().min(1),
14928
+ name: import_zod25.z.string().min(1).max(200),
14929
+ nameLower: import_zod25.z.string().min(1).max(200),
14930
+ description: import_zod25.z.string().min(1).max(2e3),
14931
+ family: import_zod25.z.nativeEnum(ProcedureFamily),
14932
+ category: import_zod25.z.any(),
14698
14933
  // We'll validate the full category object separately
14699
- subcategory: import_zod24.z.any(),
14934
+ subcategory: import_zod25.z.any(),
14700
14935
  // We'll validate the full subcategory object separately
14701
- technology: import_zod24.z.any(),
14936
+ technology: import_zod25.z.any(),
14702
14937
  // We'll validate the full technology object separately
14703
- product: import_zod24.z.any(),
14938
+ product: import_zod25.z.any(),
14704
14939
  // We'll validate the full product object separately
14705
- blockingConditions: import_zod24.z.array(import_zod24.z.any()),
14940
+ productsMetadata: import_zod25.z.array(storedProcedureProductSchema).min(1),
14941
+ // Use stored format schema
14942
+ price: import_zod25.z.number().min(0),
14943
+ currency: import_zod25.z.nativeEnum(Currency),
14944
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14945
+ duration: import_zod25.z.number().min(1).max(480),
14946
+ practitionerId: import_zod25.z.string().min(1),
14947
+ clinicBranchId: import_zod25.z.string().min(1),
14948
+ photos: import_zod25.z.array(import_zod25.z.string()).optional(),
14949
+ // Stored as URL strings
14950
+ blockingConditions: import_zod25.z.array(import_zod25.z.any()),
14706
14951
  // We'll validate blocking conditions separately
14707
- contraindications: import_zod24.z.array(import_zod24.z.any()),
14952
+ contraindications: import_zod25.z.array(import_zod25.z.any()),
14708
14953
  // We'll validate contraindications separately
14709
- treatmentBenefits: import_zod24.z.array(import_zod24.z.any()),
14954
+ contraindicationIds: import_zod25.z.array(import_zod25.z.string()),
14955
+ // Array of IDs for efficient querying
14956
+ treatmentBenefits: import_zod25.z.array(import_zod25.z.any()),
14710
14957
  // We'll validate treatment benefits separately
14711
- preRequirements: import_zod24.z.array(import_zod24.z.any()),
14958
+ treatmentBenefitIds: import_zod25.z.array(import_zod25.z.string()),
14959
+ // Array of IDs for efficient querying
14960
+ preRequirements: import_zod25.z.array(import_zod25.z.any()),
14712
14961
  // We'll validate requirements separately
14713
- postRequirements: import_zod24.z.array(import_zod24.z.any()),
14962
+ postRequirements: import_zod25.z.array(import_zod25.z.any()),
14714
14963
  // We'll validate requirements separately
14715
- certificationRequirement: import_zod24.z.any(),
14964
+ certificationRequirement: import_zod25.z.any(),
14716
14965
  // We'll validate certification requirement separately
14717
- documentationTemplates: import_zod24.z.array(import_zod24.z.any()),
14966
+ documentationTemplates: import_zod25.z.array(import_zod25.z.any()),
14718
14967
  // We'll validate documentation templates separately
14719
14968
  clinicInfo: clinicInfoSchema,
14720
14969
  // Clinic info validation
@@ -14722,9 +14971,9 @@ var procedureSchema = createProcedureSchema.extend({
14722
14971
  // Doctor info validation
14723
14972
  reviewInfo: procedureReviewInfoSchema,
14724
14973
  // Procedure review info validation
14725
- isActive: import_zod24.z.boolean(),
14726
- createdAt: import_zod24.z.date(),
14727
- updatedAt: import_zod24.z.date()
14974
+ isActive: import_zod25.z.boolean(),
14975
+ createdAt: import_zod25.z.date(),
14976
+ updatedAt: import_zod25.z.date()
14728
14977
  });
14729
14978
 
14730
14979
  // src/services/procedure/procedure.service.ts
@@ -14751,7 +15000,9 @@ var ProcedureService = class extends BaseService {
14751
15000
  return media;
14752
15001
  }
14753
15002
  if (media instanceof File || media instanceof Blob) {
14754
- console.log(`[ProcedureService] Uploading ${collectionName} media for ${ownerId}`);
15003
+ console.log(
15004
+ `[ProcedureService] Uploading ${collectionName} media for ${ownerId}`
15005
+ );
14755
15006
  const metadata = await this.mediaService.uploadMedia(
14756
15007
  media,
14757
15008
  ownerId,
@@ -14773,41 +15024,91 @@ var ProcedureService = class extends BaseService {
14773
15024
  if (!mediaArray || mediaArray.length === 0) return [];
14774
15025
  const result = [];
14775
15026
  for (const media of mediaArray) {
14776
- const processedUrl = await this.processMedia(media, ownerId, collectionName);
15027
+ const processedUrl = await this.processMedia(
15028
+ media,
15029
+ ownerId,
15030
+ collectionName
15031
+ );
14777
15032
  if (processedUrl) {
14778
15033
  result.push(processedUrl);
14779
15034
  }
14780
15035
  }
14781
15036
  return result;
14782
15037
  }
15038
+ /**
15039
+ * Transforms validated procedure product data (with productId) to ProcedureProduct objects (with full product)
15040
+ * @param productsMetadata Array of validated procedure product data
15041
+ * @param technologyId Technology ID to fetch products from
15042
+ * @returns Array of ProcedureProduct objects with full product information
15043
+ */
15044
+ async transformProductsMetadata(productsMetadata, technologyId) {
15045
+ const transformedProducts = [];
15046
+ for (const productData of productsMetadata) {
15047
+ const product = await this.productService.getById(
15048
+ technologyId,
15049
+ productData.productId
15050
+ );
15051
+ if (!product) {
15052
+ throw new Error(
15053
+ `Product with ID ${productData.productId} not found for technology ${technologyId}`
15054
+ );
15055
+ }
15056
+ transformedProducts.push({
15057
+ product,
15058
+ price: productData.price,
15059
+ currency: productData.currency,
15060
+ pricingMeasure: productData.pricingMeasure,
15061
+ isDefault: productData.isDefault
15062
+ });
15063
+ }
15064
+ return transformedProducts;
15065
+ }
14783
15066
  /**
14784
15067
  * Creates a new procedure
14785
15068
  * @param data - The data for creating a new procedure
14786
15069
  * @returns The created procedure
14787
15070
  */
14788
15071
  async createProcedure(data) {
14789
- var _a;
15072
+ var _a, _b, _c;
14790
15073
  const validatedData = createProcedureSchema.parse(data);
14791
15074
  const procedureId = this.generateId();
14792
15075
  const [category, subcategory, technology, product] = await Promise.all([
14793
15076
  this.categoryService.getById(validatedData.categoryId),
14794
- this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
15077
+ this.subcategoryService.getById(
15078
+ validatedData.categoryId,
15079
+ validatedData.subcategoryId
15080
+ ),
14795
15081
  this.technologyService.getById(validatedData.technologyId),
14796
- this.productService.getById(validatedData.technologyId, validatedData.productId)
15082
+ this.productService.getById(
15083
+ validatedData.technologyId,
15084
+ validatedData.productId
15085
+ )
14797
15086
  ]);
14798
15087
  if (!category || !subcategory || !technology || !product) {
14799
15088
  throw new Error("One or more required base entities not found");
14800
15089
  }
14801
- const clinicRef = (0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
14802
- const clinicSnapshot = await (0, import_firestore45.getDoc)(clinicRef);
15090
+ const clinicRef = (0, import_firestore46.doc)(
15091
+ this.db,
15092
+ CLINICS_COLLECTION,
15093
+ validatedData.clinicBranchId
15094
+ );
15095
+ const clinicSnapshot = await (0, import_firestore46.getDoc)(clinicRef);
14803
15096
  if (!clinicSnapshot.exists()) {
14804
- throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
15097
+ throw new Error(
15098
+ `Clinic with ID ${validatedData.clinicBranchId} not found`
15099
+ );
14805
15100
  }
14806
15101
  const clinic = clinicSnapshot.data();
14807
- const practitionerRef = (0, import_firestore45.doc)(this.db, PRACTITIONERS_COLLECTION, validatedData.practitionerId);
14808
- const practitionerSnapshot = await (0, import_firestore45.getDoc)(practitionerRef);
15102
+ const practitionerRef = (0, import_firestore46.doc)(
15103
+ this.db,
15104
+ PRACTITIONERS_COLLECTION,
15105
+ validatedData.practitionerId
15106
+ );
15107
+ const practitionerSnapshot = await (0, import_firestore46.getDoc)(practitionerRef);
14809
15108
  if (!practitionerSnapshot.exists()) {
14810
- throw new Error(`Practitioner with ID ${validatedData.practitionerId} not found`);
15109
+ throw new Error(
15110
+ `Practitioner with ID ${validatedData.practitionerId} not found`
15111
+ );
14811
15112
  }
14812
15113
  const practitioner = practitionerSnapshot.data();
14813
15114
  let processedPhotos = [];
@@ -14818,6 +15119,10 @@ var ProcedureService = class extends BaseService {
14818
15119
  "procedure-photos"
14819
15120
  );
14820
15121
  }
15122
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15123
+ validatedData.productsMetadata,
15124
+ validatedData.technologyId
15125
+ );
14821
15126
  const clinicInfo = {
14822
15127
  id: clinicSnapshot.id,
14823
15128
  name: clinic.name,
@@ -14846,9 +15151,12 @@ var ProcedureService = class extends BaseService {
14846
15151
  subcategory,
14847
15152
  technology,
14848
15153
  product,
15154
+ productsMetadata: transformedProductsMetadata,
14849
15155
  blockingConditions: technology.blockingConditions,
14850
15156
  contraindications: technology.contraindications || [],
15157
+ contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
14851
15158
  treatmentBenefits: technology.benefits,
15159
+ treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
14852
15160
  preRequirements: technology.requirements.pre,
14853
15161
  postRequirements: technology.requirements.post,
14854
15162
  certificationRequirement: technology.certificationRequirement,
@@ -14871,13 +15179,13 @@ var ProcedureService = class extends BaseService {
14871
15179
  isActive: true
14872
15180
  // Default to active
14873
15181
  };
14874
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
14875
- await (0, import_firestore45.setDoc)(procedureRef, {
15182
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
15183
+ await (0, import_firestore46.setDoc)(procedureRef, {
14876
15184
  ...newProcedure,
14877
- createdAt: (0, import_firestore45.serverTimestamp)(),
14878
- updatedAt: (0, import_firestore45.serverTimestamp)()
15185
+ createdAt: (0, import_firestore46.serverTimestamp)(),
15186
+ updatedAt: (0, import_firestore46.serverTimestamp)()
14879
15187
  });
14880
- const savedDoc = await (0, import_firestore45.getDoc)(procedureRef);
15188
+ const savedDoc = await (0, import_firestore46.getDoc)(procedureRef);
14881
15189
  return savedDoc.data();
14882
15190
  }
14883
15191
  /**
@@ -14889,7 +15197,7 @@ var ProcedureService = class extends BaseService {
14889
15197
  * @returns A promise that resolves to an array of the newly created procedures.
14890
15198
  */
14891
15199
  async bulkCreateProcedures(baseData, practitionerIds) {
14892
- var _a;
15200
+ var _a, _b, _c;
14893
15201
  if (!practitionerIds || practitionerIds.length === 0) {
14894
15202
  throw new Error("Practitioner IDs array cannot be empty.");
14895
15203
  }
@@ -14897,16 +15205,24 @@ var ProcedureService = class extends BaseService {
14897
15205
  const validatedData = createProcedureSchema.parse(validationData);
14898
15206
  const [category, subcategory, technology, product, clinicSnapshot] = await Promise.all([
14899
15207
  this.categoryService.getById(validatedData.categoryId),
14900
- this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
15208
+ this.subcategoryService.getById(
15209
+ validatedData.categoryId,
15210
+ validatedData.subcategoryId
15211
+ ),
14901
15212
  this.technologyService.getById(validatedData.technologyId),
14902
- this.productService.getById(validatedData.technologyId, validatedData.productId),
14903
- (0, import_firestore45.getDoc)((0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
15213
+ this.productService.getById(
15214
+ validatedData.technologyId,
15215
+ validatedData.productId
15216
+ ),
15217
+ (0, import_firestore46.getDoc)((0, import_firestore46.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
14904
15218
  ]);
14905
15219
  if (!category || !subcategory || !technology || !product) {
14906
15220
  throw new Error("One or more required base entities not found");
14907
15221
  }
14908
15222
  if (!clinicSnapshot.exists()) {
14909
- throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
15223
+ throw new Error(
15224
+ `Clinic with ID ${validatedData.clinicBranchId} not found`
15225
+ );
14910
15226
  }
14911
15227
  const clinic = clinicSnapshot.data();
14912
15228
  let processedPhotos = [];
@@ -14918,24 +15234,32 @@ var ProcedureService = class extends BaseService {
14918
15234
  "procedure-photos-batch"
14919
15235
  );
14920
15236
  }
15237
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15238
+ validatedData.productsMetadata,
15239
+ validatedData.technologyId
15240
+ );
14921
15241
  const practitionersMap = /* @__PURE__ */ new Map();
14922
15242
  for (let i = 0; i < practitionerIds.length; i += 30) {
14923
15243
  const chunk = practitionerIds.slice(i, i + 30);
14924
- const practitionersQuery = (0, import_firestore45.query)(
14925
- (0, import_firestore45.collection)(this.db, PRACTITIONERS_COLLECTION),
14926
- (0, import_firestore45.where)((0, import_firestore45.documentId)(), "in", chunk)
15244
+ const practitionersQuery = (0, import_firestore46.query)(
15245
+ (0, import_firestore46.collection)(this.db, PRACTITIONERS_COLLECTION),
15246
+ (0, import_firestore46.where)((0, import_firestore46.documentId)(), "in", chunk)
14927
15247
  );
14928
- const practitionersSnapshot = await (0, import_firestore45.getDocs)(practitionersQuery);
14929
- practitionersSnapshot.docs.forEach((doc37) => {
14930
- practitionersMap.set(doc37.id, doc37.data());
15248
+ const practitionersSnapshot = await (0, import_firestore46.getDocs)(practitionersQuery);
15249
+ practitionersSnapshot.docs.forEach((doc38) => {
15250
+ practitionersMap.set(doc38.id, doc38.data());
14931
15251
  });
14932
15252
  }
14933
15253
  if (practitionersMap.size !== practitionerIds.length) {
14934
15254
  const foundIds = Array.from(practitionersMap.keys());
14935
- const notFoundIds = practitionerIds.filter((id) => !foundIds.includes(id));
14936
- throw new Error(`The following practitioners were not found: ${notFoundIds.join(", ")}`);
15255
+ const notFoundIds = practitionerIds.filter(
15256
+ (id) => !foundIds.includes(id)
15257
+ );
15258
+ throw new Error(
15259
+ `The following practitioners were not found: ${notFoundIds.join(", ")}`
15260
+ );
14937
15261
  }
14938
- const batch = (0, import_firestore45.writeBatch)(this.db);
15262
+ const batch = (0, import_firestore46.writeBatch)(this.db);
14939
15263
  const createdProcedureIds = [];
14940
15264
  const clinicInfo = {
14941
15265
  id: clinicSnapshot.id,
@@ -14957,7 +15281,7 @@ var ProcedureService = class extends BaseService {
14957
15281
  };
14958
15282
  const procedureId = this.generateId();
14959
15283
  createdProcedureIds.push(procedureId);
14960
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
15284
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
14961
15285
  const newProcedure = {
14962
15286
  id: procedureId,
14963
15287
  ...validatedData,
@@ -14969,9 +15293,12 @@ var ProcedureService = class extends BaseService {
14969
15293
  subcategory,
14970
15294
  technology,
14971
15295
  product,
15296
+ productsMetadata: transformedProductsMetadata,
14972
15297
  blockingConditions: technology.blockingConditions,
14973
15298
  contraindications: technology.contraindications || [],
15299
+ contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
14974
15300
  treatmentBenefits: technology.benefits,
15301
+ treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
14975
15302
  preRequirements: technology.requirements.pre,
14976
15303
  postRequirements: technology.requirements.post,
14977
15304
  certificationRequirement: technology.certificationRequirement,
@@ -14993,18 +15320,21 @@ var ProcedureService = class extends BaseService {
14993
15320
  };
14994
15321
  batch.set(procedureRef, {
14995
15322
  ...newProcedure,
14996
- createdAt: (0, import_firestore45.serverTimestamp)(),
14997
- updatedAt: (0, import_firestore45.serverTimestamp)()
15323
+ createdAt: (0, import_firestore46.serverTimestamp)(),
15324
+ updatedAt: (0, import_firestore46.serverTimestamp)()
14998
15325
  });
14999
15326
  }
15000
15327
  await batch.commit();
15001
15328
  const fetchedProcedures = [];
15002
15329
  for (let i = 0; i < createdProcedureIds.length; i += 30) {
15003
15330
  const chunk = createdProcedureIds.slice(i, i + 30);
15004
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), (0, import_firestore45.where)((0, import_firestore45.documentId)(), "in", chunk));
15005
- const snapshot = await (0, import_firestore45.getDocs)(q);
15006
- snapshot.forEach((doc37) => {
15007
- fetchedProcedures.push(doc37.data());
15331
+ const q = (0, import_firestore46.query)(
15332
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15333
+ (0, import_firestore46.where)((0, import_firestore46.documentId)(), "in", chunk)
15334
+ );
15335
+ const snapshot = await (0, import_firestore46.getDocs)(q);
15336
+ snapshot.forEach((doc38) => {
15337
+ fetchedProcedures.push(doc38.data());
15008
15338
  });
15009
15339
  }
15010
15340
  return fetchedProcedures;
@@ -15015,8 +15345,8 @@ var ProcedureService = class extends BaseService {
15015
15345
  * @returns The procedure if found, null otherwise
15016
15346
  */
15017
15347
  async getProcedure(id) {
15018
- const docRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, id);
15019
- const docSnap = await (0, import_firestore45.getDoc)(docRef);
15348
+ const docRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15349
+ const docSnap = await (0, import_firestore46.getDoc)(docRef);
15020
15350
  if (!docSnap.exists()) {
15021
15351
  return null;
15022
15352
  }
@@ -15028,13 +15358,13 @@ var ProcedureService = class extends BaseService {
15028
15358
  * @returns List of procedures
15029
15359
  */
15030
15360
  async getProceduresByClinicBranch(clinicBranchId) {
15031
- const q = (0, import_firestore45.query)(
15032
- (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION),
15033
- (0, import_firestore45.where)("clinicBranchId", "==", clinicBranchId),
15034
- (0, import_firestore45.where)("isActive", "==", true)
15361
+ const q = (0, import_firestore46.query)(
15362
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15363
+ (0, import_firestore46.where)("clinicBranchId", "==", clinicBranchId),
15364
+ (0, import_firestore46.where)("isActive", "==", true)
15035
15365
  );
15036
- const snapshot = await (0, import_firestore45.getDocs)(q);
15037
- return snapshot.docs.map((doc37) => doc37.data());
15366
+ const snapshot = await (0, import_firestore46.getDocs)(q);
15367
+ return snapshot.docs.map((doc38) => doc38.data());
15038
15368
  }
15039
15369
  /**
15040
15370
  * Gets all procedures for a practitioner
@@ -15042,13 +15372,13 @@ var ProcedureService = class extends BaseService {
15042
15372
  * @returns List of procedures
15043
15373
  */
15044
15374
  async getProceduresByPractitioner(practitionerId) {
15045
- const q = (0, import_firestore45.query)(
15046
- (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION),
15047
- (0, import_firestore45.where)("practitionerId", "==", practitionerId),
15048
- (0, import_firestore45.where)("isActive", "==", true)
15375
+ const q = (0, import_firestore46.query)(
15376
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15377
+ (0, import_firestore46.where)("practitionerId", "==", practitionerId),
15378
+ (0, import_firestore46.where)("isActive", "==", true)
15049
15379
  );
15050
- const snapshot = await (0, import_firestore45.getDocs)(q);
15051
- return snapshot.docs.map((doc37) => doc37.data());
15380
+ const snapshot = await (0, import_firestore46.getDocs)(q);
15381
+ return snapshot.docs.map((doc38) => doc38.data());
15052
15382
  }
15053
15383
  /**
15054
15384
  * Gets all inactive procedures for a practitioner
@@ -15056,13 +15386,13 @@ var ProcedureService = class extends BaseService {
15056
15386
  * @returns List of inactive procedures
15057
15387
  */
15058
15388
  async getInactiveProceduresByPractitioner(practitionerId) {
15059
- const q = (0, import_firestore45.query)(
15060
- (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION),
15061
- (0, import_firestore45.where)("practitionerId", "==", practitionerId),
15062
- (0, import_firestore45.where)("isActive", "==", false)
15389
+ const q = (0, import_firestore46.query)(
15390
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15391
+ (0, import_firestore46.where)("practitionerId", "==", practitionerId),
15392
+ (0, import_firestore46.where)("isActive", "==", false)
15063
15393
  );
15064
- const snapshot = await (0, import_firestore45.getDocs)(q);
15065
- return snapshot.docs.map((doc37) => doc37.data());
15394
+ const snapshot = await (0, import_firestore46.getDocs)(q);
15395
+ return snapshot.docs.map((doc38) => doc38.data());
15066
15396
  }
15067
15397
  /**
15068
15398
  * Updates a procedure
@@ -15071,15 +15401,29 @@ var ProcedureService = class extends BaseService {
15071
15401
  * @returns The updated procedure
15072
15402
  */
15073
15403
  async updateProcedure(id, data) {
15074
- var _a;
15404
+ var _a, _b, _c, _d;
15075
15405
  const validatedData = updateProcedureSchema.parse(data);
15076
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, id);
15077
- const procedureSnapshot = await (0, import_firestore45.getDoc)(procedureRef);
15406
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15407
+ const procedureSnapshot = await (0, import_firestore46.getDoc)(procedureRef);
15078
15408
  if (!procedureSnapshot.exists()) {
15079
15409
  throw new Error(`Procedure with ID ${id} not found`);
15080
15410
  }
15081
15411
  const existingProcedure = procedureSnapshot.data();
15082
- let updatedProcedureData = { ...validatedData };
15412
+ let updatedProcedureData = {};
15413
+ if (validatedData.name !== void 0)
15414
+ updatedProcedureData.name = validatedData.name;
15415
+ if (validatedData.description !== void 0)
15416
+ updatedProcedureData.description = validatedData.description;
15417
+ if (validatedData.price !== void 0)
15418
+ updatedProcedureData.price = validatedData.price;
15419
+ if (validatedData.currency !== void 0)
15420
+ updatedProcedureData.currency = validatedData.currency;
15421
+ if (validatedData.pricingMeasure !== void 0)
15422
+ updatedProcedureData.pricingMeasure = validatedData.pricingMeasure;
15423
+ if (validatedData.duration !== void 0)
15424
+ updatedProcedureData.duration = validatedData.duration;
15425
+ if (validatedData.isActive !== void 0)
15426
+ updatedProcedureData.isActive = validatedData.isActive;
15083
15427
  let practitionerChanged = false;
15084
15428
  let clinicChanged = false;
15085
15429
  const oldPractitionerId = existingProcedure.practitionerId;
@@ -15093,16 +15437,30 @@ var ProcedureService = class extends BaseService {
15093
15437
  "procedure-photos"
15094
15438
  );
15095
15439
  }
15096
- if (validatedData.practitionerId && validatedData.practitionerId !== oldPractitionerId) {
15097
- practitionerChanged = true;
15098
- const newPractitionerRef = (0, import_firestore45.doc)(
15099
- this.db,
15440
+ if (validatedData.productsMetadata !== void 0) {
15441
+ const technologyId = (_a = validatedData.technologyId) != null ? _a : existingProcedure.technology.id;
15442
+ if (!technologyId) {
15443
+ throw new Error(
15444
+ "Technology ID is required for updating products metadata"
15445
+ );
15446
+ }
15447
+ updatedProcedureData.productsMetadata = await this.transformProductsMetadata(
15448
+ validatedData.productsMetadata,
15449
+ technologyId
15450
+ );
15451
+ }
15452
+ if (validatedData.practitionerId && validatedData.practitionerId !== oldPractitionerId) {
15453
+ practitionerChanged = true;
15454
+ const newPractitionerRef = (0, import_firestore46.doc)(
15455
+ this.db,
15100
15456
  PRACTITIONERS_COLLECTION,
15101
15457
  validatedData.practitionerId
15102
15458
  );
15103
- const newPractitionerSnap = await (0, import_firestore45.getDoc)(newPractitionerRef);
15459
+ const newPractitionerSnap = await (0, import_firestore46.getDoc)(newPractitionerRef);
15104
15460
  if (!newPractitionerSnap.exists())
15105
- throw new Error(`New Practitioner ${validatedData.practitionerId} not found`);
15461
+ throw new Error(
15462
+ `New Practitioner ${validatedData.practitionerId} not found`
15463
+ );
15106
15464
  newPractitioner = newPractitionerSnap.data();
15107
15465
  updatedProcedureData.doctorInfo = {
15108
15466
  id: newPractitioner.id,
@@ -15110,14 +15468,18 @@ var ProcedureService = class extends BaseService {
15110
15468
  description: newPractitioner.basicInfo.bio || "",
15111
15469
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
15112
15470
  // Default to empty string if not a processed URL
15113
- rating: ((_a = newPractitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
15471
+ rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
15114
15472
  services: newPractitioner.procedures || []
15115
15473
  };
15116
15474
  }
15117
15475
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
15118
15476
  clinicChanged = true;
15119
- const newClinicRef = (0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
15120
- const newClinicSnap = await (0, import_firestore45.getDoc)(newClinicRef);
15477
+ const newClinicRef = (0, import_firestore46.doc)(
15478
+ this.db,
15479
+ CLINICS_COLLECTION,
15480
+ validatedData.clinicBranchId
15481
+ );
15482
+ const newClinicSnap = await (0, import_firestore46.getDoc)(newClinicRef);
15121
15483
  if (!newClinicSnap.exists())
15122
15484
  throw new Error(`New Clinic ${validatedData.clinicBranchId} not found`);
15123
15485
  newClinic = newClinicSnap.data();
@@ -15135,8 +15497,11 @@ var ProcedureService = class extends BaseService {
15135
15497
  updatedProcedureData.nameLower = validatedData.name.toLowerCase();
15136
15498
  }
15137
15499
  if (validatedData.categoryId) {
15138
- const category = await this.categoryService.getById(validatedData.categoryId);
15139
- if (!category) throw new Error(`Category ${validatedData.categoryId} not found`);
15500
+ const category = await this.categoryService.getById(
15501
+ validatedData.categoryId
15502
+ );
15503
+ if (!category)
15504
+ throw new Error(`Category ${validatedData.categoryId} not found`);
15140
15505
  updatedProcedureData.category = category;
15141
15506
  finalCategoryId = category.id;
15142
15507
  }
@@ -15151,23 +15516,34 @@ var ProcedureService = class extends BaseService {
15151
15516
  );
15152
15517
  updatedProcedureData.subcategory = subcategory;
15153
15518
  } else if (validatedData.subcategoryId) {
15154
- console.warn("Attempted to update subcategory without a valid categoryId");
15519
+ console.warn(
15520
+ "Attempted to update subcategory without a valid categoryId"
15521
+ );
15155
15522
  }
15156
15523
  let finalTechnologyId = existingProcedure.technology.id;
15157
15524
  if (validatedData.technologyId) {
15158
- const technology = await this.technologyService.getById(validatedData.technologyId);
15159
- if (!technology) throw new Error(`Technology ${validatedData.technologyId} not found`);
15525
+ const technology = await this.technologyService.getById(
15526
+ validatedData.technologyId
15527
+ );
15528
+ if (!technology)
15529
+ throw new Error(`Technology ${validatedData.technologyId} not found`);
15160
15530
  updatedProcedureData.technology = technology;
15161
15531
  finalTechnologyId = technology.id;
15162
15532
  updatedProcedureData.blockingConditions = technology.blockingConditions;
15533
+ updatedProcedureData.contraindications = technology.contraindications || [];
15534
+ updatedProcedureData.contraindicationIds = ((_c = technology.contraindications) == null ? void 0 : _c.map((c) => c.id)) || [];
15163
15535
  updatedProcedureData.treatmentBenefits = technology.benefits;
15536
+ updatedProcedureData.treatmentBenefitIds = ((_d = technology.benefits) == null ? void 0 : _d.map((b) => b.id)) || [];
15164
15537
  updatedProcedureData.preRequirements = technology.requirements.pre;
15165
15538
  updatedProcedureData.postRequirements = technology.requirements.post;
15166
15539
  updatedProcedureData.certificationRequirement = technology.certificationRequirement;
15167
15540
  updatedProcedureData.documentationTemplates = technology.documentationTemplates || [];
15168
15541
  }
15169
15542
  if (validatedData.productId && finalTechnologyId) {
15170
- const product = await this.productService.getById(finalTechnologyId, validatedData.productId);
15543
+ const product = await this.productService.getById(
15544
+ finalTechnologyId,
15545
+ validatedData.productId
15546
+ );
15171
15547
  if (!product)
15172
15548
  throw new Error(
15173
15549
  `Product ${validatedData.productId} not found for technology ${finalTechnologyId}`
@@ -15176,11 +15552,11 @@ var ProcedureService = class extends BaseService {
15176
15552
  } else if (validatedData.productId) {
15177
15553
  console.warn("Attempted to update product without a valid technologyId");
15178
15554
  }
15179
- await (0, import_firestore45.updateDoc)(procedureRef, {
15555
+ await (0, import_firestore46.updateDoc)(procedureRef, {
15180
15556
  ...updatedProcedureData,
15181
- updatedAt: (0, import_firestore45.serverTimestamp)()
15557
+ updatedAt: (0, import_firestore46.serverTimestamp)()
15182
15558
  });
15183
- const updatedSnapshot = await (0, import_firestore45.getDoc)(procedureRef);
15559
+ const updatedSnapshot = await (0, import_firestore46.getDoc)(procedureRef);
15184
15560
  return updatedSnapshot.data();
15185
15561
  }
15186
15562
  /**
@@ -15188,15 +15564,15 @@ var ProcedureService = class extends BaseService {
15188
15564
  * @param id - The ID of the procedure to deactivate
15189
15565
  */
15190
15566
  async deactivateProcedure(id) {
15191
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, id);
15192
- const procedureSnap = await (0, import_firestore45.getDoc)(procedureRef);
15567
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15568
+ const procedureSnap = await (0, import_firestore46.getDoc)(procedureRef);
15193
15569
  if (!procedureSnap.exists()) {
15194
15570
  console.warn(`Procedure ${id} not found for deactivation.`);
15195
15571
  return;
15196
15572
  }
15197
- await (0, import_firestore45.updateDoc)(procedureRef, {
15573
+ await (0, import_firestore46.updateDoc)(procedureRef, {
15198
15574
  isActive: false,
15199
- updatedAt: (0, import_firestore45.serverTimestamp)()
15575
+ updatedAt: (0, import_firestore46.serverTimestamp)()
15200
15576
  });
15201
15577
  }
15202
15578
  /**
@@ -15205,12 +15581,12 @@ var ProcedureService = class extends BaseService {
15205
15581
  * @returns A boolean indicating if the deletion was successful
15206
15582
  */
15207
15583
  async deleteProcedure(id) {
15208
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, id);
15209
- const procedureSnapshot = await (0, import_firestore45.getDoc)(procedureRef);
15584
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15585
+ const procedureSnapshot = await (0, import_firestore46.getDoc)(procedureRef);
15210
15586
  if (!procedureSnapshot.exists()) {
15211
15587
  return false;
15212
15588
  }
15213
- await (0, import_firestore45.deleteDoc)(procedureRef);
15589
+ await (0, import_firestore46.deleteDoc)(procedureRef);
15214
15590
  return true;
15215
15591
  }
15216
15592
  /**
@@ -15236,31 +15612,35 @@ var ProcedureService = class extends BaseService {
15236
15612
  */
15237
15613
  async getAllProcedures(pagination, lastDoc) {
15238
15614
  try {
15239
- const proceduresCollection = (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION);
15240
- let proceduresQuery = (0, import_firestore45.query)(proceduresCollection);
15615
+ const proceduresCollection = (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION);
15616
+ let proceduresQuery = (0, import_firestore46.query)(proceduresCollection);
15241
15617
  if (pagination && pagination > 0) {
15242
- const { limit: limit16, startAfter: startAfter14 } = await import("firebase/firestore");
15618
+ const { limit: limit21, startAfter: startAfter19 } = await import("firebase/firestore");
15243
15619
  if (lastDoc) {
15244
- proceduresQuery = (0, import_firestore45.query)(
15620
+ proceduresQuery = (0, import_firestore46.query)(
15245
15621
  proceduresCollection,
15246
- (0, import_firestore45.orderBy)("name"),
15622
+ (0, import_firestore46.orderBy)("name"),
15247
15623
  // Use imported orderBy
15248
- startAfter14(lastDoc),
15249
- limit16(pagination)
15624
+ startAfter19(lastDoc),
15625
+ limit21(pagination)
15250
15626
  );
15251
15627
  } else {
15252
- proceduresQuery = (0, import_firestore45.query)(proceduresCollection, (0, import_firestore45.orderBy)("name"), limit16(pagination));
15628
+ proceduresQuery = (0, import_firestore46.query)(
15629
+ proceduresCollection,
15630
+ (0, import_firestore46.orderBy)("name"),
15631
+ limit21(pagination)
15632
+ );
15253
15633
  }
15254
15634
  } else {
15255
- proceduresQuery = (0, import_firestore45.query)(proceduresCollection, (0, import_firestore45.orderBy)("name"));
15635
+ proceduresQuery = (0, import_firestore46.query)(proceduresCollection, (0, import_firestore46.orderBy)("name"));
15256
15636
  }
15257
- const proceduresSnapshot = await (0, import_firestore45.getDocs)(proceduresQuery);
15637
+ const proceduresSnapshot = await (0, import_firestore46.getDocs)(proceduresQuery);
15258
15638
  const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
15259
- const procedures = proceduresSnapshot.docs.map((doc37) => {
15260
- const data = doc37.data();
15639
+ const procedures = proceduresSnapshot.docs.map((doc38) => {
15640
+ const data = doc38.data();
15261
15641
  return {
15262
15642
  ...data,
15263
- id: doc37.id
15643
+ id: doc38.id
15264
15644
  // Ensure ID is present
15265
15645
  };
15266
15646
  });
@@ -15280,7 +15660,7 @@ var ProcedureService = class extends BaseService {
15280
15660
  *
15281
15661
  * @param filters - Various filters to apply
15282
15662
  * @param filters.nameSearch - Optional search text for procedure name
15283
- * @param filters.treatmentBenefits - Optional array of treatment benefits to filter by
15663
+ * @param filters.treatmentBenefitIds - Optional array of treatment benefits to filter by
15284
15664
  * @param filters.procedureFamily - Optional procedure family to filter by
15285
15665
  * @param filters.procedureCategory - Optional procedure category to filter by
15286
15666
  * @param filters.procedureSubcategory - Optional procedure subcategory to filter by
@@ -15298,7 +15678,9 @@ var ProcedureService = class extends BaseService {
15298
15678
  */
15299
15679
  async getProceduresByFilters(filters) {
15300
15680
  try {
15301
- console.log("[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies");
15681
+ console.log(
15682
+ "[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies"
15683
+ );
15302
15684
  if (filters.location && filters.radiusInKm) {
15303
15685
  console.log("[PROCEDURE_SERVICE] Executing geo query:", {
15304
15686
  location: filters.location,
@@ -15306,7 +15688,10 @@ var ProcedureService = class extends BaseService {
15306
15688
  serviceName: "ProcedureService"
15307
15689
  });
15308
15690
  if (!filters.location.latitude || !filters.location.longitude) {
15309
- console.warn("[PROCEDURE_SERVICE] Invalid location data:", filters.location);
15691
+ console.warn(
15692
+ "[PROCEDURE_SERVICE] Invalid location data:",
15693
+ filters.location
15694
+ );
15310
15695
  filters.location = void 0;
15311
15696
  filters.radiusInKm = void 0;
15312
15697
  }
@@ -15318,65 +15703,88 @@ var ProcedureService = class extends BaseService {
15318
15703
  const getBaseConstraints = () => {
15319
15704
  const constraints = [];
15320
15705
  if (filters.isActive !== void 0) {
15321
- constraints.push((0, import_firestore45.where)("isActive", "==", filters.isActive));
15706
+ constraints.push((0, import_firestore46.where)("isActive", "==", filters.isActive));
15322
15707
  } else {
15323
- constraints.push((0, import_firestore45.where)("isActive", "==", true));
15708
+ constraints.push((0, import_firestore46.where)("isActive", "==", true));
15324
15709
  }
15325
15710
  if (filters.procedureFamily) {
15326
- constraints.push((0, import_firestore45.where)("family", "==", filters.procedureFamily));
15711
+ constraints.push((0, import_firestore46.where)("family", "==", filters.procedureFamily));
15327
15712
  }
15328
15713
  if (filters.procedureCategory) {
15329
- constraints.push((0, import_firestore45.where)("category.id", "==", filters.procedureCategory));
15714
+ constraints.push(
15715
+ (0, import_firestore46.where)("category.id", "==", filters.procedureCategory)
15716
+ );
15330
15717
  }
15331
15718
  if (filters.procedureSubcategory) {
15332
- constraints.push((0, import_firestore45.where)("subcategory.id", "==", filters.procedureSubcategory));
15719
+ constraints.push(
15720
+ (0, import_firestore46.where)("subcategory.id", "==", filters.procedureSubcategory)
15721
+ );
15333
15722
  }
15334
15723
  if (filters.procedureTechnology) {
15335
- constraints.push((0, import_firestore45.where)("technology.id", "==", filters.procedureTechnology));
15724
+ constraints.push(
15725
+ (0, import_firestore46.where)("technology.id", "==", filters.procedureTechnology)
15726
+ );
15336
15727
  }
15337
15728
  if (filters.minPrice !== void 0) {
15338
- constraints.push((0, import_firestore45.where)("price", ">=", filters.minPrice));
15729
+ constraints.push((0, import_firestore46.where)("price", ">=", filters.minPrice));
15339
15730
  }
15340
15731
  if (filters.maxPrice !== void 0) {
15341
- constraints.push((0, import_firestore45.where)("price", "<=", filters.maxPrice));
15732
+ constraints.push((0, import_firestore46.where)("price", "<=", filters.maxPrice));
15342
15733
  }
15343
15734
  if (filters.minRating !== void 0) {
15344
- constraints.push((0, import_firestore45.where)("reviewInfo.averageRating", ">=", filters.minRating));
15735
+ constraints.push(
15736
+ (0, import_firestore46.where)("reviewInfo.averageRating", ">=", filters.minRating)
15737
+ );
15345
15738
  }
15346
15739
  if (filters.maxRating !== void 0) {
15347
- constraints.push((0, import_firestore45.where)("reviewInfo.averageRating", "<=", filters.maxRating));
15740
+ constraints.push(
15741
+ (0, import_firestore46.where)("reviewInfo.averageRating", "<=", filters.maxRating)
15742
+ );
15348
15743
  }
15349
15744
  if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15350
- const benefitsToMatch = filters.treatmentBenefits;
15351
- constraints.push((0, import_firestore45.where)("treatmentBenefits", "array-contains-any", benefitsToMatch));
15745
+ const benefitIdsToMatch = filters.treatmentBenefits;
15746
+ constraints.push(
15747
+ (0, import_firestore46.where)(
15748
+ "treatmentBenefitIds",
15749
+ "array-contains-any",
15750
+ benefitIdsToMatch
15751
+ )
15752
+ );
15352
15753
  }
15353
15754
  return constraints;
15354
15755
  };
15355
15756
  if (filters.nameSearch && filters.nameSearch.trim()) {
15356
15757
  try {
15357
- console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
15758
+ console.log(
15759
+ "[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search"
15760
+ );
15358
15761
  const searchTerm = filters.nameSearch.trim().toLowerCase();
15359
15762
  const constraints = getBaseConstraints();
15360
- constraints.push((0, import_firestore45.where)("nameLower", ">=", searchTerm));
15361
- constraints.push((0, import_firestore45.where)("nameLower", "<=", searchTerm + "\uF8FF"));
15362
- constraints.push((0, import_firestore45.orderBy)("nameLower"));
15763
+ constraints.push((0, import_firestore46.where)("nameLower", ">=", searchTerm));
15764
+ constraints.push((0, import_firestore46.where)("nameLower", "<=", searchTerm + "\uF8FF"));
15765
+ constraints.push((0, import_firestore46.orderBy)("nameLower"));
15363
15766
  if (filters.lastDoc) {
15364
15767
  if (typeof filters.lastDoc.data === "function") {
15365
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15768
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15366
15769
  } else if (Array.isArray(filters.lastDoc)) {
15367
- constraints.push((0, import_firestore45.startAfter)(...filters.lastDoc));
15770
+ constraints.push((0, import_firestore46.startAfter)(...filters.lastDoc));
15368
15771
  } else {
15369
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15772
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15370
15773
  }
15371
15774
  }
15372
- constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15373
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15374
- const querySnapshot = await (0, import_firestore45.getDocs)(q);
15775
+ constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15776
+ const q = (0, import_firestore46.query)(
15777
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15778
+ ...constraints
15779
+ );
15780
+ const querySnapshot = await (0, import_firestore46.getDocs)(q);
15375
15781
  const procedures = querySnapshot.docs.map(
15376
- (doc37) => ({ ...doc37.data(), id: doc37.id })
15782
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
15377
15783
  );
15378
15784
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15379
- console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15785
+ console.log(
15786
+ `[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`
15787
+ );
15380
15788
  if (procedures.length < (filters.pagination || 10)) {
15381
15789
  return { procedures, lastDoc: null };
15382
15790
  }
@@ -15387,29 +15795,36 @@ var ProcedureService = class extends BaseService {
15387
15795
  }
15388
15796
  if (filters.nameSearch && filters.nameSearch.trim()) {
15389
15797
  try {
15390
- console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
15798
+ console.log(
15799
+ "[PROCEDURE_SERVICE] Strategy 2: Trying name field search"
15800
+ );
15391
15801
  const searchTerm = filters.nameSearch.trim().toLowerCase();
15392
15802
  const constraints = getBaseConstraints();
15393
- constraints.push((0, import_firestore45.where)("name", ">=", searchTerm));
15394
- constraints.push((0, import_firestore45.where)("name", "<=", searchTerm + "\uF8FF"));
15395
- constraints.push((0, import_firestore45.orderBy)("name"));
15803
+ constraints.push((0, import_firestore46.where)("name", ">=", searchTerm));
15804
+ constraints.push((0, import_firestore46.where)("name", "<=", searchTerm + "\uF8FF"));
15805
+ constraints.push((0, import_firestore46.orderBy)("name"));
15396
15806
  if (filters.lastDoc) {
15397
15807
  if (typeof filters.lastDoc.data === "function") {
15398
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15808
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15399
15809
  } else if (Array.isArray(filters.lastDoc)) {
15400
- constraints.push((0, import_firestore45.startAfter)(...filters.lastDoc));
15810
+ constraints.push((0, import_firestore46.startAfter)(...filters.lastDoc));
15401
15811
  } else {
15402
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15812
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15403
15813
  }
15404
15814
  }
15405
- constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15406
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15407
- const querySnapshot = await (0, import_firestore45.getDocs)(q);
15815
+ constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15816
+ const q = (0, import_firestore46.query)(
15817
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15818
+ ...constraints
15819
+ );
15820
+ const querySnapshot = await (0, import_firestore46.getDocs)(q);
15408
15821
  const procedures = querySnapshot.docs.map(
15409
- (doc37) => ({ ...doc37.data(), id: doc37.id })
15822
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
15410
15823
  );
15411
15824
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15412
- console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15825
+ console.log(
15826
+ `[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`
15827
+ );
15413
15828
  if (procedures.length < (filters.pagination || 10)) {
15414
15829
  return { procedures, lastDoc: null };
15415
15830
  }
@@ -15423,25 +15838,30 @@ var ProcedureService = class extends BaseService {
15423
15838
  "[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering"
15424
15839
  );
15425
15840
  const constraints = getBaseConstraints();
15426
- constraints.push((0, import_firestore45.orderBy)("createdAt", "desc"));
15841
+ constraints.push((0, import_firestore46.orderBy)("createdAt", "desc"));
15427
15842
  if (filters.lastDoc) {
15428
15843
  if (typeof filters.lastDoc.data === "function") {
15429
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15844
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15430
15845
  } else if (Array.isArray(filters.lastDoc)) {
15431
- constraints.push((0, import_firestore45.startAfter)(...filters.lastDoc));
15846
+ constraints.push((0, import_firestore46.startAfter)(...filters.lastDoc));
15432
15847
  } else {
15433
- constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
15848
+ constraints.push((0, import_firestore46.startAfter)(filters.lastDoc));
15434
15849
  }
15435
15850
  }
15436
- constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15437
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15438
- const querySnapshot = await (0, import_firestore45.getDocs)(q);
15851
+ constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15852
+ const q = (0, import_firestore46.query)(
15853
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15854
+ ...constraints
15855
+ );
15856
+ const querySnapshot = await (0, import_firestore46.getDocs)(q);
15439
15857
  let procedures = querySnapshot.docs.map(
15440
- (doc37) => ({ ...doc37.data(), id: doc37.id })
15858
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
15441
15859
  );
15442
15860
  procedures = this.applyInMemoryFilters(procedures, filters);
15443
15861
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15444
- console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
15862
+ console.log(
15863
+ `[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`
15864
+ );
15445
15865
  if (procedures.length < (filters.pagination || 10)) {
15446
15866
  return { procedures, lastDoc: null };
15447
15867
  }
@@ -15452,18 +15872,23 @@ var ProcedureService = class extends BaseService {
15452
15872
  try {
15453
15873
  console.log("[PROCEDURE_SERVICE] Strategy 4: Minimal query fallback");
15454
15874
  const constraints = [
15455
- (0, import_firestore45.where)("isActive", "==", true),
15456
- (0, import_firestore45.orderBy)("createdAt", "desc"),
15457
- (0, import_firestore45.limit)(filters.pagination || 10)
15875
+ (0, import_firestore46.where)("isActive", "==", true),
15876
+ (0, import_firestore46.orderBy)("createdAt", "desc"),
15877
+ (0, import_firestore46.limit)(filters.pagination || 10)
15458
15878
  ];
15459
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15460
- const querySnapshot = await (0, import_firestore45.getDocs)(q);
15879
+ const q = (0, import_firestore46.query)(
15880
+ (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15881
+ ...constraints
15882
+ );
15883
+ const querySnapshot = await (0, import_firestore46.getDocs)(q);
15461
15884
  let procedures = querySnapshot.docs.map(
15462
- (doc37) => ({ ...doc37.data(), id: doc37.id })
15885
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
15463
15886
  );
15464
15887
  procedures = this.applyInMemoryFilters(procedures, filters);
15465
15888
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15466
- console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
15889
+ console.log(
15890
+ `[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`
15891
+ );
15467
15892
  if (procedures.length < (filters.pagination || 10)) {
15468
15893
  return { procedures, lastDoc: null };
15469
15894
  }
@@ -15471,7 +15896,9 @@ var ProcedureService = class extends BaseService {
15471
15896
  } catch (error) {
15472
15897
  console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
15473
15898
  }
15474
- console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
15899
+ console.log(
15900
+ "[PROCEDURE_SERVICE] All strategies failed, returning empty result"
15901
+ );
15475
15902
  return { procedures: [], lastDoc: null };
15476
15903
  } catch (error) {
15477
15904
  console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
@@ -15491,13 +15918,17 @@ var ProcedureService = class extends BaseService {
15491
15918
  const nameLower = procedure.nameLower || "";
15492
15919
  return name.includes(searchTerm) || nameLower.includes(searchTerm);
15493
15920
  });
15494
- console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`);
15921
+ console.log(
15922
+ `[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`
15923
+ );
15495
15924
  }
15496
15925
  if (filters.minPrice !== void 0 || filters.maxPrice !== void 0) {
15497
15926
  filteredProcedures = filteredProcedures.filter((procedure) => {
15498
15927
  const price = procedure.price || 0;
15499
- if (filters.minPrice !== void 0 && price < filters.minPrice) return false;
15500
- if (filters.maxPrice !== void 0 && price > filters.maxPrice) return false;
15928
+ if (filters.minPrice !== void 0 && price < filters.minPrice)
15929
+ return false;
15930
+ if (filters.maxPrice !== void 0 && price > filters.maxPrice)
15931
+ return false;
15501
15932
  return true;
15502
15933
  });
15503
15934
  console.log(
@@ -15508,8 +15939,10 @@ var ProcedureService = class extends BaseService {
15508
15939
  filteredProcedures = filteredProcedures.filter((procedure) => {
15509
15940
  var _a;
15510
15941
  const rating = ((_a = procedure.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
15511
- if (filters.minRating !== void 0 && rating < filters.minRating) return false;
15512
- if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
15942
+ if (filters.minRating !== void 0 && rating < filters.minRating)
15943
+ return false;
15944
+ if (filters.maxRating !== void 0 && rating > filters.maxRating)
15945
+ return false;
15513
15946
  return true;
15514
15947
  });
15515
15948
  console.log(
@@ -15517,10 +15950,12 @@ var ProcedureService = class extends BaseService {
15517
15950
  );
15518
15951
  }
15519
15952
  if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15520
- const benefitsToMatch = filters.treatmentBenefits;
15953
+ const benefitIdsToMatch = filters.treatmentBenefits;
15521
15954
  filteredProcedures = filteredProcedures.filter((procedure) => {
15522
- const procedureBenefits = procedure.treatmentBenefits || [];
15523
- return benefitsToMatch.some((benefit) => procedureBenefits.includes(benefit));
15955
+ const procedureBenefitIds = procedure.treatmentBenefitIds || [];
15956
+ return benefitIdsToMatch.some(
15957
+ (benefitId) => procedureBenefitIds.includes(benefitId)
15958
+ );
15524
15959
  });
15525
15960
  console.log(
15526
15961
  `[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`
@@ -15583,8 +16018,12 @@ var ProcedureService = class extends BaseService {
15583
16018
  procedure.distance = distance;
15584
16019
  return distance <= radiusInKm;
15585
16020
  });
15586
- console.log(`[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`);
15587
- filteredProcedures.sort((a, b) => (a.distance || 0) - (b.distance || 0));
16021
+ console.log(
16022
+ `[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`
16023
+ );
16024
+ filteredProcedures.sort(
16025
+ (a, b) => (a.distance || 0) - (b.distance || 0)
16026
+ );
15588
16027
  }
15589
16028
  return filteredProcedures;
15590
16029
  }
@@ -15596,19 +16035,30 @@ var ProcedureService = class extends BaseService {
15596
16035
  if (!location || !radiusInKm) {
15597
16036
  return Promise.resolve({ procedures: [], lastDoc: null });
15598
16037
  }
15599
- const bounds = (0, import_geofire_common8.geohashQueryBounds)([location.latitude, location.longitude], radiusInKm * 1e3);
16038
+ const bounds = (0, import_geofire_common8.geohashQueryBounds)(
16039
+ [location.latitude, location.longitude],
16040
+ radiusInKm * 1e3
16041
+ );
15600
16042
  const fetches = bounds.map((b) => {
15601
16043
  const constraints = [
15602
- (0, import_firestore45.where)("clinicInfo.location.geohash", ">=", b[0]),
15603
- (0, import_firestore45.where)("clinicInfo.location.geohash", "<=", b[1]),
15604
- (0, import_firestore45.where)("isActive", "==", filters.isActive !== void 0 ? filters.isActive : true)
16044
+ (0, import_firestore46.where)("clinicInfo.location.geohash", ">=", b[0]),
16045
+ (0, import_firestore46.where)("clinicInfo.location.geohash", "<=", b[1]),
16046
+ (0, import_firestore46.where)(
16047
+ "isActive",
16048
+ "==",
16049
+ filters.isActive !== void 0 ? filters.isActive : true
16050
+ )
15605
16051
  ];
15606
- return (0, import_firestore45.getDocs)((0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints));
16052
+ return (0, import_firestore46.getDocs)(
16053
+ (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints)
16054
+ );
15607
16055
  });
15608
16056
  return Promise.all(fetches).then((snaps) => {
15609
16057
  const collected = [];
15610
16058
  snaps.forEach((snap) => {
15611
- snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
16059
+ snap.docs.forEach(
16060
+ (d) => collected.push({ ...d.data(), id: d.id })
16061
+ );
15612
16062
  });
15613
16063
  const uniqueMap = /* @__PURE__ */ new Map();
15614
16064
  for (const p of collected) {
@@ -15619,7 +16069,9 @@ var ProcedureService = class extends BaseService {
15619
16069
  const pageSize = filters.pagination || 10;
15620
16070
  let startIndex = 0;
15621
16071
  if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
15622
- const idx = procedures.findIndex((p) => p.id === filters.lastDoc.id);
16072
+ const idx = procedures.findIndex(
16073
+ (p) => p.id === filters.lastDoc.id
16074
+ );
15623
16075
  if (idx >= 0) startIndex = idx + 1;
15624
16076
  }
15625
16077
  const page = procedures.slice(startIndex, startIndex + pageSize);
@@ -15644,7 +16096,7 @@ var ProcedureService = class extends BaseService {
15644
16096
  * @returns The created procedure
15645
16097
  */
15646
16098
  async createConsultationProcedure(data) {
15647
- var _a;
16099
+ var _a, _b, _c;
15648
16100
  const procedureId = this.generateId();
15649
16101
  const [category, subcategory, technology] = await Promise.all([
15650
16102
  this.categoryService.getById(data.categoryId),
@@ -15654,22 +16106,34 @@ var ProcedureService = class extends BaseService {
15654
16106
  if (!category || !subcategory || !technology) {
15655
16107
  throw new Error("One or more required base entities not found");
15656
16108
  }
15657
- const clinicRef = (0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, data.clinicBranchId);
15658
- const clinicSnapshot = await (0, import_firestore45.getDoc)(clinicRef);
16109
+ const clinicRef = (0, import_firestore46.doc)(this.db, CLINICS_COLLECTION, data.clinicBranchId);
16110
+ const clinicSnapshot = await (0, import_firestore46.getDoc)(clinicRef);
15659
16111
  if (!clinicSnapshot.exists()) {
15660
16112
  throw new Error(`Clinic with ID ${data.clinicBranchId} not found`);
15661
16113
  }
15662
16114
  const clinic = clinicSnapshot.data();
15663
- const practitionerRef = (0, import_firestore45.doc)(this.db, PRACTITIONERS_COLLECTION, data.practitionerId);
15664
- const practitionerSnapshot = await (0, import_firestore45.getDoc)(practitionerRef);
16115
+ const practitionerRef = (0, import_firestore46.doc)(
16116
+ this.db,
16117
+ PRACTITIONERS_COLLECTION,
16118
+ data.practitionerId
16119
+ );
16120
+ const practitionerSnapshot = await (0, import_firestore46.getDoc)(practitionerRef);
15665
16121
  if (!practitionerSnapshot.exists()) {
15666
16122
  throw new Error(`Practitioner with ID ${data.practitionerId} not found`);
15667
16123
  }
15668
16124
  const practitioner = practitionerSnapshot.data();
15669
16125
  let processedPhotos = [];
15670
16126
  if (data.photos && data.photos.length > 0) {
15671
- processedPhotos = await this.processMediaArray(data.photos, procedureId, "procedure-photos");
16127
+ processedPhotos = await this.processMediaArray(
16128
+ data.photos,
16129
+ procedureId,
16130
+ "procedure-photos"
16131
+ );
15672
16132
  }
16133
+ const transformedProductsMetadata = await this.transformProductsMetadata(
16134
+ data.productsMetadata,
16135
+ data.technologyId
16136
+ );
15673
16137
  const clinicInfo = {
15674
16138
  id: clinicSnapshot.id,
15675
16139
  name: clinic.name,
@@ -15694,6 +16158,8 @@ var ProcedureService = class extends BaseService {
15694
16158
  brandName: "Consultation",
15695
16159
  technologyId: data.technologyId,
15696
16160
  technologyName: technology.name,
16161
+ categoryId: technology.categoryId,
16162
+ subcategoryId: technology.subcategoryId,
15697
16163
  isActive: true,
15698
16164
  createdAt: /* @__PURE__ */ new Date(),
15699
16165
  updatedAt: /* @__PURE__ */ new Date()
@@ -15708,9 +16174,12 @@ var ProcedureService = class extends BaseService {
15708
16174
  technology,
15709
16175
  product: consultationProduct,
15710
16176
  // Use placeholder product
16177
+ productsMetadata: transformedProductsMetadata,
15711
16178
  blockingConditions: technology.blockingConditions,
15712
16179
  contraindications: technology.contraindications || [],
16180
+ contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
15713
16181
  treatmentBenefits: technology.benefits,
16182
+ treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
15714
16183
  preRequirements: technology.requirements.pre,
15715
16184
  postRequirements: technology.requirements.post,
15716
16185
  certificationRequirement: technology.certificationRequirement,
@@ -15729,13 +16198,13 @@ var ProcedureService = class extends BaseService {
15729
16198
  },
15730
16199
  isActive: true
15731
16200
  };
15732
- const procedureRef = (0, import_firestore45.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
15733
- await (0, import_firestore45.setDoc)(procedureRef, {
16201
+ const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
16202
+ await (0, import_firestore46.setDoc)(procedureRef, {
15734
16203
  ...newProcedure,
15735
- createdAt: (0, import_firestore45.serverTimestamp)(),
15736
- updatedAt: (0, import_firestore45.serverTimestamp)()
16204
+ createdAt: (0, import_firestore46.serverTimestamp)(),
16205
+ updatedAt: (0, import_firestore46.serverTimestamp)()
15737
16206
  });
15738
- const savedDoc = await (0, import_firestore45.getDoc)(procedureRef);
16207
+ const savedDoc = await (0, import_firestore46.getDoc)(procedureRef);
15739
16208
  return savedDoc.data();
15740
16209
  }
15741
16210
  /**
@@ -15744,13 +16213,13 @@ var ProcedureService = class extends BaseService {
15744
16213
  * @returns Array of minimal procedure info for map
15745
16214
  */
15746
16215
  async getProceduresForMap() {
15747
- const proceduresRef = (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION);
15748
- const snapshot = await (0, import_firestore45.getDocs)(proceduresRef);
15749
- const proceduresForMap = snapshot.docs.map((doc37) => {
16216
+ const proceduresRef = (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION);
16217
+ const snapshot = await (0, import_firestore46.getDocs)(proceduresRef);
16218
+ const proceduresForMap = snapshot.docs.map((doc38) => {
15750
16219
  var _a, _b, _c, _d, _e, _f, _g, _h;
15751
- const data = doc37.data();
16220
+ const data = doc38.data();
15752
16221
  return {
15753
- id: doc37.id,
16222
+ id: doc38.id,
15754
16223
  name: data.name,
15755
16224
  clinicId: (_a = data.clinicInfo) == null ? void 0 : _a.id,
15756
16225
  clinicName: (_b = data.clinicInfo) == null ? void 0 : _b.name,
@@ -15764,8 +16233,8 @@ var ProcedureService = class extends BaseService {
15764
16233
  };
15765
16234
 
15766
16235
  // src/services/reviews/reviews.service.ts
15767
- var import_firestore46 = require("firebase/firestore");
15768
- var import_zod25 = require("zod");
16236
+ var import_firestore47 = require("firebase/firestore");
16237
+ var import_zod26 = require("zod");
15769
16238
  var ReviewService = class extends BaseService {
15770
16239
  constructor(db, auth, app) {
15771
16240
  super(db, auth, app);
@@ -15844,15 +16313,15 @@ var ReviewService = class extends BaseService {
15844
16313
  updatedAt: now
15845
16314
  };
15846
16315
  reviewSchema.parse(review);
15847
- const docRef = (0, import_firestore46.doc)(this.db, REVIEWS_COLLECTION, reviewId);
15848
- await (0, import_firestore46.setDoc)(docRef, {
16316
+ const docRef = (0, import_firestore47.doc)(this.db, REVIEWS_COLLECTION, reviewId);
16317
+ await (0, import_firestore47.setDoc)(docRef, {
15849
16318
  ...review,
15850
- createdAt: (0, import_firestore46.serverTimestamp)(),
15851
- updatedAt: (0, import_firestore46.serverTimestamp)()
16319
+ createdAt: (0, import_firestore47.serverTimestamp)(),
16320
+ updatedAt: (0, import_firestore47.serverTimestamp)()
15852
16321
  });
15853
16322
  return review;
15854
16323
  } catch (error) {
15855
- if (error instanceof import_zod25.z.ZodError) {
16324
+ if (error instanceof import_zod26.z.ZodError) {
15856
16325
  throw new Error(`Invalid review data: ${error.message}`);
15857
16326
  }
15858
16327
  throw error;
@@ -15864,8 +16333,8 @@ var ReviewService = class extends BaseService {
15864
16333
  * @returns The review if found, null otherwise
15865
16334
  */
15866
16335
  async getReview(reviewId) {
15867
- const docRef = (0, import_firestore46.doc)(this.db, REVIEWS_COLLECTION, reviewId);
15868
- const docSnap = await (0, import_firestore46.getDoc)(docRef);
16336
+ const docRef = (0, import_firestore47.doc)(this.db, REVIEWS_COLLECTION, reviewId);
16337
+ const docSnap = await (0, import_firestore47.getDoc)(docRef);
15869
16338
  if (!docSnap.exists()) {
15870
16339
  return null;
15871
16340
  }
@@ -15877,12 +16346,12 @@ var ReviewService = class extends BaseService {
15877
16346
  * @returns Array of reviews for the patient
15878
16347
  */
15879
16348
  async getReviewsByPatient(patientId) {
15880
- const q = (0, import_firestore46.query)(
15881
- (0, import_firestore46.collection)(this.db, REVIEWS_COLLECTION),
15882
- (0, import_firestore46.where)("patientId", "==", patientId)
16349
+ const q = (0, import_firestore47.query)(
16350
+ (0, import_firestore47.collection)(this.db, REVIEWS_COLLECTION),
16351
+ (0, import_firestore47.where)("patientId", "==", patientId)
15883
16352
  );
15884
- const snapshot = await (0, import_firestore46.getDocs)(q);
15885
- return snapshot.docs.map((doc37) => doc37.data());
16353
+ const snapshot = await (0, import_firestore47.getDocs)(q);
16354
+ return snapshot.docs.map((doc38) => doc38.data());
15886
16355
  }
15887
16356
  /**
15888
16357
  * Gets all reviews for a specific clinic
@@ -15890,12 +16359,12 @@ var ReviewService = class extends BaseService {
15890
16359
  * @returns Array of reviews containing clinic reviews
15891
16360
  */
15892
16361
  async getReviewsByClinic(clinicId) {
15893
- const q = (0, import_firestore46.query)(
15894
- (0, import_firestore46.collection)(this.db, REVIEWS_COLLECTION),
15895
- (0, import_firestore46.where)("clinicReview.clinicId", "==", clinicId)
16362
+ const q = (0, import_firestore47.query)(
16363
+ (0, import_firestore47.collection)(this.db, REVIEWS_COLLECTION),
16364
+ (0, import_firestore47.where)("clinicReview.clinicId", "==", clinicId)
15896
16365
  );
15897
- const snapshot = await (0, import_firestore46.getDocs)(q);
15898
- return snapshot.docs.map((doc37) => doc37.data());
16366
+ const snapshot = await (0, import_firestore47.getDocs)(q);
16367
+ return snapshot.docs.map((doc38) => doc38.data());
15899
16368
  }
15900
16369
  /**
15901
16370
  * Gets all reviews for a specific practitioner
@@ -15903,12 +16372,12 @@ var ReviewService = class extends BaseService {
15903
16372
  * @returns Array of reviews containing practitioner reviews
15904
16373
  */
15905
16374
  async getReviewsByPractitioner(practitionerId) {
15906
- const q = (0, import_firestore46.query)(
15907
- (0, import_firestore46.collection)(this.db, REVIEWS_COLLECTION),
15908
- (0, import_firestore46.where)("practitionerReview.practitionerId", "==", practitionerId)
16375
+ const q = (0, import_firestore47.query)(
16376
+ (0, import_firestore47.collection)(this.db, REVIEWS_COLLECTION),
16377
+ (0, import_firestore47.where)("practitionerReview.practitionerId", "==", practitionerId)
15909
16378
  );
15910
- const snapshot = await (0, import_firestore46.getDocs)(q);
15911
- return snapshot.docs.map((doc37) => doc37.data());
16379
+ const snapshot = await (0, import_firestore47.getDocs)(q);
16380
+ return snapshot.docs.map((doc38) => doc38.data());
15912
16381
  }
15913
16382
  /**
15914
16383
  * Gets all reviews for a specific procedure
@@ -15916,12 +16385,12 @@ var ReviewService = class extends BaseService {
15916
16385
  * @returns Array of reviews containing procedure reviews
15917
16386
  */
15918
16387
  async getReviewsByProcedure(procedureId) {
15919
- const q = (0, import_firestore46.query)(
15920
- (0, import_firestore46.collection)(this.db, REVIEWS_COLLECTION),
15921
- (0, import_firestore46.where)("procedureReview.procedureId", "==", procedureId)
16388
+ const q = (0, import_firestore47.query)(
16389
+ (0, import_firestore47.collection)(this.db, REVIEWS_COLLECTION),
16390
+ (0, import_firestore47.where)("procedureReview.procedureId", "==", procedureId)
15922
16391
  );
15923
- const snapshot = await (0, import_firestore46.getDocs)(q);
15924
- return snapshot.docs.map((doc37) => doc37.data());
16392
+ const snapshot = await (0, import_firestore47.getDocs)(q);
16393
+ return snapshot.docs.map((doc38) => doc38.data());
15925
16394
  }
15926
16395
  /**
15927
16396
  * Gets all reviews for a specific appointment
@@ -15929,11 +16398,11 @@ var ReviewService = class extends BaseService {
15929
16398
  * @returns The review for the appointment if found, null otherwise
15930
16399
  */
15931
16400
  async getReviewByAppointment(appointmentId) {
15932
- const q = (0, import_firestore46.query)(
15933
- (0, import_firestore46.collection)(this.db, REVIEWS_COLLECTION),
15934
- (0, import_firestore46.where)("appointmentId", "==", appointmentId)
16401
+ const q = (0, import_firestore47.query)(
16402
+ (0, import_firestore47.collection)(this.db, REVIEWS_COLLECTION),
16403
+ (0, import_firestore47.where)("appointmentId", "==", appointmentId)
15935
16404
  );
15936
- const snapshot = await (0, import_firestore46.getDocs)(q);
16405
+ const snapshot = await (0, import_firestore47.getDocs)(q);
15937
16406
  if (snapshot.empty) {
15938
16407
  return null;
15939
16408
  }
@@ -15948,7 +16417,7 @@ var ReviewService = class extends BaseService {
15948
16417
  if (!review) {
15949
16418
  throw new Error(`Review with ID ${reviewId} not found`);
15950
16419
  }
15951
- await (0, import_firestore46.deleteDoc)((0, import_firestore46.doc)(this.db, REVIEWS_COLLECTION, reviewId));
16420
+ await (0, import_firestore47.deleteDoc)((0, import_firestore47.doc)(this.db, REVIEWS_COLLECTION, reviewId));
15952
16421
  }
15953
16422
  /**
15954
16423
  * Calculates the average of an array of numbers
@@ -15967,7 +16436,7 @@ var ReviewService = class extends BaseService {
15967
16436
 
15968
16437
  // src/config/firebase.ts
15969
16438
  var import_app = require("firebase/app");
15970
- var import_firestore47 = require("firebase/firestore");
16439
+ var import_firestore48 = require("firebase/firestore");
15971
16440
  var import_auth9 = require("firebase/auth");
15972
16441
  var import_analytics = require("firebase/analytics");
15973
16442
  var import_react_native = require("react-native");
@@ -15977,7 +16446,7 @@ var firebaseInstance = null;
15977
16446
  var initializeFirebase = (config) => {
15978
16447
  if (!firebaseInstance) {
15979
16448
  const app = (0, import_app.initializeApp)(config);
15980
- const db = (0, import_firestore47.getFirestore)(app);
16449
+ const db = (0, import_firestore48.getFirestore)(app);
15981
16450
  const auth = (0, import_auth9.getAuth)(app);
15982
16451
  const storage = (0, import_storage4.getStorage)(app);
15983
16452
  const functions = (0, import_functions3.getFunctions)(app);
@@ -16019,7 +16488,7 @@ var getFirebaseFunctions = async () => {
16019
16488
  };
16020
16489
 
16021
16490
  // src/backoffice/services/brand.service.ts
16022
- var import_firestore48 = require("firebase/firestore");
16491
+ var import_firestore49 = require("firebase/firestore");
16023
16492
 
16024
16493
  // src/backoffice/types/brand.types.ts
16025
16494
  var BRANDS_COLLECTION = "brands";
@@ -16030,7 +16499,7 @@ var BrandService = class extends BaseService {
16030
16499
  * Gets reference to brands collection
16031
16500
  */
16032
16501
  getBrandsRef() {
16033
- return (0, import_firestore48.collection)(this.db, BRANDS_COLLECTION);
16502
+ return (0, import_firestore49.collection)(this.db, BRANDS_COLLECTION);
16034
16503
  }
16035
16504
  /**
16036
16505
  * Creates a new brand
@@ -16039,23 +16508,78 @@ var BrandService = class extends BaseService {
16039
16508
  const now = /* @__PURE__ */ new Date();
16040
16509
  const newBrand = {
16041
16510
  ...brand,
16511
+ name_lowercase: brand.name.toLowerCase(),
16042
16512
  createdAt: now,
16043
16513
  updatedAt: now,
16044
16514
  isActive: true
16045
16515
  };
16046
- const docRef = await (0, import_firestore48.addDoc)(this.getBrandsRef(), newBrand);
16516
+ const docRef = await (0, import_firestore49.addDoc)(this.getBrandsRef(), newBrand);
16047
16517
  return { id: docRef.id, ...newBrand };
16048
16518
  }
16049
16519
  /**
16050
- * Gets all active brands
16520
+ * Gets a paginated list of active brands, optionally filtered by name.
16521
+ * @param rowsPerPage - The number of brands to fetch.
16522
+ * @param searchTerm - An optional string to filter brand names by (starts-with search).
16523
+ * @param lastVisible - An optional document snapshot to use as a cursor for pagination.
16051
16524
  */
16052
- async getAll() {
16053
- const q = (0, import_firestore48.query)(this.getBrandsRef(), (0, import_firestore48.where)("isActive", "==", true));
16054
- const snapshot = await (0, import_firestore48.getDocs)(q);
16525
+ async getAll(rowsPerPage, searchTerm, lastVisible) {
16526
+ const constraints = [
16527
+ (0, import_firestore49.where)("isActive", "==", true),
16528
+ (0, import_firestore49.orderBy)("name_lowercase")
16529
+ ];
16530
+ if (searchTerm) {
16531
+ const lowercasedSearchTerm = searchTerm.toLowerCase();
16532
+ constraints.push((0, import_firestore49.where)("name_lowercase", ">=", lowercasedSearchTerm));
16533
+ constraints.push(
16534
+ (0, import_firestore49.where)("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
16535
+ );
16536
+ }
16537
+ if (lastVisible) {
16538
+ constraints.push((0, import_firestore49.startAfter)(lastVisible));
16539
+ }
16540
+ constraints.push((0, import_firestore49.limit)(rowsPerPage));
16541
+ const q = (0, import_firestore49.query)(this.getBrandsRef(), ...constraints);
16542
+ const snapshot = await (0, import_firestore49.getDocs)(q);
16543
+ const brands = snapshot.docs.map(
16544
+ (doc38) => ({
16545
+ id: doc38.id,
16546
+ ...doc38.data()
16547
+ })
16548
+ );
16549
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
16550
+ return { brands, lastVisible: newLastVisible };
16551
+ }
16552
+ /**
16553
+ * Gets the total count of active brands, optionally filtered by name.
16554
+ * @param searchTerm - An optional string to filter brand names by (starts-with search).
16555
+ */
16556
+ async getBrandsCount(searchTerm) {
16557
+ const constraints = [(0, import_firestore49.where)("isActive", "==", true)];
16558
+ if (searchTerm) {
16559
+ const lowercasedSearchTerm = searchTerm.toLowerCase();
16560
+ constraints.push((0, import_firestore49.where)("name_lowercase", ">=", lowercasedSearchTerm));
16561
+ constraints.push(
16562
+ (0, import_firestore49.where)("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
16563
+ );
16564
+ }
16565
+ const q = (0, import_firestore49.query)(this.getBrandsRef(), ...constraints);
16566
+ const snapshot = await (0, import_firestore49.getCountFromServer)(q);
16567
+ return snapshot.data().count;
16568
+ }
16569
+ /**
16570
+ * Gets all active brands for filter dropdowns (not paginated).
16571
+ */
16572
+ async getAllForFilter() {
16573
+ const q = (0, import_firestore49.query)(
16574
+ this.getBrandsRef(),
16575
+ (0, import_firestore49.where)("isActive", "==", true),
16576
+ (0, import_firestore49.orderBy)("name")
16577
+ );
16578
+ const snapshot = await (0, import_firestore49.getDocs)(q);
16055
16579
  return snapshot.docs.map(
16056
- (doc37) => ({
16057
- id: doc37.id,
16058
- ...doc37.data()
16580
+ (doc38) => ({
16581
+ id: doc38.id,
16582
+ ...doc38.data()
16059
16583
  })
16060
16584
  );
16061
16585
  }
@@ -16067,8 +16591,11 @@ var BrandService = class extends BaseService {
16067
16591
  ...brand,
16068
16592
  updatedAt: /* @__PURE__ */ new Date()
16069
16593
  };
16070
- const docRef = (0, import_firestore48.doc)(this.getBrandsRef(), brandId);
16071
- await (0, import_firestore48.updateDoc)(docRef, updateData);
16594
+ if (brand.name) {
16595
+ updateData.name_lowercase = brand.name.toLowerCase();
16596
+ }
16597
+ const docRef = (0, import_firestore49.doc)(this.getBrandsRef(), brandId);
16598
+ await (0, import_firestore49.updateDoc)(docRef, updateData);
16072
16599
  return this.getById(brandId);
16073
16600
  }
16074
16601
  /**
@@ -16083,8 +16610,8 @@ var BrandService = class extends BaseService {
16083
16610
  * Gets a brand by ID
16084
16611
  */
16085
16612
  async getById(brandId) {
16086
- const docRef = (0, import_firestore48.doc)(this.getBrandsRef(), brandId);
16087
- const docSnap = await (0, import_firestore48.getDoc)(docRef);
16613
+ const docRef = (0, import_firestore49.doc)(this.getBrandsRef(), brandId);
16614
+ const docSnap = await (0, import_firestore49.getDoc)(docRef);
16088
16615
  if (!docSnap.exists()) return null;
16089
16616
  return {
16090
16617
  id: docSnap.id,
@@ -16094,7 +16621,7 @@ var BrandService = class extends BaseService {
16094
16621
  };
16095
16622
 
16096
16623
  // src/backoffice/services/category.service.ts
16097
- var import_firestore49 = require("firebase/firestore");
16624
+ var import_firestore50 = require("firebase/firestore");
16098
16625
 
16099
16626
  // src/backoffice/types/category.types.ts
16100
16627
  var CATEGORIES_COLLECTION = "backoffice_categories";
@@ -16105,7 +16632,7 @@ var CategoryService = class extends BaseService {
16105
16632
  * Referenca na Firestore kolekciju kategorija
16106
16633
  */
16107
16634
  get categoriesRef() {
16108
- return (0, import_firestore49.collection)(this.db, CATEGORIES_COLLECTION);
16635
+ return (0, import_firestore50.collection)(this.db, CATEGORIES_COLLECTION);
16109
16636
  }
16110
16637
  /**
16111
16638
  * Kreira novu kategoriju u sistemu
@@ -16120,41 +16647,91 @@ var CategoryService = class extends BaseService {
16120
16647
  updatedAt: now,
16121
16648
  isActive: true
16122
16649
  };
16123
- const docRef = await (0, import_firestore49.addDoc)(this.categoriesRef, newCategory);
16650
+ const docRef = await (0, import_firestore50.addDoc)(this.categoriesRef, newCategory);
16124
16651
  return { id: docRef.id, ...newCategory };
16125
16652
  }
16126
16653
  /**
16127
- * Vraća sve aktivne kategorije
16128
- * @returns Lista aktivnih kategorija
16654
+ * Returns counts of categories for each family.
16655
+ * @param active - Whether to count active or inactive categories.
16656
+ * @returns A record mapping family to category count.
16129
16657
  */
16130
- async getAll() {
16131
- const q = (0, import_firestore49.query)(this.categoriesRef, (0, import_firestore49.where)("isActive", "==", true));
16132
- const snapshot = await (0, import_firestore49.getDocs)(q);
16658
+ async getCategoryCounts(active = true) {
16659
+ const counts = {};
16660
+ const families = Object.values(ProcedureFamily);
16661
+ for (const family of families) {
16662
+ const q = (0, import_firestore50.query)(
16663
+ this.categoriesRef,
16664
+ (0, import_firestore50.where)("family", "==", family),
16665
+ (0, import_firestore50.where)("isActive", "==", active)
16666
+ );
16667
+ const snapshot = await (0, import_firestore50.getCountFromServer)(q);
16668
+ counts[family] = snapshot.data().count;
16669
+ }
16670
+ return counts;
16671
+ }
16672
+ /**
16673
+ * Vraća sve kategorije za potrebe filtera (bez paginacije)
16674
+ * @returns Lista svih aktivnih kategorija
16675
+ */
16676
+ async getAllForFilter() {
16677
+ const q = (0, import_firestore50.query)(this.categoriesRef, (0, import_firestore50.where)("isActive", "==", true));
16678
+ const snapshot = await (0, import_firestore50.getDocs)(q);
16133
16679
  return snapshot.docs.map(
16134
- (doc37) => ({
16135
- id: doc37.id,
16136
- ...doc37.data()
16680
+ (doc38) => ({
16681
+ id: doc38.id,
16682
+ ...doc38.data()
16683
+ })
16684
+ );
16685
+ }
16686
+ /**
16687
+ * Vraća sve kategorije sa paginacijom
16688
+ * @param options - Pagination and filter options
16689
+ * @returns Lista kategorija i poslednji vidljiv dokument
16690
+ */
16691
+ async getAll(options = {}) {
16692
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
16693
+ const constraints = [
16694
+ (0, import_firestore50.where)("isActive", "==", active),
16695
+ (0, import_firestore50.orderBy)("name"),
16696
+ queryLimit ? (0, import_firestore50.limit)(queryLimit) : void 0,
16697
+ lastVisible ? (0, import_firestore50.startAfter)(lastVisible) : void 0
16698
+ ].filter((c) => !!c);
16699
+ const q = (0, import_firestore50.query)(this.categoriesRef, ...constraints);
16700
+ const snapshot = await (0, import_firestore50.getDocs)(q);
16701
+ const categories = snapshot.docs.map(
16702
+ (doc38) => ({
16703
+ id: doc38.id,
16704
+ ...doc38.data()
16137
16705
  })
16138
16706
  );
16707
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
16708
+ return { categories, lastVisible: newLastVisible };
16139
16709
  }
16140
16710
  /**
16141
- * Vraća sve aktivne kategorije za određenu familiju procedura
16711
+ * Vraća sve aktivne kategorije za određenu familiju procedura sa paginacijom
16142
16712
  * @param family - Familija procedura (aesthetics/surgery)
16713
+ * @param options - Pagination options
16143
16714
  * @returns Lista kategorija koje pripadaju traženoj familiji
16144
16715
  */
16145
- async getAllByFamily(family) {
16146
- const q = (0, import_firestore49.query)(
16147
- this.categoriesRef,
16148
- (0, import_firestore49.where)("family", "==", family),
16149
- (0, import_firestore49.where)("isActive", "==", true)
16150
- );
16151
- const snapshot = await (0, import_firestore49.getDocs)(q);
16152
- return snapshot.docs.map(
16153
- (doc37) => ({
16154
- id: doc37.id,
16155
- ...doc37.data()
16716
+ async getAllByFamily(family, options = {}) {
16717
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
16718
+ const constraints = [
16719
+ (0, import_firestore50.where)("family", "==", family),
16720
+ (0, import_firestore50.where)("isActive", "==", active),
16721
+ (0, import_firestore50.orderBy)("name"),
16722
+ queryLimit ? (0, import_firestore50.limit)(queryLimit) : void 0,
16723
+ lastVisible ? (0, import_firestore50.startAfter)(lastVisible) : void 0
16724
+ ].filter((c) => !!c);
16725
+ const q = (0, import_firestore50.query)(this.categoriesRef, ...constraints);
16726
+ const snapshot = await (0, import_firestore50.getDocs)(q);
16727
+ const categories = snapshot.docs.map(
16728
+ (doc38) => ({
16729
+ id: doc38.id,
16730
+ ...doc38.data()
16156
16731
  })
16157
16732
  );
16733
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
16734
+ return { categories, lastVisible: newLastVisible };
16158
16735
  }
16159
16736
  /**
16160
16737
  * Ažurira postojeću kategoriju
@@ -16167,8 +16744,8 @@ var CategoryService = class extends BaseService {
16167
16744
  ...category,
16168
16745
  updatedAt: /* @__PURE__ */ new Date()
16169
16746
  };
16170
- const docRef = (0, import_firestore49.doc)(this.categoriesRef, id);
16171
- await (0, import_firestore49.updateDoc)(docRef, updateData);
16747
+ const docRef = (0, import_firestore50.doc)(this.categoriesRef, id);
16748
+ await (0, import_firestore50.updateDoc)(docRef, updateData);
16172
16749
  return this.getById(id);
16173
16750
  }
16174
16751
  /**
@@ -16178,14 +16755,21 @@ var CategoryService = class extends BaseService {
16178
16755
  async delete(id) {
16179
16756
  await this.update(id, { isActive: false });
16180
16757
  }
16758
+ /**
16759
+ * Reactivates a category by setting its isActive flag to true.
16760
+ * @param id - The ID of the category to reactivate.
16761
+ */
16762
+ async reactivate(id) {
16763
+ await this.update(id, { isActive: true });
16764
+ }
16181
16765
  /**
16182
16766
  * Vraća kategoriju po ID-u
16183
16767
  * @param id - ID tražene kategorije
16184
16768
  * @returns Kategorija ili null ako ne postoji
16185
16769
  */
16186
16770
  async getById(id) {
16187
- const docRef = (0, import_firestore49.doc)(this.categoriesRef, id);
16188
- const docSnap = await (0, import_firestore49.getDoc)(docRef);
16771
+ const docRef = (0, import_firestore50.doc)(this.categoriesRef, id);
16772
+ const docSnap = await (0, import_firestore50.getDoc)(docRef);
16189
16773
  if (!docSnap.exists()) return null;
16190
16774
  return {
16191
16775
  id: docSnap.id,
@@ -16195,7 +16779,7 @@ var CategoryService = class extends BaseService {
16195
16779
  };
16196
16780
 
16197
16781
  // src/backoffice/services/subcategory.service.ts
16198
- var import_firestore50 = require("firebase/firestore");
16782
+ var import_firestore51 = require("firebase/firestore");
16199
16783
 
16200
16784
  // src/backoffice/types/subcategory.types.ts
16201
16785
  var SUBCATEGORIES_COLLECTION = "subcategories";
@@ -16207,7 +16791,7 @@ var SubcategoryService = class extends BaseService {
16207
16791
  * @param categoryId - ID roditeljske kategorije
16208
16792
  */
16209
16793
  getSubcategoriesRef(categoryId) {
16210
- return (0, import_firestore50.collection)(
16794
+ return (0, import_firestore51.collection)(
16211
16795
  this.db,
16212
16796
  CATEGORIES_COLLECTION,
16213
16797
  categoryId,
@@ -16229,27 +16813,117 @@ var SubcategoryService = class extends BaseService {
16229
16813
  updatedAt: now,
16230
16814
  isActive: true
16231
16815
  };
16232
- const docRef = await (0, import_firestore50.addDoc)(
16816
+ const docRef = await (0, import_firestore51.addDoc)(
16233
16817
  this.getSubcategoriesRef(categoryId),
16234
16818
  newSubcategory
16235
16819
  );
16236
16820
  return { id: docRef.id, ...newSubcategory };
16237
16821
  }
16238
16822
  /**
16239
- * Vraća sve aktivne podkategorije za određenu kategoriju
16823
+ * Returns counts of subcategories for all categories.
16824
+ * @param active - Whether to count active or inactive subcategories.
16825
+ * @returns A record mapping category ID to subcategory count.
16826
+ */
16827
+ async getSubcategoryCounts(active = true) {
16828
+ const categoriesRef = (0, import_firestore51.collection)(this.db, CATEGORIES_COLLECTION);
16829
+ const categoriesSnapshot = await (0, import_firestore51.getDocs)(categoriesRef);
16830
+ const counts = {};
16831
+ for (const categoryDoc of categoriesSnapshot.docs) {
16832
+ const categoryId = categoryDoc.id;
16833
+ const subcategoriesRef = this.getSubcategoriesRef(categoryId);
16834
+ const q = (0, import_firestore51.query)(subcategoriesRef, (0, import_firestore51.where)("isActive", "==", active));
16835
+ const snapshot = await (0, import_firestore51.getCountFromServer)(q);
16836
+ counts[categoryId] = snapshot.data().count;
16837
+ }
16838
+ return counts;
16839
+ }
16840
+ /**
16841
+ * Vraća sve aktivne podkategorije za određenu kategoriju sa paginacijom
16240
16842
  * @param categoryId - ID kategorije čije podkategorije tražimo
16241
- * @returns Lista aktivnih podkategorija
16843
+ * @param options - Pagination options
16844
+ * @returns Lista aktivnih podkategorija i poslednji vidljiv dokument
16845
+ */
16846
+ async getAllByCategoryId(categoryId, options = {}) {
16847
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
16848
+ const constraints = [
16849
+ (0, import_firestore51.where)("isActive", "==", active),
16850
+ (0, import_firestore51.orderBy)("name"),
16851
+ queryLimit ? (0, import_firestore51.limit)(queryLimit) : void 0,
16852
+ lastVisible ? (0, import_firestore51.startAfter)(lastVisible) : void 0
16853
+ ].filter((c) => !!c);
16854
+ const q = (0, import_firestore51.query)(this.getSubcategoriesRef(categoryId), ...constraints);
16855
+ const querySnapshot = await (0, import_firestore51.getDocs)(q);
16856
+ const subcategories = querySnapshot.docs.map(
16857
+ (doc38) => ({
16858
+ id: doc38.id,
16859
+ ...doc38.data()
16860
+ })
16861
+ );
16862
+ const newLastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];
16863
+ return { subcategories, lastVisible: newLastVisible };
16864
+ }
16865
+ /**
16866
+ * Vraća sve podkategorije sa paginacijom koristeći collection group query.
16867
+ * NOTE: This query requires a composite index in Firestore on the 'subcategories' collection group.
16868
+ * The index should be on 'isActive' (ascending) and 'name' (ascending).
16869
+ * Firestore will provide a link to create this index in the console error if it's missing.
16870
+ * @param options - Pagination options
16871
+ * @returns Lista podkategorija i poslednji vidljiv dokument
16242
16872
  */
16243
- async getAllByCategoryId(categoryId) {
16244
- const q = (0, import_firestore50.query)(
16873
+ async getAll(options = {}) {
16874
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
16875
+ const constraints = [
16876
+ (0, import_firestore51.where)("isActive", "==", active),
16877
+ (0, import_firestore51.orderBy)("name"),
16878
+ queryLimit ? (0, import_firestore51.limit)(queryLimit) : void 0,
16879
+ lastVisible ? (0, import_firestore51.startAfter)(lastVisible) : void 0
16880
+ ].filter((c) => !!c);
16881
+ const q = (0, import_firestore51.query)(
16882
+ (0, import_firestore51.collectionGroup)(this.db, SUBCATEGORIES_COLLECTION),
16883
+ ...constraints
16884
+ );
16885
+ const querySnapshot = await (0, import_firestore51.getDocs)(q);
16886
+ const subcategories = querySnapshot.docs.map(
16887
+ (doc38) => ({
16888
+ id: doc38.id,
16889
+ ...doc38.data()
16890
+ })
16891
+ );
16892
+ const newLastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];
16893
+ return { subcategories, lastVisible: newLastVisible };
16894
+ }
16895
+ /**
16896
+ * Vraća sve subkategorije za određenu kategoriju za potrebe filtera (bez paginacije)
16897
+ * @param categoryId - ID kategorije čije subkategorije tražimo
16898
+ * @returns Lista svih aktivnih subkategorija
16899
+ */
16900
+ async getAllForFilterByCategoryId(categoryId) {
16901
+ const q = (0, import_firestore51.query)(
16245
16902
  this.getSubcategoriesRef(categoryId),
16246
- (0, import_firestore50.where)("isActive", "==", true)
16903
+ (0, import_firestore51.where)("isActive", "==", true)
16247
16904
  );
16248
- const snapshot = await (0, import_firestore50.getDocs)(q);
16249
- return snapshot.docs.map(
16250
- (doc37) => ({
16251
- id: doc37.id,
16252
- ...doc37.data()
16905
+ const querySnapshot = await (0, import_firestore51.getDocs)(q);
16906
+ return querySnapshot.docs.map(
16907
+ (doc38) => ({
16908
+ id: doc38.id,
16909
+ ...doc38.data()
16910
+ })
16911
+ );
16912
+ }
16913
+ /**
16914
+ * Vraća sve subkategorije za potrebe filtera (bez paginacije)
16915
+ * @returns Lista svih aktivnih subkategorija
16916
+ */
16917
+ async getAllForFilter() {
16918
+ const q = (0, import_firestore51.query)(
16919
+ (0, import_firestore51.collectionGroup)(this.db, SUBCATEGORIES_COLLECTION),
16920
+ (0, import_firestore51.where)("isActive", "==", true)
16921
+ );
16922
+ const querySnapshot = await (0, import_firestore51.getDocs)(q);
16923
+ return querySnapshot.docs.map(
16924
+ (doc38) => ({
16925
+ id: doc38.id,
16926
+ ...doc38.data()
16253
16927
  })
16254
16928
  );
16255
16929
  }
@@ -16261,13 +16935,42 @@ var SubcategoryService = class extends BaseService {
16261
16935
  * @returns Ažurirana podkategorija
16262
16936
  */
16263
16937
  async update(categoryId, subcategoryId, subcategory) {
16264
- const updateData = {
16265
- ...subcategory,
16266
- updatedAt: /* @__PURE__ */ new Date()
16267
- };
16268
- const docRef = (0, import_firestore50.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
16269
- await (0, import_firestore50.updateDoc)(docRef, updateData);
16270
- return this.getById(categoryId, subcategoryId);
16938
+ const newCategoryId = subcategory.categoryId;
16939
+ if (newCategoryId && newCategoryId !== categoryId) {
16940
+ const oldDocRef = (0, import_firestore51.doc)(
16941
+ this.getSubcategoriesRef(categoryId),
16942
+ subcategoryId
16943
+ );
16944
+ const docSnap = await (0, import_firestore51.getDoc)(oldDocRef);
16945
+ if (!docSnap.exists()) {
16946
+ throw new Error("Subcategory to update does not exist.");
16947
+ }
16948
+ const existingData = docSnap.data();
16949
+ const newData = {
16950
+ ...existingData,
16951
+ ...subcategory,
16952
+ categoryId: newCategoryId,
16953
+ // Ensure categoryId is updated
16954
+ createdAt: existingData.createdAt,
16955
+ // Preserve original creation date
16956
+ updatedAt: /* @__PURE__ */ new Date()
16957
+ };
16958
+ const newDocRef = (0, import_firestore51.doc)(
16959
+ this.getSubcategoriesRef(newCategoryId),
16960
+ subcategoryId
16961
+ );
16962
+ await (0, import_firestore51.setDoc)(newDocRef, newData);
16963
+ await (0, import_firestore51.deleteDoc)(oldDocRef);
16964
+ return { id: subcategoryId, ...newData };
16965
+ } else {
16966
+ const updateData = {
16967
+ ...subcategory,
16968
+ updatedAt: /* @__PURE__ */ new Date()
16969
+ };
16970
+ const docRef = (0, import_firestore51.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
16971
+ await (0, import_firestore51.updateDoc)(docRef, updateData);
16972
+ return this.getById(categoryId, subcategoryId);
16973
+ }
16271
16974
  }
16272
16975
  /**
16273
16976
  * Soft delete podkategorije (postavlja isActive na false)
@@ -16277,6 +16980,14 @@ var SubcategoryService = class extends BaseService {
16277
16980
  async delete(categoryId, subcategoryId) {
16278
16981
  await this.update(categoryId, subcategoryId, { isActive: false });
16279
16982
  }
16983
+ /**
16984
+ * Reactivates a subcategory by setting its isActive flag to true.
16985
+ * @param categoryId - The ID of the category to which the subcategory belongs.
16986
+ * @param subcategoryId - The ID of the subcategory to reactivate.
16987
+ */
16988
+ async reactivate(categoryId, subcategoryId) {
16989
+ await this.update(categoryId, subcategoryId, { isActive: true });
16990
+ }
16280
16991
  /**
16281
16992
  * Vraća podkategoriju po ID-u
16282
16993
  * @param categoryId - ID kategorije kojoj pripada podkategorija
@@ -16284,8 +16995,8 @@ var SubcategoryService = class extends BaseService {
16284
16995
  * @returns Podkategorija ili null ako ne postoji
16285
16996
  */
16286
16997
  async getById(categoryId, subcategoryId) {
16287
- const docRef = (0, import_firestore50.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
16288
- const docSnap = await (0, import_firestore50.getDoc)(docRef);
16998
+ const docRef = (0, import_firestore51.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
16999
+ const docSnap = await (0, import_firestore51.getDoc)(docRef);
16289
17000
  if (!docSnap.exists()) return null;
16290
17001
  return {
16291
17002
  id: docSnap.id,
@@ -16295,145 +17006,193 @@ var SubcategoryService = class extends BaseService {
16295
17006
  };
16296
17007
 
16297
17008
  // src/backoffice/services/technology.service.ts
16298
- var import_firestore51 = require("firebase/firestore");
17009
+ var import_firestore52 = require("firebase/firestore");
16299
17010
  var DEFAULT_CERTIFICATION_REQUIREMENT = {
16300
17011
  minimumLevel: "aesthetician" /* AESTHETICIAN */,
16301
17012
  requiredSpecialties: []
16302
17013
  };
16303
17014
  var TechnologyService = class extends BaseService {
16304
17015
  /**
16305
- * Vraća referencu na Firestore kolekciju tehnologija
17016
+ * Reference to the Firestore collection of technologies.
16306
17017
  */
16307
- getTechnologiesRef() {
16308
- return (0, import_firestore51.collection)(this.db, TECHNOLOGIES_COLLECTION);
17018
+ get technologiesRef() {
17019
+ return (0, import_firestore52.collection)(this.db, TECHNOLOGIES_COLLECTION);
16309
17020
  }
16310
17021
  /**
16311
- * Kreira novu tehnologiju
16312
- * @param technology - Podaci za novu tehnologiju
16313
- * @returns Kreirana tehnologija sa generisanim ID-em
17022
+ * Creates a new technology.
17023
+ * @param technology - Data for the new technology.
17024
+ * @returns The created technology with its generated ID.
16314
17025
  */
16315
17026
  async create(technology) {
16316
17027
  const now = /* @__PURE__ */ new Date();
16317
17028
  const newTechnology = {
16318
- ...technology,
16319
- createdAt: now,
16320
- updatedAt: now,
16321
- isActive: true,
16322
- requirements: technology.requirements || {
16323
- pre: [],
16324
- post: []
16325
- },
17029
+ name: technology.name,
17030
+ description: technology.description,
17031
+ family: technology.family,
17032
+ categoryId: technology.categoryId,
17033
+ subcategoryId: technology.subcategoryId,
17034
+ requirements: technology.requirements || { pre: [], post: [] },
16326
17035
  blockingConditions: technology.blockingConditions || [],
16327
17036
  contraindications: technology.contraindications || [],
16328
17037
  benefits: technology.benefits || [],
16329
- certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
17038
+ certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT,
17039
+ documentationTemplates: technology.documentationTemplates || [],
17040
+ isActive: true,
17041
+ createdAt: now,
17042
+ updatedAt: now
16330
17043
  };
16331
- const docRef = await (0, import_firestore51.addDoc)(this.getTechnologiesRef(), newTechnology);
17044
+ if (technology.technicalDetails) {
17045
+ newTechnology.technicalDetails = technology.technicalDetails;
17046
+ }
17047
+ const docRef = await (0, import_firestore52.addDoc)(this.technologiesRef, newTechnology);
16332
17048
  return { id: docRef.id, ...newTechnology };
16333
17049
  }
16334
17050
  /**
16335
- * Vraća sve aktivne tehnologije
16336
- * @returns Lista aktivnih tehnologija
17051
+ * Returns counts of technologies for each subcategory.
17052
+ * @param active - Whether to count active or inactive technologies.
17053
+ * @returns A record mapping subcategory ID to technology count.
16337
17054
  */
16338
- async getAll() {
16339
- const q = (0, import_firestore51.query)(this.getTechnologiesRef(), (0, import_firestore51.where)("isActive", "==", true));
16340
- const snapshot = await (0, import_firestore51.getDocs)(q);
16341
- return snapshot.docs.map(
16342
- (doc37) => ({
16343
- id: doc37.id,
16344
- ...doc37.data()
16345
- })
16346
- );
17055
+ async getTechnologyCounts(active = true) {
17056
+ const q = (0, import_firestore52.query)(this.technologiesRef, (0, import_firestore52.where)("isActive", "==", active));
17057
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17058
+ const counts = {};
17059
+ snapshot.docs.forEach((doc38) => {
17060
+ const tech = doc38.data();
17061
+ counts[tech.subcategoryId] = (counts[tech.subcategoryId] || 0) + 1;
17062
+ });
17063
+ return counts;
16347
17064
  }
16348
17065
  /**
16349
- * Vraća sve aktivne tehnologije za određenu familiju
16350
- * @param family - Familija procedura
16351
- * @returns Lista aktivnih tehnologija
17066
+ * Returns counts of technologies for each category.
17067
+ * @param active - Whether to count active or inactive technologies.
17068
+ * @returns A record mapping category ID to technology count.
16352
17069
  */
16353
- async getAllByFamily(family) {
16354
- const q = (0, import_firestore51.query)(
16355
- this.getTechnologiesRef(),
16356
- (0, import_firestore51.where)("isActive", "==", true),
16357
- (0, import_firestore51.where)("family", "==", family)
16358
- );
16359
- const snapshot = await (0, import_firestore51.getDocs)(q);
16360
- return snapshot.docs.map(
16361
- (doc37) => ({
16362
- id: doc37.id,
16363
- ...doc37.data()
17070
+ async getTechnologyCountsByCategory(active = true) {
17071
+ const q = (0, import_firestore52.query)(this.technologiesRef, (0, import_firestore52.where)("isActive", "==", active));
17072
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17073
+ const counts = {};
17074
+ snapshot.docs.forEach((doc38) => {
17075
+ const tech = doc38.data();
17076
+ counts[tech.categoryId] = (counts[tech.categoryId] || 0) + 1;
17077
+ });
17078
+ return counts;
17079
+ }
17080
+ /**
17081
+ * Returns all technologies with pagination.
17082
+ * @param options - Pagination and filter options.
17083
+ * @returns A list of technologies and the last visible document.
17084
+ */
17085
+ async getAll(options = {}) {
17086
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
17087
+ const constraints = [
17088
+ (0, import_firestore52.where)("isActive", "==", active),
17089
+ (0, import_firestore52.orderBy)("name"),
17090
+ queryLimit ? (0, import_firestore52.limit)(queryLimit) : void 0,
17091
+ lastVisible ? (0, import_firestore52.startAfter)(lastVisible) : void 0
17092
+ ].filter((c) => !!c);
17093
+ const q = (0, import_firestore52.query)(this.technologiesRef, ...constraints);
17094
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17095
+ const technologies = snapshot.docs.map(
17096
+ (doc38) => ({
17097
+ id: doc38.id,
17098
+ ...doc38.data()
16364
17099
  })
16365
17100
  );
17101
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
17102
+ return { technologies, lastVisible: newLastVisible };
16366
17103
  }
16367
17104
  /**
16368
- * Vraća sve aktivne tehnologije za određenu kategoriju
16369
- * @param categoryId - ID kategorije
16370
- * @returns Lista aktivnih tehnologija
17105
+ * Returns all technologies for a specific category with pagination.
17106
+ * @param categoryId - The ID of the category.
17107
+ * @param options - Pagination options.
17108
+ * @returns A list of technologies for the specified category.
16371
17109
  */
16372
- async getAllByCategoryId(categoryId) {
16373
- const q = (0, import_firestore51.query)(
16374
- this.getTechnologiesRef(),
16375
- (0, import_firestore51.where)("isActive", "==", true),
16376
- (0, import_firestore51.where)("categoryId", "==", categoryId)
16377
- );
16378
- const snapshot = await (0, import_firestore51.getDocs)(q);
16379
- return snapshot.docs.map(
16380
- (doc37) => ({
16381
- id: doc37.id,
16382
- ...doc37.data()
17110
+ async getAllByCategoryId(categoryId, options = {}) {
17111
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
17112
+ const constraints = [
17113
+ (0, import_firestore52.where)("categoryId", "==", categoryId),
17114
+ (0, import_firestore52.where)("isActive", "==", active),
17115
+ (0, import_firestore52.orderBy)("name"),
17116
+ queryLimit ? (0, import_firestore52.limit)(queryLimit) : void 0,
17117
+ lastVisible ? (0, import_firestore52.startAfter)(lastVisible) : void 0
17118
+ ].filter((c) => !!c);
17119
+ const q = (0, import_firestore52.query)(this.technologiesRef, ...constraints);
17120
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17121
+ const technologies = snapshot.docs.map(
17122
+ (doc38) => ({
17123
+ id: doc38.id,
17124
+ ...doc38.data()
16383
17125
  })
16384
17126
  );
17127
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
17128
+ return { technologies, lastVisible: newLastVisible };
16385
17129
  }
16386
17130
  /**
16387
- * Vraća sve aktivne tehnologije za određenu podkategoriju
16388
- * @param subcategoryId - ID podkategorije
16389
- * @returns Lista aktivnih tehnologija
17131
+ * Returns all technologies for a specific subcategory with pagination.
17132
+ * @param subcategoryId - The ID of the subcategory.
17133
+ * @param options - Pagination options.
17134
+ * @returns A list of technologies for the specified subcategory.
16390
17135
  */
16391
- async getAllBySubcategoryId(subcategoryId) {
16392
- const q = (0, import_firestore51.query)(
16393
- this.getTechnologiesRef(),
16394
- (0, import_firestore51.where)("isActive", "==", true),
16395
- (0, import_firestore51.where)("subcategoryId", "==", subcategoryId)
16396
- );
16397
- const snapshot = await (0, import_firestore51.getDocs)(q);
16398
- return snapshot.docs.map(
16399
- (doc37) => ({
16400
- id: doc37.id,
16401
- ...doc37.data()
17136
+ async getAllBySubcategoryId(subcategoryId, options = {}) {
17137
+ const { active = true, limit: queryLimit = 10, lastVisible } = options;
17138
+ const constraints = [
17139
+ (0, import_firestore52.where)("subcategoryId", "==", subcategoryId),
17140
+ (0, import_firestore52.where)("isActive", "==", active),
17141
+ (0, import_firestore52.orderBy)("name"),
17142
+ queryLimit ? (0, import_firestore52.limit)(queryLimit) : void 0,
17143
+ lastVisible ? (0, import_firestore52.startAfter)(lastVisible) : void 0
17144
+ ].filter((c) => !!c);
17145
+ const q = (0, import_firestore52.query)(this.technologiesRef, ...constraints);
17146
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17147
+ const technologies = snapshot.docs.map(
17148
+ (doc38) => ({
17149
+ id: doc38.id,
17150
+ ...doc38.data()
16402
17151
  })
16403
17152
  );
17153
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
17154
+ return { technologies, lastVisible: newLastVisible };
16404
17155
  }
16405
17156
  /**
16406
- * Ažurira postojeću tehnologiju
16407
- * @param technologyId - ID tehnologije
16408
- * @param technology - Novi podaci za tehnologiju
16409
- * @returns Ažurirana tehnologija
17157
+ * Updates an existing technology.
17158
+ * @param id - The ID of the technology to update.
17159
+ * @param technology - New data for the technology.
17160
+ * @returns The updated technology.
16410
17161
  */
16411
- async update(technologyId, technology) {
16412
- const updateData = {
16413
- ...technology,
16414
- updatedAt: /* @__PURE__ */ new Date()
16415
- };
16416
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16417
- await (0, import_firestore51.updateDoc)(docRef, updateData);
16418
- return this.getById(technologyId);
17162
+ async update(id, technology) {
17163
+ const updateData = { ...technology };
17164
+ Object.keys(updateData).forEach((key) => {
17165
+ if (updateData[key] === void 0) {
17166
+ delete updateData[key];
17167
+ }
17168
+ });
17169
+ updateData.updatedAt = /* @__PURE__ */ new Date();
17170
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, id);
17171
+ await (0, import_firestore52.updateDoc)(docRef, updateData);
17172
+ return this.getById(id);
16419
17173
  }
16420
17174
  /**
16421
- * Soft delete tehnologije (postavlja isActive na false)
16422
- * @param technologyId - ID tehnologije koja se briše
17175
+ * Soft deletes a technology.
17176
+ * @param id - The ID of the technology to delete.
16423
17177
  */
16424
- async delete(technologyId) {
16425
- await this.update(technologyId, {
16426
- isActive: false
16427
- });
17178
+ async delete(id) {
17179
+ await this.update(id, { isActive: false });
16428
17180
  }
16429
17181
  /**
16430
- * Vraća tehnologiju po ID-u
16431
- * @param technologyId - ID tražene tehnologije
16432
- * @returns Tehnologija ili null ako ne postoji
17182
+ * Reactivates a technology.
17183
+ * @param id - The ID of the technology to reactivate.
16433
17184
  */
16434
- async getById(technologyId) {
16435
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16436
- const docSnap = await (0, import_firestore51.getDoc)(docRef);
17185
+ async reactivate(id) {
17186
+ await this.update(id, { isActive: true });
17187
+ }
17188
+ /**
17189
+ * Returns a technology by its ID.
17190
+ * @param id - The ID of the requested technology.
17191
+ * @returns The technology or null if it doesn't exist.
17192
+ */
17193
+ async getById(id) {
17194
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, id);
17195
+ const docSnap = await (0, import_firestore52.getDoc)(docRef);
16437
17196
  if (!docSnap.exists()) return null;
16438
17197
  return {
16439
17198
  id: docSnap.id,
@@ -16447,10 +17206,10 @@ var TechnologyService = class extends BaseService {
16447
17206
  * @returns Ažurirana tehnologija sa novim zahtevom
16448
17207
  */
16449
17208
  async addRequirement(technologyId, requirement) {
16450
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
17209
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
16451
17210
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
16452
- await (0, import_firestore51.updateDoc)(docRef, {
16453
- [requirementType]: (0, import_firestore51.arrayUnion)(requirement),
17211
+ await (0, import_firestore52.updateDoc)(docRef, {
17212
+ [requirementType]: (0, import_firestore52.arrayUnion)(requirement),
16454
17213
  updatedAt: /* @__PURE__ */ new Date()
16455
17214
  });
16456
17215
  return this.getById(technologyId);
@@ -16462,10 +17221,10 @@ var TechnologyService = class extends BaseService {
16462
17221
  * @returns Ažurirana tehnologija bez uklonjenog zahteva
16463
17222
  */
16464
17223
  async removeRequirement(technologyId, requirement) {
16465
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
17224
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
16466
17225
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
16467
- await (0, import_firestore51.updateDoc)(docRef, {
16468
- [requirementType]: (0, import_firestore51.arrayRemove)(requirement),
17226
+ await (0, import_firestore52.updateDoc)(docRef, {
17227
+ [requirementType]: (0, import_firestore52.arrayRemove)(requirement),
16469
17228
  updatedAt: /* @__PURE__ */ new Date()
16470
17229
  });
16471
17230
  return this.getById(technologyId);
@@ -16502,9 +17261,9 @@ var TechnologyService = class extends BaseService {
16502
17261
  * @returns Ažurirana tehnologija
16503
17262
  */
16504
17263
  async addBlockingCondition(technologyId, condition) {
16505
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16506
- await (0, import_firestore51.updateDoc)(docRef, {
16507
- blockingConditions: (0, import_firestore51.arrayUnion)(condition),
17264
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17265
+ await (0, import_firestore52.updateDoc)(docRef, {
17266
+ blockingConditions: (0, import_firestore52.arrayUnion)(condition),
16508
17267
  updatedAt: /* @__PURE__ */ new Date()
16509
17268
  });
16510
17269
  return this.getById(technologyId);
@@ -16516,9 +17275,9 @@ var TechnologyService = class extends BaseService {
16516
17275
  * @returns Ažurirana tehnologija
16517
17276
  */
16518
17277
  async removeBlockingCondition(technologyId, condition) {
16519
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16520
- await (0, import_firestore51.updateDoc)(docRef, {
16521
- blockingConditions: (0, import_firestore51.arrayRemove)(condition),
17278
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17279
+ await (0, import_firestore52.updateDoc)(docRef, {
17280
+ blockingConditions: (0, import_firestore52.arrayRemove)(condition),
16522
17281
  updatedAt: /* @__PURE__ */ new Date()
16523
17282
  });
16524
17283
  return this.getById(technologyId);
@@ -16530,9 +17289,17 @@ var TechnologyService = class extends BaseService {
16530
17289
  * @returns Ažurirana tehnologija
16531
17290
  */
16532
17291
  async addContraindication(technologyId, contraindication) {
16533
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16534
- await (0, import_firestore51.updateDoc)(docRef, {
16535
- contraindications: (0, import_firestore51.arrayUnion)(contraindication),
17292
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17293
+ const technology = await this.getById(technologyId);
17294
+ if (!technology) {
17295
+ throw new Error(`Technology with id ${technologyId} not found`);
17296
+ }
17297
+ const existingContraindications = technology.contraindications || [];
17298
+ if (existingContraindications.some((c) => c.id === contraindication.id)) {
17299
+ return technology;
17300
+ }
17301
+ await (0, import_firestore52.updateDoc)(docRef, {
17302
+ contraindications: [...existingContraindications, contraindication],
16536
17303
  updatedAt: /* @__PURE__ */ new Date()
16537
17304
  });
16538
17305
  return this.getById(technologyId);
@@ -16544,9 +17311,45 @@ var TechnologyService = class extends BaseService {
16544
17311
  * @returns Ažurirana tehnologija
16545
17312
  */
16546
17313
  async removeContraindication(technologyId, contraindication) {
16547
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16548
- await (0, import_firestore51.updateDoc)(docRef, {
16549
- contraindications: (0, import_firestore51.arrayRemove)(contraindication),
17314
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17315
+ const technology = await this.getById(technologyId);
17316
+ if (!technology) {
17317
+ throw new Error(`Technology with id ${technologyId} not found`);
17318
+ }
17319
+ const updatedContraindications = (technology.contraindications || []).filter((c) => c.id !== contraindication.id);
17320
+ await (0, import_firestore52.updateDoc)(docRef, {
17321
+ contraindications: updatedContraindications,
17322
+ updatedAt: /* @__PURE__ */ new Date()
17323
+ });
17324
+ return this.getById(technologyId);
17325
+ }
17326
+ /**
17327
+ * Updates an existing contraindication in a technology's list.
17328
+ * If the contraindication does not exist, it will not be added.
17329
+ * @param technologyId - ID of the technology
17330
+ * @param contraindication - The updated contraindication object
17331
+ * @returns The updated technology
17332
+ */
17333
+ async updateContraindication(technologyId, contraindication) {
17334
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17335
+ const technology = await this.getById(technologyId);
17336
+ if (!technology) {
17337
+ throw new Error(`Technology with id ${technologyId} not found`);
17338
+ }
17339
+ const contraindications = technology.contraindications || [];
17340
+ const index = contraindications.findIndex(
17341
+ (c) => c.id === contraindication.id
17342
+ );
17343
+ if (index === -1) {
17344
+ console.warn(
17345
+ `Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`
17346
+ );
17347
+ return technology;
17348
+ }
17349
+ const updatedContraindications = [...contraindications];
17350
+ updatedContraindications[index] = contraindication;
17351
+ await (0, import_firestore52.updateDoc)(docRef, {
17352
+ contraindications: updatedContraindications,
16550
17353
  updatedAt: /* @__PURE__ */ new Date()
16551
17354
  });
16552
17355
  return this.getById(technologyId);
@@ -16558,9 +17361,17 @@ var TechnologyService = class extends BaseService {
16558
17361
  * @returns Ažurirana tehnologija
16559
17362
  */
16560
17363
  async addBenefit(technologyId, benefit) {
16561
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16562
- await (0, import_firestore51.updateDoc)(docRef, {
16563
- benefits: (0, import_firestore51.arrayUnion)(benefit),
17364
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17365
+ const technology = await this.getById(technologyId);
17366
+ if (!technology) {
17367
+ throw new Error(`Technology with id ${technologyId} not found`);
17368
+ }
17369
+ const existingBenefits = technology.benefits || [];
17370
+ if (existingBenefits.some((b) => b.id === benefit.id)) {
17371
+ return technology;
17372
+ }
17373
+ await (0, import_firestore52.updateDoc)(docRef, {
17374
+ benefits: [...existingBenefits, benefit],
16564
17375
  updatedAt: /* @__PURE__ */ new Date()
16565
17376
  });
16566
17377
  return this.getById(technologyId);
@@ -16572,9 +17383,45 @@ var TechnologyService = class extends BaseService {
16572
17383
  * @returns Ažurirana tehnologija
16573
17384
  */
16574
17385
  async removeBenefit(technologyId, benefit) {
16575
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16576
- await (0, import_firestore51.updateDoc)(docRef, {
16577
- benefits: (0, import_firestore51.arrayRemove)(benefit),
17386
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17387
+ const technology = await this.getById(technologyId);
17388
+ if (!technology) {
17389
+ throw new Error(`Technology with id ${technologyId} not found`);
17390
+ }
17391
+ const updatedBenefits = (technology.benefits || []).filter(
17392
+ (b) => b.id !== benefit.id
17393
+ );
17394
+ await (0, import_firestore52.updateDoc)(docRef, {
17395
+ benefits: updatedBenefits,
17396
+ updatedAt: /* @__PURE__ */ new Date()
17397
+ });
17398
+ return this.getById(technologyId);
17399
+ }
17400
+ /**
17401
+ * Updates an existing benefit in a technology's list.
17402
+ * If the benefit does not exist, it will not be added.
17403
+ * @param technologyId - ID of the technology
17404
+ * @param benefit - The updated benefit object
17405
+ * @returns The updated technology
17406
+ */
17407
+ async updateBenefit(technologyId, benefit) {
17408
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17409
+ const technology = await this.getById(technologyId);
17410
+ if (!technology) {
17411
+ throw new Error(`Technology with id ${technologyId} not found`);
17412
+ }
17413
+ const benefits = technology.benefits || [];
17414
+ const index = benefits.findIndex((b) => b.id === benefit.id);
17415
+ if (index === -1) {
17416
+ console.warn(
17417
+ `Benefit with id ${benefit.id} not found for technology ${technologyId}. No update performed.`
17418
+ );
17419
+ return technology;
17420
+ }
17421
+ const updatedBenefits = [...benefits];
17422
+ updatedBenefits[index] = benefit;
17423
+ await (0, import_firestore52.updateDoc)(docRef, {
17424
+ benefits: updatedBenefits,
16578
17425
  updatedAt: /* @__PURE__ */ new Date()
16579
17426
  });
16580
17427
  return this.getById(technologyId);
@@ -16613,8 +17460,8 @@ var TechnologyService = class extends BaseService {
16613
17460
  * @returns Ažurirana tehnologija
16614
17461
  */
16615
17462
  async updateCertificationRequirement(technologyId, certificationRequirement) {
16616
- const docRef = (0, import_firestore51.doc)(this.getTechnologiesRef(), technologyId);
16617
- await (0, import_firestore51.updateDoc)(docRef, {
17463
+ const docRef = (0, import_firestore52.doc)(this.technologiesRef, technologyId);
17464
+ await (0, import_firestore52.updateDoc)(docRef, {
16618
17465
  certificationRequirement,
16619
17466
  updatedAt: /* @__PURE__ */ new Date()
16620
17467
  });
@@ -16691,7 +17538,7 @@ var TechnologyService = class extends BaseService {
16691
17538
  */
16692
17539
  async getAllowedTechnologies(practitioner) {
16693
17540
  const allTechnologies = await this.getAll();
16694
- const allowedTechnologies = allTechnologies.filter(
17541
+ const allowedTechnologies = allTechnologies.technologies.filter(
16695
17542
  (technology) => this.validateCertification(
16696
17543
  technology.certificationRequirement,
16697
17544
  practitioner.certification
@@ -16711,10 +17558,48 @@ var TechnologyService = class extends BaseService {
16711
17558
  subcategories
16712
17559
  };
16713
17560
  }
17561
+ /**
17562
+ * Gets all active technologies for a subcategory for filter dropdowns.
17563
+ * @param categoryId - The ID of the parent category.
17564
+ * @param subcategoryId - The ID of the subcategory.
17565
+ */
17566
+ async getAllForFilterBySubcategoryId(categoryId, subcategoryId) {
17567
+ const q = (0, import_firestore52.query)(
17568
+ (0, import_firestore52.collection)(this.db, TECHNOLOGIES_COLLECTION),
17569
+ (0, import_firestore52.where)("isActive", "==", true),
17570
+ (0, import_firestore52.where)("categoryId", "==", categoryId),
17571
+ (0, import_firestore52.where)("subcategoryId", "==", subcategoryId),
17572
+ (0, import_firestore52.orderBy)("name")
17573
+ );
17574
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17575
+ return snapshot.docs.map(
17576
+ (doc38) => ({
17577
+ id: doc38.id,
17578
+ ...doc38.data()
17579
+ })
17580
+ );
17581
+ }
17582
+ /**
17583
+ * Gets all active technologies for filter dropdowns.
17584
+ */
17585
+ async getAllForFilter() {
17586
+ const q = (0, import_firestore52.query)(
17587
+ (0, import_firestore52.collection)(this.db, TECHNOLOGIES_COLLECTION),
17588
+ (0, import_firestore52.where)("isActive", "==", true),
17589
+ (0, import_firestore52.orderBy)("name")
17590
+ );
17591
+ const snapshot = await (0, import_firestore52.getDocs)(q);
17592
+ return snapshot.docs.map(
17593
+ (doc38) => ({
17594
+ id: doc38.id,
17595
+ ...doc38.data()
17596
+ })
17597
+ );
17598
+ }
16714
17599
  };
16715
17600
 
16716
17601
  // src/backoffice/services/product.service.ts
16717
- var import_firestore52 = require("firebase/firestore");
17602
+ var import_firestore53 = require("firebase/firestore");
16718
17603
 
16719
17604
  // src/backoffice/types/product.types.ts
16720
17605
  var PRODUCTS_COLLECTION = "products";
@@ -16727,7 +17612,7 @@ var ProductService = class extends BaseService {
16727
17612
  * @returns Firestore collection reference
16728
17613
  */
16729
17614
  getProductsRef(technologyId) {
16730
- return (0, import_firestore52.collection)(
17615
+ return (0, import_firestore53.collection)(
16731
17616
  this.db,
16732
17617
  TECHNOLOGIES_COLLECTION,
16733
17618
  technologyId,
@@ -16747,47 +17632,129 @@ var ProductService = class extends BaseService {
16747
17632
  updatedAt: now,
16748
17633
  isActive: true
16749
17634
  };
16750
- const productRef = await (0, import_firestore52.addDoc)(
17635
+ const productRef = await (0, import_firestore53.addDoc)(
16751
17636
  this.getProductsRef(technologyId),
16752
17637
  newProduct
16753
17638
  );
16754
17639
  return { id: productRef.id, ...newProduct };
16755
17640
  }
16756
17641
  /**
16757
- * Gets all products for a technology
17642
+ * Gets a paginated list of all products, with optional filters.
17643
+ * This uses a collectionGroup query to search across all technologies.
16758
17644
  */
16759
- async getAllByTechnology(technologyId) {
16760
- const q = (0, import_firestore52.query)(
16761
- this.getProductsRef(technologyId),
16762
- (0, import_firestore52.where)("isActive", "==", true)
16763
- );
16764
- const snapshot = await (0, import_firestore52.getDocs)(q);
16765
- return snapshot.docs.map(
16766
- (doc37) => ({
16767
- id: doc37.id,
16768
- ...doc37.data()
17645
+ async getAll(options) {
17646
+ const {
17647
+ rowsPerPage,
17648
+ lastVisible,
17649
+ categoryId,
17650
+ subcategoryId,
17651
+ technologyId
17652
+ } = options;
17653
+ const constraints = [
17654
+ (0, import_firestore53.where)("isActive", "==", true),
17655
+ (0, import_firestore53.orderBy)("name")
17656
+ ];
17657
+ if (categoryId) {
17658
+ constraints.push((0, import_firestore53.where)("categoryId", "==", categoryId));
17659
+ }
17660
+ if (subcategoryId) {
17661
+ constraints.push((0, import_firestore53.where)("subcategoryId", "==", subcategoryId));
17662
+ }
17663
+ if (technologyId) {
17664
+ constraints.push((0, import_firestore53.where)("technologyId", "==", technologyId));
17665
+ }
17666
+ if (lastVisible) {
17667
+ constraints.push((0, import_firestore53.startAfter)(lastVisible));
17668
+ }
17669
+ constraints.push((0, import_firestore53.limit)(rowsPerPage));
17670
+ const q = (0, import_firestore53.query)(
17671
+ (0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
17672
+ ...constraints
17673
+ );
17674
+ const snapshot = await (0, import_firestore53.getDocs)(q);
17675
+ const products = snapshot.docs.map(
17676
+ (doc38) => ({
17677
+ id: doc38.id,
17678
+ ...doc38.data()
16769
17679
  })
16770
17680
  );
17681
+ const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
17682
+ return { products, lastVisible: newLastVisible };
17683
+ }
17684
+ /**
17685
+ * Gets the total count of active products, with optional filters.
17686
+ */
17687
+ async getProductsCount(options) {
17688
+ const { categoryId, subcategoryId, technologyId } = options;
17689
+ const constraints = [(0, import_firestore53.where)("isActive", "==", true)];
17690
+ if (categoryId) {
17691
+ constraints.push((0, import_firestore53.where)("categoryId", "==", categoryId));
17692
+ }
17693
+ if (subcategoryId) {
17694
+ constraints.push((0, import_firestore53.where)("subcategoryId", "==", subcategoryId));
17695
+ }
17696
+ if (technologyId) {
17697
+ constraints.push((0, import_firestore53.where)("technologyId", "==", technologyId));
17698
+ }
17699
+ const q = (0, import_firestore53.query)(
17700
+ (0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
17701
+ ...constraints
17702
+ );
17703
+ const snapshot = await (0, import_firestore53.getCountFromServer)(q);
17704
+ return snapshot.data().count;
17705
+ }
17706
+ /**
17707
+ * Gets counts of active products grouped by category, subcategory, and technology.
17708
+ * This uses a single collectionGroup query for efficiency.
17709
+ */
17710
+ async getProductCounts() {
17711
+ const q = (0, import_firestore53.query)(
17712
+ (0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
17713
+ (0, import_firestore53.where)("isActive", "==", true)
17714
+ );
17715
+ const snapshot = await (0, import_firestore53.getDocs)(q);
17716
+ const counts = {
17717
+ byCategory: {},
17718
+ bySubcategory: {},
17719
+ byTechnology: {}
17720
+ };
17721
+ if (snapshot.empty) {
17722
+ return counts;
17723
+ }
17724
+ snapshot.docs.forEach((doc38) => {
17725
+ const product = doc38.data();
17726
+ const { categoryId, subcategoryId, technologyId } = product;
17727
+ if (categoryId) {
17728
+ counts.byCategory[categoryId] = (counts.byCategory[categoryId] || 0) + 1;
17729
+ }
17730
+ if (subcategoryId) {
17731
+ counts.bySubcategory[subcategoryId] = (counts.bySubcategory[subcategoryId] || 0) + 1;
17732
+ }
17733
+ if (technologyId) {
17734
+ counts.byTechnology[technologyId] = (counts.byTechnology[technologyId] || 0) + 1;
17735
+ }
17736
+ });
17737
+ return counts;
16771
17738
  }
16772
17739
  /**
16773
17740
  * Gets all products for a brand by filtering through all technologies
16774
17741
  */
16775
17742
  async getAllByBrand(brandId) {
16776
- const allTechnologiesRef = (0, import_firestore52.collection)(this.db, TECHNOLOGIES_COLLECTION);
16777
- const technologiesSnapshot = await (0, import_firestore52.getDocs)(allTechnologiesRef);
17743
+ const allTechnologiesRef = (0, import_firestore53.collection)(this.db, TECHNOLOGIES_COLLECTION);
17744
+ const technologiesSnapshot = await (0, import_firestore53.getDocs)(allTechnologiesRef);
16778
17745
  const products = [];
16779
17746
  for (const techDoc of technologiesSnapshot.docs) {
16780
- const q = (0, import_firestore52.query)(
17747
+ const q = (0, import_firestore53.query)(
16781
17748
  this.getProductsRef(techDoc.id),
16782
- (0, import_firestore52.where)("brandId", "==", brandId),
16783
- (0, import_firestore52.where)("isActive", "==", true)
17749
+ (0, import_firestore53.where)("brandId", "==", brandId),
17750
+ (0, import_firestore53.where)("isActive", "==", true)
16784
17751
  );
16785
- const snapshot = await (0, import_firestore52.getDocs)(q);
17752
+ const snapshot = await (0, import_firestore53.getDocs)(q);
16786
17753
  products.push(
16787
17754
  ...snapshot.docs.map(
16788
- (doc37) => ({
16789
- id: doc37.id,
16790
- ...doc37.data()
17755
+ (doc38) => ({
17756
+ id: doc38.id,
17757
+ ...doc38.data()
16791
17758
  })
16792
17759
  )
16793
17760
  );
@@ -16802,8 +17769,8 @@ var ProductService = class extends BaseService {
16802
17769
  ...product,
16803
17770
  updatedAt: /* @__PURE__ */ new Date()
16804
17771
  };
16805
- const docRef = (0, import_firestore52.doc)(this.getProductsRef(technologyId), productId);
16806
- await (0, import_firestore52.updateDoc)(docRef, updateData);
17772
+ const docRef = (0, import_firestore53.doc)(this.getProductsRef(technologyId), productId);
17773
+ await (0, import_firestore53.updateDoc)(docRef, updateData);
16807
17774
  return this.getById(technologyId, productId);
16808
17775
  }
16809
17776
  /**
@@ -16818,8 +17785,8 @@ var ProductService = class extends BaseService {
16818
17785
  * Gets a product by ID
16819
17786
  */
16820
17787
  async getById(technologyId, productId) {
16821
- const docRef = (0, import_firestore52.doc)(this.getProductsRef(technologyId), productId);
16822
- const docSnap = await (0, import_firestore52.getDoc)(docRef);
17788
+ const docRef = (0, import_firestore53.doc)(this.getProductsRef(technologyId), productId);
17789
+ const docSnap = await (0, import_firestore53.getDoc)(docRef);
16823
17790
  if (!docSnap.exists()) return null;
16824
17791
  return {
16825
17792
  id: docSnap.id,
@@ -16828,6 +17795,255 @@ var ProductService = class extends BaseService {
16828
17795
  }
16829
17796
  };
16830
17797
 
17798
+ // src/backoffice/services/constants.service.ts
17799
+ var import_firestore54 = require("firebase/firestore");
17800
+ var ADMIN_CONSTANTS_COLLECTION = "admin-constants";
17801
+ var TREATMENT_BENEFITS_DOC = "treatment-benefits";
17802
+ var CONTRAINDICATIONS_DOC = "contraindications";
17803
+ var ConstantsService = class extends BaseService {
17804
+ /**
17805
+ * @description Gets the reference to the document holding treatment benefits.
17806
+ * @private
17807
+ * @type {DocumentReference}
17808
+ */
17809
+ get treatmentBenefitsDocRef() {
17810
+ return (0, import_firestore54.doc)(this.db, ADMIN_CONSTANTS_COLLECTION, TREATMENT_BENEFITS_DOC);
17811
+ }
17812
+ /**
17813
+ * @description Gets the reference to the document holding contraindications.
17814
+ * @private
17815
+ * @type {DocumentReference}
17816
+ */
17817
+ get contraindicationsDocRef() {
17818
+ return (0, import_firestore54.doc)(this.db, ADMIN_CONSTANTS_COLLECTION, CONTRAINDICATIONS_DOC);
17819
+ }
17820
+ // =================================================================
17821
+ // Treatment Benefits
17822
+ // =================================================================
17823
+ /**
17824
+ * @description Retrieves all treatment benefits without pagination.
17825
+ * @returns {Promise<TreatmentBenefitDynamic[]>} An array of all treatment benefits.
17826
+ */
17827
+ async getAllBenefitsForFilter() {
17828
+ const docSnap = await (0, import_firestore54.getDoc)(this.treatmentBenefitsDocRef);
17829
+ if (!docSnap.exists()) {
17830
+ return [];
17831
+ }
17832
+ return docSnap.data().benefits;
17833
+ }
17834
+ /**
17835
+ * @description Retrieves a paginated list of treatment benefits.
17836
+ * @param {{ page: number; limit: number }} options - Pagination options.
17837
+ * @returns {Promise<{ benefits: TreatmentBenefitDynamic[]; total: number }>} A paginated list of benefits and the total count.
17838
+ */
17839
+ async getAllBenefits(options) {
17840
+ const allBenefits = await this.getAllBenefitsForFilter();
17841
+ const { page, limit: limit21 } = options;
17842
+ const startIndex = page * limit21;
17843
+ const endIndex = startIndex + limit21;
17844
+ const paginatedBenefits = allBenefits.slice(startIndex, endIndex);
17845
+ return { benefits: paginatedBenefits, total: allBenefits.length };
17846
+ }
17847
+ /**
17848
+ * @description Adds a new treatment benefit.
17849
+ * @param {Omit<TreatmentBenefitDynamic, "id">} benefit - The treatment benefit to add, without an ID.
17850
+ * @returns {Promise<TreatmentBenefitDynamic>} The newly created treatment benefit with its generated ID.
17851
+ */
17852
+ async addTreatmentBenefit(benefit) {
17853
+ const newBenefit = {
17854
+ id: this.generateId(),
17855
+ ...benefit
17856
+ };
17857
+ const docSnap = await (0, import_firestore54.getDoc)(this.treatmentBenefitsDocRef);
17858
+ if (!docSnap.exists()) {
17859
+ await (0, import_firestore54.setDoc)(this.treatmentBenefitsDocRef, { benefits: [newBenefit] });
17860
+ } else {
17861
+ await (0, import_firestore54.updateDoc)(this.treatmentBenefitsDocRef, {
17862
+ benefits: (0, import_firestore54.arrayUnion)(newBenefit)
17863
+ });
17864
+ }
17865
+ return newBenefit;
17866
+ }
17867
+ /**
17868
+ * @description Retrieves a single treatment benefit by its ID.
17869
+ * @param {string} benefitId - The ID of the treatment benefit to retrieve.
17870
+ * @returns {Promise<TreatmentBenefitDynamic | undefined>} The found treatment benefit or undefined.
17871
+ */
17872
+ async getBenefitById(benefitId) {
17873
+ const benefits = await this.getAllBenefitsForFilter();
17874
+ return benefits.find((b) => b.id === benefitId);
17875
+ }
17876
+ /**
17877
+ * @description Searches for treatment benefits by name (case-insensitive).
17878
+ * @param {string} searchTerm - The term to search for in the benefit names.
17879
+ * @returns {Promise<TreatmentBenefitDynamic[]>} An array of matching treatment benefits.
17880
+ */
17881
+ async searchBenefitsByName(searchTerm) {
17882
+ const benefits = await this.getAllBenefitsForFilter();
17883
+ const normalizedSearchTerm = searchTerm.toLowerCase();
17884
+ return benefits.filter(
17885
+ (b) => b.name.toLowerCase().includes(normalizedSearchTerm)
17886
+ );
17887
+ }
17888
+ /**
17889
+ * @description Updates an existing treatment benefit.
17890
+ * @param {TreatmentBenefitDynamic} benefit - The treatment benefit with updated data. Its ID must match an existing benefit.
17891
+ * @returns {Promise<TreatmentBenefitDynamic>} The updated treatment benefit.
17892
+ * @throws {Error} If the treatment benefit is not found.
17893
+ */
17894
+ async updateTreatmentBenefit(benefit) {
17895
+ const benefits = await this.getAllBenefitsForFilter();
17896
+ const benefitIndex = benefits.findIndex((b) => b.id === benefit.id);
17897
+ if (benefitIndex === -1) {
17898
+ throw new Error("Treatment benefit not found.");
17899
+ }
17900
+ benefits[benefitIndex] = benefit;
17901
+ await (0, import_firestore54.updateDoc)(this.treatmentBenefitsDocRef, { benefits });
17902
+ return benefit;
17903
+ }
17904
+ /**
17905
+ * @description Deletes a treatment benefit by its ID.
17906
+ * @param {string} benefitId - The ID of the treatment benefit to delete.
17907
+ * @returns {Promise<void>}
17908
+ */
17909
+ async deleteTreatmentBenefit(benefitId) {
17910
+ const benefits = await this.getAllBenefitsForFilter();
17911
+ const benefitToRemove = benefits.find((b) => b.id === benefitId);
17912
+ if (!benefitToRemove) {
17913
+ return;
17914
+ }
17915
+ await (0, import_firestore54.updateDoc)(this.treatmentBenefitsDocRef, {
17916
+ benefits: (0, import_firestore54.arrayRemove)(benefitToRemove)
17917
+ });
17918
+ }
17919
+ // =================================================================
17920
+ // Contraindications
17921
+ // =================================================================
17922
+ /**
17923
+ * @description Retrieves all contraindications without pagination.
17924
+ * @returns {Promise<ContraindicationDynamic[]>} An array of all contraindications.
17925
+ */
17926
+ async getAllContraindicationsForFilter() {
17927
+ const docSnap = await (0, import_firestore54.getDoc)(this.contraindicationsDocRef);
17928
+ if (!docSnap.exists()) {
17929
+ return [];
17930
+ }
17931
+ return docSnap.data().contraindications;
17932
+ }
17933
+ /**
17934
+ * @description Retrieves a paginated list of contraindications.
17935
+ * @param {{ page: number; limit: number }} options - Pagination options.
17936
+ * @returns {Promise<{ contraindications: ContraindicationDynamic[]; total: number }>} A paginated list and the total count.
17937
+ */
17938
+ async getAllContraindications(options) {
17939
+ const allContraindications = await this.getAllContraindicationsForFilter();
17940
+ const { page, limit: limit21 } = options;
17941
+ const startIndex = page * limit21;
17942
+ const endIndex = startIndex + limit21;
17943
+ const paginatedContraindications = allContraindications.slice(
17944
+ startIndex,
17945
+ endIndex
17946
+ );
17947
+ return {
17948
+ contraindications: paginatedContraindications,
17949
+ total: allContraindications.length
17950
+ };
17951
+ }
17952
+ /**
17953
+ * @description Adds a new contraindication.
17954
+ * @param {Omit<ContraindicationDynamic, "id">} contraindication - The contraindication to add, without an ID.
17955
+ * @returns {Promise<ContraindicationDynamic>} The newly created contraindication with its generated ID.
17956
+ */
17957
+ async addContraindication(contraindication) {
17958
+ const newContraindication = {
17959
+ id: this.generateId(),
17960
+ ...contraindication
17961
+ };
17962
+ const docSnap = await (0, import_firestore54.getDoc)(this.contraindicationsDocRef);
17963
+ if (!docSnap.exists()) {
17964
+ await (0, import_firestore54.setDoc)(this.contraindicationsDocRef, {
17965
+ contraindications: [newContraindication]
17966
+ });
17967
+ } else {
17968
+ await (0, import_firestore54.updateDoc)(this.contraindicationsDocRef, {
17969
+ contraindications: (0, import_firestore54.arrayUnion)(newContraindication)
17970
+ });
17971
+ }
17972
+ return newContraindication;
17973
+ }
17974
+ /**
17975
+ * @description Retrieves a single contraindication by its ID.
17976
+ * @param {string} contraindicationId - The ID of the contraindication to retrieve.
17977
+ * @returns {Promise<ContraindicationDynamic | undefined>} The found contraindication or undefined.
17978
+ */
17979
+ async getContraindicationById(contraindicationId) {
17980
+ const contraindications = await this.getAllContraindicationsForFilter();
17981
+ return contraindications.find((c) => c.id === contraindicationId);
17982
+ }
17983
+ /**
17984
+ * @description Searches for contraindications by name (case-insensitive).
17985
+ * @param {string} searchTerm - The term to search for in the contraindication names.
17986
+ * @returns {Promise<ContraindicationDynamic[]>} An array of matching contraindications.
17987
+ */
17988
+ async searchContraindicationsByName(searchTerm) {
17989
+ const contraindications = await this.getAllContraindicationsForFilter();
17990
+ const normalizedSearchTerm = searchTerm.toLowerCase();
17991
+ return contraindications.filter(
17992
+ (c) => c.name.toLowerCase().includes(normalizedSearchTerm)
17993
+ );
17994
+ }
17995
+ /**
17996
+ * @description Updates an existing contraindication.
17997
+ * @param {ContraindicationDynamic} contraindication - The contraindication with updated data. Its ID must match an existing one.
17998
+ * @returns {Promise<ContraindicationDynamic>} The updated contraindication.
17999
+ * @throws {Error} If the contraindication is not found.
18000
+ */
18001
+ async updateContraindication(contraindication) {
18002
+ const contraindications = await this.getAllContraindicationsForFilter();
18003
+ const index = contraindications.findIndex(
18004
+ (c) => c.id === contraindication.id
18005
+ );
18006
+ if (index === -1) {
18007
+ throw new Error("Contraindication not found.");
18008
+ }
18009
+ contraindications[index] = contraindication;
18010
+ await (0, import_firestore54.updateDoc)(this.contraindicationsDocRef, { contraindications });
18011
+ return contraindication;
18012
+ }
18013
+ /**
18014
+ * @description Deletes a contraindication by its ID.
18015
+ * @param {string} contraindicationId - The ID of the contraindication to delete.
18016
+ * @returns {Promise<void>}
18017
+ */
18018
+ async deleteContraindication(contraindicationId) {
18019
+ const contraindications = await this.getAllContraindicationsForFilter();
18020
+ const toRemove = contraindications.find((c) => c.id === contraindicationId);
18021
+ if (!toRemove) {
18022
+ return;
18023
+ }
18024
+ await (0, import_firestore54.updateDoc)(this.contraindicationsDocRef, {
18025
+ contraindications: (0, import_firestore54.arrayRemove)(toRemove)
18026
+ });
18027
+ }
18028
+ };
18029
+
18030
+ // src/backoffice/types/static/contraindication.types.ts
18031
+ var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
18032
+ Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
18033
+ Contraindication2["RECENT_TANNING"] = "recent_tanning";
18034
+ Contraindication2["RECENT_BOTOX"] = "recent_botox";
18035
+ Contraindication2["RECENT_FILLERS"] = "recent_fillers";
18036
+ Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
18037
+ Contraindication2["MEDICATIONS"] = "medications";
18038
+ Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
18039
+ Contraindication2["RECENT_LASER"] = "recent_laser";
18040
+ Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
18041
+ Contraindication2["OPEN_WOUNDS"] = "open_wounds";
18042
+ Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
18043
+ Contraindication2["COLD_SORES"] = "cold_sores";
18044
+ return Contraindication2;
18045
+ })(Contraindication || {});
18046
+
16831
18047
  // src/backoffice/types/static/treatment-benefit.types.ts
16832
18048
  var TreatmentBenefit = /* @__PURE__ */ ((TreatmentBenefit2) => {
16833
18049
  TreatmentBenefit2["WRINKLE_REDUCTION"] = "wrinkle_reduction";
@@ -16887,6 +18103,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
16887
18103
  ClinicPhotoTag,
16888
18104
  ClinicService,
16889
18105
  ClinicTag,
18106
+ ConstantsService,
16890
18107
  Contraindication,
16891
18108
  CosmeticAllergySubtype,
16892
18109
  Currency,