@blackcode_sa/metaestetics-api 1.8.14 → 1.8.16

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
@@ -6879,81 +6879,235 @@ var PractitionerService = class extends BaseService {
6879
6879
  */
6880
6880
  async getPractitionersByFilters(filters) {
6881
6881
  try {
6882
- const constraints = [];
6883
- if (!filters.includeDraftPractitioners) {
6884
- constraints.push(where10("status", "==", "active" /* ACTIVE */));
6885
- }
6886
- constraints.push(where10("isActive", "==", true));
6887
- if (filters.certifications && filters.certifications.length > 0) {
6888
- constraints.push(
6889
- where10(
6890
- "certification.certifications",
6891
- "array-contains-any",
6892
- filters.certifications
6893
- )
6894
- );
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
+ }
6895
6894
  }
6896
6895
  if (filters.nameSearch && filters.nameSearch.trim()) {
6897
- const searchTerm = filters.nameSearch.trim().toLowerCase();
6898
- constraints.push(where10("fullNameLower", ">=", searchTerm));
6899
- constraints.push(where10("fullNameLower", "<=", searchTerm + "\uF8FF"));
6900
- }
6901
- if (filters.procedureTechnology) {
6902
- constraints.push(where10("proceduresInfo.technologyName", "==", filters.procedureTechnology));
6903
- } else if (filters.procedureSubcategory) {
6904
- constraints.push(where10("proceduresInfo.subcategoryName", "==", filters.procedureSubcategory));
6905
- } else if (filters.procedureCategory) {
6906
- constraints.push(where10("proceduresInfo.categoryName", "==", filters.procedureCategory));
6907
- } else if (filters.procedureFamily) {
6908
- constraints.push(where10("proceduresInfo.family", "==", filters.procedureFamily));
6909
- }
6910
- if (filters.minRating !== void 0) {
6911
- constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
6912
- }
6913
- if (filters.maxRating !== void 0) {
6914
- 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
+ }
6915
6929
  }
6916
- constraints.push(orderBy4("fullNameLower"));
6917
- if (filters.lastDoc) {
6918
- if (typeof filters.lastDoc.data === "function") {
6919
- constraints.push(startAfter6(filters.lastDoc));
6920
- } else if (Array.isArray(filters.lastDoc)) {
6921
- 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
+ const certificationsToMatch = filters.certifications;
6939
+ constraints.push(
6940
+ where10("certification.specialties", "array-contains-any", certificationsToMatch)
6941
+ );
6942
+ }
6943
+ if (filters.minRating !== void 0) {
6944
+ constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
6945
+ }
6946
+ if (filters.maxRating !== void 0) {
6947
+ constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
6948
+ }
6949
+ constraints.push(orderBy4("createdAt", "desc"));
6950
+ if (filters.location && filters.radiusInKm) {
6951
+ constraints.push(limit7((filters.pagination || 10) * 2));
6922
6952
  } else {
6923
- constraints.push(startAfter6(filters.lastDoc));
6953
+ if (filters.lastDoc) {
6954
+ if (typeof filters.lastDoc.data === "function") {
6955
+ constraints.push(startAfter6(filters.lastDoc));
6956
+ } else if (Array.isArray(filters.lastDoc)) {
6957
+ constraints.push(startAfter6(...filters.lastDoc));
6958
+ } else {
6959
+ constraints.push(startAfter6(filters.lastDoc));
6960
+ }
6961
+ }
6962
+ constraints.push(limit7(filters.pagination || 10));
6924
6963
  }
6925
- }
6926
- constraints.push(limit7(filters.pagination || 5));
6927
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6928
- const querySnapshot = await getDocs10(q);
6929
- let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6930
- if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6931
- const location = filters.location;
6932
- const radiusInKm = filters.radiusInKm;
6933
- practitioners = practitioners.filter((practitioner) => {
6934
- const clinics = practitioner.clinicsInfo || [];
6935
- return clinics.some((clinic) => {
6936
- const distance = distanceBetween(
6937
- [location.latitude, location.longitude],
6938
- [clinic.location.latitude, clinic.location.longitude]
6939
- );
6940
- const distanceInKm = distance / 1e3;
6941
- return distanceInKm <= radiusInKm;
6964
+ const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6965
+ const querySnapshot = await getDocs10(q);
6966
+ let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6967
+ if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6968
+ const location = filters.location;
6969
+ const radiusInKm = filters.radiusInKm;
6970
+ practitioners = practitioners.filter((practitioner) => {
6971
+ const clinics = practitioner.clinicsInfo || [];
6972
+ return clinics.some((clinic) => {
6973
+ const distance = distanceBetween(
6974
+ [location.latitude, location.longitude],
6975
+ [clinic.location.latitude, clinic.location.longitude]
6976
+ );
6977
+ const distanceInKm = distance / 1e3;
6978
+ return distanceInKm <= radiusInKm;
6979
+ });
6942
6980
  });
6943
- });
6981
+ practitioners = practitioners.slice(0, filters.pagination || 10);
6982
+ }
6983
+ practitioners = this.applyInMemoryFilters(practitioners, filters);
6984
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6985
+ console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
6986
+ if (practitioners.length < (filters.pagination || 10)) {
6987
+ return { practitioners, lastDoc: null };
6988
+ }
6989
+ return { practitioners, lastDoc };
6990
+ } catch (error) {
6991
+ console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
6944
6992
  }
6945
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6946
- return {
6947
- practitioners,
6948
- lastDoc
6949
- };
6993
+ try {
6994
+ console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
6995
+ const constraints = [
6996
+ where10("isActive", "==", true),
6997
+ orderBy4("createdAt", "desc"),
6998
+ limit7(filters.pagination || 10)
6999
+ ];
7000
+ const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7001
+ const querySnapshot = await getDocs10(q);
7002
+ let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
7003
+ practitioners = this.applyInMemoryFilters(practitioners, filters);
7004
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7005
+ console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
7006
+ if (practitioners.length < (filters.pagination || 10)) {
7007
+ return { practitioners, lastDoc: null };
7008
+ }
7009
+ return { practitioners, lastDoc };
7010
+ } catch (error) {
7011
+ console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
7012
+ }
7013
+ console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
7014
+ return { practitioners: [], lastDoc: null };
6950
7015
  } catch (error) {
6951
- console.error(
6952
- "[PRACTITIONER_SERVICE] Error filtering practitioners:",
6953
- error
6954
- );
6955
- throw error;
7016
+ console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
7017
+ return { practitioners: [], lastDoc: null };
7018
+ }
7019
+ }
7020
+ /**
7021
+ * Applies in-memory filters to practitioners array
7022
+ * Used when Firestore queries fail or for complex filtering
7023
+ */
7024
+ applyInMemoryFilters(practitioners, filters) {
7025
+ let filteredPractitioners = [...practitioners];
7026
+ if (filters.nameSearch && filters.nameSearch.trim()) {
7027
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
7028
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7029
+ var _a, _b;
7030
+ const firstName = (((_a = practitioner.basicInfo) == null ? void 0 : _a.firstName) || "").toLowerCase();
7031
+ const lastName = (((_b = practitioner.basicInfo) == null ? void 0 : _b.lastName) || "").toLowerCase();
7032
+ const fullName = `${firstName} ${lastName}`.trim();
7033
+ const fullNameLower = practitioner.fullNameLower || "";
7034
+ return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
7035
+ });
7036
+ console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`);
7037
+ }
7038
+ if (filters.certifications && filters.certifications.length > 0) {
7039
+ const certificationsToMatch = filters.certifications;
7040
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7041
+ var _a;
7042
+ const practitionerCerts = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7043
+ return certificationsToMatch.some((cert) => practitionerCerts.includes(cert));
7044
+ });
7045
+ console.log(`[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`);
7046
+ }
7047
+ if (filters.specialties && filters.specialties.length > 0) {
7048
+ const specialtiesToMatch = filters.specialties;
7049
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7050
+ var _a;
7051
+ const practitionerSpecs = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7052
+ return specialtiesToMatch.some((spec) => practitionerSpecs.includes(spec));
7053
+ });
7054
+ console.log(`[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`);
7055
+ }
7056
+ if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
7057
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7058
+ var _a;
7059
+ const rating = ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
7060
+ if (filters.minRating !== void 0 && rating < filters.minRating) return false;
7061
+ if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
7062
+ return true;
7063
+ });
7064
+ console.log(`[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`);
7065
+ }
7066
+ if (filters.procedureFamily) {
7067
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7068
+ const proceduresInfo = practitioner.proceduresInfo || [];
7069
+ return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
7070
+ });
7071
+ console.log(`[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`);
7072
+ }
7073
+ if (filters.procedureCategory) {
7074
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7075
+ const proceduresInfo = practitioner.proceduresInfo || [];
7076
+ return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
7077
+ });
7078
+ console.log(`[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`);
7079
+ }
7080
+ if (filters.procedureSubcategory) {
7081
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7082
+ const proceduresInfo = practitioner.proceduresInfo || [];
7083
+ return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
7084
+ });
7085
+ console.log(`[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`);
6956
7086
  }
7087
+ if (filters.procedureTechnology) {
7088
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7089
+ const proceduresInfo = practitioner.proceduresInfo || [];
7090
+ return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
7091
+ });
7092
+ console.log(`[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`);
7093
+ }
7094
+ if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
7095
+ const location = filters.location;
7096
+ const radiusInKm = filters.radiusInKm;
7097
+ filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7098
+ const clinics = practitioner.clinicsInfo || [];
7099
+ return clinics.some((clinic) => {
7100
+ const distance = distanceBetween(
7101
+ [location.latitude, location.longitude],
7102
+ [clinic.location.latitude, clinic.location.longitude]
7103
+ );
7104
+ const distanceInKm = distance / 1e3;
7105
+ return distanceInKm <= radiusInKm;
7106
+ });
7107
+ });
7108
+ console.log(`[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`);
7109
+ }
7110
+ return filteredPractitioners;
6957
7111
  }
6958
7112
  /**
6959
7113
  * Enables free consultation for a practitioner in a specific clinic
@@ -8637,49 +8791,181 @@ import {
8637
8791
  } from "firebase/firestore";
8638
8792
  import { distanceBetween as distanceBetween4 } from "geofire-common";
8639
8793
  async function getClinicsByFilters(db, filters) {
8640
- var _a;
8641
- const constraints = [];
8642
- constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8643
- if (filters.tags && filters.tags.length > 0) {
8644
- constraints.push(where15("tags", "array-contains", filters.tags[0]));
8645
- }
8646
- if (filters.procedureTechnology) {
8647
- constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
8648
- } else if (filters.procedureSubcategory) {
8649
- constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
8650
- } else if (filters.procedureCategory) {
8651
- constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
8652
- } else if (filters.procedureFamily) {
8653
- constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
8654
- }
8655
- let useNameLower = false;
8656
- let searchTerm = "";
8657
- if (filters.nameSearch && filters.nameSearch.trim()) {
8658
- searchTerm = filters.nameSearch.trim().toLowerCase();
8659
- constraints.push(where15("nameLower", ">=", searchTerm));
8660
- constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
8661
- useNameLower = true;
8662
- }
8663
- if (filters.minRating !== void 0) {
8664
- constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
8665
- }
8666
- if (filters.maxRating !== void 0) {
8667
- constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
8668
- }
8669
- constraints.push(orderBy5("nameLower"));
8670
- if (filters.lastDoc) {
8671
- if (typeof filters.lastDoc.data === "function") {
8672
- constraints.push(startAfter8(filters.lastDoc));
8673
- } else if (Array.isArray(filters.lastDoc)) {
8674
- constraints.push(startAfter8(...filters.lastDoc));
8675
- } else {
8676
- constraints.push(startAfter8(filters.lastDoc));
8794
+ try {
8795
+ console.log("[CLINIC_SERVICE] Starting clinic filtering with multiple strategies");
8796
+ if (filters.center && filters.radiusInKm) {
8797
+ console.log("[CLINIC_SERVICE] Executing geo query:", {
8798
+ center: filters.center,
8799
+ radius: filters.radiusInKm,
8800
+ serviceName: "ClinicService"
8801
+ });
8802
+ if (!filters.center.latitude || !filters.center.longitude) {
8803
+ console.warn("[CLINIC_SERVICE] Invalid location data:", filters.center);
8804
+ filters.center = void 0;
8805
+ filters.radiusInKm = void 0;
8806
+ }
8807
+ }
8808
+ const getBaseConstraints = () => {
8809
+ var _a;
8810
+ const constraints = [];
8811
+ constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8812
+ if (filters.tags && filters.tags.length > 0) {
8813
+ constraints.push(where15("tags", "array-contains", filters.tags[0]));
8814
+ }
8815
+ if (filters.procedureTechnology) {
8816
+ constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
8817
+ } else if (filters.procedureSubcategory) {
8818
+ constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
8819
+ } else if (filters.procedureCategory) {
8820
+ constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
8821
+ } else if (filters.procedureFamily) {
8822
+ constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
8823
+ }
8824
+ if (filters.minRating !== void 0) {
8825
+ constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
8826
+ }
8827
+ if (filters.maxRating !== void 0) {
8828
+ constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
8829
+ }
8830
+ return constraints;
8831
+ };
8832
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8833
+ try {
8834
+ console.log("[CLINIC_SERVICE] Strategy 1: Trying nameLower search");
8835
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8836
+ const constraints = getBaseConstraints();
8837
+ constraints.push(where15("nameLower", ">=", searchTerm));
8838
+ constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
8839
+ constraints.push(orderBy5("nameLower"));
8840
+ if (filters.lastDoc) {
8841
+ if (typeof filters.lastDoc.data === "function") {
8842
+ constraints.push(startAfter8(filters.lastDoc));
8843
+ } else if (Array.isArray(filters.lastDoc)) {
8844
+ constraints.push(startAfter8(...filters.lastDoc));
8845
+ } else {
8846
+ constraints.push(startAfter8(filters.lastDoc));
8847
+ }
8848
+ }
8849
+ constraints.push(limit9(filters.pagination || 5));
8850
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8851
+ const querySnapshot = await getDocs15(q);
8852
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8853
+ clinics = applyInMemoryFilters(clinics, filters);
8854
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8855
+ console.log(`[CLINIC_SERVICE] Strategy 1 success: ${clinics.length} clinics`);
8856
+ if (clinics.length < (filters.pagination || 5)) {
8857
+ return { clinics, lastDoc: null };
8858
+ }
8859
+ return { clinics, lastDoc };
8860
+ } catch (error) {
8861
+ console.log("[CLINIC_SERVICE] Strategy 1 failed:", error);
8862
+ }
8677
8863
  }
8864
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8865
+ try {
8866
+ console.log("[CLINIC_SERVICE] Strategy 2: Trying name field search");
8867
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8868
+ const constraints = getBaseConstraints();
8869
+ constraints.push(where15("name", ">=", searchTerm));
8870
+ constraints.push(where15("name", "<=", searchTerm + "\uF8FF"));
8871
+ constraints.push(orderBy5("name"));
8872
+ if (filters.lastDoc) {
8873
+ if (typeof filters.lastDoc.data === "function") {
8874
+ constraints.push(startAfter8(filters.lastDoc));
8875
+ } else if (Array.isArray(filters.lastDoc)) {
8876
+ constraints.push(startAfter8(...filters.lastDoc));
8877
+ } else {
8878
+ constraints.push(startAfter8(filters.lastDoc));
8879
+ }
8880
+ }
8881
+ constraints.push(limit9(filters.pagination || 5));
8882
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8883
+ const querySnapshot = await getDocs15(q);
8884
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8885
+ clinics = applyInMemoryFilters(clinics, filters);
8886
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8887
+ console.log(`[CLINIC_SERVICE] Strategy 2 success: ${clinics.length} clinics`);
8888
+ if (clinics.length < (filters.pagination || 5)) {
8889
+ return { clinics, lastDoc: null };
8890
+ }
8891
+ return { clinics, lastDoc };
8892
+ } catch (error) {
8893
+ console.log("[CLINIC_SERVICE] Strategy 2 failed:", error);
8894
+ }
8895
+ }
8896
+ try {
8897
+ console.log("[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering");
8898
+ const constraints = getBaseConstraints();
8899
+ constraints.push(orderBy5("createdAt", "desc"));
8900
+ if (filters.lastDoc) {
8901
+ if (typeof filters.lastDoc.data === "function") {
8902
+ constraints.push(startAfter8(filters.lastDoc));
8903
+ } else if (Array.isArray(filters.lastDoc)) {
8904
+ constraints.push(startAfter8(...filters.lastDoc));
8905
+ } else {
8906
+ constraints.push(startAfter8(filters.lastDoc));
8907
+ }
8908
+ }
8909
+ constraints.push(limit9(filters.pagination || 5));
8910
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8911
+ const querySnapshot = await getDocs15(q);
8912
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8913
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8914
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8915
+ clinics = clinics.filter((clinic) => {
8916
+ const name = (clinic.name || "").toLowerCase();
8917
+ const nameLower = clinic.nameLower || "";
8918
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
8919
+ });
8920
+ console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
8921
+ }
8922
+ clinics = applyInMemoryFilters(clinics, filters);
8923
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8924
+ console.log(`[CLINIC_SERVICE] Strategy 3 success: ${clinics.length} clinics`);
8925
+ if (clinics.length < (filters.pagination || 5)) {
8926
+ return { clinics, lastDoc: null };
8927
+ }
8928
+ return { clinics, lastDoc };
8929
+ } catch (error) {
8930
+ console.log("[CLINIC_SERVICE] Strategy 3 failed:", error);
8931
+ }
8932
+ try {
8933
+ console.log("[CLINIC_SERVICE] Strategy 4: Minimal fallback");
8934
+ const constraints = [
8935
+ where15("isActive", "==", true),
8936
+ orderBy5("createdAt", "desc"),
8937
+ limit9(filters.pagination || 5)
8938
+ ];
8939
+ const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8940
+ const querySnapshot = await getDocs15(q);
8941
+ let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8942
+ if (filters.nameSearch && filters.nameSearch.trim()) {
8943
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
8944
+ clinics = clinics.filter((clinic) => {
8945
+ const name = (clinic.name || "").toLowerCase();
8946
+ const nameLower = clinic.nameLower || "";
8947
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
8948
+ });
8949
+ console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
8950
+ }
8951
+ clinics = applyInMemoryFilters(clinics, filters);
8952
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8953
+ console.log(`[CLINIC_SERVICE] Strategy 4 success: ${clinics.length} clinics`);
8954
+ if (clinics.length < (filters.pagination || 5)) {
8955
+ return { clinics, lastDoc: null };
8956
+ }
8957
+ return { clinics, lastDoc };
8958
+ } catch (error) {
8959
+ console.log("[CLINIC_SERVICE] Strategy 4 failed:", error);
8960
+ }
8961
+ console.log("[CLINIC_SERVICE] All strategies failed, returning empty result");
8962
+ return { clinics: [], lastDoc: null };
8963
+ } catch (error) {
8964
+ console.error("[CLINIC_SERVICE] Error filtering clinics:", error);
8965
+ return { clinics: [], lastDoc: null };
8678
8966
  }
8679
- constraints.push(limit9(filters.pagination || 5));
8680
- const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8681
- const querySnapshot = await getDocs15(q);
8682
- let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
8967
+ }
8968
+ function applyInMemoryFilters(clinics, filters) {
8683
8969
  if (filters.tags && filters.tags.length > 1) {
8684
8970
  clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
8685
8971
  }
@@ -8692,9 +8978,9 @@ async function getClinicsByFilters(db, filters) {
8692
8978
  clinic.distance = distance;
8693
8979
  return distance <= filters.radiusInKm;
8694
8980
  });
8981
+ clinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
8695
8982
  }
8696
- const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8697
- return { clinics, lastDoc: lastVisibleDoc };
8983
+ return clinics;
8698
8984
  }
8699
8985
 
8700
8986
  // src/services/clinic/clinic.service.ts
@@ -14531,7 +14817,7 @@ var procedureSchema = createProcedureSchema.extend({
14531
14817
  });
14532
14818
 
14533
14819
  // src/services/procedure/procedure.service.ts
14534
- import { distanceBetween as distanceBetween6, geohashQueryBounds as geohashQueryBounds5 } from "geofire-common";
14820
+ import { distanceBetween as distanceBetween6 } from "geofire-common";
14535
14821
  var ProcedureService = class extends BaseService {
14536
14822
  constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService, mediaService) {
14537
14823
  super(db, auth, app);
@@ -15160,126 +15446,292 @@ var ProcedureService = class extends BaseService {
15160
15446
  */
15161
15447
  async getProceduresByFilters(filters) {
15162
15448
  try {
15163
- const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
15164
- const constraints = [];
15165
- if (filters.isActive !== void 0) {
15166
- constraints.push(where29("isActive", "==", filters.isActive));
15167
- } else {
15168
- constraints.push(where29("isActive", "==", true));
15169
- }
15170
- if (filters.procedureFamily) {
15171
- constraints.push(where29("family", "==", filters.procedureFamily));
15172
- }
15173
- if (filters.procedureCategory) {
15174
- constraints.push(where29("category.id", "==", filters.procedureCategory));
15175
- }
15176
- if (filters.procedureSubcategory) {
15177
- constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
15178
- }
15179
- if (filters.procedureTechnology) {
15180
- constraints.push(where29("technology.id", "==", filters.procedureTechnology));
15181
- }
15182
- if (filters.minPrice !== void 0) {
15183
- constraints.push(where29("price", ">=", filters.minPrice));
15184
- }
15185
- if (filters.maxPrice !== void 0) {
15186
- constraints.push(where29("price", "<=", filters.maxPrice));
15187
- }
15188
- if (filters.minRating !== void 0) {
15189
- constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
15190
- }
15191
- if (filters.maxRating !== void 0) {
15192
- constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
15193
- }
15194
- if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15195
- constraints.push(where29("treatmentBenefits", "array-contains-any", filters.treatmentBenefits));
15449
+ console.log("[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies");
15450
+ if (filters.location && filters.radiusInKm) {
15451
+ console.log("[PROCEDURE_SERVICE] Executing geo query:", {
15452
+ location: filters.location,
15453
+ radius: filters.radiusInKm,
15454
+ serviceName: "ProcedureService"
15455
+ });
15456
+ if (!filters.location.latitude || !filters.location.longitude) {
15457
+ console.warn("[PROCEDURE_SERVICE] Invalid location data:", filters.location);
15458
+ filters.location = void 0;
15459
+ filters.radiusInKm = void 0;
15460
+ }
15196
15461
  }
15197
- let useNameLower = false;
15198
- let searchTerm = "";
15199
- if (filters.nameSearch && filters.nameSearch.trim() !== "") {
15200
- searchTerm = filters.nameSearch.trim().toLowerCase();
15201
- useNameLower = true;
15202
- constraints.push(where29("nameLower", ">=", searchTerm));
15203
- constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
15204
- constraints.push(orderBy17("nameLower"));
15205
- } else {
15206
- constraints.push(orderBy17("nameLower"));
15462
+ const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
15463
+ if (isGeoQuery) {
15464
+ return this.handleGeoQuery(filters);
15207
15465
  }
15208
- if (filters.lastDoc) {
15209
- if (typeof filters.lastDoc.data === "function") {
15210
- constraints.push(startAfter13(filters.lastDoc));
15211
- } else if (Array.isArray(filters.lastDoc)) {
15212
- constraints.push(startAfter13(...filters.lastDoc));
15466
+ const getBaseConstraints = () => {
15467
+ const constraints = [];
15468
+ if (filters.isActive !== void 0) {
15469
+ constraints.push(where29("isActive", "==", filters.isActive));
15213
15470
  } else {
15214
- constraints.push(startAfter13(filters.lastDoc));
15471
+ constraints.push(where29("isActive", "==", true));
15215
15472
  }
15216
- }
15217
- if (filters.pagination && filters.pagination > 0) {
15218
- constraints.push(limit15(filters.pagination));
15219
- }
15220
- if (isGeoQuery) {
15221
- const center = filters.location;
15222
- const radiusInKm = filters.radiusInKm;
15223
- const bounds = geohashQueryBounds5(
15224
- [center.latitude, center.longitude],
15225
- radiusInKm * 1e3
15226
- // Convert to meters
15227
- );
15228
- let allDocs = [];
15229
- for (const bound of bounds) {
15230
- const geoConstraints = [
15231
- ...constraints.filter((c) => !c.fieldPath || c.fieldPath !== "name"),
15232
- // Remove name orderBy for geo
15233
- where29("clinicInfo.location.geohash", ">=", bound[0]),
15234
- where29("clinicInfo.location.geohash", "<=", bound[1]),
15235
- orderBy17("clinicInfo.location.geohash")
15236
- ];
15237
- const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...geoConstraints);
15238
- const querySnapshot = await getDocs29(q);
15239
- for (const doc37 of querySnapshot.docs) {
15240
- const procedure = { ...doc37.data(), id: doc37.id };
15241
- const distance = distanceBetween6(
15242
- [center.latitude, center.longitude],
15243
- [procedure.clinicInfo.location.latitude, procedure.clinicInfo.location.longitude]
15244
- );
15245
- const distanceInKm = distance / 1e3;
15246
- if (distanceInKm <= radiusInKm) {
15247
- allDocs.push({ ...procedure, distance: distanceInKm });
15248
- }
15249
- }
15473
+ if (filters.procedureFamily) {
15474
+ constraints.push(where29("family", "==", filters.procedureFamily));
15475
+ }
15476
+ if (filters.procedureCategory) {
15477
+ constraints.push(where29("category.id", "==", filters.procedureCategory));
15478
+ }
15479
+ if (filters.procedureSubcategory) {
15480
+ constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
15481
+ }
15482
+ if (filters.procedureTechnology) {
15483
+ constraints.push(where29("technology.id", "==", filters.procedureTechnology));
15484
+ }
15485
+ if (filters.minPrice !== void 0) {
15486
+ constraints.push(where29("price", ">=", filters.minPrice));
15487
+ }
15488
+ if (filters.maxPrice !== void 0) {
15489
+ constraints.push(where29("price", "<=", filters.maxPrice));
15250
15490
  }
15251
- allDocs.sort((a, b) => a.distance - b.distance);
15252
- let paginated = allDocs;
15253
- if (filters.pagination && filters.pagination > 0) {
15254
- let startIndex = 0;
15491
+ if (filters.minRating !== void 0) {
15492
+ constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
15493
+ }
15494
+ if (filters.maxRating !== void 0) {
15495
+ constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
15496
+ }
15497
+ if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15498
+ const benefitsToMatch = filters.treatmentBenefits;
15499
+ constraints.push(where29("treatmentBenefits", "array-contains-any", benefitsToMatch));
15500
+ }
15501
+ return constraints;
15502
+ };
15503
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15504
+ try {
15505
+ console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
15506
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15507
+ const constraints = getBaseConstraints();
15508
+ constraints.push(where29("nameLower", ">=", searchTerm));
15509
+ constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
15510
+ constraints.push(orderBy17("nameLower"));
15255
15511
  if (filters.lastDoc) {
15256
- const lastDocIndex = allDocs.findIndex((p) => p.id === filters.lastDoc.id);
15257
- if (lastDocIndex !== -1) startIndex = lastDocIndex + 1;
15512
+ if (typeof filters.lastDoc.data === "function") {
15513
+ constraints.push(startAfter13(filters.lastDoc));
15514
+ } else if (Array.isArray(filters.lastDoc)) {
15515
+ constraints.push(startAfter13(...filters.lastDoc));
15516
+ } else {
15517
+ constraints.push(startAfter13(filters.lastDoc));
15518
+ }
15258
15519
  }
15259
- paginated = allDocs.slice(startIndex, startIndex + filters.pagination);
15520
+ constraints.push(limit15(filters.pagination || 10));
15521
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15522
+ const querySnapshot = await getDocs29(q);
15523
+ const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15524
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15525
+ console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15526
+ if (procedures.length < (filters.pagination || 10)) {
15527
+ return { procedures, lastDoc: null };
15528
+ }
15529
+ return { procedures, lastDoc };
15530
+ } catch (error) {
15531
+ console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
15260
15532
  }
15261
- const lastVisibleDoc = paginated.length > 0 ? paginated[paginated.length - 1] : null;
15262
- return { procedures: paginated, lastDoc: lastVisibleDoc };
15263
- } else {
15264
- let q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15265
- let querySnapshot = await getDocs29(q);
15266
- if (useNameLower && querySnapshot.empty && searchTerm) {
15267
- constraints.pop();
15268
- constraints.pop();
15269
- constraints.pop();
15533
+ }
15534
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15535
+ try {
15536
+ console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
15537
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15538
+ const constraints = getBaseConstraints();
15270
15539
  constraints.push(where29("name", ">=", searchTerm));
15271
15540
  constraints.push(where29("name", "<=", searchTerm + "\uF8FF"));
15272
15541
  constraints.push(orderBy17("name"));
15273
- q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15274
- querySnapshot = await getDocs29(q);
15542
+ if (filters.lastDoc) {
15543
+ if (typeof filters.lastDoc.data === "function") {
15544
+ constraints.push(startAfter13(filters.lastDoc));
15545
+ } else if (Array.isArray(filters.lastDoc)) {
15546
+ constraints.push(startAfter13(...filters.lastDoc));
15547
+ } else {
15548
+ constraints.push(startAfter13(filters.lastDoc));
15549
+ }
15550
+ }
15551
+ constraints.push(limit15(filters.pagination || 10));
15552
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15553
+ const querySnapshot = await getDocs29(q);
15554
+ const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15555
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15556
+ console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15557
+ if (procedures.length < (filters.pagination || 10)) {
15558
+ return { procedures, lastDoc: null };
15559
+ }
15560
+ return { procedures, lastDoc };
15561
+ } catch (error) {
15562
+ console.log("[PROCEDURE_SERVICE] Strategy 2 failed:", error);
15275
15563
  }
15276
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15277
- const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15278
- return { procedures, lastDoc: lastVisibleDoc };
15279
15564
  }
15565
+ try {
15566
+ console.log("[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering");
15567
+ const constraints = getBaseConstraints();
15568
+ constraints.push(orderBy17("createdAt", "desc"));
15569
+ if (filters.lastDoc) {
15570
+ if (typeof filters.lastDoc.data === "function") {
15571
+ constraints.push(startAfter13(filters.lastDoc));
15572
+ } else if (Array.isArray(filters.lastDoc)) {
15573
+ constraints.push(startAfter13(...filters.lastDoc));
15574
+ } else {
15575
+ constraints.push(startAfter13(filters.lastDoc));
15576
+ }
15577
+ }
15578
+ constraints.push(limit15(filters.pagination || 10));
15579
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15580
+ const querySnapshot = await getDocs29(q);
15581
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15582
+ procedures = this.applyInMemoryFilters(procedures, filters);
15583
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15584
+ console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
15585
+ if (procedures.length < (filters.pagination || 10)) {
15586
+ return { procedures, lastDoc: null };
15587
+ }
15588
+ return { procedures, lastDoc };
15589
+ } catch (error) {
15590
+ console.log("[PROCEDURE_SERVICE] Strategy 3 failed:", error);
15591
+ }
15592
+ try {
15593
+ console.log("[PROCEDURE_SERVICE] Strategy 4: Minimal query fallback");
15594
+ const constraints = [
15595
+ where29("isActive", "==", true),
15596
+ orderBy17("createdAt", "desc"),
15597
+ limit15(filters.pagination || 10)
15598
+ ];
15599
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15600
+ const querySnapshot = await getDocs29(q);
15601
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15602
+ procedures = this.applyInMemoryFilters(procedures, filters);
15603
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15604
+ console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
15605
+ if (procedures.length < (filters.pagination || 10)) {
15606
+ return { procedures, lastDoc: null };
15607
+ }
15608
+ return { procedures, lastDoc };
15609
+ } catch (error) {
15610
+ console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
15611
+ }
15612
+ console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
15613
+ return { procedures: [], lastDoc: null };
15280
15614
  } catch (error) {
15281
15615
  console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
15282
- throw error;
15616
+ return { procedures: [], lastDoc: null };
15617
+ }
15618
+ }
15619
+ /**
15620
+ * Applies in-memory filters to procedures array
15621
+ * Used when Firestore queries fail or for complex filtering
15622
+ */
15623
+ applyInMemoryFilters(procedures, filters) {
15624
+ let filteredProcedures = [...procedures];
15625
+ if (filters.nameSearch && filters.nameSearch.trim()) {
15626
+ const searchTerm = filters.nameSearch.trim().toLowerCase();
15627
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15628
+ const name = (procedure.name || "").toLowerCase();
15629
+ const nameLower = procedure.nameLower || "";
15630
+ return name.includes(searchTerm) || nameLower.includes(searchTerm);
15631
+ });
15632
+ console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`);
15633
+ }
15634
+ if (filters.minPrice !== void 0 || filters.maxPrice !== void 0) {
15635
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15636
+ const price = procedure.price || 0;
15637
+ if (filters.minPrice !== void 0 && price < filters.minPrice) return false;
15638
+ if (filters.maxPrice !== void 0 && price > filters.maxPrice) return false;
15639
+ return true;
15640
+ });
15641
+ console.log(`[PROCEDURE_SERVICE] Applied price filter (${filters.minPrice}-${filters.maxPrice}), results: ${filteredProcedures.length}`);
15642
+ }
15643
+ if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
15644
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15645
+ var _a;
15646
+ const rating = ((_a = procedure.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
15647
+ if (filters.minRating !== void 0 && rating < filters.minRating) return false;
15648
+ if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
15649
+ return true;
15650
+ });
15651
+ console.log(`[PROCEDURE_SERVICE] Applied rating filter, results: ${filteredProcedures.length}`);
15652
+ }
15653
+ if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15654
+ const benefitsToMatch = filters.treatmentBenefits;
15655
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15656
+ const procedureBenefits = procedure.treatmentBenefits || [];
15657
+ return benefitsToMatch.some((benefit) => procedureBenefits.includes(benefit));
15658
+ });
15659
+ console.log(`[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`);
15660
+ }
15661
+ if (filters.procedureFamily) {
15662
+ filteredProcedures = filteredProcedures.filter((procedure) => procedure.family === filters.procedureFamily);
15663
+ console.log(`[PROCEDURE_SERVICE] Applied family filter, results: ${filteredProcedures.length}`);
15664
+ }
15665
+ if (filters.procedureCategory) {
15666
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15667
+ var _a;
15668
+ return ((_a = procedure.category) == null ? void 0 : _a.id) === filters.procedureCategory;
15669
+ });
15670
+ console.log(`[PROCEDURE_SERVICE] Applied category filter, results: ${filteredProcedures.length}`);
15671
+ }
15672
+ if (filters.procedureSubcategory) {
15673
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15674
+ var _a;
15675
+ return ((_a = procedure.subcategory) == null ? void 0 : _a.id) === filters.procedureSubcategory;
15676
+ });
15677
+ console.log(`[PROCEDURE_SERVICE] Applied subcategory filter, results: ${filteredProcedures.length}`);
15678
+ }
15679
+ if (filters.procedureTechnology) {
15680
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15681
+ var _a;
15682
+ return ((_a = procedure.technology) == null ? void 0 : _a.id) === filters.procedureTechnology;
15683
+ });
15684
+ console.log(`[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`);
15685
+ }
15686
+ if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
15687
+ const location = filters.location;
15688
+ const radiusInKm = filters.radiusInKm;
15689
+ filteredProcedures = filteredProcedures.filter((procedure) => {
15690
+ var _a;
15691
+ const clinicLocation = (_a = procedure.clinicInfo) == null ? void 0 : _a.location;
15692
+ if (!(clinicLocation == null ? void 0 : clinicLocation.latitude) || !(clinicLocation == null ? void 0 : clinicLocation.longitude)) {
15693
+ return false;
15694
+ }
15695
+ const distance = distanceBetween6(
15696
+ [location.latitude, location.longitude],
15697
+ [clinicLocation.latitude, clinicLocation.longitude]
15698
+ ) / 1e3;
15699
+ procedure.distance = distance;
15700
+ return distance <= radiusInKm;
15701
+ });
15702
+ console.log(`[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`);
15703
+ filteredProcedures.sort((a, b) => (a.distance || 0) - (b.distance || 0));
15704
+ }
15705
+ return filteredProcedures;
15706
+ }
15707
+ handleGeoQuery(filters) {
15708
+ console.log("[PROCEDURE_SERVICE] Executing geo query with enhanced debugging");
15709
+ try {
15710
+ const location = filters.location;
15711
+ const radiusInKm = filters.radiusInKm;
15712
+ console.log("[PROCEDURE_SERVICE] Geo query parameters:", {
15713
+ latitude: location.latitude,
15714
+ longitude: location.longitude,
15715
+ radiusInKm,
15716
+ pagination: filters.pagination || 10
15717
+ });
15718
+ const constraints = [
15719
+ where29("isActive", "==", true),
15720
+ orderBy17("createdAt", "desc"),
15721
+ limit15((filters.pagination || 10) * 3)
15722
+ // Get more results for geo filtering
15723
+ ];
15724
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15725
+ return getDocs29(q).then((querySnapshot) => {
15726
+ let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15727
+ procedures = this.applyInMemoryFilters(procedures, filters);
15728
+ console.log(`[PROCEDURE_SERVICE] Geo query success: ${procedures.length} procedures within ${radiusInKm}km`);
15729
+ const lastDoc = procedures.length < (filters.pagination || 10) ? null : querySnapshot.docs[querySnapshot.docs.length - 1];
15730
+ return { procedures, lastDoc };
15731
+ });
15732
+ } catch (error) {
15733
+ console.error("[PROCEDURE_SERVICE] Geo query failed:", error);
15734
+ return Promise.resolve({ procedures: [], lastDoc: null });
15283
15735
  }
15284
15736
  }
15285
15737
  /**