@blackcode_sa/metaestetics-api 1.8.14 → 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.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +535 -213
- package/dist/index.mjs +536 -214
- package/package.json +1 -1
- package/src/services/clinic/utils/filter.utils.ts +242 -57
- package/src/services/practitioner/practitioner.service.ts +191 -80
- package/src/services/procedure/procedure.service.ts +279 -123
package/dist/index.mjs
CHANGED
|
@@ -6879,80 +6879,163 @@ var PractitionerService = class extends BaseService {
|
|
|
6879
6879
|
*/
|
|
6880
6880
|
async getPractitionersByFilters(filters) {
|
|
6881
6881
|
try {
|
|
6882
|
-
|
|
6883
|
-
if (
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
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
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
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
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
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));
|
|
6922
6951
|
} else {
|
|
6923
|
-
|
|
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}`);
|
|
6924
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);
|
|
6925
7002
|
}
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
const
|
|
6941
|
-
|
|
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);
|
|
6942
7022
|
});
|
|
6943
|
-
|
|
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);
|
|
6944
7033
|
}
|
|
6945
|
-
|
|
6946
|
-
return {
|
|
6947
|
-
practitioners,
|
|
6948
|
-
lastDoc
|
|
6949
|
-
};
|
|
7034
|
+
console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
|
|
7035
|
+
return { practitioners: [], lastDoc: null };
|
|
6950
7036
|
} catch (error) {
|
|
6951
|
-
console.error(
|
|
6952
|
-
|
|
6953
|
-
error
|
|
6954
|
-
);
|
|
6955
|
-
throw error;
|
|
7037
|
+
console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
|
|
7038
|
+
return { practitioners: [], lastDoc: null };
|
|
6956
7039
|
}
|
|
6957
7040
|
}
|
|
6958
7041
|
/**
|
|
@@ -8637,49 +8720,181 @@ import {
|
|
|
8637
8720
|
} from "firebase/firestore";
|
|
8638
8721
|
import { distanceBetween as distanceBetween4 } from "geofire-common";
|
|
8639
8722
|
async function getClinicsByFilters(db, filters) {
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
constraints
|
|
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);
|
|
8677
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 };
|
|
8678
8895
|
}
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
const querySnapshot = await getDocs15(q);
|
|
8682
|
-
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8896
|
+
}
|
|
8897
|
+
function applyInMemoryFilters(clinics, filters) {
|
|
8683
8898
|
if (filters.tags && filters.tags.length > 1) {
|
|
8684
8899
|
clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
|
|
8685
8900
|
}
|
|
@@ -8692,9 +8907,9 @@ async function getClinicsByFilters(db, filters) {
|
|
|
8692
8907
|
clinic.distance = distance;
|
|
8693
8908
|
return distance <= filters.radiusInKm;
|
|
8694
8909
|
});
|
|
8910
|
+
clinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
|
|
8695
8911
|
}
|
|
8696
|
-
|
|
8697
|
-
return { clinics, lastDoc: lastVisibleDoc };
|
|
8912
|
+
return clinics;
|
|
8698
8913
|
}
|
|
8699
8914
|
|
|
8700
8915
|
// src/services/clinic/clinic.service.ts
|
|
@@ -14531,7 +14746,7 @@ var procedureSchema = createProcedureSchema.extend({
|
|
|
14531
14746
|
});
|
|
14532
14747
|
|
|
14533
14748
|
// src/services/procedure/procedure.service.ts
|
|
14534
|
-
import { distanceBetween as distanceBetween6
|
|
14749
|
+
import { distanceBetween as distanceBetween6 } from "geofire-common";
|
|
14535
14750
|
var ProcedureService = class extends BaseService {
|
|
14536
14751
|
constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService, mediaService) {
|
|
14537
14752
|
super(db, auth, app);
|
|
@@ -15160,126 +15375,233 @@ var ProcedureService = class extends BaseService {
|
|
|
15160
15375
|
*/
|
|
15161
15376
|
async getProceduresByFilters(filters) {
|
|
15162
15377
|
try {
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
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));
|
|
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
|
+
}
|
|
15196
15390
|
}
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
|
|
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"));
|
|
15391
|
+
const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
|
|
15392
|
+
if (isGeoQuery) {
|
|
15393
|
+
return this.handleGeoQuery(filters);
|
|
15207
15394
|
}
|
|
15208
|
-
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
|
|
15212
|
-
constraints.push(startAfter13(...filters.lastDoc));
|
|
15395
|
+
const getBaseConstraints = () => {
|
|
15396
|
+
const constraints = [];
|
|
15397
|
+
if (filters.isActive !== void 0) {
|
|
15398
|
+
constraints.push(where29("isActive", "==", filters.isActive));
|
|
15213
15399
|
} else {
|
|
15214
|
-
constraints.push(
|
|
15400
|
+
constraints.push(where29("isActive", "==", true));
|
|
15215
15401
|
}
|
|
15216
|
-
|
|
15217
|
-
|
|
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
|
-
}
|
|
15402
|
+
if (filters.procedureFamily) {
|
|
15403
|
+
constraints.push(where29("family", "==", filters.procedureFamily));
|
|
15250
15404
|
}
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
|
|
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"));
|
|
15255
15439
|
if (filters.lastDoc) {
|
|
15256
|
-
|
|
15257
|
-
|
|
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 };
|
|
15258
15456
|
}
|
|
15259
|
-
|
|
15457
|
+
return { procedures, lastDoc };
|
|
15458
|
+
} catch (error) {
|
|
15459
|
+
console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
|
|
15260
15460
|
}
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
constraints.pop();
|
|
15268
|
-
constraints.pop();
|
|
15269
|
-
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();
|
|
15270
15467
|
constraints.push(where29("name", ">=", searchTerm));
|
|
15271
15468
|
constraints.push(where29("name", "<=", searchTerm + "\uF8FF"));
|
|
15272
15469
|
constraints.push(orderBy17("name"));
|
|
15273
|
-
|
|
15274
|
-
|
|
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}`);
|
|
15275
15546
|
}
|
|
15276
|
-
const
|
|
15277
|
-
|
|
15278
|
-
|
|
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);
|
|
15279
15555
|
}
|
|
15556
|
+
console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
|
|
15557
|
+
return { procedures: [], lastDoc: null };
|
|
15280
15558
|
} catch (error) {
|
|
15281
15559
|
console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
|
|
15282
|
-
|
|
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 });
|
|
15283
15605
|
}
|
|
15284
15606
|
}
|
|
15285
15607
|
/**
|