@blackcode_sa/metaestetics-api 1.8.12 → 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/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
- constraints.push(orderBy4("basicInfo.lastName", "asc"));
6894
- constraints.push(orderBy4("basicInfo.firstName", "asc"));
6895
- if (filters.pagination && filters.pagination > 0) {
6896
- if (filters.lastDoc) {
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
- const q = query10(
6902
- collection10(this.db, PRACTITIONERS_COLLECTION),
6903
- ...constraints
6904
- );
6905
- const querySnapshot = await getDocs10(q);
6906
- console.log(
6907
- `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
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.specialties && filters.specialties.length > 0) {
6921
- practitioners = practitioners.filter((practitioner) => {
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.procedureTechnology || filters.procedureSubcategory || filters.procedureCategory || filters.procedureFamily) {
6928
- practitioners = practitioners.filter((practitioner) => {
6929
- const procedures = practitioner.proceduresInfo || [];
6930
- return procedures.some((procedure) => {
6931
- if (filters.procedureTechnology) {
6932
- return procedure.technologyName === filters.procedureTechnology;
6933
- }
6934
- if (filters.procedureSubcategory) {
6935
- return procedure.subcategoryName === filters.procedureSubcategory;
6936
- }
6937
- if (filters.procedureCategory) {
6938
- return procedure.categoryName === filters.procedureCategory;
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
- if (filters.minRating !== void 0) {
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
@@ -8190,8 +8157,10 @@ var ClinicGroupService = class extends BaseService {
8190
8157
 
8191
8158
  // src/services/clinic/clinic.service.ts
8192
8159
  import {
8160
+ collection as collection16,
8193
8161
  doc as doc15,
8194
8162
  getDoc as getDoc18,
8163
+ getDocs as getDocs16,
8195
8164
  updateDoc as updateDoc15,
8196
8165
  serverTimestamp as serverTimestamp14,
8197
8166
  writeBatch as writeBatch4,
@@ -8665,170 +8634,66 @@ import {
8665
8634
  limit as limit9,
8666
8635
  orderBy as orderBy5
8667
8636
  } from "firebase/firestore";
8668
- import { geohashQueryBounds as geohashQueryBounds3, distanceBetween as distanceBetween4 } from "geofire-common";
8637
+ import { distanceBetween as distanceBetween4 } from "geofire-common";
8669
8638
  async function getClinicsByFilters(db, filters) {
8670
- console.log(
8671
- "[FILTER_UTILS] Starting clinic filtering with criteria:",
8672
- filters
8673
- );
8674
- const isGeoQuery = filters.center && filters.radiusInKm && filters.radiusInKm > 0;
8639
+ var _a;
8675
8640
  const constraints = [];
8676
- if (filters.isActive !== void 0) {
8677
- constraints.push(where15("isActive", "==", filters.isActive));
8678
- } else {
8679
- constraints.push(where15("isActive", "==", true));
8680
- }
8641
+ constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8681
8642
  if (filters.tags && filters.tags.length > 0) {
8682
8643
  constraints.push(where15("tags", "array-contains", filters.tags[0]));
8683
8644
  }
8684
8645
  if (filters.procedureTechnology) {
8685
- constraints.push(
8686
- where15("servicesInfo.technology", "==", filters.procedureTechnology)
8687
- );
8646
+ constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
8688
8647
  } else if (filters.procedureSubcategory) {
8689
- constraints.push(
8690
- where15("servicesInfo.subCategory", "==", filters.procedureSubcategory)
8691
- );
8648
+ constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
8692
8649
  } else if (filters.procedureCategory) {
8693
- constraints.push(
8694
- where15("servicesInfo.category", "==", filters.procedureCategory)
8695
- );
8650
+ constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
8696
8651
  } else if (filters.procedureFamily) {
8697
- constraints.push(
8698
- where15("servicesInfo.procedureFamily", "==", filters.procedureFamily)
8699
- );
8700
- }
8701
- if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
8702
- constraints.push(startAfter8(filters.lastDoc));
8703
- constraints.push(limit9(filters.pagination));
8704
- } else if (filters.pagination && filters.pagination > 0) {
8705
- constraints.push(limit9(filters.pagination));
8706
- }
8707
- constraints.push(orderBy5("location.geohash"));
8708
- let clinicsResult = [];
8709
- let lastVisibleDoc = null;
8710
- if (isGeoQuery) {
8711
- const center = filters.center;
8712
- const radiusInKm = filters.radiusInKm;
8713
- const bounds = geohashQueryBounds3(
8714
- [center.latitude, center.longitude],
8715
- radiusInKm * 1e3
8716
- // Convert to meters
8717
- );
8718
- const matchingClinics = [];
8719
- for (const bound of bounds) {
8720
- const geoConstraints = [
8721
- ...constraints,
8722
- where15("location.geohash", ">=", bound[0]),
8723
- where15("location.geohash", "<=", bound[1])
8724
- ];
8725
- const q = query15(collection15(db, CLINICS_COLLECTION), ...geoConstraints);
8726
- const querySnapshot = await getDocs15(q);
8727
- console.log(
8728
- `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
8729
- );
8730
- for (const doc37 of querySnapshot.docs) {
8731
- const clinic = { ...doc37.data(), id: doc37.id };
8732
- const distance = distanceBetween4(
8733
- [center.latitude, center.longitude],
8734
- [clinic.location.latitude, clinic.location.longitude]
8735
- );
8736
- const distanceInKm = distance / 1e3;
8737
- if (distanceInKm <= radiusInKm) {
8738
- matchingClinics.push({
8739
- ...clinic,
8740
- distance: distanceInKm
8741
- });
8742
- }
8743
- }
8744
- }
8745
- let filteredClinics = matchingClinics;
8746
- if (filters.tags && filters.tags.length > 1) {
8747
- filteredClinics = filteredClinics.filter((clinic) => {
8748
- return filters.tags.every((tag) => clinic.tags.includes(tag));
8749
- });
8750
- }
8751
- if (filters.minRating !== void 0) {
8752
- filteredClinics = filteredClinics.filter(
8753
- (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
8754
- );
8755
- }
8756
- if (filters.maxRating !== void 0) {
8757
- filteredClinics = filteredClinics.filter(
8758
- (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
8759
- );
8760
- }
8761
- filteredClinics.sort((a, b) => a.distance - b.distance);
8762
- if (filters.pagination && filters.pagination > 0) {
8763
- let startIndex = 0;
8764
- if (filters.lastDoc) {
8765
- const lastDocIndex = filteredClinics.findIndex(
8766
- (clinic) => clinic.id === filters.lastDoc.id
8767
- );
8768
- if (lastDocIndex !== -1) {
8769
- startIndex = lastDocIndex + 1;
8770
- }
8771
- }
8772
- const paginatedClinics = filteredClinics.slice(
8773
- startIndex,
8774
- startIndex + filters.pagination
8775
- );
8776
- lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
8777
- 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));
8778
8674
  } else {
8779
- clinicsResult = filteredClinics;
8675
+ constraints.push(startAfter8(filters.lastDoc));
8780
8676
  }
8781
- } else {
8782
- const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8783
- const querySnapshot = await getDocs15(q);
8784
- console.log(
8785
- `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
8786
- );
8787
- const clinics = querySnapshot.docs.map((doc37) => {
8788
- return { ...doc37.data(), id: doc37.id };
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;
8789
8693
  });
8790
- let filteredClinics = clinics;
8791
- if (filters.center) {
8792
- const center = filters.center;
8793
- const clinicsWithDistance = [];
8794
- filteredClinics.forEach((clinic) => {
8795
- const distance = distanceBetween4(
8796
- [center.latitude, center.longitude],
8797
- [clinic.location.latitude, clinic.location.longitude]
8798
- );
8799
- clinicsWithDistance.push({
8800
- ...clinic,
8801
- distance: distance / 1e3
8802
- // Convert to kilometers
8803
- });
8804
- });
8805
- filteredClinics = clinicsWithDistance;
8806
- filteredClinics.sort(
8807
- (a, b) => a.distance - b.distance
8808
- );
8809
- }
8810
- if (filters.tags && filters.tags.length > 1) {
8811
- filteredClinics = filteredClinics.filter((clinic) => {
8812
- return filters.tags.every((tag) => clinic.tags.includes(tag));
8813
- });
8814
- }
8815
- if (filters.minRating !== void 0) {
8816
- filteredClinics = filteredClinics.filter(
8817
- (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
8818
- );
8819
- }
8820
- if (filters.maxRating !== void 0) {
8821
- filteredClinics = filteredClinics.filter(
8822
- (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
8823
- );
8824
- }
8825
- lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8826
- clinicsResult = filteredClinics;
8827
8694
  }
8828
- return {
8829
- clinics: clinicsResult,
8830
- lastDoc: lastVisibleDoc
8831
- };
8695
+ const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
8696
+ return { clinics, lastDoc: lastVisibleDoc };
8832
8697
  }
8833
8698
 
8834
8699
  // src/services/clinic/clinic.service.ts
@@ -8964,6 +8829,8 @@ var ClinicService = class extends BaseService {
8964
8829
  id: clinicId,
8965
8830
  clinicGroupId: validatedData.clinicGroupId,
8966
8831
  name: validatedData.name,
8832
+ nameLower: validatedData.name.toLowerCase(),
8833
+ // Add this line
8967
8834
  description: validatedData.description,
8968
8835
  location: { ...location, geohash: hash },
8969
8836
  contactInfo: validatedData.contactInfo,
@@ -9064,6 +8931,9 @@ var ClinicService = class extends BaseService {
9064
8931
  updatePayload[field] = validatedData[field];
9065
8932
  }
9066
8933
  }
8934
+ if (validatedData.name) {
8935
+ updatePayload.nameLower = validatedData.name.toLowerCase();
8936
+ }
9067
8937
  if (validatedData.location) {
9068
8938
  const loc = validatedData.location;
9069
8939
  updatePayload.location = {
@@ -9239,6 +9109,27 @@ var ClinicService = class extends BaseService {
9239
9109
  async getClinicsByFilters(filters) {
9240
9110
  return getClinicsByFilters(this.db, filters);
9241
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
+ }
9242
9133
  };
9243
9134
 
9244
9135
  // src/services/auth/utils/firebase.utils.ts
@@ -15087,7 +14978,7 @@ var ProcedureService = class extends BaseService {
15087
14978
  }
15088
14979
  let finalCategoryId = existingProcedure.category.id;
15089
14980
  if (validatedData.name) {
15090
- updatedProcedureData.nameLower = validatedData.nameLower || validatedData.name.toLowerCase();
14981
+ updatedProcedureData.nameLower = validatedData.name.toLowerCase();
15091
14982
  }
15092
14983
  if (validatedData.categoryId) {
15093
14984
  const category = await this.categoryService.getById(
@@ -15314,7 +15205,13 @@ var ProcedureService = class extends BaseService {
15314
15205
  constraints.push(orderBy17("nameLower"));
15315
15206
  }
15316
15207
  if (filters.lastDoc) {
15317
- constraints.push(startAfter13(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
+ }
15318
15215
  }
15319
15216
  if (filters.pagination && filters.pagination > 0) {
15320
15217
  constraints.push(limit15(filters.pagination));
@@ -15493,6 +15390,29 @@ var ProcedureService = class extends BaseService {
15493
15390
  const savedDoc = await getDoc32(procedureRef);
15494
15391
  return savedDoc.data();
15495
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
+ }
15496
15416
  };
15497
15417
 
15498
15418
  // src/services/reviews/reviews.service.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.8.12",
4
+ "version": "1.8.13",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -0,0 +1,23 @@
1
+ const admin = require("firebase-admin");
2
+ const serviceAccount = require("./serviceAccountKey.json");
3
+
4
+ admin.initializeApp({
5
+ credential: admin.credential.cert(serviceAccount),
6
+ projectId: "metaestetics"
7
+ });
8
+
9
+ const db = admin.firestore();
10
+
11
+ async function migrateProcedures() {
12
+ const snapshot = await db.collection("procedures").get();
13
+ for (const doc of snapshot.docs) {
14
+ const data = doc.data();
15
+ if (!data.nameLower && data.name) {
16
+ await doc.ref.update({ nameLower: data.name.toLowerCase() });
17
+ console.log(`Updated ${doc.id}`);
18
+ }
19
+ }
20
+ console.log("Migration complete!");
21
+ }
22
+
23
+ migrateProcedures();
@@ -0,0 +1,13 @@
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "metaestetics",
4
+ "private_key_id": "e2dccd35845667bdebcea99959ca40a52f54d27f",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7yzLPjlr/6pSA\ns3Og/2kuwdAfoBr8+M2HoVlydy/WXm73u29i9ps+ilvUBB90PRkidBCaBmqOwjdV\n0MEgUWF+7Zi3PLbfuFGX929uzpAEWuNR3ZqiyrtqsnGycNw0tdccH/RM4pTgDrLP\nETyN6HlnKIcaPgpU/qKXasOYEv8UlMRuSAFG6ZjsMr15fHzECgHNUqDwHz4u1aN3\nNDwYAnucVIpCQqKjwp6nxtSO8WSLKP5P/E3J2Dob1EYEPf8UvhXwtWVXXI/rbIQe\nfnQopHSLesvw2poks9hCQXNsLNptCRG3hj1asNZ6HutMPWqQPAKss/FpkkF6/RNu\niOnWOzf/AgMBAAECggEAFnQpUx/WSZsmvmy2ep2PWgPaeq2ODIlDKeBk7YbKtXr9\nEanbm52Y2lV4vVTw3dkgVDpEceYqf39BVoVrUg3o9mA6Tk54Hy/OsbjoHfucxKiJ\nXZR9lNFgr1U+uvM7oSHM4pP/heHhoxie0Jti/iS5v1fdL4oTei4oCqq9UEWVMkSS\n52yoBH7oeH15WVp2B3KEVU7cAI5MeFXQxQ8idFfqqShhR5uQnwx8uR38b9vaq+Cy\nK5zV+dStsphVq3/gEsjmFkYe7BgpMQyHkw7kmNuISDYdy/W1G6t0kUNn5LzhJ88E\nICr1FttaNQDeBE4VgnC3Daj1hBOQyrbGszbgxmklgQKBgQDm1f3uyLwmVTsTF3sE\nsggTYsmz9AppI778IuWjhiegfmbWI5YsgGl9c9XOcBCZ+2vI7rIDeFneRxBX4TrT\nAPcT+z8AG5PiJuyOa7Nny+tNzplfPf/2X2MrQXaYvWihPWDZtXmqYY3p/Z8wkYhA\n1C/2vMLyKiP/Md7mtSBXmjgnrwKBgQDQRAQL69osb07mJDNoln+FWyQhJQoVQFSw\npPBkcic0d1gglW7ne2O43mOUG7t3EQBPgXg8xXMiv4dqz1PQpVJp4CewCklbAh/C\nfFmhWCUvgG21Sc3t0hpvsPLN3xeqVOUeB5FNhf5t+j4HqTGClD98Plks0iXVnfFO\nPmNYK764sQKBgD4W+UKtQ86bxlQQUMqmiH2OaOq6jcJSFyEC0fn2L9p/pXGcCNzX\nfYh9C9mHUy/X7NoTOlasnJ+pRcAdmREAhXUec4e340NFbQOx/IPC2fwHwkFYD+1Z\nIveTmC7lY6tbMx3cLmmh6+Ywjg0mWBv39x7LDzTMGPqfk3FC7vwhQ1GJAoGARpoY\nKRZuYsvlGl3BU75ZQpMQH3BYB7ZEP5HasKKGKeIfbQRbkXuh5cT2SvpPxeBsk4dX\nhHqHOotlU88vIbc5xgyoR6RlE8YXkC3pkKm6CW1nQ6LefbXRInYBCcuMUUDwXwq/\ntmErTIsdxikUUKkDEJJuVqRzEQS3DghWU0iZIjECgYEA5PMdyGMZJQVTzP/QjSjC\no5uEDGOAjg/wMGFfXRbKBcJZ1yoqUuSOKuuacyNborfTj3RTckl9uO/I68wnFk5p\nRNNndYQXWAmjSvPBKnRuE+eSE1eDPmpZPPBgJqwbSxUfWMprY7yEWpKF2oEbkzpD\nrUkzrniMVABYZnj8CoNV3DM=\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "firebase-adminsdk-5nsyj@metaestetics.iam.gserviceaccount.com",
7
+ "client_id": "114278988963249785723",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-5nsyj%40metaestetics.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
@@ -244,6 +244,7 @@ export class ClinicService extends BaseService {
244
244
  id: clinicId,
245
245
  clinicGroupId: validatedData.clinicGroupId,
246
246
  name: validatedData.name,
247
+ nameLower: validatedData.name.toLowerCase(), // Add this line
247
248
  description: validatedData.description,
248
249
  location: { ...location, geohash: hash },
249
250
  contactInfo: validatedData.contactInfo,
@@ -384,6 +385,11 @@ export class ClinicService extends BaseService {
384
385
  }
385
386
  }
386
387
 
388
+ // Always update nameLower if name is changed
389
+ if (validatedData.name) {
390
+ updatePayload.nameLower = validatedData.name.toLowerCase();
391
+ }
392
+
387
393
  // Handle location update with geohash
388
394
  if (validatedData.location) {
389
395
  const loc = validatedData.location;
@@ -646,4 +652,31 @@ export class ClinicService extends BaseService {
646
652
  }> {
647
653
  return FilterUtils.getClinicsByFilters(this.db, filters);
648
654
  }
655
+
656
+ /**
657
+ * Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
658
+ * This is optimized for mobile map usage to reduce payload size.
659
+ * @returns Array of minimal clinic info for map
660
+ */
661
+ async getClinicsForMap(): Promise<{
662
+ id: string;
663
+ name: string;
664
+ address: string;
665
+ latitude: number | undefined;
666
+ longitude: number | undefined;
667
+ }[]> {
668
+ const clinicsRef = collection(this.db, CLINICS_COLLECTION);
669
+ const snapshot = await getDocs(clinicsRef);
670
+ const clinicsForMap = snapshot.docs.map(doc => {
671
+ const data = doc.data();
672
+ return {
673
+ id: doc.id,
674
+ name: data.name,
675
+ address: data.location?.address || '',
676
+ latitude: data.location?.latitude,
677
+ longitude: data.location?.longitude,
678
+ };
679
+ });
680
+ return clinicsForMap;
681
+ }
649
682
  }