@blackcode_sa/metaestetics-api 1.8.11 → 1.8.13
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/admin/index.d.mts +4 -0
- package/dist/admin/index.d.ts +4 -0
- package/dist/backoffice/index.d.mts +1 -0
- package/dist/backoffice/index.d.ts +1 -0
- package/dist/index.d.mts +36 -9
- package/dist/index.d.ts +36 -9
- package/dist/index.js +218 -375
- package/dist/index.mjs +221 -376
- package/package.json +1 -1
- package/src/admin/scripts/migrateProcedures.js +23 -0
- package/src/admin/scripts/serviceAccountKey.json +13 -0
- package/src/services/clinic/clinic.service.ts +33 -0
- package/src/services/clinic/utils/filter.utils.ts +54 -225
- package/src/services/practitioner/practitioner.service.ts +48 -115
- package/src/services/procedure/procedure.service.ts +123 -249
- package/src/types/clinic/index.ts +1 -0
- package/src/types/practitioner/index.ts +1 -0
- package/src/types/procedure/index.ts +6 -0
- package/src/validations/procedure.schema.ts +3 -0
package/dist/index.mjs
CHANGED
|
@@ -6257,6 +6257,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6257
6257
|
trustworthiness: 0,
|
|
6258
6258
|
recommendationPercentage: 0
|
|
6259
6259
|
};
|
|
6260
|
+
const fullNameLower = `${validData.basicInfo.firstName} ${validData.basicInfo.lastName}`.toLowerCase();
|
|
6260
6261
|
const practitioner = {
|
|
6261
6262
|
id: practitionerId,
|
|
6262
6263
|
userRef: validData.userRef,
|
|
@@ -6264,6 +6265,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6264
6265
|
validData.basicInfo,
|
|
6265
6266
|
practitionerId
|
|
6266
6267
|
),
|
|
6268
|
+
fullNameLower,
|
|
6269
|
+
// Ensure this is present
|
|
6267
6270
|
certification: validData.certification,
|
|
6268
6271
|
clinics: validData.clinics || [],
|
|
6269
6272
|
clinicWorkingHours: validData.clinicWorkingHours || [],
|
|
@@ -6359,6 +6362,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6359
6362
|
}
|
|
6360
6363
|
const finalClinicsInfo = validatedData.clinicsInfo && validatedData.clinicsInfo.length > 0 ? validatedData.clinicsInfo : clinicsInfo;
|
|
6361
6364
|
const proceduresInfo = [];
|
|
6365
|
+
const fullNameLowerDraft = `${validatedData.basicInfo.firstName} ${validatedData.basicInfo.lastName}`.toLowerCase();
|
|
6362
6366
|
const practitionerData = {
|
|
6363
6367
|
id: practitionerId,
|
|
6364
6368
|
userRef: "",
|
|
@@ -6367,6 +6371,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6367
6371
|
validatedData.basicInfo,
|
|
6368
6372
|
practitionerId
|
|
6369
6373
|
),
|
|
6374
|
+
fullNameLower: fullNameLowerDraft,
|
|
6375
|
+
// Ensure this is present
|
|
6370
6376
|
certification: validatedData.certification,
|
|
6371
6377
|
clinics,
|
|
6372
6378
|
clinicWorkingHours: validatedData.clinicWorkingHours || [],
|
|
@@ -6872,10 +6878,6 @@ var PractitionerService = class extends BaseService {
|
|
|
6872
6878
|
*/
|
|
6873
6879
|
async getPractitionersByFilters(filters) {
|
|
6874
6880
|
try {
|
|
6875
|
-
console.log(
|
|
6876
|
-
"[PRACTITIONER_SERVICE] Starting practitioner filtering with criteria:",
|
|
6877
|
-
filters
|
|
6878
|
-
);
|
|
6879
6881
|
const constraints = [];
|
|
6880
6882
|
if (!filters.includeDraftPractitioners) {
|
|
6881
6883
|
constraints.push(where10("status", "==", "active" /* ACTIVE */));
|
|
@@ -6890,60 +6892,40 @@ var PractitionerService = class extends BaseService {
|
|
|
6890
6892
|
)
|
|
6891
6893
|
);
|
|
6892
6894
|
}
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
constraints.push(startAfter6(filters.lastDoc));
|
|
6898
|
-
}
|
|
6899
|
-
constraints.push(limit7(filters.pagination));
|
|
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"));
|
|
6900
6899
|
}
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
let practitioners = querySnapshot.docs.map((doc37) => {
|
|
6910
|
-
return { ...doc37.data(), id: doc37.id };
|
|
6911
|
-
});
|
|
6912
|
-
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6913
|
-
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
6914
|
-
const searchTerm = filters.nameSearch.toLowerCase().trim();
|
|
6915
|
-
practitioners = practitioners.filter((practitioner) => {
|
|
6916
|
-
const fullName = `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`.toLowerCase();
|
|
6917
|
-
return fullName.includes(searchTerm);
|
|
6918
|
-
});
|
|
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));
|
|
6919
6908
|
}
|
|
6920
|
-
if (filters.
|
|
6921
|
-
|
|
6922
|
-
return filters.specialties.every(
|
|
6923
|
-
(specialty) => practitioner.certification.specialties.includes(specialty)
|
|
6924
|
-
);
|
|
6925
|
-
});
|
|
6909
|
+
if (filters.minRating !== void 0) {
|
|
6910
|
+
constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
|
|
6926
6911
|
}
|
|
6927
|
-
if (filters.
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
}
|
|
6940
|
-
if (filters.procedureFamily) {
|
|
6941
|
-
return procedure.family === filters.procedureFamily;
|
|
6942
|
-
}
|
|
6943
|
-
return false;
|
|
6944
|
-
});
|
|
6945
|
-
});
|
|
6912
|
+
if (filters.maxRating !== void 0) {
|
|
6913
|
+
constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
6914
|
+
}
|
|
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));
|
|
6921
|
+
} else {
|
|
6922
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6923
|
+
}
|
|
6946
6924
|
}
|
|
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 }));
|
|
6947
6929
|
if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
|
|
6948
6930
|
const location = filters.location;
|
|
6949
6931
|
const radiusInKm = filters.radiusInKm;
|
|
@@ -6959,22 +6941,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6959
6941
|
});
|
|
6960
6942
|
});
|
|
6961
6943
|
}
|
|
6962
|
-
|
|
6963
|
-
practitioners = practitioners.filter(
|
|
6964
|
-
(p) => p.reviewInfo.averageRating >= filters.minRating
|
|
6965
|
-
);
|
|
6966
|
-
}
|
|
6967
|
-
if (filters.maxRating !== void 0) {
|
|
6968
|
-
practitioners = practitioners.filter(
|
|
6969
|
-
(p) => p.reviewInfo.averageRating <= filters.maxRating
|
|
6970
|
-
);
|
|
6971
|
-
}
|
|
6972
|
-
console.log(
|
|
6973
|
-
`[PRACTITIONER_SERVICE] Filtered to ${practitioners.length} practitioners`
|
|
6974
|
-
);
|
|
6975
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
6976
|
-
practitioners = practitioners.slice(0, filters.pagination);
|
|
6977
|
-
}
|
|
6944
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6978
6945
|
return {
|
|
6979
6946
|
practitioners,
|
|
6980
6947
|
lastDoc
|
|
@@ -7039,6 +7006,7 @@ var PractitionerService = class extends BaseService {
|
|
|
7039
7006
|
}
|
|
7040
7007
|
const consultationData = {
|
|
7041
7008
|
name: "Free Consultation",
|
|
7009
|
+
nameLower: "free consultation",
|
|
7042
7010
|
description: "Free initial consultation to discuss treatment options and assess patient needs.",
|
|
7043
7011
|
family: "aesthetics" /* AESTHETICS */,
|
|
7044
7012
|
categoryId: "consultation",
|
|
@@ -8189,8 +8157,10 @@ var ClinicGroupService = class extends BaseService {
|
|
|
8189
8157
|
|
|
8190
8158
|
// src/services/clinic/clinic.service.ts
|
|
8191
8159
|
import {
|
|
8160
|
+
collection as collection16,
|
|
8192
8161
|
doc as doc15,
|
|
8193
8162
|
getDoc as getDoc18,
|
|
8163
|
+
getDocs as getDocs16,
|
|
8194
8164
|
updateDoc as updateDoc15,
|
|
8195
8165
|
serverTimestamp as serverTimestamp14,
|
|
8196
8166
|
writeBatch as writeBatch4,
|
|
@@ -8664,170 +8634,66 @@ import {
|
|
|
8664
8634
|
limit as limit9,
|
|
8665
8635
|
orderBy as orderBy5
|
|
8666
8636
|
} from "firebase/firestore";
|
|
8667
|
-
import {
|
|
8637
|
+
import { distanceBetween as distanceBetween4 } from "geofire-common";
|
|
8668
8638
|
async function getClinicsByFilters(db, filters) {
|
|
8669
|
-
|
|
8670
|
-
"[FILTER_UTILS] Starting clinic filtering with criteria:",
|
|
8671
|
-
filters
|
|
8672
|
-
);
|
|
8673
|
-
const isGeoQuery = filters.center && filters.radiusInKm && filters.radiusInKm > 0;
|
|
8639
|
+
var _a;
|
|
8674
8640
|
const constraints = [];
|
|
8675
|
-
|
|
8676
|
-
constraints.push(where15("isActive", "==", filters.isActive));
|
|
8677
|
-
} else {
|
|
8678
|
-
constraints.push(where15("isActive", "==", true));
|
|
8679
|
-
}
|
|
8641
|
+
constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
|
|
8680
8642
|
if (filters.tags && filters.tags.length > 0) {
|
|
8681
8643
|
constraints.push(where15("tags", "array-contains", filters.tags[0]));
|
|
8682
8644
|
}
|
|
8683
8645
|
if (filters.procedureTechnology) {
|
|
8684
|
-
constraints.push(
|
|
8685
|
-
where15("servicesInfo.technology", "==", filters.procedureTechnology)
|
|
8686
|
-
);
|
|
8646
|
+
constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
|
|
8687
8647
|
} else if (filters.procedureSubcategory) {
|
|
8688
|
-
constraints.push(
|
|
8689
|
-
where15("servicesInfo.subCategory", "==", filters.procedureSubcategory)
|
|
8690
|
-
);
|
|
8648
|
+
constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
|
|
8691
8649
|
} else if (filters.procedureCategory) {
|
|
8692
|
-
constraints.push(
|
|
8693
|
-
where15("servicesInfo.category", "==", filters.procedureCategory)
|
|
8694
|
-
);
|
|
8650
|
+
constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
|
|
8695
8651
|
} else if (filters.procedureFamily) {
|
|
8696
|
-
constraints.push(
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
if (filters.
|
|
8701
|
-
|
|
8702
|
-
constraints.push(
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
}
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
if (
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
)
|
|
8717
|
-
|
|
8718
|
-
for (const bound of bounds) {
|
|
8719
|
-
const geoConstraints = [
|
|
8720
|
-
...constraints,
|
|
8721
|
-
where15("location.geohash", ">=", bound[0]),
|
|
8722
|
-
where15("location.geohash", "<=", bound[1])
|
|
8723
|
-
];
|
|
8724
|
-
const q = query15(collection15(db, CLINICS_COLLECTION), ...geoConstraints);
|
|
8725
|
-
const querySnapshot = await getDocs15(q);
|
|
8726
|
-
console.log(
|
|
8727
|
-
`[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
|
|
8728
|
-
);
|
|
8729
|
-
for (const doc37 of querySnapshot.docs) {
|
|
8730
|
-
const clinic = { ...doc37.data(), id: doc37.id };
|
|
8731
|
-
const distance = distanceBetween4(
|
|
8732
|
-
[center.latitude, center.longitude],
|
|
8733
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8734
|
-
);
|
|
8735
|
-
const distanceInKm = distance / 1e3;
|
|
8736
|
-
if (distanceInKm <= radiusInKm) {
|
|
8737
|
-
matchingClinics.push({
|
|
8738
|
-
...clinic,
|
|
8739
|
-
distance: distanceInKm
|
|
8740
|
-
});
|
|
8741
|
-
}
|
|
8742
|
-
}
|
|
8743
|
-
}
|
|
8744
|
-
let filteredClinics = matchingClinics;
|
|
8745
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8746
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8747
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8748
|
-
});
|
|
8749
|
-
}
|
|
8750
|
-
if (filters.minRating !== void 0) {
|
|
8751
|
-
filteredClinics = filteredClinics.filter(
|
|
8752
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8753
|
-
);
|
|
8754
|
-
}
|
|
8755
|
-
if (filters.maxRating !== void 0) {
|
|
8756
|
-
filteredClinics = filteredClinics.filter(
|
|
8757
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8758
|
-
);
|
|
8759
|
-
}
|
|
8760
|
-
filteredClinics.sort((a, b) => a.distance - b.distance);
|
|
8761
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
8762
|
-
let startIndex = 0;
|
|
8763
|
-
if (filters.lastDoc) {
|
|
8764
|
-
const lastDocIndex = filteredClinics.findIndex(
|
|
8765
|
-
(clinic) => clinic.id === filters.lastDoc.id
|
|
8766
|
-
);
|
|
8767
|
-
if (lastDocIndex !== -1) {
|
|
8768
|
-
startIndex = lastDocIndex + 1;
|
|
8769
|
-
}
|
|
8770
|
-
}
|
|
8771
|
-
const paginatedClinics = filteredClinics.slice(
|
|
8772
|
-
startIndex,
|
|
8773
|
-
startIndex + filters.pagination
|
|
8774
|
-
);
|
|
8775
|
-
lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
|
|
8776
|
-
clinicsResult = paginatedClinics;
|
|
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));
|
|
8777
8674
|
} else {
|
|
8778
|
-
|
|
8675
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8779
8676
|
}
|
|
8780
|
-
}
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8677
|
+
}
|
|
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 }));
|
|
8682
|
+
if (filters.tags && filters.tags.length > 1) {
|
|
8683
|
+
clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
|
|
8684
|
+
}
|
|
8685
|
+
if (filters.center && filters.radiusInKm) {
|
|
8686
|
+
clinics = clinics.filter((clinic) => {
|
|
8687
|
+
const distance = distanceBetween4(
|
|
8688
|
+
[filters.center.latitude, filters.center.longitude],
|
|
8689
|
+
[clinic.location.latitude, clinic.location.longitude]
|
|
8690
|
+
) / 1e3;
|
|
8691
|
+
clinic.distance = distance;
|
|
8692
|
+
return distance <= filters.radiusInKm;
|
|
8788
8693
|
});
|
|
8789
|
-
let filteredClinics = clinics;
|
|
8790
|
-
if (filters.center) {
|
|
8791
|
-
const center = filters.center;
|
|
8792
|
-
const clinicsWithDistance = [];
|
|
8793
|
-
filteredClinics.forEach((clinic) => {
|
|
8794
|
-
const distance = distanceBetween4(
|
|
8795
|
-
[center.latitude, center.longitude],
|
|
8796
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8797
|
-
);
|
|
8798
|
-
clinicsWithDistance.push({
|
|
8799
|
-
...clinic,
|
|
8800
|
-
distance: distance / 1e3
|
|
8801
|
-
// Convert to kilometers
|
|
8802
|
-
});
|
|
8803
|
-
});
|
|
8804
|
-
filteredClinics = clinicsWithDistance;
|
|
8805
|
-
filteredClinics.sort(
|
|
8806
|
-
(a, b) => a.distance - b.distance
|
|
8807
|
-
);
|
|
8808
|
-
}
|
|
8809
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8810
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8811
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8812
|
-
});
|
|
8813
|
-
}
|
|
8814
|
-
if (filters.minRating !== void 0) {
|
|
8815
|
-
filteredClinics = filteredClinics.filter(
|
|
8816
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8817
|
-
);
|
|
8818
|
-
}
|
|
8819
|
-
if (filters.maxRating !== void 0) {
|
|
8820
|
-
filteredClinics = filteredClinics.filter(
|
|
8821
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8822
|
-
);
|
|
8823
|
-
}
|
|
8824
|
-
lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8825
|
-
clinicsResult = filteredClinics;
|
|
8826
8694
|
}
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
lastDoc: lastVisibleDoc
|
|
8830
|
-
};
|
|
8695
|
+
const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8696
|
+
return { clinics, lastDoc: lastVisibleDoc };
|
|
8831
8697
|
}
|
|
8832
8698
|
|
|
8833
8699
|
// src/services/clinic/clinic.service.ts
|
|
@@ -8963,6 +8829,8 @@ var ClinicService = class extends BaseService {
|
|
|
8963
8829
|
id: clinicId,
|
|
8964
8830
|
clinicGroupId: validatedData.clinicGroupId,
|
|
8965
8831
|
name: validatedData.name,
|
|
8832
|
+
nameLower: validatedData.name.toLowerCase(),
|
|
8833
|
+
// Add this line
|
|
8966
8834
|
description: validatedData.description,
|
|
8967
8835
|
location: { ...location, geohash: hash },
|
|
8968
8836
|
contactInfo: validatedData.contactInfo,
|
|
@@ -9063,6 +8931,9 @@ var ClinicService = class extends BaseService {
|
|
|
9063
8931
|
updatePayload[field] = validatedData[field];
|
|
9064
8932
|
}
|
|
9065
8933
|
}
|
|
8934
|
+
if (validatedData.name) {
|
|
8935
|
+
updatePayload.nameLower = validatedData.name.toLowerCase();
|
|
8936
|
+
}
|
|
9066
8937
|
if (validatedData.location) {
|
|
9067
8938
|
const loc = validatedData.location;
|
|
9068
8939
|
updatePayload.location = {
|
|
@@ -9238,6 +9109,27 @@ var ClinicService = class extends BaseService {
|
|
|
9238
9109
|
async getClinicsByFilters(filters) {
|
|
9239
9110
|
return getClinicsByFilters(this.db, filters);
|
|
9240
9111
|
}
|
|
9112
|
+
/**
|
|
9113
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
9114
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
9115
|
+
* @returns Array of minimal clinic info for map
|
|
9116
|
+
*/
|
|
9117
|
+
async getClinicsForMap() {
|
|
9118
|
+
const clinicsRef = collection16(this.db, CLINICS_COLLECTION);
|
|
9119
|
+
const snapshot = await getDocs16(clinicsRef);
|
|
9120
|
+
const clinicsForMap = snapshot.docs.map((doc37) => {
|
|
9121
|
+
var _a, _b, _c;
|
|
9122
|
+
const data = doc37.data();
|
|
9123
|
+
return {
|
|
9124
|
+
id: doc37.id,
|
|
9125
|
+
name: data.name,
|
|
9126
|
+
address: ((_a = data.location) == null ? void 0 : _a.address) || "",
|
|
9127
|
+
latitude: (_b = data.location) == null ? void 0 : _b.latitude,
|
|
9128
|
+
longitude: (_c = data.location) == null ? void 0 : _c.longitude
|
|
9129
|
+
};
|
|
9130
|
+
});
|
|
9131
|
+
return clinicsForMap;
|
|
9132
|
+
}
|
|
9241
9133
|
};
|
|
9242
9134
|
|
|
9243
9135
|
// src/services/auth/utils/firebase.utils.ts
|
|
@@ -14568,6 +14460,7 @@ import {
|
|
|
14568
14460
|
import { z as z24 } from "zod";
|
|
14569
14461
|
var createProcedureSchema = z24.object({
|
|
14570
14462
|
name: z24.string().min(1).max(200),
|
|
14463
|
+
nameLower: z24.string().min(1).max(200),
|
|
14571
14464
|
description: z24.string().min(1).max(2e3),
|
|
14572
14465
|
family: z24.nativeEnum(ProcedureFamily),
|
|
14573
14466
|
categoryId: z24.string().min(1),
|
|
@@ -14585,6 +14478,7 @@ var createProcedureSchema = z24.object({
|
|
|
14585
14478
|
});
|
|
14586
14479
|
var updateProcedureSchema = z24.object({
|
|
14587
14480
|
name: z24.string().min(3).max(100).optional(),
|
|
14481
|
+
nameLower: z24.string().min(1).max(200).optional(),
|
|
14588
14482
|
description: z24.string().min(3).max(1e3).optional(),
|
|
14589
14483
|
price: z24.number().min(0).optional(),
|
|
14590
14484
|
currency: z24.nativeEnum(Currency).optional(),
|
|
@@ -14601,6 +14495,7 @@ var updateProcedureSchema = z24.object({
|
|
|
14601
14495
|
});
|
|
14602
14496
|
var procedureSchema = createProcedureSchema.extend({
|
|
14603
14497
|
id: z24.string().min(1),
|
|
14498
|
+
nameLower: z24.string().min(1).max(200),
|
|
14604
14499
|
category: z24.any(),
|
|
14605
14500
|
// We'll validate the full category object separately
|
|
14606
14501
|
subcategory: z24.any(),
|
|
@@ -14769,6 +14664,7 @@ var ProcedureService = class extends BaseService {
|
|
|
14769
14664
|
const newProcedure = {
|
|
14770
14665
|
id: procedureId,
|
|
14771
14666
|
...validatedData,
|
|
14667
|
+
nameLower: validatedData.nameLower || validatedData.name.toLowerCase(),
|
|
14772
14668
|
photos: processedPhotos,
|
|
14773
14669
|
category,
|
|
14774
14670
|
// Embed full objects
|
|
@@ -14902,6 +14798,7 @@ var ProcedureService = class extends BaseService {
|
|
|
14902
14798
|
const newProcedure = {
|
|
14903
14799
|
id: procedureId,
|
|
14904
14800
|
...validatedData,
|
|
14801
|
+
nameLower: validatedData.nameLower || validatedData.name.toLowerCase(),
|
|
14905
14802
|
practitionerId,
|
|
14906
14803
|
// Override practitionerId with the correct one
|
|
14907
14804
|
photos: processedPhotos,
|
|
@@ -15080,6 +14977,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15080
14977
|
};
|
|
15081
14978
|
}
|
|
15082
14979
|
let finalCategoryId = existingProcedure.category.id;
|
|
14980
|
+
if (validatedData.name) {
|
|
14981
|
+
updatedProcedureData.nameLower = validatedData.name.toLowerCase();
|
|
14982
|
+
}
|
|
15083
14983
|
if (validatedData.categoryId) {
|
|
15084
14984
|
const category = await this.categoryService.getById(
|
|
15085
14985
|
validatedData.categoryId
|
|
@@ -15237,6 +15137,8 @@ var ProcedureService = class extends BaseService {
|
|
|
15237
15137
|
/**
|
|
15238
15138
|
* Searches and filters procedures based on multiple criteria
|
|
15239
15139
|
*
|
|
15140
|
+
* @note Frontend MORA da šalje ceo snapshot (ili barem sva polja po kojima sortiraš, npr. nameLower) kao lastDoc za paginaciju, a ne samo id!
|
|
15141
|
+
*
|
|
15240
15142
|
* @param filters - Various filters to apply
|
|
15241
15143
|
* @param filters.nameSearch - Optional search text for procedure name
|
|
15242
15144
|
* @param filters.treatmentBenefits - Optional array of treatment benefits to filter by
|
|
@@ -15257,10 +15159,6 @@ var ProcedureService = class extends BaseService {
|
|
|
15257
15159
|
*/
|
|
15258
15160
|
async getProceduresByFilters(filters) {
|
|
15259
15161
|
try {
|
|
15260
|
-
console.log(
|
|
15261
|
-
"[PROCEDURE_SERVICE] Starting procedure filtering with criteria:",
|
|
15262
|
-
filters
|
|
15263
|
-
);
|
|
15264
15162
|
const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
|
|
15265
15163
|
const constraints = [];
|
|
15266
15164
|
if (filters.isActive !== void 0) {
|
|
@@ -15271,15 +15169,53 @@ var ProcedureService = class extends BaseService {
|
|
|
15271
15169
|
if (filters.procedureFamily) {
|
|
15272
15170
|
constraints.push(where29("family", "==", filters.procedureFamily));
|
|
15273
15171
|
}
|
|
15274
|
-
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
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));
|
|
15195
|
+
}
|
|
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"));
|
|
15206
|
+
}
|
|
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));
|
|
15212
|
+
} else {
|
|
15213
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15214
|
+
}
|
|
15215
|
+
}
|
|
15216
|
+
if (filters.pagination && filters.pagination > 0) {
|
|
15279
15217
|
constraints.push(limit15(filters.pagination));
|
|
15280
15218
|
}
|
|
15281
|
-
let proceduresResult = [];
|
|
15282
|
-
let lastVisibleDoc = null;
|
|
15283
15219
|
if (isGeoQuery) {
|
|
15284
15220
|
const center = filters.location;
|
|
15285
15221
|
const radiusInKm = filters.radiusInKm;
|
|
@@ -15288,178 +15224,63 @@ var ProcedureService = class extends BaseService {
|
|
|
15288
15224
|
radiusInKm * 1e3
|
|
15289
15225
|
// Convert to meters
|
|
15290
15226
|
);
|
|
15291
|
-
|
|
15227
|
+
let allDocs = [];
|
|
15292
15228
|
for (const bound of bounds) {
|
|
15293
15229
|
const geoConstraints = [
|
|
15294
|
-
...constraints,
|
|
15230
|
+
...constraints.filter((c) => !c.fieldPath || c.fieldPath !== "name"),
|
|
15231
|
+
// Remove name orderBy for geo
|
|
15295
15232
|
where29("clinicInfo.location.geohash", ">=", bound[0]),
|
|
15296
|
-
where29("clinicInfo.location.geohash", "<=", bound[1])
|
|
15233
|
+
where29("clinicInfo.location.geohash", "<=", bound[1]),
|
|
15234
|
+
orderBy17("clinicInfo.location.geohash")
|
|
15297
15235
|
];
|
|
15298
|
-
const q = query29(
|
|
15299
|
-
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15300
|
-
...geoConstraints
|
|
15301
|
-
);
|
|
15236
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...geoConstraints);
|
|
15302
15237
|
const querySnapshot = await getDocs29(q);
|
|
15303
|
-
console.log(
|
|
15304
|
-
`[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
|
|
15305
|
-
);
|
|
15306
15238
|
for (const doc37 of querySnapshot.docs) {
|
|
15307
15239
|
const procedure = { ...doc37.data(), id: doc37.id };
|
|
15308
15240
|
const distance = distanceBetween6(
|
|
15309
15241
|
[center.latitude, center.longitude],
|
|
15310
|
-
[
|
|
15311
|
-
procedure.clinicInfo.location.latitude,
|
|
15312
|
-
procedure.clinicInfo.location.longitude
|
|
15313
|
-
]
|
|
15242
|
+
[procedure.clinicInfo.location.latitude, procedure.clinicInfo.location.longitude]
|
|
15314
15243
|
);
|
|
15315
15244
|
const distanceInKm = distance / 1e3;
|
|
15316
15245
|
if (distanceInKm <= radiusInKm) {
|
|
15317
|
-
|
|
15318
|
-
...procedure,
|
|
15319
|
-
distance: distanceInKm
|
|
15320
|
-
});
|
|
15246
|
+
allDocs.push({ ...procedure, distance: distanceInKm });
|
|
15321
15247
|
}
|
|
15322
15248
|
}
|
|
15323
15249
|
}
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
filteredProcedures,
|
|
15327
|
-
filters
|
|
15328
|
-
);
|
|
15329
|
-
filteredProcedures.sort((a, b) => a.distance - b.distance);
|
|
15250
|
+
allDocs.sort((a, b) => a.distance - b.distance);
|
|
15251
|
+
let paginated = allDocs;
|
|
15330
15252
|
if (filters.pagination && filters.pagination > 0) {
|
|
15331
15253
|
let startIndex = 0;
|
|
15332
15254
|
if (filters.lastDoc) {
|
|
15333
|
-
const lastDocIndex =
|
|
15334
|
-
|
|
15335
|
-
);
|
|
15336
|
-
if (lastDocIndex !== -1) {
|
|
15337
|
-
startIndex = lastDocIndex + 1;
|
|
15338
|
-
}
|
|
15255
|
+
const lastDocIndex = allDocs.findIndex((p) => p.id === filters.lastDoc.id);
|
|
15256
|
+
if (lastDocIndex !== -1) startIndex = lastDocIndex + 1;
|
|
15339
15257
|
}
|
|
15340
|
-
|
|
15341
|
-
startIndex,
|
|
15342
|
-
startIndex + filters.pagination
|
|
15343
|
-
);
|
|
15344
|
-
lastVisibleDoc = paginatedProcedures.length > 0 ? paginatedProcedures[paginatedProcedures.length - 1] : null;
|
|
15345
|
-
proceduresResult = paginatedProcedures;
|
|
15346
|
-
} else {
|
|
15347
|
-
proceduresResult = filteredProcedures;
|
|
15258
|
+
paginated = allDocs.slice(startIndex, startIndex + filters.pagination);
|
|
15348
15259
|
}
|
|
15260
|
+
const lastVisibleDoc = paginated.length > 0 ? paginated[paginated.length - 1] : null;
|
|
15261
|
+
return { procedures: paginated, lastDoc: lastVisibleDoc };
|
|
15349
15262
|
} else {
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
if (filters.location) {
|
|
15362
|
-
const center = filters.location;
|
|
15363
|
-
const proceduresWithDistance = [];
|
|
15364
|
-
procedures.forEach((procedure) => {
|
|
15365
|
-
const distance = distanceBetween6(
|
|
15366
|
-
[center.latitude, center.longitude],
|
|
15367
|
-
[
|
|
15368
|
-
procedure.clinicInfo.location.latitude,
|
|
15369
|
-
procedure.clinicInfo.location.longitude
|
|
15370
|
-
]
|
|
15371
|
-
);
|
|
15372
|
-
proceduresWithDistance.push({
|
|
15373
|
-
...procedure,
|
|
15374
|
-
distance: distance / 1e3
|
|
15375
|
-
// Convert to kilometers
|
|
15376
|
-
});
|
|
15377
|
-
});
|
|
15378
|
-
let filteredProcedures = proceduresWithDistance;
|
|
15379
|
-
filteredProcedures = this.applyInMemoryFilters(
|
|
15380
|
-
filteredProcedures,
|
|
15381
|
-
filters
|
|
15382
|
-
);
|
|
15383
|
-
filteredProcedures.sort((a, b) => a.distance - b.distance);
|
|
15384
|
-
proceduresResult = filteredProcedures;
|
|
15385
|
-
} else {
|
|
15386
|
-
let filteredProcedures = this.applyInMemoryFilters(
|
|
15387
|
-
procedures,
|
|
15388
|
-
filters
|
|
15389
|
-
);
|
|
15390
|
-
proceduresResult = filteredProcedures;
|
|
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();
|
|
15269
|
+
constraints.push(where29("name", ">=", searchTerm));
|
|
15270
|
+
constraints.push(where29("name", "<=", searchTerm + "\uF8FF"));
|
|
15271
|
+
constraints.push(orderBy17("name"));
|
|
15272
|
+
q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15273
|
+
querySnapshot = await getDocs29(q);
|
|
15391
15274
|
}
|
|
15392
|
-
|
|
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 };
|
|
15393
15278
|
}
|
|
15394
|
-
return {
|
|
15395
|
-
procedures: proceduresResult,
|
|
15396
|
-
lastDoc: lastVisibleDoc
|
|
15397
|
-
};
|
|
15398
15279
|
} catch (error) {
|
|
15399
15280
|
console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
|
|
15400
15281
|
throw error;
|
|
15401
15282
|
}
|
|
15402
15283
|
}
|
|
15403
|
-
/**
|
|
15404
|
-
* Helper method to apply in-memory filters to procedures
|
|
15405
|
-
* Used by getProceduresByFilters to apply filters that can't be done in Firestore queries
|
|
15406
|
-
*
|
|
15407
|
-
* @param procedures - The procedures to filter
|
|
15408
|
-
* @param filters - The filters to apply
|
|
15409
|
-
* @returns Filtered procedures
|
|
15410
|
-
*/
|
|
15411
|
-
applyInMemoryFilters(procedures, filters) {
|
|
15412
|
-
let filteredProcedures = procedures;
|
|
15413
|
-
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
15414
|
-
const searchTerm = filters.nameSearch.toLowerCase().trim();
|
|
15415
|
-
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
15416
|
-
return procedure.name.toLowerCase().includes(searchTerm);
|
|
15417
|
-
});
|
|
15418
|
-
}
|
|
15419
|
-
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
15420
|
-
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
15421
|
-
return filters.treatmentBenefits.every(
|
|
15422
|
-
(benefit) => procedure.treatmentBenefits.includes(benefit)
|
|
15423
|
-
);
|
|
15424
|
-
});
|
|
15425
|
-
}
|
|
15426
|
-
if (filters.procedureCategory) {
|
|
15427
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15428
|
-
(procedure) => procedure.category.id === filters.procedureCategory
|
|
15429
|
-
);
|
|
15430
|
-
}
|
|
15431
|
-
if (filters.procedureSubcategory) {
|
|
15432
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15433
|
-
(procedure) => procedure.subcategory.id === filters.procedureSubcategory
|
|
15434
|
-
);
|
|
15435
|
-
}
|
|
15436
|
-
if (filters.procedureTechnology) {
|
|
15437
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15438
|
-
(procedure) => procedure.technology.id === filters.procedureTechnology
|
|
15439
|
-
);
|
|
15440
|
-
}
|
|
15441
|
-
if (filters.minPrice !== void 0) {
|
|
15442
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15443
|
-
(procedure) => procedure.price >= filters.minPrice
|
|
15444
|
-
);
|
|
15445
|
-
}
|
|
15446
|
-
if (filters.maxPrice !== void 0) {
|
|
15447
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15448
|
-
(procedure) => procedure.price <= filters.maxPrice
|
|
15449
|
-
);
|
|
15450
|
-
}
|
|
15451
|
-
if (filters.minRating !== void 0) {
|
|
15452
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15453
|
-
(procedure) => procedure.reviewInfo.averageRating >= filters.minRating
|
|
15454
|
-
);
|
|
15455
|
-
}
|
|
15456
|
-
if (filters.maxRating !== void 0) {
|
|
15457
|
-
filteredProcedures = filteredProcedures.filter(
|
|
15458
|
-
(procedure) => procedure.reviewInfo.averageRating <= filters.maxRating
|
|
15459
|
-
);
|
|
15460
|
-
}
|
|
15461
|
-
return filteredProcedures;
|
|
15462
|
-
}
|
|
15463
15284
|
/**
|
|
15464
15285
|
* Creates a consultation procedure without requiring a product
|
|
15465
15286
|
* This is a special method for consultation procedures that don't use products
|
|
@@ -15532,6 +15353,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15532
15353
|
const newProcedure = {
|
|
15533
15354
|
id: procedureId,
|
|
15534
15355
|
...data,
|
|
15356
|
+
nameLower: data.nameLower || data.name.toLowerCase(),
|
|
15535
15357
|
photos: processedPhotos,
|
|
15536
15358
|
category,
|
|
15537
15359
|
subcategory,
|
|
@@ -15568,6 +15390,29 @@ var ProcedureService = class extends BaseService {
|
|
|
15568
15390
|
const savedDoc = await getDoc32(procedureRef);
|
|
15569
15391
|
return savedDoc.data();
|
|
15570
15392
|
}
|
|
15393
|
+
/**
|
|
15394
|
+
* Gets all procedures with minimal info for map display (id, name, clinicId, clinicName, address, latitude, longitude)
|
|
15395
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
15396
|
+
* @returns Array of minimal procedure info for map
|
|
15397
|
+
*/
|
|
15398
|
+
async getProceduresForMap() {
|
|
15399
|
+
const proceduresRef = collection29(this.db, PROCEDURES_COLLECTION);
|
|
15400
|
+
const snapshot = await getDocs29(proceduresRef);
|
|
15401
|
+
const proceduresForMap = snapshot.docs.map((doc37) => {
|
|
15402
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
15403
|
+
const data = doc37.data();
|
|
15404
|
+
return {
|
|
15405
|
+
id: doc37.id,
|
|
15406
|
+
name: data.name,
|
|
15407
|
+
clinicId: (_a = data.clinicInfo) == null ? void 0 : _a.id,
|
|
15408
|
+
clinicName: (_b = data.clinicInfo) == null ? void 0 : _b.name,
|
|
15409
|
+
address: ((_d = (_c = data.clinicInfo) == null ? void 0 : _c.location) == null ? void 0 : _d.address) || "",
|
|
15410
|
+
latitude: (_f = (_e = data.clinicInfo) == null ? void 0 : _e.location) == null ? void 0 : _f.latitude,
|
|
15411
|
+
longitude: (_h = (_g = data.clinicInfo) == null ? void 0 : _g.location) == null ? void 0 : _h.longitude
|
|
15412
|
+
};
|
|
15413
|
+
});
|
|
15414
|
+
return proceduresForMap;
|
|
15415
|
+
}
|
|
15571
15416
|
};
|
|
15572
15417
|
|
|
15573
15418
|
// src/services/reviews/reviews.service.ts
|