@blackcode_sa/metaestetics-api 1.8.13 → 1.8.15

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
@@ -6651,6 +6651,7 @@ var PractitionerService = class extends BaseService {
6651
6651
  validData.basicInfo,
6652
6652
  practitionerId
6653
6653
  );
6654
+ processedData.fullNameLower = `${processedData.basicInfo.firstName} ${processedData.basicInfo.lastName}`.toLowerCase();
6654
6655
  }
6655
6656
  const updateData = {
6656
6657
  ...processedData,
@@ -6878,80 +6879,163 @@ var PractitionerService = class extends BaseService {
6878
6879
  */
6879
6880
  async getPractitionersByFilters(filters) {
6880
6881
  try {
6881
- const constraints = [];
6882
- if (!filters.includeDraftPractitioners) {
6883
- constraints.push(where10("status", "==", "active" /* ACTIVE */));
6884
- }
6885
- constraints.push(where10("isActive", "==", true));
6886
- if (filters.certifications && filters.certifications.length > 0) {
6887
- constraints.push(
6888
- where10(
6889
- "certification.certifications",
6890
- "array-contains-any",
6891
- filters.certifications
6892
- )
6893
- );
6882
+ console.log("[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies");
6883
+ if (filters.location && filters.radiusInKm) {
6884
+ console.log("[PRACTITIONER_SERVICE] Executing geo query:", {
6885
+ location: filters.location,
6886
+ radius: filters.radiusInKm,
6887
+ serviceName: "PractitionerService"
6888
+ });
6889
+ if (!filters.location.latitude || !filters.location.longitude) {
6890
+ console.warn("[PRACTITIONER_SERVICE] Invalid location data:", filters.location);
6891
+ filters.location = void 0;
6892
+ filters.radiusInKm = void 0;
6893
+ }
6894
6894
  }
6895
6895
  if (filters.nameSearch && filters.nameSearch.trim()) {
6896
- const searchTerm = filters.nameSearch.trim().toLowerCase();
6897
- constraints.push(where10("fullNameLower", ">=", searchTerm));
6898
- constraints.push(where10("fullNameLower", "<=", searchTerm + "\uF8FF"));
6899
- }
6900
- if (filters.procedureTechnology) {
6901
- constraints.push(where10("proceduresInfo.technologyName", "==", filters.procedureTechnology));
6902
- } else if (filters.procedureSubcategory) {
6903
- constraints.push(where10("proceduresInfo.subcategoryName", "==", filters.procedureSubcategory));
6904
- } else if (filters.procedureCategory) {
6905
- constraints.push(where10("proceduresInfo.categoryName", "==", filters.procedureCategory));
6906
- } else if (filters.procedureFamily) {
6907
- constraints.push(where10("proceduresInfo.family", "==", filters.procedureFamily));
6908
- }
6909
- if (filters.minRating !== void 0) {
6910
- constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
6911
- }
6912
- if (filters.maxRating !== void 0) {
6913
- constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
6896
+ try {
6897
+ console.log("[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search");
6898
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
6899
+ const constraints = [];
6900
+ if (!filters.includeDraftPractitioners) {
6901
+ constraints.push(where10("status", "==", "active" /* ACTIVE */));
6902
+ }
6903
+ constraints.push(where10("isActive", "==", true));
6904
+ constraints.push(where10("fullNameLower", ">=", searchTerm));
6905
+ constraints.push(where10("fullNameLower", "<=", searchTerm + "\uF8FF"));
6906
+ constraints.push(orderBy4("fullNameLower"));
6907
+ if (filters.lastDoc) {
6908
+ if (typeof filters.lastDoc.data === "function") {
6909
+ constraints.push(startAfter6(filters.lastDoc));
6910
+ } else if (Array.isArray(filters.lastDoc)) {
6911
+ constraints.push(startAfter6(...filters.lastDoc));
6912
+ } else {
6913
+ constraints.push(startAfter6(filters.lastDoc));
6914
+ }
6915
+ }
6916
+ constraints.push(limit7(filters.pagination || 10));
6917
+ const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6918
+ const querySnapshot = await getDocs10(q);
6919
+ const practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6920
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6921
+ console.log(`[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`);
6922
+ if (practitioners.length < (filters.pagination || 10)) {
6923
+ return { practitioners, lastDoc: null };
6924
+ }
6925
+ return { practitioners, lastDoc };
6926
+ } catch (error) {
6927
+ console.log("[PRACTITIONER_SERVICE] Strategy 1 failed:", error);
6928
+ }
6914
6929
  }
6915
- constraints.push(orderBy4("fullNameLower"));
6916
- if (filters.lastDoc) {
6917
- if (typeof filters.lastDoc.data === "function") {
6918
- constraints.push(startAfter6(filters.lastDoc));
6919
- } else if (Array.isArray(filters.lastDoc)) {
6920
- constraints.push(startAfter6(...filters.lastDoc));
6930
+ try {
6931
+ console.log("[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering");
6932
+ const constraints = [];
6933
+ if (!filters.includeDraftPractitioners) {
6934
+ constraints.push(where10("status", "==", "active" /* ACTIVE */));
6935
+ }
6936
+ constraints.push(where10("isActive", "==", true));
6937
+ if (filters.certifications && filters.certifications.length > 0) {
6938
+ constraints.push(
6939
+ where10("certification.specialties", "array-contains-any", filters.certifications)
6940
+ );
6941
+ }
6942
+ if (filters.minRating !== void 0) {
6943
+ constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
6944
+ }
6945
+ if (filters.maxRating !== void 0) {
6946
+ constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
6947
+ }
6948
+ constraints.push(orderBy4("createdAt", "desc"));
6949
+ if (filters.location && filters.radiusInKm) {
6950
+ constraints.push(limit7((filters.pagination || 10) * 2));
6921
6951
  } else {
6922
- constraints.push(startAfter6(filters.lastDoc));
6952
+ if (filters.lastDoc) {
6953
+ if (typeof filters.lastDoc.data === "function") {
6954
+ constraints.push(startAfter6(filters.lastDoc));
6955
+ } else if (Array.isArray(filters.lastDoc)) {
6956
+ constraints.push(startAfter6(...filters.lastDoc));
6957
+ } else {
6958
+ constraints.push(startAfter6(filters.lastDoc));
6959
+ }
6960
+ }
6961
+ constraints.push(limit7(filters.pagination || 10));
6962
+ }
6963
+ const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6964
+ const querySnapshot = await getDocs10(q);
6965
+ let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6966
+ if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6967
+ const location = filters.location;
6968
+ const radiusInKm = filters.radiusInKm;
6969
+ practitioners = practitioners.filter((practitioner) => {
6970
+ const clinics = practitioner.clinicsInfo || [];
6971
+ return clinics.some((clinic) => {
6972
+ const distance = distanceBetween(
6973
+ [location.latitude, location.longitude],
6974
+ [clinic.location.latitude, clinic.location.longitude]
6975
+ );
6976
+ const distanceInKm = distance / 1e3;
6977
+ return distanceInKm <= radiusInKm;
6978
+ });
6979
+ });
6980
+ practitioners = practitioners.slice(0, filters.pagination || 10);
6981
+ }
6982
+ if (filters.nameSearch && filters.nameSearch.trim()) {
6983
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
6984
+ practitioners = practitioners.filter((practitioner) => {
6985
+ var _a, _b;
6986
+ const firstName = (((_a = practitioner.basicInfo) == null ? void 0 : _a.firstName) || "").toLowerCase();
6987
+ const lastName = (((_b = practitioner.basicInfo) == null ? void 0 : _b.lastName) || "").toLowerCase();
6988
+ const fullName = `${firstName} ${lastName}`.trim();
6989
+ const fullNameLower = practitioner.fullNameLower || "";
6990
+ return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
6991
+ });
6992
+ console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${practitioners.length}`);
6923
6993
  }
6994
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6995
+ console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
6996
+ if (practitioners.length < (filters.pagination || 10)) {
6997
+ return { practitioners, lastDoc: null };
6998
+ }
6999
+ return { practitioners, lastDoc };
7000
+ } catch (error) {
7001
+ console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
6924
7002
  }
6925
- constraints.push(limit7(filters.pagination || 5));
6926
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6927
- const querySnapshot = await getDocs10(q);
6928
- let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6929
- if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6930
- const location = filters.location;
6931
- const radiusInKm = filters.radiusInKm;
6932
- practitioners = practitioners.filter((practitioner) => {
6933
- const clinics = practitioner.clinicsInfo || [];
6934
- return clinics.some((clinic) => {
6935
- const distance = distanceBetween(
6936
- [location.latitude, location.longitude],
6937
- [clinic.location.latitude, clinic.location.longitude]
6938
- );
6939
- const distanceInKm = distance / 1e3;
6940
- return distanceInKm <= radiusInKm;
7003
+ try {
7004
+ console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
7005
+ const constraints = [
7006
+ where10("isActive", "==", true),
7007
+ orderBy4("createdAt", "desc"),
7008
+ limit7(filters.pagination || 10)
7009
+ ];
7010
+ const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7011
+ const querySnapshot = await getDocs10(q);
7012
+ let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
7013
+ if (filters.nameSearch && filters.nameSearch.trim()) {
7014
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
7015
+ practitioners = practitioners.filter((practitioner) => {
7016
+ var _a, _b;
7017
+ const firstName = (((_a = practitioner.basicInfo) == null ? void 0 : _a.firstName) || "").toLowerCase();
7018
+ const lastName = (((_b = practitioner.basicInfo) == null ? void 0 : _b.lastName) || "").toLowerCase();
7019
+ const fullName = `${firstName} ${lastName}`.trim();
7020
+ const fullNameLower = practitioner.fullNameLower || "";
7021
+ return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
6941
7022
  });
6942
- });
7023
+ console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${practitioners.length}`);
7024
+ }
7025
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7026
+ console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
7027
+ if (practitioners.length < (filters.pagination || 10)) {
7028
+ return { practitioners, lastDoc: null };
7029
+ }
7030
+ return { practitioners, lastDoc };
7031
+ } catch (error) {
7032
+ console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
6943
7033
  }
6944
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6945
- return {
6946
- practitioners,
6947
- lastDoc
6948
- };
7034
+ console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
7035
+ return { practitioners: [], lastDoc: null };
6949
7036
  } catch (error) {
6950
- console.error(
6951
- "[PRACTITIONER_SERVICE] Error filtering practitioners:",
6952
- error
6953
- );
6954
- throw error;
7037
+ console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
7038
+ return { practitioners: [], lastDoc: null };
6955
7039
  }
6956
7040
  }
6957
7041
  /**
@@ -8636,49 +8720,181 @@ import {
8636
8720
  } from "firebase/firestore";
8637
8721
  import { distanceBetween as distanceBetween4 } from "geofire-common";
8638
8722
  async function getClinicsByFilters(db, filters) {
8639
- var _a;
8640
- const constraints = [];
8641
- constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8642
- if (filters.tags && filters.tags.length > 0) {
8643
- constraints.push(where15("tags", "array-contains", filters.tags[0]));
8644
- }
8645
- if (filters.procedureTechnology) {
8646
- constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
8647
- } else if (filters.procedureSubcategory) {
8648
- constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
8649
- } else if (filters.procedureCategory) {
8650
- constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
8651
- } else if (filters.procedureFamily) {
8652
- constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
8653
- }
8654
- let useNameLower = false;
8655
- let searchTerm = "";
8656
- if (filters.nameSearch && filters.nameSearch.trim()) {
8657
- searchTerm = filters.nameSearch.trim().toLowerCase();
8658
- constraints.push(where15("nameLower", ">=", searchTerm));
8659
- constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
8660
- useNameLower = true;
8661
- }
8662
- if (filters.minRating !== void 0) {
8663
- constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
8664
- }
8665
- if (filters.maxRating !== void 0) {
8666
- constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
8667
- }
8668
- constraints.push(orderBy5("nameLower"));
8669
- if (filters.lastDoc) {
8670
- if (typeof filters.lastDoc.data === "function") {
8671
- constraints.push(startAfter8(filters.lastDoc));
8672
- } else if (Array.isArray(filters.lastDoc)) {
8673
- constraints.push(startAfter8(...filters.lastDoc));
8674
- } else {
8675
- constraints.push(startAfter8(filters.lastDoc));
8723
+ try {
8724
+ console.log("[CLINIC_SERVICE] Starting clinic filtering with multiple strategies");
8725
+ if (filters.center && filters.radiusInKm) {
8726
+ console.log("[CLINIC_SERVICE] Executing geo query:", {
8727
+ center: filters.center,
8728
+ radius: filters.radiusInKm,
8729
+ serviceName: "ClinicService"
8730
+ });
8731
+ if (!filters.center.latitude || !filters.center.longitude) {
8732
+ console.warn("[CLINIC_SERVICE] Invalid location data:", filters.center);
8733
+ filters.center = void 0;
8734
+ filters.radiusInKm = void 0;
8735
+ }
8736
+ }
8737
+ const getBaseConstraints = () => {
8738
+ var _a;
8739
+ const constraints = [];
8740
+ constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8741
+ if (filters.tags && filters.tags.length > 0) {
8742
+ constraints.push(where15("tags", "array-contains", filters.tags[0]));
8743
+ }
8744
+ if (filters.procedureTechnology) {
8745
+ constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
8746
+ } else if (filters.procedureSubcategory) {
8747
+ constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
8748
+ } else if (filters.procedureCategory) {
8749
+ constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
8750
+ } else if (filters.procedureFamily) {
8751
+ constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
8752
+ }
8753
+ if (filters.minRating !== void 0) {
8754
+ constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
8755
+ }
8756
+ if (filters.maxRating !== void 0) {
8757
+ constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
8758
+ }
8759
+ return constraints;
8760
+ };
8761
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8762
+ try {
8763
+ console.log("[CLINIC_SERVICE] Strategy 1: Trying nameLower search");
8764
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8765
+ const constraints = getBaseConstraints();
8766
+ constraints.push(where15("nameLower", ">=", searchTerm));
8767
+ constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
8768
+ constraints.push(orderBy5("nameLower"));
8769
+ if (filters.lastDoc) {
8770
+ if (typeof filters.lastDoc.data === "function") {
8771
+ constraints.push(startAfter8(filters.lastDoc));
8772
+ } else if (Array.isArray(filters.lastDoc)) {
8773
+ constraints.push(startAfter8(...filters.lastDoc));
8774
+ } else {
8775
+ constraints.push(startAfter8(filters.lastDoc));
8776
+ }
8777
+ }
8778
+ constraints.push(limit9(filters.pagination || 5));
8779
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8780
+ const querySnapshot = await getDocs15(q);
8781
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8782
+ clinics = applyInMemoryFilters(clinics, filters);
8783
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8784
+ console.log(`[CLINIC_SERVICE] Strategy 1 success: ${clinics.length} clinics`);
8785
+ if (clinics.length < (filters.pagination || 5)) {
8786
+ return { clinics, lastDoc: null };
8787
+ }
8788
+ return { clinics, lastDoc };
8789
+ } catch (error) {
8790
+ console.log("[CLINIC_SERVICE] Strategy 1 failed:", error);
8791
+ }
8792
+ }
8793
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8794
+ try {
8795
+ console.log("[CLINIC_SERVICE] Strategy 2: Trying name field search");
8796
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8797
+ const constraints = getBaseConstraints();
8798
+ constraints.push(where15("name", ">=", searchTerm));
8799
+ constraints.push(where15("name", "<=", searchTerm + "\uF8FF"));
8800
+ constraints.push(orderBy5("name"));
8801
+ if (filters.lastDoc) {
8802
+ if (typeof filters.lastDoc.data === "function") {
8803
+ constraints.push(startAfter8(filters.lastDoc));
8804
+ } else if (Array.isArray(filters.lastDoc)) {
8805
+ constraints.push(startAfter8(...filters.lastDoc));
8806
+ } else {
8807
+ constraints.push(startAfter8(filters.lastDoc));
8808
+ }
8809
+ }
8810
+ constraints.push(limit9(filters.pagination || 5));
8811
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8812
+ const querySnapshot = await getDocs15(q);
8813
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8814
+ clinics = applyInMemoryFilters(clinics, filters);
8815
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8816
+ console.log(`[CLINIC_SERVICE] Strategy 2 success: ${clinics.length} clinics`);
8817
+ if (clinics.length < (filters.pagination || 5)) {
8818
+ return { clinics, lastDoc: null };
8819
+ }
8820
+ return { clinics, lastDoc };
8821
+ } catch (error) {
8822
+ console.log("[CLINIC_SERVICE] Strategy 2 failed:", error);
8823
+ }
8824
+ }
8825
+ try {
8826
+ console.log("[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering");
8827
+ const constraints = getBaseConstraints();
8828
+ constraints.push(orderBy5("createdAt", "desc"));
8829
+ if (filters.lastDoc) {
8830
+ if (typeof filters.lastDoc.data === "function") {
8831
+ constraints.push(startAfter8(filters.lastDoc));
8832
+ } else if (Array.isArray(filters.lastDoc)) {
8833
+ constraints.push(startAfter8(...filters.lastDoc));
8834
+ } else {
8835
+ constraints.push(startAfter8(filters.lastDoc));
8836
+ }
8837
+ }
8838
+ constraints.push(limit9(filters.pagination || 5));
8839
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8840
+ const querySnapshot = await getDocs15(q);
8841
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8842
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8843
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8844
+ clinics = clinics.filter((clinic) => {
8845
+ const name = (clinic.name || "").toLowerCase();
8846
+ const nameLower = clinic.nameLower || "";
8847
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
8848
+ });
8849
+ console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
8850
+ }
8851
+ clinics = applyInMemoryFilters(clinics, filters);
8852
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8853
+ console.log(`[CLINIC_SERVICE] Strategy 3 success: ${clinics.length} clinics`);
8854
+ if (clinics.length < (filters.pagination || 5)) {
8855
+ return { clinics, lastDoc: null };
8856
+ }
8857
+ return { clinics, lastDoc };
8858
+ } catch (error) {
8859
+ console.log("[CLINIC_SERVICE] Strategy 3 failed:", error);
8676
8860
  }
8861
+ try {
8862
+ console.log("[CLINIC_SERVICE] Strategy 4: Minimal fallback");
8863
+ const constraints = [
8864
+ where15("isActive", "==", true),
8865
+ orderBy5("createdAt", "desc"),
8866
+ limit9(filters.pagination || 5)
8867
+ ];
8868
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8869
+ const querySnapshot = await getDocs15(q);
8870
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8871
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8872
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8873
+ clinics = clinics.filter((clinic) => {
8874
+ const name = (clinic.name || "").toLowerCase();
8875
+ const nameLower = clinic.nameLower || "";
8876
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
8877
+ });
8878
+ console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
8879
+ }
8880
+ clinics = applyInMemoryFilters(clinics, filters);
8881
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8882
+ console.log(`[CLINIC_SERVICE] Strategy 4 success: ${clinics.length} clinics`);
8883
+ if (clinics.length < (filters.pagination || 5)) {
8884
+ return { clinics, lastDoc: null };
8885
+ }
8886
+ return { clinics, lastDoc };
8887
+ } catch (error) {
8888
+ console.log("[CLINIC_SERVICE] Strategy 4 failed:", error);
8889
+ }
8890
+ console.log("[CLINIC_SERVICE] All strategies failed, returning empty result");
8891
+ return { clinics: [], lastDoc: null };
8892
+ } catch (error) {
8893
+ console.error("[CLINIC_SERVICE] Error filtering clinics:", error);
8894
+ return { clinics: [], lastDoc: null };
8677
8895
  }
8678
- constraints.push(limit9(filters.pagination || 5));
8679
- const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8680
- const querySnapshot = await getDocs15(q);
8681
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8896
+ }
8897
+ function applyInMemoryFilters(clinics, filters) {
8682
8898
  if (filters.tags && filters.tags.length > 1) {
8683
8899
  clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
8684
8900
  }
@@ -8691,9 +8907,9 @@ async function getClinicsByFilters(db, filters) {
8691
8907
  clinic.distance = distance;
8692
8908
  return distance <= filters.radiusInKm;
8693
8909
  });
8910
+ clinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
8694
8911
  }
8695
- const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8696
- return { clinics, lastDoc: lastVisibleDoc };
8912
+ return clinics;
8697
8913
  }
8698
8914
 
8699
8915
  // src/services/clinic/clinic.service.ts
@@ -14530,7 +14746,7 @@ var procedureSchema = createProcedureSchema.extend({
14530
14746
  });
14531
14747
 
14532
14748
  // src/services/procedure/procedure.service.ts
14533
- import { distanceBetween as distanceBetween6, geohashQueryBounds as geohashQueryBounds5 } from "geofire-common";
14749
+ import { distanceBetween as distanceBetween6 } from "geofire-common";
14534
14750
  var ProcedureService = class extends BaseService {
14535
14751
  constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService, mediaService) {
14536
14752
  super(db, auth, app);
@@ -15159,126 +15375,233 @@ var ProcedureService = class extends BaseService {
15159
15375
  */
15160
15376
  async getProceduresByFilters(filters) {
15161
15377
  try {
15162
- const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
15163
- const constraints = [];
15164
- if (filters.isActive !== void 0) {
15165
- constraints.push(where29("isActive", "==", filters.isActive));
15166
- } else {
15167
- constraints.push(where29("isActive", "==", true));
15168
- }
15169
- if (filters.procedureFamily) {
15170
- constraints.push(where29("family", "==", filters.procedureFamily));
15171
- }
15172
- if (filters.procedureCategory) {
15173
- constraints.push(where29("category.id", "==", filters.procedureCategory));
15174
- }
15175
- if (filters.procedureSubcategory) {
15176
- constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
15177
- }
15178
- if (filters.procedureTechnology) {
15179
- constraints.push(where29("technology.id", "==", filters.procedureTechnology));
15180
- }
15181
- if (filters.minPrice !== void 0) {
15182
- constraints.push(where29("price", ">=", filters.minPrice));
15183
- }
15184
- if (filters.maxPrice !== void 0) {
15185
- constraints.push(where29("price", "<=", filters.maxPrice));
15186
- }
15187
- if (filters.minRating !== void 0) {
15188
- constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
15189
- }
15190
- if (filters.maxRating !== void 0) {
15191
- constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
15192
- }
15193
- if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15194
- constraints.push(where29("treatmentBenefits", "array-contains-any", filters.treatmentBenefits));
15378
+ console.log("[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies");
15379
+ if (filters.location && filters.radiusInKm) {
15380
+ console.log("[PROCEDURE_SERVICE] Executing geo query:", {
15381
+ location: filters.location,
15382
+ radius: filters.radiusInKm,
15383
+ serviceName: "ProcedureService"
15384
+ });
15385
+ if (!filters.location.latitude || !filters.location.longitude) {
15386
+ console.warn("[PROCEDURE_SERVICE] Invalid location data:", filters.location);
15387
+ filters.location = void 0;
15388
+ filters.radiusInKm = void 0;
15389
+ }
15195
15390
  }
15196
- let useNameLower = false;
15197
- let searchTerm = "";
15198
- if (filters.nameSearch && filters.nameSearch.trim() !== "") {
15199
- searchTerm = filters.nameSearch.trim().toLowerCase();
15200
- useNameLower = true;
15201
- constraints.push(where29("nameLower", ">=", searchTerm));
15202
- constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
15203
- constraints.push(orderBy17("nameLower"));
15204
- } else {
15205
- constraints.push(orderBy17("nameLower"));
15391
+ const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
15392
+ if (isGeoQuery) {
15393
+ return this.handleGeoQuery(filters);
15206
15394
  }
15207
- if (filters.lastDoc) {
15208
- if (typeof filters.lastDoc.data === "function") {
15209
- constraints.push(startAfter13(filters.lastDoc));
15210
- } else if (Array.isArray(filters.lastDoc)) {
15211
- constraints.push(startAfter13(...filters.lastDoc));
15395
+ const getBaseConstraints = () => {
15396
+ const constraints = [];
15397
+ if (filters.isActive !== void 0) {
15398
+ constraints.push(where29("isActive", "==", filters.isActive));
15212
15399
  } else {
15213
- constraints.push(startAfter13(filters.lastDoc));
15400
+ constraints.push(where29("isActive", "==", true));
15214
15401
  }
15215
- }
15216
- if (filters.pagination && filters.pagination > 0) {
15217
- constraints.push(limit15(filters.pagination));
15218
- }
15219
- if (isGeoQuery) {
15220
- const center = filters.location;
15221
- const radiusInKm = filters.radiusInKm;
15222
- const bounds = geohashQueryBounds5(
15223
- [center.latitude, center.longitude],
15224
- radiusInKm * 1e3
15225
- // Convert to meters
15226
- );
15227
- let allDocs = [];
15228
- for (const bound of bounds) {
15229
- const geoConstraints = [
15230
- ...constraints.filter((c) => !c.fieldPath || c.fieldPath !== "name"),
15231
- // Remove name orderBy for geo
15232
- where29("clinicInfo.location.geohash", ">=", bound[0]),
15233
- where29("clinicInfo.location.geohash", "<=", bound[1]),
15234
- orderBy17("clinicInfo.location.geohash")
15235
- ];
15236
- const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...geoConstraints);
15237
- const querySnapshot = await getDocs29(q);
15238
- for (const doc37 of querySnapshot.docs) {
15239
- const procedure = { ...doc37.data(), id: doc37.id };
15240
- const distance = distanceBetween6(
15241
- [center.latitude, center.longitude],
15242
- [procedure.clinicInfo.location.latitude, procedure.clinicInfo.location.longitude]
15243
- );
15244
- const distanceInKm = distance / 1e3;
15245
- if (distanceInKm <= radiusInKm) {
15246
- allDocs.push({ ...procedure, distance: distanceInKm });
15247
- }
15248
- }
15402
+ if (filters.procedureFamily) {
15403
+ constraints.push(where29("family", "==", filters.procedureFamily));
15249
15404
  }
15250
- allDocs.sort((a, b) => a.distance - b.distance);
15251
- let paginated = allDocs;
15252
- if (filters.pagination && filters.pagination > 0) {
15253
- let startIndex = 0;
15405
+ if (filters.procedureCategory) {
15406
+ constraints.push(where29("category.id", "==", filters.procedureCategory));
15407
+ }
15408
+ if (filters.procedureSubcategory) {
15409
+ constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
15410
+ }
15411
+ if (filters.procedureTechnology) {
15412
+ constraints.push(where29("technology.id", "==", filters.procedureTechnology));
15413
+ }
15414
+ if (filters.minPrice !== void 0) {
15415
+ constraints.push(where29("price", ">=", filters.minPrice));
15416
+ }
15417
+ if (filters.maxPrice !== void 0) {
15418
+ constraints.push(where29("price", "<=", filters.maxPrice));
15419
+ }
15420
+ if (filters.minRating !== void 0) {
15421
+ constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
15422
+ }
15423
+ if (filters.maxRating !== void 0) {
15424
+ constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
15425
+ }
15426
+ if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15427
+ constraints.push(where29("treatmentBenefits", "array-contains-any", filters.treatmentBenefits));
15428
+ }
15429
+ return constraints;
15430
+ };
15431
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15432
+ try {
15433
+ console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
15434
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15435
+ const constraints = getBaseConstraints();
15436
+ constraints.push(where29("nameLower", ">=", searchTerm));
15437
+ constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
15438
+ constraints.push(orderBy17("nameLower"));
15254
15439
  if (filters.lastDoc) {
15255
- const lastDocIndex = allDocs.findIndex((p) => p.id === filters.lastDoc.id);
15256
- if (lastDocIndex !== -1) startIndex = lastDocIndex + 1;
15440
+ if (typeof filters.lastDoc.data === "function") {
15441
+ constraints.push(startAfter13(filters.lastDoc));
15442
+ } else if (Array.isArray(filters.lastDoc)) {
15443
+ constraints.push(startAfter13(...filters.lastDoc));
15444
+ } else {
15445
+ constraints.push(startAfter13(filters.lastDoc));
15446
+ }
15447
+ }
15448
+ constraints.push(limit15(filters.pagination || 10));
15449
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15450
+ const querySnapshot = await getDocs29(q);
15451
+ const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15452
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15453
+ console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15454
+ if (procedures.length < (filters.pagination || 10)) {
15455
+ return { procedures, lastDoc: null };
15257
15456
  }
15258
- paginated = allDocs.slice(startIndex, startIndex + filters.pagination);
15457
+ return { procedures, lastDoc };
15458
+ } catch (error) {
15459
+ console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
15259
15460
  }
15260
- const lastVisibleDoc = paginated.length > 0 ? paginated[paginated.length - 1] : null;
15261
- return { procedures: paginated, lastDoc: lastVisibleDoc };
15262
- } else {
15263
- let q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15264
- let querySnapshot = await getDocs29(q);
15265
- if (useNameLower && querySnapshot.empty && searchTerm) {
15266
- constraints.pop();
15267
- constraints.pop();
15268
- constraints.pop();
15461
+ }
15462
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15463
+ try {
15464
+ console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
15465
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15466
+ const constraints = getBaseConstraints();
15269
15467
  constraints.push(where29("name", ">=", searchTerm));
15270
15468
  constraints.push(where29("name", "<=", searchTerm + "\uF8FF"));
15271
15469
  constraints.push(orderBy17("name"));
15272
- q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15273
- querySnapshot = await getDocs29(q);
15470
+ if (filters.lastDoc) {
15471
+ if (typeof filters.lastDoc.data === "function") {
15472
+ constraints.push(startAfter13(filters.lastDoc));
15473
+ } else if (Array.isArray(filters.lastDoc)) {
15474
+ constraints.push(startAfter13(...filters.lastDoc));
15475
+ } else {
15476
+ constraints.push(startAfter13(filters.lastDoc));
15477
+ }
15478
+ }
15479
+ constraints.push(limit15(filters.pagination || 10));
15480
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15481
+ const querySnapshot = await getDocs29(q);
15482
+ const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15483
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15484
+ console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15485
+ if (procedures.length < (filters.pagination || 10)) {
15486
+ return { procedures, lastDoc: null };
15487
+ }
15488
+ return { procedures, lastDoc };
15489
+ } catch (error) {
15490
+ console.log("[PROCEDURE_SERVICE] Strategy 2 failed:", error);
15491
+ }
15492
+ }
15493
+ try {
15494
+ console.log("[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering");
15495
+ const constraints = getBaseConstraints();
15496
+ constraints.push(orderBy17("createdAt", "desc"));
15497
+ if (filters.lastDoc) {
15498
+ if (typeof filters.lastDoc.data === "function") {
15499
+ constraints.push(startAfter13(filters.lastDoc));
15500
+ } else if (Array.isArray(filters.lastDoc)) {
15501
+ constraints.push(startAfter13(...filters.lastDoc));
15502
+ } else {
15503
+ constraints.push(startAfter13(filters.lastDoc));
15504
+ }
15505
+ }
15506
+ constraints.push(limit15(filters.pagination || 10));
15507
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15508
+ const querySnapshot = await getDocs29(q);
15509
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15510
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15511
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15512
+ procedures = procedures.filter((procedure) => {
15513
+ const name = (procedure.name || "").toLowerCase();
15514
+ const nameLower = procedure.nameLower || "";
15515
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
15516
+ });
15517
+ console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${procedures.length}`);
15518
+ }
15519
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15520
+ console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
15521
+ if (procedures.length < (filters.pagination || 10)) {
15522
+ return { procedures, lastDoc: null };
15523
+ }
15524
+ return { procedures, lastDoc };
15525
+ } catch (error) {
15526
+ console.log("[PROCEDURE_SERVICE] Strategy 3 failed:", error);
15527
+ }
15528
+ try {
15529
+ console.log("[PROCEDURE_SERVICE] Strategy 4: Minimal query fallback");
15530
+ const constraints = [
15531
+ where29("isActive", "==", true),
15532
+ orderBy17("createdAt", "desc"),
15533
+ limit15(filters.pagination || 10)
15534
+ ];
15535
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15536
+ const querySnapshot = await getDocs29(q);
15537
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15538
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15539
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15540
+ procedures = procedures.filter((procedure) => {
15541
+ const name = (procedure.name || "").toLowerCase();
15542
+ const nameLower = procedure.nameLower || "";
15543
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
15544
+ });
15545
+ console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${procedures.length}`);
15274
15546
  }
15275
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15276
- const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15277
- return { procedures, lastDoc: lastVisibleDoc };
15547
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15548
+ console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
15549
+ if (procedures.length < (filters.pagination || 10)) {
15550
+ return { procedures, lastDoc: null };
15551
+ }
15552
+ return { procedures, lastDoc };
15553
+ } catch (error) {
15554
+ console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
15278
15555
  }
15556
+ console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
15557
+ return { procedures: [], lastDoc: null };
15279
15558
  } catch (error) {
15280
15559
  console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
15281
- throw error;
15560
+ return { procedures: [], lastDoc: null };
15561
+ }
15562
+ }
15563
+ handleGeoQuery(filters) {
15564
+ console.log("[PROCEDURE_SERVICE] Executing geo query with enhanced debugging");
15565
+ try {
15566
+ const location = filters.location;
15567
+ const radiusInKm = filters.radiusInKm;
15568
+ console.log("[PROCEDURE_SERVICE] Geo query parameters:", {
15569
+ latitude: location.latitude,
15570
+ longitude: location.longitude,
15571
+ radiusInKm,
15572
+ pagination: filters.pagination || 10
15573
+ });
15574
+ const constraints = [
15575
+ where29("isActive", "==", true),
15576
+ orderBy17("createdAt", "desc"),
15577
+ limit15((filters.pagination || 10) * 3)
15578
+ // Get more results for geo filtering
15579
+ ];
15580
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15581
+ return getDocs29(q).then((querySnapshot) => {
15582
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15583
+ procedures = procedures.filter((procedure) => {
15584
+ var _a;
15585
+ const clinicLocation = (_a = procedure.clinicInfo) == null ? void 0 : _a.location;
15586
+ if (!(clinicLocation == null ? void 0 : clinicLocation.latitude) || !(clinicLocation == null ? void 0 : clinicLocation.longitude)) {
15587
+ return false;
15588
+ }
15589
+ const distance = distanceBetween6(
15590
+ [location.latitude, location.longitude],
15591
+ [clinicLocation.latitude, clinicLocation.longitude]
15592
+ ) / 1e3;
15593
+ procedure.distance = distance;
15594
+ return distance <= radiusInKm;
15595
+ });
15596
+ procedures.sort((a, b) => (a.distance || 0) - (b.distance || 0));
15597
+ procedures = procedures.slice(0, filters.pagination || 10);
15598
+ console.log(`[PROCEDURE_SERVICE] Geo query success: ${procedures.length} procedures within ${radiusInKm}km`);
15599
+ const lastDoc = procedures.length < (filters.pagination || 10) ? null : querySnapshot.docs[querySnapshot.docs.length - 1];
15600
+ return { procedures, lastDoc };
15601
+ });
15602
+ } catch (error) {
15603
+ console.error("[PROCEDURE_SERVICE] Geo query failed:", error);
15604
+ return Promise.resolve({ procedures: [], lastDoc: null });
15282
15605
  }
15283
15606
  }
15284
15607
  /**