@blackcode_sa/metaestetics-api 1.5.30 → 1.5.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1349,9 +1349,9 @@ var addAllergyUtil = async (db, patientId, data, userRef) => {
1349
1349
  var updateAllergyUtil = async (db, patientId, data, userRef) => {
1350
1350
  const validatedData = updateAllergySchema.parse(data);
1351
1351
  const { allergyIndex, ...updateData } = validatedData;
1352
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1353
- if (!doc28.exists()) throw new Error("Medical info not found");
1354
- const medicalInfo = doc28.data();
1352
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1353
+ if (!doc29.exists()) throw new Error("Medical info not found");
1354
+ const medicalInfo = doc29.data();
1355
1355
  if (allergyIndex >= medicalInfo.allergies.length) {
1356
1356
  throw new Error("Invalid allergy index");
1357
1357
  }
@@ -1367,9 +1367,9 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
1367
1367
  });
1368
1368
  };
1369
1369
  var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1370
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1371
- if (!doc28.exists()) throw new Error("Medical info not found");
1372
- const medicalInfo = doc28.data();
1370
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1371
+ if (!doc29.exists()) throw new Error("Medical info not found");
1372
+ const medicalInfo = doc29.data();
1373
1373
  if (allergyIndex >= medicalInfo.allergies.length) {
1374
1374
  throw new Error("Invalid allergy index");
1375
1375
  }
@@ -1394,9 +1394,9 @@ var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
1394
1394
  var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1395
1395
  const validatedData = updateBlockingConditionSchema.parse(data);
1396
1396
  const { conditionIndex, ...updateData } = validatedData;
1397
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1398
- if (!doc28.exists()) throw new Error("Medical info not found");
1399
- const medicalInfo = doc28.data();
1397
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1398
+ if (!doc29.exists()) throw new Error("Medical info not found");
1399
+ const medicalInfo = doc29.data();
1400
1400
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1401
1401
  throw new Error("Invalid blocking condition index");
1402
1402
  }
@@ -1412,9 +1412,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1412
1412
  });
1413
1413
  };
1414
1414
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
1415
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1416
- if (!doc28.exists()) throw new Error("Medical info not found");
1417
- const medicalInfo = doc28.data();
1415
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1416
+ if (!doc29.exists()) throw new Error("Medical info not found");
1417
+ const medicalInfo = doc29.data();
1418
1418
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
1419
1419
  throw new Error("Invalid blocking condition index");
1420
1420
  }
@@ -1439,9 +1439,9 @@ var addContraindicationUtil = async (db, patientId, data, userRef) => {
1439
1439
  var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1440
1440
  const validatedData = updateContraindicationSchema.parse(data);
1441
1441
  const { contraindicationIndex, ...updateData } = validatedData;
1442
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1443
- if (!doc28.exists()) throw new Error("Medical info not found");
1444
- const medicalInfo = doc28.data();
1442
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1443
+ if (!doc29.exists()) throw new Error("Medical info not found");
1444
+ const medicalInfo = doc29.data();
1445
1445
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1446
1446
  throw new Error("Invalid contraindication index");
1447
1447
  }
@@ -1457,9 +1457,9 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1457
1457
  });
1458
1458
  };
1459
1459
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
1460
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1461
- if (!doc28.exists()) throw new Error("Medical info not found");
1462
- const medicalInfo = doc28.data();
1460
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1461
+ if (!doc29.exists()) throw new Error("Medical info not found");
1462
+ const medicalInfo = doc29.data();
1463
1463
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
1464
1464
  throw new Error("Invalid contraindication index");
1465
1465
  }
@@ -1484,9 +1484,9 @@ var addMedicationUtil = async (db, patientId, data, userRef) => {
1484
1484
  var updateMedicationUtil = async (db, patientId, data, userRef) => {
1485
1485
  const validatedData = updateMedicationSchema.parse(data);
1486
1486
  const { medicationIndex, ...updateData } = validatedData;
1487
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1488
- if (!doc28.exists()) throw new Error("Medical info not found");
1489
- const medicalInfo = doc28.data();
1487
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1488
+ if (!doc29.exists()) throw new Error("Medical info not found");
1489
+ const medicalInfo = doc29.data();
1490
1490
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1491
1491
  throw new Error("Invalid medication index");
1492
1492
  }
@@ -1502,9 +1502,9 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
1502
1502
  });
1503
1503
  };
1504
1504
  var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
1505
- const doc28 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1506
- if (!doc28.exists()) throw new Error("Medical info not found");
1507
- const medicalInfo = doc28.data();
1505
+ const doc29 = await getDoc3(getMedicalInfoDocRef(db, patientId));
1506
+ if (!doc29.exists()) throw new Error("Medical info not found");
1507
+ const medicalInfo = doc29.data();
1508
1508
  if (medicationIndex >= medicalInfo.currentMedications.length) {
1509
1509
  throw new Error("Invalid medication index");
1510
1510
  }
@@ -1782,7 +1782,7 @@ var searchPatientsUtil = async (db, params, requester) => {
1782
1782
  try {
1783
1783
  const finalQuery = query2(patientsCollectionRef, ...constraints);
1784
1784
  const querySnapshot = await getDocs2(finalQuery);
1785
- const patients = querySnapshot.docs.map((doc28) => doc28.data());
1785
+ const patients = querySnapshot.docs.map((doc29) => doc29.data());
1786
1786
  console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
1787
1787
  return patients;
1788
1788
  } catch (error) {
@@ -1806,8 +1806,8 @@ var getAllPatientsUtil = async (db, options) => {
1806
1806
  }
1807
1807
  const patientsSnapshot = await getDocs2(q);
1808
1808
  const patients = [];
1809
- patientsSnapshot.forEach((doc28) => {
1810
- patients.push(doc28.data());
1809
+ patientsSnapshot.forEach((doc29) => {
1810
+ patients.push(doc29.data());
1811
1811
  });
1812
1812
  console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
1813
1813
  return patients;
@@ -3165,7 +3165,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
3165
3165
  where3("clinicGroupId", "==", clinicGroupId)
3166
3166
  );
3167
3167
  const querySnapshot = await getDocs3(q);
3168
- return querySnapshot.docs.map((doc28) => doc28.data());
3168
+ return querySnapshot.docs.map((doc29) => doc29.data());
3169
3169
  }
3170
3170
  async function updateClinicAdmin(db, adminId, data) {
3171
3171
  const admin = await getClinicAdmin(db, adminId);
@@ -3687,7 +3687,7 @@ var PractitionerService = class extends BaseService {
3687
3687
  where4("expiresAt", ">", Timestamp8.now())
3688
3688
  );
3689
3689
  const querySnapshot = await getDocs4(q);
3690
- return querySnapshot.docs.map((doc28) => doc28.data());
3690
+ return querySnapshot.docs.map((doc29) => doc29.data());
3691
3691
  }
3692
3692
  /**
3693
3693
  * Gets a token by its string value and validates it
@@ -3770,7 +3770,7 @@ var PractitionerService = class extends BaseService {
3770
3770
  where4("status", "==", "active" /* ACTIVE */)
3771
3771
  );
3772
3772
  const querySnapshot = await getDocs4(q);
3773
- return querySnapshot.docs.map((doc28) => doc28.data());
3773
+ return querySnapshot.docs.map((doc29) => doc29.data());
3774
3774
  }
3775
3775
  /**
3776
3776
  * Dohvata sve zdravstvene radnike za određenu kliniku
@@ -3782,7 +3782,7 @@ var PractitionerService = class extends BaseService {
3782
3782
  where4("isActive", "==", true)
3783
3783
  );
3784
3784
  const querySnapshot = await getDocs4(q);
3785
- return querySnapshot.docs.map((doc28) => doc28.data());
3785
+ return querySnapshot.docs.map((doc29) => doc29.data());
3786
3786
  }
3787
3787
  /**
3788
3788
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
@@ -3794,7 +3794,7 @@ var PractitionerService = class extends BaseService {
3794
3794
  where4("status", "==", "draft" /* DRAFT */)
3795
3795
  );
3796
3796
  const querySnapshot = await getDocs4(q);
3797
- return querySnapshot.docs.map((doc28) => doc28.data());
3797
+ return querySnapshot.docs.map((doc29) => doc29.data());
3798
3798
  }
3799
3799
  /**
3800
3800
  * Updates a practitioner
@@ -3976,7 +3976,7 @@ var PractitionerService = class extends BaseService {
3976
3976
  );
3977
3977
  const querySnapshot = await getDocs4(q);
3978
3978
  const practitioners = querySnapshot.docs.map(
3979
- (doc28) => doc28.data()
3979
+ (doc29) => doc29.data()
3980
3980
  );
3981
3981
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
3982
3982
  return {
@@ -4047,8 +4047,8 @@ var PractitionerService = class extends BaseService {
4047
4047
  console.log(
4048
4048
  `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
4049
4049
  );
4050
- let practitioners = querySnapshot.docs.map((doc28) => {
4051
- return { ...doc28.data(), id: doc28.id };
4050
+ let practitioners = querySnapshot.docs.map((doc29) => {
4051
+ return { ...doc29.data(), id: doc29.id };
4052
4052
  });
4053
4053
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
4054
4054
  if (filters.nameSearch && filters.nameSearch.trim() !== "") {
@@ -4302,7 +4302,7 @@ var UserService = class extends BaseService {
4302
4302
  ];
4303
4303
  const q = query5(collection5(this.db, USERS_COLLECTION), ...constraints);
4304
4304
  const querySnapshot = await getDocs5(q);
4305
- const users = querySnapshot.docs.map((doc28) => doc28.data());
4305
+ const users = querySnapshot.docs.map((doc29) => doc29.data());
4306
4306
  return Promise.all(users.map((userData) => userSchema.parse(userData)));
4307
4307
  }
4308
4308
  /**
@@ -4682,7 +4682,7 @@ async function getAllActiveGroups(db) {
4682
4682
  where6("isActive", "==", true)
4683
4683
  );
4684
4684
  const querySnapshot = await getDocs6(q);
4685
- return querySnapshot.docs.map((doc28) => doc28.data());
4685
+ return querySnapshot.docs.map((doc29) => doc29.data());
4686
4686
  }
4687
4687
  async function updateClinicGroup(db, groupId, data, app) {
4688
4688
  console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
@@ -5106,7 +5106,7 @@ async function getClinicsByGroup(db, groupId) {
5106
5106
  where7("isActive", "==", true)
5107
5107
  );
5108
5108
  const querySnapshot = await getDocs7(q);
5109
- return querySnapshot.docs.map((doc28) => doc28.data());
5109
+ return querySnapshot.docs.map((doc29) => doc29.data());
5110
5110
  }
5111
5111
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
5112
5112
  console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
@@ -5300,7 +5300,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
5300
5300
  }
5301
5301
  const q = query7(collection7(db, CLINICS_COLLECTION), ...constraints);
5302
5302
  const querySnapshot = await getDocs7(q);
5303
- return querySnapshot.docs.map((doc28) => doc28.data());
5303
+ return querySnapshot.docs.map((doc29) => doc29.data());
5304
5304
  }
5305
5305
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
5306
5306
  return getClinicsByAdmin(
@@ -5345,11 +5345,11 @@ async function getAllClinics(db, pagination, lastDoc) {
5345
5345
  }
5346
5346
  const clinicsSnapshot = await getDocs7(clinicsQuery);
5347
5347
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
5348
- const clinics = clinicsSnapshot.docs.map((doc28) => {
5349
- const data = doc28.data();
5348
+ const clinics = clinicsSnapshot.docs.map((doc29) => {
5349
+ const data = doc29.data();
5350
5350
  return {
5351
5351
  ...data,
5352
- id: doc28.id
5352
+ id: doc29.id
5353
5353
  };
5354
5354
  });
5355
5355
  return {
@@ -5376,8 +5376,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
5376
5376
  ];
5377
5377
  const q = query7(collection7(db, CLINICS_COLLECTION), ...constraints);
5378
5378
  const querySnapshot = await getDocs7(q);
5379
- for (const doc28 of querySnapshot.docs) {
5380
- const clinic = doc28.data();
5379
+ for (const doc29 of querySnapshot.docs) {
5380
+ const clinic = doc29.data();
5381
5381
  const distance = distanceBetween2(
5382
5382
  [center.latitude, center.longitude],
5383
5383
  [clinic.location.latitude, clinic.location.longitude]
@@ -5499,8 +5499,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
5499
5499
  }
5500
5500
  const q = query8(collection8(db, CLINICS_COLLECTION), ...constraints);
5501
5501
  const querySnapshot = await getDocs8(q);
5502
- for (const doc28 of querySnapshot.docs) {
5503
- const clinic = doc28.data();
5502
+ for (const doc29 of querySnapshot.docs) {
5503
+ const clinic = doc29.data();
5504
5504
  const distance = distanceBetween3(
5505
5505
  [center.latitude, center.longitude],
5506
5506
  [clinic.location.latitude, clinic.location.longitude]
@@ -5532,7 +5532,6 @@ import {
5532
5532
  getDocs as getDocs9,
5533
5533
  startAfter as startAfter4,
5534
5534
  limit as limit4,
5535
- documentId,
5536
5535
  orderBy as orderBy2
5537
5536
  } from "firebase/firestore";
5538
5537
  import { geohashQueryBounds as geohashQueryBounds3, distanceBetween as distanceBetween4 } from "geofire-common";
@@ -5574,7 +5573,7 @@ async function getClinicsByFilters(db, filters) {
5574
5573
  } else if (filters.pagination && filters.pagination > 0) {
5575
5574
  constraints.push(limit4(filters.pagination));
5576
5575
  }
5577
- constraints.push(orderBy2(documentId()));
5576
+ constraints.push(orderBy2("location.geohash"));
5578
5577
  let clinicsResult = [];
5579
5578
  let lastVisibleDoc = null;
5580
5579
  if (isGeoQuery) {
@@ -5597,8 +5596,8 @@ async function getClinicsByFilters(db, filters) {
5597
5596
  console.log(
5598
5597
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
5599
5598
  );
5600
- for (const doc28 of querySnapshot.docs) {
5601
- const clinic = { ...doc28.data(), id: doc28.id };
5599
+ for (const doc29 of querySnapshot.docs) {
5600
+ const clinic = { ...doc29.data(), id: doc29.id };
5602
5601
  const distance = distanceBetween4(
5603
5602
  [center.latitude, center.longitude],
5604
5603
  [clinic.location.latitude, clinic.location.longitude]
@@ -5654,10 +5653,29 @@ async function getClinicsByFilters(db, filters) {
5654
5653
  console.log(
5655
5654
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
5656
5655
  );
5657
- const clinics = querySnapshot.docs.map((doc28) => {
5658
- return { ...doc28.data(), id: doc28.id };
5656
+ const clinics = querySnapshot.docs.map((doc29) => {
5657
+ return { ...doc29.data(), id: doc29.id };
5659
5658
  });
5660
5659
  let filteredClinics = clinics;
5660
+ if (filters.center) {
5661
+ const center = filters.center;
5662
+ const clinicsWithDistance = [];
5663
+ filteredClinics.forEach((clinic) => {
5664
+ const distance = distanceBetween4(
5665
+ [center.latitude, center.longitude],
5666
+ [clinic.location.latitude, clinic.location.longitude]
5667
+ );
5668
+ clinicsWithDistance.push({
5669
+ ...clinic,
5670
+ distance: distance / 1e3
5671
+ // Convert to kilometers
5672
+ });
5673
+ });
5674
+ filteredClinics = clinicsWithDistance;
5675
+ filteredClinics.sort(
5676
+ (a, b) => a.distance - b.distance
5677
+ );
5678
+ }
5661
5679
  if (filters.tags && filters.tags.length > 1) {
5662
5680
  filteredClinics = filteredClinics.filter((clinic) => {
5663
5681
  return filters.tags.every((tag) => clinic.tags.includes(tag));
@@ -5946,6 +5964,12 @@ var ClinicService = class extends BaseService {
5946
5964
  lastDoc
5947
5965
  );
5948
5966
  }
5967
+ /**
5968
+ * Get clinics based on multiple filtering criteria
5969
+ *
5970
+ * @param filters - Various filters to apply
5971
+ * @returns Filtered clinics and the last document for pagination
5972
+ */
5949
5973
  async getClinicsByFilters(filters) {
5950
5974
  return getClinicsByFilters(this.db, filters);
5951
5975
  }
@@ -6693,9 +6717,9 @@ var NotificationService = class extends BaseService {
6693
6717
  orderBy3("notificationTime", "desc")
6694
6718
  );
6695
6719
  const querySnapshot = await getDocs12(q);
6696
- return querySnapshot.docs.map((doc28) => ({
6697
- id: doc28.id,
6698
- ...doc28.data()
6720
+ return querySnapshot.docs.map((doc29) => ({
6721
+ id: doc29.id,
6722
+ ...doc29.data()
6699
6723
  }));
6700
6724
  }
6701
6725
  /**
@@ -6709,9 +6733,9 @@ var NotificationService = class extends BaseService {
6709
6733
  orderBy3("notificationTime", "desc")
6710
6734
  );
6711
6735
  const querySnapshot = await getDocs12(q);
6712
- return querySnapshot.docs.map((doc28) => ({
6713
- id: doc28.id,
6714
- ...doc28.data()
6736
+ return querySnapshot.docs.map((doc29) => ({
6737
+ id: doc29.id,
6738
+ ...doc29.data()
6715
6739
  }));
6716
6740
  }
6717
6741
  /**
@@ -6783,9 +6807,9 @@ var NotificationService = class extends BaseService {
6783
6807
  orderBy3("notificationTime", "desc")
6784
6808
  );
6785
6809
  const querySnapshot = await getDocs12(q);
6786
- return querySnapshot.docs.map((doc28) => ({
6787
- id: doc28.id,
6788
- ...doc28.data()
6810
+ return querySnapshot.docs.map((doc29) => ({
6811
+ id: doc29.id,
6812
+ ...doc29.data()
6789
6813
  }));
6790
6814
  }
6791
6815
  /**
@@ -6798,9 +6822,9 @@ var NotificationService = class extends BaseService {
6798
6822
  orderBy3("notificationTime", "desc")
6799
6823
  );
6800
6824
  const querySnapshot = await getDocs12(q);
6801
- return querySnapshot.docs.map((doc28) => ({
6802
- id: doc28.id,
6803
- ...doc28.data()
6825
+ return querySnapshot.docs.map((doc29) => ({
6826
+ id: doc29.id,
6827
+ ...doc29.data()
6804
6828
  }));
6805
6829
  }
6806
6830
  };
@@ -6819,8 +6843,7 @@ import {
6819
6843
  serverTimestamp as serverTimestamp14,
6820
6844
  orderBy as orderBy4,
6821
6845
  limit as limit5,
6822
- startAfter as startAfter5,
6823
- documentId as documentId2
6846
+ startAfter as startAfter5
6824
6847
  } from "firebase/firestore";
6825
6848
 
6826
6849
  // src/types/procedure/index.ts
@@ -7032,7 +7055,7 @@ var ProcedureService = class extends BaseService {
7032
7055
  where13("isActive", "==", true)
7033
7056
  );
7034
7057
  const snapshot = await getDocs13(q);
7035
- return snapshot.docs.map((doc28) => doc28.data());
7058
+ return snapshot.docs.map((doc29) => doc29.data());
7036
7059
  }
7037
7060
  /**
7038
7061
  * Gets all procedures for a practitioner
@@ -7046,7 +7069,7 @@ var ProcedureService = class extends BaseService {
7046
7069
  where13("isActive", "==", true)
7047
7070
  );
7048
7071
  const snapshot = await getDocs13(q);
7049
- return snapshot.docs.map((doc28) => doc28.data());
7072
+ return snapshot.docs.map((doc29) => doc29.data());
7050
7073
  }
7051
7074
  /**
7052
7075
  * Updates a procedure
@@ -7250,11 +7273,11 @@ var ProcedureService = class extends BaseService {
7250
7273
  }
7251
7274
  const proceduresSnapshot = await getDocs13(proceduresQuery);
7252
7275
  const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
7253
- const procedures = proceduresSnapshot.docs.map((doc28) => {
7254
- const data = doc28.data();
7276
+ const procedures = proceduresSnapshot.docs.map((doc29) => {
7277
+ const data = doc29.data();
7255
7278
  return {
7256
7279
  ...data,
7257
- id: doc28.id
7280
+ id: doc29.id
7258
7281
  // Ensure ID is present
7259
7282
  };
7260
7283
  });
@@ -7304,7 +7327,7 @@ var ProcedureService = class extends BaseService {
7304
7327
  if (filters.procedureFamily) {
7305
7328
  constraints.push(where13("family", "==", filters.procedureFamily));
7306
7329
  }
7307
- constraints.push(orderBy4(documentId2()));
7330
+ constraints.push(orderBy4("clinicInfo.location.geohash"));
7308
7331
  if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
7309
7332
  constraints.push(startAfter5(filters.lastDoc));
7310
7333
  constraints.push(limit5(filters.pagination));
@@ -7336,8 +7359,8 @@ var ProcedureService = class extends BaseService {
7336
7359
  console.log(
7337
7360
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
7338
7361
  );
7339
- for (const doc28 of querySnapshot.docs) {
7340
- const procedure = { ...doc28.data(), id: doc28.id };
7362
+ for (const doc29 of querySnapshot.docs) {
7363
+ const procedure = { ...doc29.data(), id: doc29.id };
7341
7364
  const distance = distanceBetween6(
7342
7365
  [center.latitude, center.longitude],
7343
7366
  [
@@ -7388,12 +7411,41 @@ var ProcedureService = class extends BaseService {
7388
7411
  console.log(
7389
7412
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
7390
7413
  );
7391
- const procedures = querySnapshot.docs.map((doc28) => {
7392
- return { ...doc28.data(), id: doc28.id };
7414
+ const procedures = querySnapshot.docs.map((doc29) => {
7415
+ return { ...doc29.data(), id: doc29.id };
7393
7416
  });
7394
- let filteredProcedures = this.applyInMemoryFilters(procedures, filters);
7417
+ if (filters.location) {
7418
+ const center = filters.location;
7419
+ const proceduresWithDistance = [];
7420
+ procedures.forEach((procedure) => {
7421
+ const distance = distanceBetween6(
7422
+ [center.latitude, center.longitude],
7423
+ [
7424
+ procedure.clinicInfo.location.latitude,
7425
+ procedure.clinicInfo.location.longitude
7426
+ ]
7427
+ );
7428
+ proceduresWithDistance.push({
7429
+ ...procedure,
7430
+ distance: distance / 1e3
7431
+ // Convert to kilometers
7432
+ });
7433
+ });
7434
+ let filteredProcedures = proceduresWithDistance;
7435
+ filteredProcedures = this.applyInMemoryFilters(
7436
+ filteredProcedures,
7437
+ filters
7438
+ );
7439
+ filteredProcedures.sort((a, b) => a.distance - b.distance);
7440
+ proceduresResult = filteredProcedures;
7441
+ } else {
7442
+ let filteredProcedures = this.applyInMemoryFilters(
7443
+ procedures,
7444
+ filters
7445
+ );
7446
+ proceduresResult = filteredProcedures;
7447
+ }
7395
7448
  lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7396
- proceduresResult = filteredProcedures;
7397
7449
  }
7398
7450
  return {
7399
7451
  procedures: proceduresResult,
@@ -7591,9 +7643,9 @@ var DocumentationTemplateService = class extends BaseService {
7591
7643
  const querySnapshot = await getDocs14(q);
7592
7644
  const templates = [];
7593
7645
  let lastVisible = null;
7594
- querySnapshot.forEach((doc28) => {
7595
- templates.push(doc28.data());
7596
- lastVisible = doc28;
7646
+ querySnapshot.forEach((doc29) => {
7647
+ templates.push(doc29.data());
7648
+ lastVisible = doc29;
7597
7649
  });
7598
7650
  return {
7599
7651
  templates,
@@ -7621,9 +7673,9 @@ var DocumentationTemplateService = class extends BaseService {
7621
7673
  const querySnapshot = await getDocs14(q);
7622
7674
  const templates = [];
7623
7675
  let lastVisible = null;
7624
- querySnapshot.forEach((doc28) => {
7625
- templates.push(doc28.data());
7626
- lastVisible = doc28;
7676
+ querySnapshot.forEach((doc29) => {
7677
+ templates.push(doc29.data());
7678
+ lastVisible = doc29;
7627
7679
  });
7628
7680
  return {
7629
7681
  templates,
@@ -7650,9 +7702,9 @@ var DocumentationTemplateService = class extends BaseService {
7650
7702
  const querySnapshot = await getDocs14(q);
7651
7703
  const templates = [];
7652
7704
  let lastVisible = null;
7653
- querySnapshot.forEach((doc28) => {
7654
- templates.push(doc28.data());
7655
- lastVisible = doc28;
7705
+ querySnapshot.forEach((doc29) => {
7706
+ templates.push(doc29.data());
7707
+ lastVisible = doc29;
7656
7708
  });
7657
7709
  return {
7658
7710
  templates,
@@ -7777,9 +7829,9 @@ var FilledDocumentService = class extends BaseService {
7777
7829
  const querySnapshot = await getDocs15(q);
7778
7830
  const documents = [];
7779
7831
  let lastVisible = null;
7780
- querySnapshot.forEach((doc28) => {
7781
- documents.push(doc28.data());
7782
- lastVisible = doc28;
7832
+ querySnapshot.forEach((doc29) => {
7833
+ documents.push(doc29.data());
7834
+ lastVisible = doc29;
7783
7835
  });
7784
7836
  return {
7785
7837
  documents,
@@ -7806,9 +7858,9 @@ var FilledDocumentService = class extends BaseService {
7806
7858
  const querySnapshot = await getDocs15(q);
7807
7859
  const documents = [];
7808
7860
  let lastVisible = null;
7809
- querySnapshot.forEach((doc28) => {
7810
- documents.push(doc28.data());
7811
- lastVisible = doc28;
7861
+ querySnapshot.forEach((doc29) => {
7862
+ documents.push(doc29.data());
7863
+ lastVisible = doc29;
7812
7864
  });
7813
7865
  return {
7814
7866
  documents,
@@ -7835,9 +7887,9 @@ var FilledDocumentService = class extends BaseService {
7835
7887
  const querySnapshot = await getDocs15(q);
7836
7888
  const documents = [];
7837
7889
  let lastVisible = null;
7838
- querySnapshot.forEach((doc28) => {
7839
- documents.push(doc28.data());
7840
- lastVisible = doc28;
7890
+ querySnapshot.forEach((doc29) => {
7891
+ documents.push(doc29.data());
7892
+ lastVisible = doc29;
7841
7893
  });
7842
7894
  return {
7843
7895
  documents,
@@ -7864,9 +7916,9 @@ var FilledDocumentService = class extends BaseService {
7864
7916
  const querySnapshot = await getDocs15(q);
7865
7917
  const documents = [];
7866
7918
  let lastVisible = null;
7867
- querySnapshot.forEach((doc28) => {
7868
- documents.push(doc28.data());
7869
- lastVisible = doc28;
7919
+ querySnapshot.forEach((doc29) => {
7920
+ documents.push(doc29.data());
7921
+ lastVisible = doc29;
7870
7922
  });
7871
7923
  return {
7872
7924
  documents,
@@ -7893,9 +7945,9 @@ var FilledDocumentService = class extends BaseService {
7893
7945
  const querySnapshot = await getDocs15(q);
7894
7946
  const documents = [];
7895
7947
  let lastVisible = null;
7896
- querySnapshot.forEach((doc28) => {
7897
- documents.push(doc28.data());
7898
- lastVisible = doc28;
7948
+ querySnapshot.forEach((doc29) => {
7949
+ documents.push(doc29.data());
7950
+ lastVisible = doc29;
7899
7951
  });
7900
7952
  return {
7901
7953
  documents,
@@ -8337,37 +8389,19 @@ async function createAppointmentUtil(db, clinicId, practitionerId, patientId, ev
8337
8389
  () => eventId
8338
8390
  // Use the same ID for all calendars
8339
8391
  );
8340
- const [clinicEvent] = await Promise.all([
8341
- clinicPromise,
8342
- practitionerPromise,
8343
- patientPromise
8344
- ]);
8392
+ const [clinicEvent] = await Promise.all([clinicPromise, practitionerPromise, patientPromise]);
8345
8393
  return clinicEvent;
8346
8394
  }
8347
8395
  async function updateAppointmentUtil(db, clinicId, practitionerId, patientId, eventId, updateData) {
8348
- const clinicPromise = updateClinicCalendarEventUtil(
8349
- db,
8350
- clinicId,
8351
- eventId,
8352
- updateData
8353
- );
8396
+ const clinicPromise = updateClinicCalendarEventUtil(db, clinicId, eventId, updateData);
8354
8397
  const practitionerPromise = updatePractitionerCalendarEventUtil(
8355
8398
  db,
8356
8399
  practitionerId,
8357
8400
  eventId,
8358
8401
  updateData
8359
8402
  );
8360
- const patientPromise = updatePatientCalendarEventUtil(
8361
- db,
8362
- patientId,
8363
- eventId,
8364
- updateData
8365
- );
8366
- const [clinicEvent] = await Promise.all([
8367
- clinicPromise,
8368
- practitionerPromise,
8369
- patientPromise
8370
- ]);
8403
+ const patientPromise = updatePatientCalendarEventUtil(db, patientId, eventId, updateData);
8404
+ const [clinicEvent] = await Promise.all([clinicPromise, practitionerPromise, patientPromise]);
8371
8405
  return clinicEvent;
8372
8406
  }
8373
8407
 
@@ -8469,7 +8503,7 @@ async function searchCalendarEventsUtil(db, params) {
8469
8503
  const finalQuery = query19(collectionRef, ...constraints);
8470
8504
  const querySnapshot = await getDocs19(finalQuery);
8471
8505
  const events = querySnapshot.docs.map(
8472
- (doc28) => ({ id: doc28.id, ...doc28.data() })
8506
+ (doc29) => ({ id: doc29.id, ...doc29.data() })
8473
8507
  );
8474
8508
  return events;
8475
8509
  } catch (error) {
@@ -8562,7 +8596,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
8562
8596
  );
8563
8597
  const q = query20(calendarsRef, orderBy11("createdAt", "desc"));
8564
8598
  const querySnapshot = await getDocs20(q);
8565
- return querySnapshot.docs.map((doc28) => doc28.data());
8599
+ return querySnapshot.docs.map((doc29) => doc29.data());
8566
8600
  }
8567
8601
  async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
8568
8602
  const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
@@ -8579,7 +8613,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
8579
8613
  );
8580
8614
  const q = query20(calendarsRef, orderBy11("createdAt", "desc"));
8581
8615
  const querySnapshot = await getDocs20(q);
8582
- return querySnapshot.docs.map((doc28) => doc28.data());
8616
+ return querySnapshot.docs.map((doc29) => doc29.data());
8583
8617
  }
8584
8618
  async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
8585
8619
  const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
@@ -8596,7 +8630,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
8596
8630
  );
8597
8631
  const q = query20(calendarsRef, orderBy11("createdAt", "desc"));
8598
8632
  const querySnapshot = await getDocs20(q);
8599
- return querySnapshot.docs.map((doc28) => doc28.data());
8633
+ return querySnapshot.docs.map((doc29) => doc29.data());
8600
8634
  }
8601
8635
  async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
8602
8636
  const calendarRef = getPractitionerSyncedCalendarDocRef(
@@ -9951,9 +9985,9 @@ var CalendarServiceV2 = class extends BaseService {
9951
9985
  where21("eventTime.start", "<=", Timestamp25.fromDate(endDate))
9952
9986
  );
9953
9987
  const eventsSnapshot = await getDocs21(q);
9954
- const events = eventsSnapshot.docs.map((doc28) => ({
9955
- id: doc28.id,
9956
- ...doc28.data()
9988
+ const events = eventsSnapshot.docs.map((doc29) => ({
9989
+ id: doc29.id,
9990
+ ...doc29.data()
9957
9991
  }));
9958
9992
  const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
9959
9993
  doctorId
@@ -10585,7 +10619,7 @@ var CalendarServiceV2 = class extends BaseService {
10585
10619
  ])
10586
10620
  );
10587
10621
  const querySnapshot = await getDocs21(q);
10588
- return querySnapshot.docs.map((doc28) => doc28.data());
10622
+ return querySnapshot.docs.map((doc29) => doc29.data());
10589
10623
  }
10590
10624
  /**
10591
10625
  * Calculates available time slots based on working hours, schedule and existing appointments
@@ -10709,16 +10743,637 @@ var CalendarServiceV2 = class extends BaseService {
10709
10743
  // #endregion
10710
10744
  };
10711
10745
 
10712
- // src/backoffice/services/brand.service.ts
10746
+ // src/services/reviews/reviews.service.ts
10713
10747
  import {
10714
- addDoc as addDoc3,
10715
10748
  collection as collection22,
10716
10749
  doc as doc23,
10717
10750
  getDoc as getDoc25,
10718
10751
  getDocs as getDocs22,
10719
10752
  query as query22,
10753
+ where as where22,
10720
10754
  updateDoc as updateDoc24,
10721
- where as where22
10755
+ setDoc as setDoc22,
10756
+ deleteDoc as deleteDoc15,
10757
+ serverTimestamp as serverTimestamp22,
10758
+ writeBatch as writeBatch7
10759
+ } from "firebase/firestore";
10760
+
10761
+ // src/types/reviews/index.ts
10762
+ var REVIEWS_COLLECTION = "reviews";
10763
+
10764
+ // src/services/reviews/reviews.service.ts
10765
+ import { z as z21 } from "zod";
10766
+ var ReviewService = class extends BaseService {
10767
+ constructor(db, auth, app) {
10768
+ super(db, auth, app);
10769
+ }
10770
+ /**
10771
+ * Creates a new review and updates related entities
10772
+ * @param data - The review data to create
10773
+ * @param appointmentId - ID of the completed appointment
10774
+ * @returns The created review
10775
+ */
10776
+ async createReview(data, appointmentId) {
10777
+ try {
10778
+ const validatedData = createReviewSchema.parse(data);
10779
+ const ratings = [];
10780
+ if (data.clinicReview) {
10781
+ const clinicRatings = [
10782
+ data.clinicReview.cleanliness,
10783
+ data.clinicReview.facilities,
10784
+ data.clinicReview.staffFriendliness,
10785
+ data.clinicReview.waitingTime,
10786
+ data.clinicReview.accessibility
10787
+ ];
10788
+ const clinicAverage = this.calculateAverage(clinicRatings);
10789
+ data.clinicReview.overallRating = clinicAverage;
10790
+ ratings.push(clinicAverage);
10791
+ }
10792
+ if (data.practitionerReview) {
10793
+ const practitionerRatings = [
10794
+ data.practitionerReview.knowledgeAndExpertise,
10795
+ data.practitionerReview.communicationSkills,
10796
+ data.practitionerReview.bedSideManner,
10797
+ data.practitionerReview.thoroughness,
10798
+ data.practitionerReview.trustworthiness
10799
+ ];
10800
+ const practitionerAverage = this.calculateAverage(practitionerRatings);
10801
+ data.practitionerReview.overallRating = practitionerAverage;
10802
+ ratings.push(practitionerAverage);
10803
+ }
10804
+ if (data.procedureReview) {
10805
+ const procedureRatings = [
10806
+ data.procedureReview.effectivenessOfTreatment,
10807
+ data.procedureReview.outcomeExplanation,
10808
+ data.procedureReview.painManagement,
10809
+ data.procedureReview.followUpCare,
10810
+ data.procedureReview.valueForMoney
10811
+ ];
10812
+ const procedureAverage = this.calculateAverage(procedureRatings);
10813
+ data.procedureReview.overallRating = procedureAverage;
10814
+ ratings.push(procedureAverage);
10815
+ }
10816
+ const overallRating = this.calculateAverage(ratings);
10817
+ const reviewId = this.generateId();
10818
+ if (data.clinicReview) {
10819
+ data.clinicReview.id = this.generateId();
10820
+ data.clinicReview.fullReviewId = reviewId;
10821
+ }
10822
+ if (data.practitionerReview) {
10823
+ data.practitionerReview.id = this.generateId();
10824
+ data.practitionerReview.fullReviewId = reviewId;
10825
+ }
10826
+ if (data.procedureReview) {
10827
+ data.procedureReview.id = this.generateId();
10828
+ data.procedureReview.fullReviewId = reviewId;
10829
+ }
10830
+ const now = /* @__PURE__ */ new Date();
10831
+ const review = {
10832
+ id: reviewId,
10833
+ appointmentId,
10834
+ patientId: data.patientId,
10835
+ clinicReview: data.clinicReview,
10836
+ practitionerReview: data.practitionerReview,
10837
+ procedureReview: data.procedureReview,
10838
+ overallComment: data.overallComment,
10839
+ overallRating,
10840
+ createdAt: now,
10841
+ updatedAt: now
10842
+ };
10843
+ reviewSchema.parse(review);
10844
+ const docRef = doc23(this.db, REVIEWS_COLLECTION, reviewId);
10845
+ await setDoc22(docRef, {
10846
+ ...review,
10847
+ createdAt: serverTimestamp22(),
10848
+ updatedAt: serverTimestamp22()
10849
+ });
10850
+ const updatePromises = [];
10851
+ if (data.clinicReview) {
10852
+ updatePromises.push(
10853
+ this.updateClinicReviewInfo(data.clinicReview.clinicId)
10854
+ );
10855
+ }
10856
+ if (data.practitionerReview) {
10857
+ updatePromises.push(
10858
+ this.updatePractitionerReviewInfo(
10859
+ data.practitionerReview.practitionerId
10860
+ )
10861
+ );
10862
+ }
10863
+ if (data.procedureReview) {
10864
+ updatePromises.push(
10865
+ this.updateProcedureReviewInfo(data.procedureReview.procedureId)
10866
+ );
10867
+ }
10868
+ await Promise.all(updatePromises);
10869
+ return review;
10870
+ } catch (error) {
10871
+ if (error instanceof z21.ZodError) {
10872
+ throw new Error(`Invalid review data: ${error.message}`);
10873
+ }
10874
+ throw error;
10875
+ }
10876
+ }
10877
+ /**
10878
+ * Gets a review by ID
10879
+ * @param reviewId The ID of the review to get
10880
+ * @returns The review if found, null otherwise
10881
+ */
10882
+ async getReview(reviewId) {
10883
+ const docRef = doc23(this.db, REVIEWS_COLLECTION, reviewId);
10884
+ const docSnap = await getDoc25(docRef);
10885
+ if (!docSnap.exists()) {
10886
+ return null;
10887
+ }
10888
+ return docSnap.data();
10889
+ }
10890
+ /**
10891
+ * Gets all reviews for a specific patient
10892
+ * @param patientId The ID of the patient
10893
+ * @returns Array of reviews for the patient
10894
+ */
10895
+ async getReviewsByPatient(patientId) {
10896
+ const q = query22(
10897
+ collection22(this.db, REVIEWS_COLLECTION),
10898
+ where22("patientId", "==", patientId)
10899
+ );
10900
+ const snapshot = await getDocs22(q);
10901
+ return snapshot.docs.map((doc29) => doc29.data());
10902
+ }
10903
+ /**
10904
+ * Gets all reviews for a specific clinic
10905
+ * @param clinicId The ID of the clinic
10906
+ * @returns Array of reviews containing clinic reviews
10907
+ */
10908
+ async getReviewsByClinic(clinicId) {
10909
+ const q = query22(
10910
+ collection22(this.db, REVIEWS_COLLECTION),
10911
+ where22("clinicReview.clinicId", "==", clinicId)
10912
+ );
10913
+ const snapshot = await getDocs22(q);
10914
+ return snapshot.docs.map((doc29) => doc29.data());
10915
+ }
10916
+ /**
10917
+ * Gets all reviews for a specific practitioner
10918
+ * @param practitionerId The ID of the practitioner
10919
+ * @returns Array of reviews containing practitioner reviews
10920
+ */
10921
+ async getReviewsByPractitioner(practitionerId) {
10922
+ const q = query22(
10923
+ collection22(this.db, REVIEWS_COLLECTION),
10924
+ where22("practitionerReview.practitionerId", "==", practitionerId)
10925
+ );
10926
+ const snapshot = await getDocs22(q);
10927
+ return snapshot.docs.map((doc29) => doc29.data());
10928
+ }
10929
+ /**
10930
+ * Gets all reviews for a specific procedure
10931
+ * @param procedureId The ID of the procedure
10932
+ * @returns Array of reviews containing procedure reviews
10933
+ */
10934
+ async getReviewsByProcedure(procedureId) {
10935
+ const q = query22(
10936
+ collection22(this.db, REVIEWS_COLLECTION),
10937
+ where22("procedureReview.procedureId", "==", procedureId)
10938
+ );
10939
+ const snapshot = await getDocs22(q);
10940
+ return snapshot.docs.map((doc29) => doc29.data());
10941
+ }
10942
+ /**
10943
+ * Gets all reviews for a specific appointment
10944
+ * @param appointmentId The ID of the appointment
10945
+ * @returns The review for the appointment if found, null otherwise
10946
+ */
10947
+ async getReviewByAppointment(appointmentId) {
10948
+ const q = query22(
10949
+ collection22(this.db, REVIEWS_COLLECTION),
10950
+ where22("appointmentId", "==", appointmentId)
10951
+ );
10952
+ const snapshot = await getDocs22(q);
10953
+ if (snapshot.empty) {
10954
+ return null;
10955
+ }
10956
+ return snapshot.docs[0].data();
10957
+ }
10958
+ /**
10959
+ * Deletes a review and updates related entities
10960
+ * @param reviewId The ID of the review to delete
10961
+ */
10962
+ async deleteReview(reviewId) {
10963
+ const review = await this.getReview(reviewId);
10964
+ if (!review) {
10965
+ throw new Error(`Review with ID ${reviewId} not found`);
10966
+ }
10967
+ await deleteDoc15(doc23(this.db, REVIEWS_COLLECTION, reviewId));
10968
+ const updatePromises = [];
10969
+ if (review.clinicReview) {
10970
+ updatePromises.push(
10971
+ this.updateClinicReviewInfo(
10972
+ review.clinicReview.clinicId,
10973
+ review.clinicReview,
10974
+ true
10975
+ )
10976
+ );
10977
+ }
10978
+ if (review.practitionerReview) {
10979
+ updatePromises.push(
10980
+ this.updatePractitionerReviewInfo(
10981
+ review.practitionerReview.practitionerId,
10982
+ review.practitionerReview,
10983
+ true
10984
+ )
10985
+ );
10986
+ }
10987
+ if (review.procedureReview) {
10988
+ updatePromises.push(
10989
+ this.updateProcedureReviewInfo(
10990
+ review.procedureReview.procedureId,
10991
+ review.procedureReview,
10992
+ true
10993
+ )
10994
+ );
10995
+ }
10996
+ await Promise.all(updatePromises);
10997
+ }
10998
+ /**
10999
+ * Updates the review info for a clinic
11000
+ * @param clinicId The ID of the clinic to update
11001
+ * @param newReview Optional new review being added or removed
11002
+ * @param isRemoval Whether this update is for a review removal
11003
+ * @returns The updated clinic review info
11004
+ */
11005
+ async updateClinicReviewInfo(clinicId, newReview, isRemoval = false) {
11006
+ const clinicDoc = await getDoc25(doc23(this.db, CLINICS_COLLECTION, clinicId));
11007
+ if (!clinicDoc.exists()) {
11008
+ throw new Error(`Clinic with ID ${clinicId} not found`);
11009
+ }
11010
+ const clinicData = clinicDoc.data();
11011
+ const currentReviewInfo = clinicData.reviewInfo || {
11012
+ totalReviews: 0,
11013
+ averageRating: 0,
11014
+ cleanliness: 0,
11015
+ facilities: 0,
11016
+ staffFriendliness: 0,
11017
+ waitingTime: 0,
11018
+ accessibility: 0,
11019
+ recommendationPercentage: 0
11020
+ };
11021
+ if (currentReviewInfo.totalReviews === 0 && !newReview) {
11022
+ await updateDoc24(doc23(this.db, CLINICS_COLLECTION, clinicId), {
11023
+ reviewInfo: currentReviewInfo,
11024
+ updatedAt: serverTimestamp22()
11025
+ });
11026
+ return currentReviewInfo;
11027
+ }
11028
+ let updatedReviewInfo;
11029
+ if (newReview) {
11030
+ const oldTotal = currentReviewInfo.totalReviews;
11031
+ const newTotal = isRemoval ? oldTotal - 1 : oldTotal + 1;
11032
+ if (newTotal === 0) {
11033
+ updatedReviewInfo = {
11034
+ totalReviews: 0,
11035
+ averageRating: 0,
11036
+ cleanliness: 0,
11037
+ facilities: 0,
11038
+ staffFriendliness: 0,
11039
+ waitingTime: 0,
11040
+ accessibility: 0,
11041
+ recommendationPercentage: 0
11042
+ };
11043
+ } else {
11044
+ const updateAverage = (currentAvg, newValue) => {
11045
+ const currentSum = currentAvg * oldTotal;
11046
+ const newSum = isRemoval ? currentSum - newValue : currentSum + newValue;
11047
+ const newAvg = newSum / newTotal;
11048
+ return Math.round(newAvg * 10) / 10;
11049
+ };
11050
+ const currentRecommendations = currentReviewInfo.recommendationPercentage / 100 * oldTotal;
11051
+ const newRecommendations = isRemoval ? newReview.wouldRecommend ? currentRecommendations - 1 : currentRecommendations : newReview.wouldRecommend ? currentRecommendations + 1 : currentRecommendations;
11052
+ const newRecommendationPercentage = newRecommendations / newTotal * 100;
11053
+ updatedReviewInfo = {
11054
+ totalReviews: newTotal,
11055
+ averageRating: updateAverage(
11056
+ currentReviewInfo.averageRating,
11057
+ newReview.overallRating
11058
+ ),
11059
+ cleanliness: updateAverage(
11060
+ currentReviewInfo.cleanliness,
11061
+ newReview.cleanliness
11062
+ ),
11063
+ facilities: updateAverage(
11064
+ currentReviewInfo.facilities,
11065
+ newReview.facilities
11066
+ ),
11067
+ staffFriendliness: updateAverage(
11068
+ currentReviewInfo.staffFriendliness,
11069
+ newReview.staffFriendliness
11070
+ ),
11071
+ waitingTime: updateAverage(
11072
+ currentReviewInfo.waitingTime,
11073
+ newReview.waitingTime
11074
+ ),
11075
+ accessibility: updateAverage(
11076
+ currentReviewInfo.accessibility,
11077
+ newReview.accessibility
11078
+ ),
11079
+ recommendationPercentage: Math.round(newRecommendationPercentage * 10) / 10
11080
+ };
11081
+ }
11082
+ } else {
11083
+ updatedReviewInfo = { ...currentReviewInfo };
11084
+ }
11085
+ await updateDoc24(doc23(this.db, CLINICS_COLLECTION, clinicId), {
11086
+ reviewInfo: updatedReviewInfo,
11087
+ updatedAt: serverTimestamp22()
11088
+ });
11089
+ return updatedReviewInfo;
11090
+ }
11091
+ /**
11092
+ * Updates the review info for a practitioner
11093
+ * @param practitionerId The ID of the practitioner to update
11094
+ * @param newReview Optional new review being added or removed
11095
+ * @param isRemoval Whether this update is for a review removal
11096
+ * @returns The updated practitioner review info
11097
+ */
11098
+ async updatePractitionerReviewInfo(practitionerId, newReview, isRemoval = false) {
11099
+ const practitionerDoc = await getDoc25(
11100
+ doc23(this.db, PRACTITIONERS_COLLECTION, practitionerId)
11101
+ );
11102
+ if (!practitionerDoc.exists()) {
11103
+ throw new Error(`Practitioner with ID ${practitionerId} not found`);
11104
+ }
11105
+ const practitionerData = practitionerDoc.data();
11106
+ const currentReviewInfo = practitionerData.reviewInfo || {
11107
+ totalReviews: 0,
11108
+ averageRating: 0,
11109
+ knowledgeAndExpertise: 0,
11110
+ communicationSkills: 0,
11111
+ bedSideManner: 0,
11112
+ thoroughness: 0,
11113
+ trustworthiness: 0,
11114
+ recommendationPercentage: 0
11115
+ };
11116
+ if (currentReviewInfo.totalReviews === 0 && !newReview) {
11117
+ await updateDoc24(doc23(this.db, PRACTITIONERS_COLLECTION, practitionerId), {
11118
+ reviewInfo: currentReviewInfo,
11119
+ updatedAt: serverTimestamp22()
11120
+ });
11121
+ return currentReviewInfo;
11122
+ }
11123
+ let updatedReviewInfo;
11124
+ if (newReview) {
11125
+ const oldTotal = currentReviewInfo.totalReviews;
11126
+ const newTotal = isRemoval ? oldTotal - 1 : oldTotal + 1;
11127
+ if (newTotal === 0) {
11128
+ updatedReviewInfo = {
11129
+ totalReviews: 0,
11130
+ averageRating: 0,
11131
+ knowledgeAndExpertise: 0,
11132
+ communicationSkills: 0,
11133
+ bedSideManner: 0,
11134
+ thoroughness: 0,
11135
+ trustworthiness: 0,
11136
+ recommendationPercentage: 0
11137
+ };
11138
+ } else {
11139
+ const updateAverage = (currentAvg, newValue) => {
11140
+ const currentSum = currentAvg * oldTotal;
11141
+ const newSum = isRemoval ? currentSum - newValue : currentSum + newValue;
11142
+ const newAvg = newSum / newTotal;
11143
+ return Math.round(newAvg * 10) / 10;
11144
+ };
11145
+ const currentRecommendations = currentReviewInfo.recommendationPercentage / 100 * oldTotal;
11146
+ const newRecommendations = isRemoval ? newReview.wouldRecommend ? currentRecommendations - 1 : currentRecommendations : newReview.wouldRecommend ? currentRecommendations + 1 : currentRecommendations;
11147
+ const newRecommendationPercentage = newRecommendations / newTotal * 100;
11148
+ updatedReviewInfo = {
11149
+ totalReviews: newTotal,
11150
+ averageRating: updateAverage(
11151
+ currentReviewInfo.averageRating,
11152
+ newReview.overallRating
11153
+ ),
11154
+ knowledgeAndExpertise: updateAverage(
11155
+ currentReviewInfo.knowledgeAndExpertise,
11156
+ newReview.knowledgeAndExpertise
11157
+ ),
11158
+ communicationSkills: updateAverage(
11159
+ currentReviewInfo.communicationSkills,
11160
+ newReview.communicationSkills
11161
+ ),
11162
+ bedSideManner: updateAverage(
11163
+ currentReviewInfo.bedSideManner,
11164
+ newReview.bedSideManner
11165
+ ),
11166
+ thoroughness: updateAverage(
11167
+ currentReviewInfo.thoroughness,
11168
+ newReview.thoroughness
11169
+ ),
11170
+ trustworthiness: updateAverage(
11171
+ currentReviewInfo.trustworthiness,
11172
+ newReview.trustworthiness
11173
+ ),
11174
+ recommendationPercentage: Math.round(newRecommendationPercentage * 10) / 10
11175
+ };
11176
+ }
11177
+ } else {
11178
+ updatedReviewInfo = { ...currentReviewInfo };
11179
+ }
11180
+ await updateDoc24(doc23(this.db, PRACTITIONERS_COLLECTION, practitionerId), {
11181
+ reviewInfo: updatedReviewInfo,
11182
+ updatedAt: serverTimestamp22()
11183
+ });
11184
+ await this.updateDoctorInfoInProcedures(
11185
+ practitionerId,
11186
+ updatedReviewInfo.averageRating
11187
+ );
11188
+ return updatedReviewInfo;
11189
+ }
11190
+ /**
11191
+ * Updates the review info for a procedure
11192
+ * @param procedureId The ID of the procedure to update
11193
+ * @param newReview Optional new review being added or removed
11194
+ * @param isRemoval Whether this update is for a review removal
11195
+ * @returns The updated procedure review info
11196
+ */
11197
+ async updateProcedureReviewInfo(procedureId, newReview, isRemoval = false) {
11198
+ const procedureDoc = await getDoc25(
11199
+ doc23(this.db, PROCEDURES_COLLECTION, procedureId)
11200
+ );
11201
+ if (!procedureDoc.exists()) {
11202
+ throw new Error(`Procedure with ID ${procedureId} not found`);
11203
+ }
11204
+ const procedureData = procedureDoc.data();
11205
+ const currentReviewInfo = procedureData.reviewInfo || {
11206
+ totalReviews: 0,
11207
+ averageRating: 0,
11208
+ effectivenessOfTreatment: 0,
11209
+ outcomeExplanation: 0,
11210
+ painManagement: 0,
11211
+ followUpCare: 0,
11212
+ valueForMoney: 0,
11213
+ recommendationPercentage: 0
11214
+ };
11215
+ if (currentReviewInfo.totalReviews === 0 && !newReview) {
11216
+ await updateDoc24(doc23(this.db, PROCEDURES_COLLECTION, procedureId), {
11217
+ reviewInfo: currentReviewInfo,
11218
+ updatedAt: serverTimestamp22()
11219
+ });
11220
+ return currentReviewInfo;
11221
+ }
11222
+ let updatedReviewInfo;
11223
+ if (newReview) {
11224
+ const oldTotal = currentReviewInfo.totalReviews;
11225
+ const newTotal = isRemoval ? oldTotal - 1 : oldTotal + 1;
11226
+ if (newTotal === 0) {
11227
+ updatedReviewInfo = {
11228
+ totalReviews: 0,
11229
+ averageRating: 0,
11230
+ effectivenessOfTreatment: 0,
11231
+ outcomeExplanation: 0,
11232
+ painManagement: 0,
11233
+ followUpCare: 0,
11234
+ valueForMoney: 0,
11235
+ recommendationPercentage: 0
11236
+ };
11237
+ } else {
11238
+ const updateAverage = (currentAvg, newValue) => {
11239
+ const currentSum = currentAvg * oldTotal;
11240
+ const newSum = isRemoval ? currentSum - newValue : currentSum + newValue;
11241
+ const newAvg = newSum / newTotal;
11242
+ return Math.round(newAvg * 10) / 10;
11243
+ };
11244
+ const currentRecommendations = currentReviewInfo.recommendationPercentage / 100 * oldTotal;
11245
+ const newRecommendations = isRemoval ? newReview.wouldRecommend ? currentRecommendations - 1 : currentRecommendations : newReview.wouldRecommend ? currentRecommendations + 1 : currentRecommendations;
11246
+ const newRecommendationPercentage = newRecommendations / newTotal * 100;
11247
+ updatedReviewInfo = {
11248
+ totalReviews: newTotal,
11249
+ averageRating: updateAverage(
11250
+ currentReviewInfo.averageRating,
11251
+ newReview.overallRating
11252
+ ),
11253
+ effectivenessOfTreatment: updateAverage(
11254
+ currentReviewInfo.effectivenessOfTreatment,
11255
+ newReview.effectivenessOfTreatment
11256
+ ),
11257
+ outcomeExplanation: updateAverage(
11258
+ currentReviewInfo.outcomeExplanation,
11259
+ newReview.outcomeExplanation
11260
+ ),
11261
+ painManagement: updateAverage(
11262
+ currentReviewInfo.painManagement,
11263
+ newReview.painManagement
11264
+ ),
11265
+ followUpCare: updateAverage(
11266
+ currentReviewInfo.followUpCare,
11267
+ newReview.followUpCare
11268
+ ),
11269
+ valueForMoney: updateAverage(
11270
+ currentReviewInfo.valueForMoney,
11271
+ newReview.valueForMoney
11272
+ ),
11273
+ recommendationPercentage: Math.round(newRecommendationPercentage * 10) / 10
11274
+ };
11275
+ }
11276
+ } else {
11277
+ updatedReviewInfo = { ...currentReviewInfo };
11278
+ }
11279
+ await updateDoc24(doc23(this.db, PROCEDURES_COLLECTION, procedureId), {
11280
+ reviewInfo: updatedReviewInfo,
11281
+ updatedAt: serverTimestamp22()
11282
+ });
11283
+ return updatedReviewInfo;
11284
+ }
11285
+ /**
11286
+ * Updates doctorInfo rating in all procedures for a practitioner
11287
+ * @param practitionerId The ID of the practitioner
11288
+ * @param rating The new rating to set
11289
+ */
11290
+ async updateDoctorInfoInProcedures(practitionerId, rating) {
11291
+ const q = query22(
11292
+ collection22(this.db, PROCEDURES_COLLECTION),
11293
+ where22("practitionerId", "==", practitionerId)
11294
+ );
11295
+ const snapshot = await getDocs22(q);
11296
+ if (snapshot.empty) {
11297
+ return;
11298
+ }
11299
+ const batch = writeBatch7(this.db);
11300
+ snapshot.docs.forEach((docSnapshot) => {
11301
+ const procedureRef = doc23(this.db, PROCEDURES_COLLECTION, docSnapshot.id);
11302
+ batch.update(procedureRef, {
11303
+ "doctorInfo.rating": rating,
11304
+ updatedAt: serverTimestamp22()
11305
+ });
11306
+ });
11307
+ await batch.commit();
11308
+ }
11309
+ /**
11310
+ * Verifies a review as checked by admin/staff
11311
+ * @param reviewId The ID of the review to verify
11312
+ */
11313
+ async verifyReview(reviewId) {
11314
+ const review = await this.getReview(reviewId);
11315
+ if (!review) {
11316
+ throw new Error(`Review with ID ${reviewId} not found`);
11317
+ }
11318
+ const batch = writeBatch7(this.db);
11319
+ batch.update(doc23(this.db, REVIEWS_COLLECTION, reviewId), {
11320
+ updatedAt: serverTimestamp22()
11321
+ });
11322
+ if (review.clinicReview) {
11323
+ review.clinicReview.isVerified = true;
11324
+ }
11325
+ if (review.practitionerReview) {
11326
+ review.practitionerReview.isVerified = true;
11327
+ }
11328
+ if (review.procedureReview) {
11329
+ review.procedureReview.isVerified = true;
11330
+ }
11331
+ await batch.commit();
11332
+ const updatePromises = [];
11333
+ if (review.clinicReview) {
11334
+ updatePromises.push(
11335
+ this.updateClinicReviewInfo(review.clinicReview.clinicId)
11336
+ );
11337
+ }
11338
+ if (review.practitionerReview) {
11339
+ updatePromises.push(
11340
+ this.updatePractitionerReviewInfo(
11341
+ review.practitionerReview.practitionerId
11342
+ )
11343
+ );
11344
+ }
11345
+ if (review.procedureReview) {
11346
+ updatePromises.push(
11347
+ this.updateProcedureReviewInfo(review.procedureReview.procedureId)
11348
+ );
11349
+ }
11350
+ await Promise.all(updatePromises);
11351
+ }
11352
+ /**
11353
+ * Calculates the average of an array of numbers
11354
+ * @param numbers Array of numbers to average
11355
+ * @returns The average, or 0 if the array is empty
11356
+ */
11357
+ calculateAverage(numbers) {
11358
+ if (numbers.length === 0) {
11359
+ return 0;
11360
+ }
11361
+ const sum = numbers.reduce((a, b) => a + b, 0);
11362
+ const avg = sum / numbers.length;
11363
+ return Math.round(avg * 10) / 10;
11364
+ }
11365
+ };
11366
+
11367
+ // src/backoffice/services/brand.service.ts
11368
+ import {
11369
+ addDoc as addDoc3,
11370
+ collection as collection23,
11371
+ doc as doc24,
11372
+ getDoc as getDoc26,
11373
+ getDocs as getDocs23,
11374
+ query as query23,
11375
+ updateDoc as updateDoc25,
11376
+ where as where23
10722
11377
  } from "firebase/firestore";
10723
11378
 
10724
11379
  // src/backoffice/types/brand.types.ts
@@ -10730,7 +11385,7 @@ var BrandService = class extends BaseService {
10730
11385
  * Gets reference to brands collection
10731
11386
  */
10732
11387
  getBrandsRef() {
10733
- return collection22(this.db, BRANDS_COLLECTION);
11388
+ return collection23(this.db, BRANDS_COLLECTION);
10734
11389
  }
10735
11390
  /**
10736
11391
  * Creates a new brand
@@ -10750,12 +11405,12 @@ var BrandService = class extends BaseService {
10750
11405
  * Gets all active brands
10751
11406
  */
10752
11407
  async getAll() {
10753
- const q = query22(this.getBrandsRef(), where22("isActive", "==", true));
10754
- const snapshot = await getDocs22(q);
11408
+ const q = query23(this.getBrandsRef(), where23("isActive", "==", true));
11409
+ const snapshot = await getDocs23(q);
10755
11410
  return snapshot.docs.map(
10756
- (doc28) => ({
10757
- id: doc28.id,
10758
- ...doc28.data()
11411
+ (doc29) => ({
11412
+ id: doc29.id,
11413
+ ...doc29.data()
10759
11414
  })
10760
11415
  );
10761
11416
  }
@@ -10767,8 +11422,8 @@ var BrandService = class extends BaseService {
10767
11422
  ...brand,
10768
11423
  updatedAt: /* @__PURE__ */ new Date()
10769
11424
  };
10770
- const docRef = doc23(this.getBrandsRef(), brandId);
10771
- await updateDoc24(docRef, updateData);
11425
+ const docRef = doc24(this.getBrandsRef(), brandId);
11426
+ await updateDoc25(docRef, updateData);
10772
11427
  return this.getById(brandId);
10773
11428
  }
10774
11429
  /**
@@ -10783,8 +11438,8 @@ var BrandService = class extends BaseService {
10783
11438
  * Gets a brand by ID
10784
11439
  */
10785
11440
  async getById(brandId) {
10786
- const docRef = doc23(this.getBrandsRef(), brandId);
10787
- const docSnap = await getDoc25(docRef);
11441
+ const docRef = doc24(this.getBrandsRef(), brandId);
11442
+ const docSnap = await getDoc26(docRef);
10788
11443
  if (!docSnap.exists()) return null;
10789
11444
  return {
10790
11445
  id: docSnap.id,
@@ -10796,13 +11451,13 @@ var BrandService = class extends BaseService {
10796
11451
  // src/backoffice/services/category.service.ts
10797
11452
  import {
10798
11453
  addDoc as addDoc4,
10799
- collection as collection23,
10800
- doc as doc24,
10801
- getDoc as getDoc26,
10802
- getDocs as getDocs23,
10803
- query as query23,
10804
- updateDoc as updateDoc25,
10805
- where as where23
11454
+ collection as collection24,
11455
+ doc as doc25,
11456
+ getDoc as getDoc27,
11457
+ getDocs as getDocs24,
11458
+ query as query24,
11459
+ updateDoc as updateDoc26,
11460
+ where as where24
10806
11461
  } from "firebase/firestore";
10807
11462
 
10808
11463
  // src/backoffice/types/category.types.ts
@@ -10814,7 +11469,7 @@ var CategoryService = class extends BaseService {
10814
11469
  * Referenca na Firestore kolekciju kategorija
10815
11470
  */
10816
11471
  get categoriesRef() {
10817
- return collection23(this.db, CATEGORIES_COLLECTION);
11472
+ return collection24(this.db, CATEGORIES_COLLECTION);
10818
11473
  }
10819
11474
  /**
10820
11475
  * Kreira novu kategoriju u sistemu
@@ -10837,12 +11492,12 @@ var CategoryService = class extends BaseService {
10837
11492
  * @returns Lista aktivnih kategorija
10838
11493
  */
10839
11494
  async getAll() {
10840
- const q = query23(this.categoriesRef, where23("isActive", "==", true));
10841
- const snapshot = await getDocs23(q);
11495
+ const q = query24(this.categoriesRef, where24("isActive", "==", true));
11496
+ const snapshot = await getDocs24(q);
10842
11497
  return snapshot.docs.map(
10843
- (doc28) => ({
10844
- id: doc28.id,
10845
- ...doc28.data()
11498
+ (doc29) => ({
11499
+ id: doc29.id,
11500
+ ...doc29.data()
10846
11501
  })
10847
11502
  );
10848
11503
  }
@@ -10852,16 +11507,16 @@ var CategoryService = class extends BaseService {
10852
11507
  * @returns Lista kategorija koje pripadaju traženoj familiji
10853
11508
  */
10854
11509
  async getAllByFamily(family) {
10855
- const q = query23(
11510
+ const q = query24(
10856
11511
  this.categoriesRef,
10857
- where23("family", "==", family),
10858
- where23("isActive", "==", true)
11512
+ where24("family", "==", family),
11513
+ where24("isActive", "==", true)
10859
11514
  );
10860
- const snapshot = await getDocs23(q);
11515
+ const snapshot = await getDocs24(q);
10861
11516
  return snapshot.docs.map(
10862
- (doc28) => ({
10863
- id: doc28.id,
10864
- ...doc28.data()
11517
+ (doc29) => ({
11518
+ id: doc29.id,
11519
+ ...doc29.data()
10865
11520
  })
10866
11521
  );
10867
11522
  }
@@ -10876,8 +11531,8 @@ var CategoryService = class extends BaseService {
10876
11531
  ...category,
10877
11532
  updatedAt: /* @__PURE__ */ new Date()
10878
11533
  };
10879
- const docRef = doc24(this.categoriesRef, id);
10880
- await updateDoc25(docRef, updateData);
11534
+ const docRef = doc25(this.categoriesRef, id);
11535
+ await updateDoc26(docRef, updateData);
10881
11536
  return this.getById(id);
10882
11537
  }
10883
11538
  /**
@@ -10893,8 +11548,8 @@ var CategoryService = class extends BaseService {
10893
11548
  * @returns Kategorija ili null ako ne postoji
10894
11549
  */
10895
11550
  async getById(id) {
10896
- const docRef = doc24(this.categoriesRef, id);
10897
- const docSnap = await getDoc26(docRef);
11551
+ const docRef = doc25(this.categoriesRef, id);
11552
+ const docSnap = await getDoc27(docRef);
10898
11553
  if (!docSnap.exists()) return null;
10899
11554
  return {
10900
11555
  id: docSnap.id,
@@ -10906,13 +11561,13 @@ var CategoryService = class extends BaseService {
10906
11561
  // src/backoffice/services/subcategory.service.ts
10907
11562
  import {
10908
11563
  addDoc as addDoc5,
10909
- collection as collection24,
10910
- doc as doc25,
10911
- getDoc as getDoc27,
10912
- getDocs as getDocs24,
10913
- query as query24,
10914
- updateDoc as updateDoc26,
10915
- where as where24
11564
+ collection as collection25,
11565
+ doc as doc26,
11566
+ getDoc as getDoc28,
11567
+ getDocs as getDocs25,
11568
+ query as query25,
11569
+ updateDoc as updateDoc27,
11570
+ where as where25
10916
11571
  } from "firebase/firestore";
10917
11572
 
10918
11573
  // src/backoffice/types/subcategory.types.ts
@@ -10925,7 +11580,7 @@ var SubcategoryService = class extends BaseService {
10925
11580
  * @param categoryId - ID roditeljske kategorije
10926
11581
  */
10927
11582
  getSubcategoriesRef(categoryId) {
10928
- return collection24(
11583
+ return collection25(
10929
11584
  this.db,
10930
11585
  CATEGORIES_COLLECTION,
10931
11586
  categoryId,
@@ -10959,15 +11614,15 @@ var SubcategoryService = class extends BaseService {
10959
11614
  * @returns Lista aktivnih podkategorija
10960
11615
  */
10961
11616
  async getAllByCategoryId(categoryId) {
10962
- const q = query24(
11617
+ const q = query25(
10963
11618
  this.getSubcategoriesRef(categoryId),
10964
- where24("isActive", "==", true)
11619
+ where25("isActive", "==", true)
10965
11620
  );
10966
- const snapshot = await getDocs24(q);
11621
+ const snapshot = await getDocs25(q);
10967
11622
  return snapshot.docs.map(
10968
- (doc28) => ({
10969
- id: doc28.id,
10970
- ...doc28.data()
11623
+ (doc29) => ({
11624
+ id: doc29.id,
11625
+ ...doc29.data()
10971
11626
  })
10972
11627
  );
10973
11628
  }
@@ -10983,8 +11638,8 @@ var SubcategoryService = class extends BaseService {
10983
11638
  ...subcategory,
10984
11639
  updatedAt: /* @__PURE__ */ new Date()
10985
11640
  };
10986
- const docRef = doc25(this.getSubcategoriesRef(categoryId), subcategoryId);
10987
- await updateDoc26(docRef, updateData);
11641
+ const docRef = doc26(this.getSubcategoriesRef(categoryId), subcategoryId);
11642
+ await updateDoc27(docRef, updateData);
10988
11643
  return this.getById(categoryId, subcategoryId);
10989
11644
  }
10990
11645
  /**
@@ -11002,8 +11657,8 @@ var SubcategoryService = class extends BaseService {
11002
11657
  * @returns Podkategorija ili null ako ne postoji
11003
11658
  */
11004
11659
  async getById(categoryId, subcategoryId) {
11005
- const docRef = doc25(this.getSubcategoriesRef(categoryId), subcategoryId);
11006
- const docSnap = await getDoc27(docRef);
11660
+ const docRef = doc26(this.getSubcategoriesRef(categoryId), subcategoryId);
11661
+ const docSnap = await getDoc28(docRef);
11007
11662
  if (!docSnap.exists()) return null;
11008
11663
  return {
11009
11664
  id: docSnap.id,
@@ -11015,13 +11670,13 @@ var SubcategoryService = class extends BaseService {
11015
11670
  // src/backoffice/services/technology.service.ts
11016
11671
  import {
11017
11672
  addDoc as addDoc6,
11018
- collection as collection25,
11019
- doc as doc26,
11020
- getDoc as getDoc28,
11021
- getDocs as getDocs25,
11022
- query as query25,
11023
- updateDoc as updateDoc27,
11024
- where as where25,
11673
+ collection as collection26,
11674
+ doc as doc27,
11675
+ getDoc as getDoc29,
11676
+ getDocs as getDocs26,
11677
+ query as query26,
11678
+ updateDoc as updateDoc28,
11679
+ where as where26,
11025
11680
  arrayUnion as arrayUnion8,
11026
11681
  arrayRemove as arrayRemove7
11027
11682
  } from "firebase/firestore";
@@ -11039,7 +11694,7 @@ var TechnologyService = class extends BaseService {
11039
11694
  * Vraća referencu na Firestore kolekciju tehnologija
11040
11695
  */
11041
11696
  getTechnologiesRef() {
11042
- return collection25(this.db, TECHNOLOGIES_COLLECTION);
11697
+ return collection26(this.db, TECHNOLOGIES_COLLECTION);
11043
11698
  }
11044
11699
  /**
11045
11700
  * Kreira novu tehnologiju
@@ -11070,12 +11725,12 @@ var TechnologyService = class extends BaseService {
11070
11725
  * @returns Lista aktivnih tehnologija
11071
11726
  */
11072
11727
  async getAll() {
11073
- const q = query25(this.getTechnologiesRef(), where25("isActive", "==", true));
11074
- const snapshot = await getDocs25(q);
11728
+ const q = query26(this.getTechnologiesRef(), where26("isActive", "==", true));
11729
+ const snapshot = await getDocs26(q);
11075
11730
  return snapshot.docs.map(
11076
- (doc28) => ({
11077
- id: doc28.id,
11078
- ...doc28.data()
11731
+ (doc29) => ({
11732
+ id: doc29.id,
11733
+ ...doc29.data()
11079
11734
  })
11080
11735
  );
11081
11736
  }
@@ -11085,16 +11740,16 @@ var TechnologyService = class extends BaseService {
11085
11740
  * @returns Lista aktivnih tehnologija
11086
11741
  */
11087
11742
  async getAllByFamily(family) {
11088
- const q = query25(
11743
+ const q = query26(
11089
11744
  this.getTechnologiesRef(),
11090
- where25("isActive", "==", true),
11091
- where25("family", "==", family)
11745
+ where26("isActive", "==", true),
11746
+ where26("family", "==", family)
11092
11747
  );
11093
- const snapshot = await getDocs25(q);
11748
+ const snapshot = await getDocs26(q);
11094
11749
  return snapshot.docs.map(
11095
- (doc28) => ({
11096
- id: doc28.id,
11097
- ...doc28.data()
11750
+ (doc29) => ({
11751
+ id: doc29.id,
11752
+ ...doc29.data()
11098
11753
  })
11099
11754
  );
11100
11755
  }
@@ -11104,16 +11759,16 @@ var TechnologyService = class extends BaseService {
11104
11759
  * @returns Lista aktivnih tehnologija
11105
11760
  */
11106
11761
  async getAllByCategoryId(categoryId) {
11107
- const q = query25(
11762
+ const q = query26(
11108
11763
  this.getTechnologiesRef(),
11109
- where25("isActive", "==", true),
11110
- where25("categoryId", "==", categoryId)
11764
+ where26("isActive", "==", true),
11765
+ where26("categoryId", "==", categoryId)
11111
11766
  );
11112
- const snapshot = await getDocs25(q);
11767
+ const snapshot = await getDocs26(q);
11113
11768
  return snapshot.docs.map(
11114
- (doc28) => ({
11115
- id: doc28.id,
11116
- ...doc28.data()
11769
+ (doc29) => ({
11770
+ id: doc29.id,
11771
+ ...doc29.data()
11117
11772
  })
11118
11773
  );
11119
11774
  }
@@ -11123,16 +11778,16 @@ var TechnologyService = class extends BaseService {
11123
11778
  * @returns Lista aktivnih tehnologija
11124
11779
  */
11125
11780
  async getAllBySubcategoryId(subcategoryId) {
11126
- const q = query25(
11781
+ const q = query26(
11127
11782
  this.getTechnologiesRef(),
11128
- where25("isActive", "==", true),
11129
- where25("subcategoryId", "==", subcategoryId)
11783
+ where26("isActive", "==", true),
11784
+ where26("subcategoryId", "==", subcategoryId)
11130
11785
  );
11131
- const snapshot = await getDocs25(q);
11786
+ const snapshot = await getDocs26(q);
11132
11787
  return snapshot.docs.map(
11133
- (doc28) => ({
11134
- id: doc28.id,
11135
- ...doc28.data()
11788
+ (doc29) => ({
11789
+ id: doc29.id,
11790
+ ...doc29.data()
11136
11791
  })
11137
11792
  );
11138
11793
  }
@@ -11147,8 +11802,8 @@ var TechnologyService = class extends BaseService {
11147
11802
  ...technology,
11148
11803
  updatedAt: /* @__PURE__ */ new Date()
11149
11804
  };
11150
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11151
- await updateDoc27(docRef, updateData);
11805
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11806
+ await updateDoc28(docRef, updateData);
11152
11807
  return this.getById(technologyId);
11153
11808
  }
11154
11809
  /**
@@ -11166,8 +11821,8 @@ var TechnologyService = class extends BaseService {
11166
11821
  * @returns Tehnologija ili null ako ne postoji
11167
11822
  */
11168
11823
  async getById(technologyId) {
11169
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11170
- const docSnap = await getDoc28(docRef);
11824
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11825
+ const docSnap = await getDoc29(docRef);
11171
11826
  if (!docSnap.exists()) return null;
11172
11827
  return {
11173
11828
  id: docSnap.id,
@@ -11181,9 +11836,9 @@ var TechnologyService = class extends BaseService {
11181
11836
  * @returns Ažurirana tehnologija sa novim zahtevom
11182
11837
  */
11183
11838
  async addRequirement(technologyId, requirement) {
11184
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11839
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11185
11840
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
11186
- await updateDoc27(docRef, {
11841
+ await updateDoc28(docRef, {
11187
11842
  [requirementType]: arrayUnion8(requirement),
11188
11843
  updatedAt: /* @__PURE__ */ new Date()
11189
11844
  });
@@ -11196,9 +11851,9 @@ var TechnologyService = class extends BaseService {
11196
11851
  * @returns Ažurirana tehnologija bez uklonjenog zahteva
11197
11852
  */
11198
11853
  async removeRequirement(technologyId, requirement) {
11199
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11854
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11200
11855
  const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
11201
- await updateDoc27(docRef, {
11856
+ await updateDoc28(docRef, {
11202
11857
  [requirementType]: arrayRemove7(requirement),
11203
11858
  updatedAt: /* @__PURE__ */ new Date()
11204
11859
  });
@@ -11236,8 +11891,8 @@ var TechnologyService = class extends BaseService {
11236
11891
  * @returns Ažurirana tehnologija
11237
11892
  */
11238
11893
  async addBlockingCondition(technologyId, condition) {
11239
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11240
- await updateDoc27(docRef, {
11894
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11895
+ await updateDoc28(docRef, {
11241
11896
  blockingConditions: arrayUnion8(condition),
11242
11897
  updatedAt: /* @__PURE__ */ new Date()
11243
11898
  });
@@ -11250,8 +11905,8 @@ var TechnologyService = class extends BaseService {
11250
11905
  * @returns Ažurirana tehnologija
11251
11906
  */
11252
11907
  async removeBlockingCondition(technologyId, condition) {
11253
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11254
- await updateDoc27(docRef, {
11908
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11909
+ await updateDoc28(docRef, {
11255
11910
  blockingConditions: arrayRemove7(condition),
11256
11911
  updatedAt: /* @__PURE__ */ new Date()
11257
11912
  });
@@ -11264,8 +11919,8 @@ var TechnologyService = class extends BaseService {
11264
11919
  * @returns Ažurirana tehnologija
11265
11920
  */
11266
11921
  async addContraindication(technologyId, contraindication) {
11267
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11268
- await updateDoc27(docRef, {
11922
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11923
+ await updateDoc28(docRef, {
11269
11924
  contraindications: arrayUnion8(contraindication),
11270
11925
  updatedAt: /* @__PURE__ */ new Date()
11271
11926
  });
@@ -11278,8 +11933,8 @@ var TechnologyService = class extends BaseService {
11278
11933
  * @returns Ažurirana tehnologija
11279
11934
  */
11280
11935
  async removeContraindication(technologyId, contraindication) {
11281
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11282
- await updateDoc27(docRef, {
11936
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11937
+ await updateDoc28(docRef, {
11283
11938
  contraindications: arrayRemove7(contraindication),
11284
11939
  updatedAt: /* @__PURE__ */ new Date()
11285
11940
  });
@@ -11292,8 +11947,8 @@ var TechnologyService = class extends BaseService {
11292
11947
  * @returns Ažurirana tehnologija
11293
11948
  */
11294
11949
  async addBenefit(technologyId, benefit) {
11295
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11296
- await updateDoc27(docRef, {
11950
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11951
+ await updateDoc28(docRef, {
11297
11952
  benefits: arrayUnion8(benefit),
11298
11953
  updatedAt: /* @__PURE__ */ new Date()
11299
11954
  });
@@ -11306,8 +11961,8 @@ var TechnologyService = class extends BaseService {
11306
11961
  * @returns Ažurirana tehnologija
11307
11962
  */
11308
11963
  async removeBenefit(technologyId, benefit) {
11309
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11310
- await updateDoc27(docRef, {
11964
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
11965
+ await updateDoc28(docRef, {
11311
11966
  benefits: arrayRemove7(benefit),
11312
11967
  updatedAt: /* @__PURE__ */ new Date()
11313
11968
  });
@@ -11347,8 +12002,8 @@ var TechnologyService = class extends BaseService {
11347
12002
  * @returns Ažurirana tehnologija
11348
12003
  */
11349
12004
  async updateCertificationRequirement(technologyId, certificationRequirement) {
11350
- const docRef = doc26(this.getTechnologiesRef(), technologyId);
11351
- await updateDoc27(docRef, {
12005
+ const docRef = doc27(this.getTechnologiesRef(), technologyId);
12006
+ await updateDoc28(docRef, {
11352
12007
  certificationRequirement,
11353
12008
  updatedAt: /* @__PURE__ */ new Date()
11354
12009
  });
@@ -11450,13 +12105,13 @@ var TechnologyService = class extends BaseService {
11450
12105
  // src/backoffice/services/product.service.ts
11451
12106
  import {
11452
12107
  addDoc as addDoc7,
11453
- collection as collection26,
11454
- doc as doc27,
11455
- getDoc as getDoc29,
11456
- getDocs as getDocs26,
11457
- query as query26,
11458
- updateDoc as updateDoc28,
11459
- where as where26
12108
+ collection as collection27,
12109
+ doc as doc28,
12110
+ getDoc as getDoc30,
12111
+ getDocs as getDocs27,
12112
+ query as query27,
12113
+ updateDoc as updateDoc29,
12114
+ where as where27
11460
12115
  } from "firebase/firestore";
11461
12116
 
11462
12117
  // src/backoffice/types/product.types.ts
@@ -11470,7 +12125,7 @@ var ProductService = class extends BaseService {
11470
12125
  * @returns Firestore collection reference
11471
12126
  */
11472
12127
  getProductsRef(technologyId) {
11473
- return collection26(
12128
+ return collection27(
11474
12129
  this.db,
11475
12130
  TECHNOLOGIES_COLLECTION,
11476
12131
  technologyId,
@@ -11500,15 +12155,15 @@ var ProductService = class extends BaseService {
11500
12155
  * Gets all products for a technology
11501
12156
  */
11502
12157
  async getAllByTechnology(technologyId) {
11503
- const q = query26(
12158
+ const q = query27(
11504
12159
  this.getProductsRef(technologyId),
11505
- where26("isActive", "==", true)
12160
+ where27("isActive", "==", true)
11506
12161
  );
11507
- const snapshot = await getDocs26(q);
12162
+ const snapshot = await getDocs27(q);
11508
12163
  return snapshot.docs.map(
11509
- (doc28) => ({
11510
- id: doc28.id,
11511
- ...doc28.data()
12164
+ (doc29) => ({
12165
+ id: doc29.id,
12166
+ ...doc29.data()
11512
12167
  })
11513
12168
  );
11514
12169
  }
@@ -11516,21 +12171,21 @@ var ProductService = class extends BaseService {
11516
12171
  * Gets all products for a brand by filtering through all technologies
11517
12172
  */
11518
12173
  async getAllByBrand(brandId) {
11519
- const allTechnologiesRef = collection26(this.db, TECHNOLOGIES_COLLECTION);
11520
- const technologiesSnapshot = await getDocs26(allTechnologiesRef);
12174
+ const allTechnologiesRef = collection27(this.db, TECHNOLOGIES_COLLECTION);
12175
+ const technologiesSnapshot = await getDocs27(allTechnologiesRef);
11521
12176
  const products = [];
11522
12177
  for (const techDoc of technologiesSnapshot.docs) {
11523
- const q = query26(
12178
+ const q = query27(
11524
12179
  this.getProductsRef(techDoc.id),
11525
- where26("brandId", "==", brandId),
11526
- where26("isActive", "==", true)
12180
+ where27("brandId", "==", brandId),
12181
+ where27("isActive", "==", true)
11527
12182
  );
11528
- const snapshot = await getDocs26(q);
12183
+ const snapshot = await getDocs27(q);
11529
12184
  products.push(
11530
12185
  ...snapshot.docs.map(
11531
- (doc28) => ({
11532
- id: doc28.id,
11533
- ...doc28.data()
12186
+ (doc29) => ({
12187
+ id: doc29.id,
12188
+ ...doc29.data()
11534
12189
  })
11535
12190
  )
11536
12191
  );
@@ -11545,8 +12200,8 @@ var ProductService = class extends BaseService {
11545
12200
  ...product,
11546
12201
  updatedAt: /* @__PURE__ */ new Date()
11547
12202
  };
11548
- const docRef = doc27(this.getProductsRef(technologyId), productId);
11549
- await updateDoc28(docRef, updateData);
12203
+ const docRef = doc28(this.getProductsRef(technologyId), productId);
12204
+ await updateDoc29(docRef, updateData);
11550
12205
  return this.getById(technologyId, productId);
11551
12206
  }
11552
12207
  /**
@@ -11561,8 +12216,8 @@ var ProductService = class extends BaseService {
11561
12216
  * Gets a product by ID
11562
12217
  */
11563
12218
  async getById(technologyId, productId) {
11564
- const docRef = doc27(this.getProductsRef(technologyId), productId);
11565
- const docSnap = await getDoc29(docRef);
12219
+ const docRef = doc28(this.getProductsRef(technologyId), productId);
12220
+ const docSnap = await getDoc30(docRef);
11566
12221
  if (!docSnap.exists()) return null;
11567
12222
  return {
11568
12223
  id: docSnap.id,
@@ -11572,54 +12227,54 @@ var ProductService = class extends BaseService {
11572
12227
  };
11573
12228
 
11574
12229
  // src/validations/notification.schema.ts
11575
- import { z as z21 } from "zod";
11576
- var baseNotificationSchema = z21.object({
11577
- id: z21.string().optional(),
11578
- userId: z21.string(),
11579
- notificationTime: z21.any(),
12230
+ import { z as z22 } from "zod";
12231
+ var baseNotificationSchema = z22.object({
12232
+ id: z22.string().optional(),
12233
+ userId: z22.string(),
12234
+ notificationTime: z22.any(),
11580
12235
  // Timestamp
11581
- notificationType: z21.nativeEnum(NotificationType),
11582
- notificationTokens: z21.array(z21.string()),
11583
- status: z21.nativeEnum(NotificationStatus),
11584
- createdAt: z21.any().optional(),
12236
+ notificationType: z22.nativeEnum(NotificationType),
12237
+ notificationTokens: z22.array(z22.string()),
12238
+ status: z22.nativeEnum(NotificationStatus),
12239
+ createdAt: z22.any().optional(),
11585
12240
  // Timestamp
11586
- updatedAt: z21.any().optional(),
12241
+ updatedAt: z22.any().optional(),
11587
12242
  // Timestamp
11588
- title: z21.string(),
11589
- body: z21.string(),
11590
- isRead: z21.boolean(),
11591
- userRole: z21.nativeEnum(UserRole)
12243
+ title: z22.string(),
12244
+ body: z22.string(),
12245
+ isRead: z22.boolean(),
12246
+ userRole: z22.nativeEnum(UserRole)
11592
12247
  });
11593
12248
  var preRequirementNotificationSchema = baseNotificationSchema.extend({
11594
- notificationType: z21.literal("preRequirement" /* PRE_REQUIREMENT */),
11595
- treatmentId: z21.string(),
11596
- requirements: z21.array(z21.string()),
11597
- deadline: z21.any()
12249
+ notificationType: z22.literal("preRequirement" /* PRE_REQUIREMENT */),
12250
+ treatmentId: z22.string(),
12251
+ requirements: z22.array(z22.string()),
12252
+ deadline: z22.any()
11598
12253
  // Timestamp
11599
12254
  });
11600
12255
  var postRequirementNotificationSchema = baseNotificationSchema.extend({
11601
- notificationType: z21.literal("postRequirement" /* POST_REQUIREMENT */),
11602
- treatmentId: z21.string(),
11603
- requirements: z21.array(z21.string()),
11604
- deadline: z21.any()
12256
+ notificationType: z22.literal("postRequirement" /* POST_REQUIREMENT */),
12257
+ treatmentId: z22.string(),
12258
+ requirements: z22.array(z22.string()),
12259
+ deadline: z22.any()
11605
12260
  // Timestamp
11606
12261
  });
11607
12262
  var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
11608
- notificationType: z21.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
11609
- appointmentId: z21.string(),
11610
- appointmentTime: z21.any(),
12263
+ notificationType: z22.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
12264
+ appointmentId: z22.string(),
12265
+ appointmentTime: z22.any(),
11611
12266
  // Timestamp
11612
- treatmentType: z21.string(),
11613
- doctorName: z21.string()
12267
+ treatmentType: z22.string(),
12268
+ doctorName: z22.string()
11614
12269
  });
11615
12270
  var appointmentNotificationSchema = baseNotificationSchema.extend({
11616
- notificationType: z21.literal("appointmentNotification" /* APPOINTMENT_NOTIFICATION */),
11617
- appointmentId: z21.string(),
11618
- appointmentStatus: z21.string(),
11619
- previousStatus: z21.string(),
11620
- reason: z21.string().optional()
12271
+ notificationType: z22.literal("appointmentNotification" /* APPOINTMENT_NOTIFICATION */),
12272
+ appointmentId: z22.string(),
12273
+ appointmentStatus: z22.string(),
12274
+ previousStatus: z22.string(),
12275
+ reason: z22.string().optional()
11621
12276
  });
11622
- var notificationSchema = z21.discriminatedUnion("notificationType", [
12277
+ var notificationSchema = z22.discriminatedUnion("notificationType", [
11623
12278
  preRequirementNotificationSchema,
11624
12279
  postRequirementNotificationSchema,
11625
12280
  appointmentReminderNotificationSchema,
@@ -11646,8 +12301,17 @@ var TreatmentBenefit = /* @__PURE__ */ ((TreatmentBenefit2) => {
11646
12301
  return TreatmentBenefit2;
11647
12302
  })(TreatmentBenefit || {});
11648
12303
 
11649
- // src/types/reviews/index.ts
11650
- var REVIEWS_COLLECTION = "reviews";
12304
+ // src/backoffice/types/requirement.types.ts
12305
+ var TimeUnit = /* @__PURE__ */ ((TimeUnit2) => {
12306
+ TimeUnit2["HOURS"] = "hours";
12307
+ TimeUnit2["DAYS"] = "days";
12308
+ return TimeUnit2;
12309
+ })(TimeUnit || {});
12310
+ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
12311
+ RequirementType2["PRE"] = "pre";
12312
+ RequirementType2["POST"] = "post";
12313
+ return RequirementType2;
12314
+ })(RequirementType || {});
11651
12315
  export {
11652
12316
  AUTH_ERRORS,
11653
12317
  AdminTokenStatus,
@@ -11711,6 +12375,8 @@ export {
11711
12375
  ProductService,
11712
12376
  REGISTER_TOKENS_COLLECTION,
11713
12377
  REVIEWS_COLLECTION,
12378
+ RequirementType,
12379
+ ReviewService,
11714
12380
  SYNCED_CALENDARS_COLLECTION,
11715
12381
  SearchLocationEnum,
11716
12382
  SubcategoryService,
@@ -11718,6 +12384,7 @@ export {
11718
12384
  SyncedCalendarProvider,
11719
12385
  SyncedCalendarsService,
11720
12386
  TechnologyService,
12387
+ TimeUnit,
11721
12388
  TreatmentBenefit,
11722
12389
  USER_ERRORS,
11723
12390
  UserService,