@blackcode_sa/metaestetics-api 1.8.18 → 1.10.0

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
@@ -8342,9 +8342,7 @@ import {
8342
8342
  writeBatch as writeBatch4,
8343
8343
  arrayUnion as arrayUnion7
8344
8344
  } from "firebase/firestore";
8345
- import {
8346
- geohashForLocation as geohashForLocation4
8347
- } from "geofire-common";
8345
+ import { geohashForLocation as geohashForLocation4 } from "geofire-common";
8348
8346
  import { z as z20 } from "zod";
8349
8347
 
8350
8348
  // src/services/clinic/utils/clinic.utils.ts
@@ -8810,8 +8808,9 @@ import {
8810
8808
  limit as limit9,
8811
8809
  orderBy as orderBy5
8812
8810
  } from "firebase/firestore";
8813
- import { distanceBetween as distanceBetween4 } from "geofire-common";
8811
+ import { geohashQueryBounds as geohashQueryBounds3, distanceBetween as distanceBetween4 } from "geofire-common";
8814
8812
  async function getClinicsByFilters(db, filters) {
8813
+ var _a;
8815
8814
  try {
8816
8815
  console.log("[CLINIC_SERVICE] Starting clinic filtering with multiple strategies");
8817
8816
  if (filters.center && filters.radiusInKm) {
@@ -8826,10 +8825,53 @@ async function getClinicsByFilters(db, filters) {
8826
8825
  filters.radiusInKm = void 0;
8827
8826
  }
8828
8827
  }
8828
+ if (filters.center && filters.radiusInKm) {
8829
+ try {
8830
+ console.log("[CLINIC_SERVICE] Strategy 0: Geohash bounds prefilter");
8831
+ const bounds = geohashQueryBounds3(
8832
+ [filters.center.latitude, filters.center.longitude],
8833
+ (filters.radiusInKm || 0) * 1e3
8834
+ );
8835
+ const collected = [];
8836
+ for (const b of bounds) {
8837
+ const constraints = [
8838
+ where15("location.geohash", ">=", b[0]),
8839
+ where15("location.geohash", "<=", b[1]),
8840
+ where15("isActive", "==", (_a = filters.isActive) != null ? _a : true)
8841
+ ];
8842
+ if (filters.tags && filters.tags.length > 0) {
8843
+ constraints.push(where15("tags", "array-contains", filters.tags[0]));
8844
+ }
8845
+ const q0 = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
8846
+ const snap = await getDocs15(q0);
8847
+ snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
8848
+ }
8849
+ const uniqueMap = /* @__PURE__ */ new Map();
8850
+ for (const c of collected) {
8851
+ uniqueMap.set(c.id, c);
8852
+ }
8853
+ let clinics = Array.from(uniqueMap.values());
8854
+ clinics = applyInMemoryFilters(clinics, filters);
8855
+ const pageSize = filters.pagination || 5;
8856
+ let startIndex = 0;
8857
+ if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
8858
+ const idx = clinics.findIndex((c) => c.id === filters.lastDoc.id);
8859
+ if (idx >= 0) startIndex = idx + 1;
8860
+ }
8861
+ const page = clinics.slice(startIndex, startIndex + pageSize);
8862
+ const newLastDoc = page.length === pageSize ? page[page.length - 1] : null;
8863
+ console.log(
8864
+ `[CLINIC_SERVICE] Strategy 0 success: ${page.length} clinics (of ${clinics.length})`
8865
+ );
8866
+ return { clinics: page, lastDoc: newLastDoc };
8867
+ } catch (geoErr) {
8868
+ console.log("[CLINIC_SERVICE] Strategy 0 failed:", geoErr);
8869
+ }
8870
+ }
8829
8871
  const getBaseConstraints = () => {
8830
- var _a;
8872
+ var _a2;
8831
8873
  const constraints = [];
8832
- constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8874
+ constraints.push(where15("isActive", "==", (_a2 = filters.isActive) != null ? _a2 : true));
8833
8875
  if (filters.tags && filters.tags.length > 0) {
8834
8876
  constraints.push(where15("tags", "array-contains", filters.tags[0]));
8835
8877
  }
@@ -8906,7 +8948,9 @@ async function getClinicsByFilters(db, filters) {
8906
8948
  }
8907
8949
  }
8908
8950
  try {
8909
- console.log("[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering");
8951
+ console.log(
8952
+ "[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering"
8953
+ );
8910
8954
  const constraints = getBaseConstraints();
8911
8955
  constraints.push(orderBy5("createdAt", "desc"));
8912
8956
  if (filters.lastDoc) {
@@ -8961,20 +9005,24 @@ async function getClinicsByFilters(db, filters) {
8961
9005
  }
8962
9006
  function applyInMemoryFilters(clinics, filters) {
8963
9007
  let filteredClinics = [...clinics];
8964
- console.log(`[CLINIC_SERVICE] Applying in-memory filters - input: ${filteredClinics.length} clinics`);
9008
+ console.log(
9009
+ `[CLINIC_SERVICE] Applying in-memory filters - input: ${filteredClinics.length} clinics`
9010
+ );
8965
9011
  if (filters.tags && filters.tags.length > 1) {
8966
9012
  const initialCount = filteredClinics.length;
8967
9013
  filteredClinics = filteredClinics.filter(
8968
9014
  (clinic) => filters.tags.every((tag) => clinic.tags.includes(tag))
8969
9015
  );
8970
- console.log(`[CLINIC_SERVICE] Applied multi-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9016
+ console.log(
9017
+ `[CLINIC_SERVICE] Applied multi-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`
9018
+ );
8971
9019
  }
8972
9020
  if (filters.tags && filters.tags.length === 1) {
8973
9021
  const initialCount = filteredClinics.length;
8974
- filteredClinics = filteredClinics.filter(
8975
- (clinic) => clinic.tags.includes(filters.tags[0])
9022
+ filteredClinics = filteredClinics.filter((clinic) => clinic.tags.includes(filters.tags[0]));
9023
+ console.log(
9024
+ `[CLINIC_SERVICE] Applied single-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`
8976
9025
  );
8977
- console.log(`[CLINIC_SERVICE] Applied single-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8978
9026
  }
8979
9027
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
8980
9028
  const initialCount = filteredClinics.length;
@@ -8985,7 +9033,9 @@ function applyInMemoryFilters(clinics, filters) {
8985
9033
  if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
8986
9034
  return true;
8987
9035
  });
8988
- console.log(`[CLINIC_SERVICE] Applied rating filter (${filters.minRating}-${filters.maxRating}): ${initialCount} \u2192 ${filteredClinics.length}`);
9036
+ console.log(
9037
+ `[CLINIC_SERVICE] Applied rating filter (${filters.minRating}-${filters.maxRating}): ${initialCount} \u2192 ${filteredClinics.length}`
9038
+ );
8989
9039
  }
8990
9040
  if (filters.nameSearch && filters.nameSearch.trim()) {
8991
9041
  const initialCount = filteredClinics.length;
@@ -8995,7 +9045,9 @@ function applyInMemoryFilters(clinics, filters) {
8995
9045
  const nameLower = clinic.nameLower || "";
8996
9046
  return name.includes(searchTerm) || nameLower.includes(searchTerm);
8997
9047
  });
8998
- console.log(`[CLINIC_SERVICE] Applied name search filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9048
+ console.log(
9049
+ `[CLINIC_SERVICE] Applied name search filter: ${initialCount} \u2192 ${filteredClinics.length}`
9050
+ );
8999
9051
  }
9000
9052
  if (filters.procedureFamily) {
9001
9053
  const initialCount = filteredClinics.length;
@@ -9003,7 +9055,9 @@ function applyInMemoryFilters(clinics, filters) {
9003
9055
  const proceduresInfo = clinic.proceduresInfo || [];
9004
9056
  return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
9005
9057
  });
9006
- console.log(`[CLINIC_SERVICE] Applied procedure family filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9058
+ console.log(
9059
+ `[CLINIC_SERVICE] Applied procedure family filter: ${initialCount} \u2192 ${filteredClinics.length}`
9060
+ );
9007
9061
  }
9008
9062
  if (filters.procedureCategory) {
9009
9063
  const initialCount = filteredClinics.length;
@@ -9011,7 +9065,9 @@ function applyInMemoryFilters(clinics, filters) {
9011
9065
  const proceduresInfo = clinic.proceduresInfo || [];
9012
9066
  return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
9013
9067
  });
9014
- console.log(`[CLINIC_SERVICE] Applied procedure category filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9068
+ console.log(
9069
+ `[CLINIC_SERVICE] Applied procedure category filter: ${initialCount} \u2192 ${filteredClinics.length}`
9070
+ );
9015
9071
  }
9016
9072
  if (filters.procedureSubcategory) {
9017
9073
  const initialCount = filteredClinics.length;
@@ -9019,7 +9075,9 @@ function applyInMemoryFilters(clinics, filters) {
9019
9075
  const proceduresInfo = clinic.proceduresInfo || [];
9020
9076
  return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
9021
9077
  });
9022
- console.log(`[CLINIC_SERVICE] Applied procedure subcategory filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9078
+ console.log(
9079
+ `[CLINIC_SERVICE] Applied procedure subcategory filter: ${initialCount} \u2192 ${filteredClinics.length}`
9080
+ );
9023
9081
  }
9024
9082
  if (filters.procedureTechnology) {
9025
9083
  const initialCount = filteredClinics.length;
@@ -9027,7 +9085,9 @@ function applyInMemoryFilters(clinics, filters) {
9027
9085
  const proceduresInfo = clinic.proceduresInfo || [];
9028
9086
  return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
9029
9087
  });
9030
- console.log(`[CLINIC_SERVICE] Applied procedure technology filter: ${initialCount} \u2192 ${filteredClinics.length}`);
9088
+ console.log(
9089
+ `[CLINIC_SERVICE] Applied procedure technology filter: ${initialCount} \u2192 ${filteredClinics.length}`
9090
+ );
9031
9091
  }
9032
9092
  if (filters.center && filters.radiusInKm) {
9033
9093
  const initialCount = filteredClinics.length;
@@ -9041,11 +9101,15 @@ function applyInMemoryFilters(clinics, filters) {
9041
9101
  [filters.center.latitude, filters.center.longitude],
9042
9102
  [clinic.location.latitude, clinic.location.longitude]
9043
9103
  ) / 1e3;
9044
- console.log(`[CLINIC_SERVICE] Clinic ${clinic.name}: distance ${distance.toFixed(2)}km (limit: ${filters.radiusInKm}km)`);
9104
+ console.log(
9105
+ `[CLINIC_SERVICE] Clinic ${clinic.name}: distance ${distance.toFixed(2)}km (limit: ${filters.radiusInKm}km)`
9106
+ );
9045
9107
  clinic.distance = distance;
9046
9108
  return distance <= filters.radiusInKm;
9047
9109
  });
9048
- console.log(`[CLINIC_SERVICE] Applied geo filter (${filters.radiusInKm}km): ${initialCount} \u2192 ${filteredClinics.length}`);
9110
+ console.log(
9111
+ `[CLINIC_SERVICE] Applied geo filter (${filters.radiusInKm}km): ${initialCount} \u2192 ${filteredClinics.length}`
9112
+ );
9049
9113
  filteredClinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
9050
9114
  }
9051
9115
  console.log(`[CLINIC_SERVICE] Final filtered result: ${filteredClinics.length} clinics`);
@@ -9073,9 +9137,7 @@ var ClinicService = class extends BaseService {
9073
9137
  return media;
9074
9138
  }
9075
9139
  if (media instanceof File || media instanceof Blob) {
9076
- console.log(
9077
- `[ClinicService] Uploading ${collectionName} media for ${ownerId}`
9078
- );
9140
+ console.log(`[ClinicService] Uploading ${collectionName} media for ${ownerId}`);
9079
9141
  const metadata = await this.mediaService.uploadMedia(
9080
9142
  media,
9081
9143
  ownerId,
@@ -9097,11 +9159,7 @@ var ClinicService = class extends BaseService {
9097
9159
  if (!mediaArray || mediaArray.length === 0) return [];
9098
9160
  const result = [];
9099
9161
  for (const media of mediaArray) {
9100
- const processedUrl = await this.processMedia(
9101
- media,
9102
- ownerId,
9103
- collectionName
9104
- );
9162
+ const processedUrl = await this.processMedia(media, ownerId, collectionName);
9105
9163
  if (processedUrl) {
9106
9164
  result.push(processedUrl);
9107
9165
  }
@@ -9119,11 +9177,7 @@ var ClinicService = class extends BaseService {
9119
9177
  if (!photosWithTags || photosWithTags.length === 0) return [];
9120
9178
  const result = [];
9121
9179
  for (const item of photosWithTags) {
9122
- const processedUrl = await this.processMedia(
9123
- item.url,
9124
- ownerId,
9125
- collectionName
9126
- );
9180
+ const processedUrl = await this.processMedia(item.url, ownerId, collectionName);
9127
9181
  if (processedUrl) {
9128
9182
  result.push({
9129
9183
  url: processedUrl,
@@ -9141,19 +9195,11 @@ var ClinicService = class extends BaseService {
9141
9195
  try {
9142
9196
  const clinicId = this.generateId();
9143
9197
  const validatedData = createClinicSchema.parse(data);
9144
- const group = await this.clinicGroupService.getClinicGroup(
9145
- validatedData.clinicGroupId
9146
- );
9198
+ const group = await this.clinicGroupService.getClinicGroup(validatedData.clinicGroupId);
9147
9199
  if (!group) {
9148
- throw new Error(
9149
- `Clinic group ${validatedData.clinicGroupId} not found`
9150
- );
9200
+ throw new Error(`Clinic group ${validatedData.clinicGroupId} not found`);
9151
9201
  }
9152
- const logoUrl = await this.processMedia(
9153
- validatedData.logo,
9154
- clinicId,
9155
- "clinic-logos"
9156
- );
9202
+ const logoUrl = await this.processMedia(validatedData.logo, clinicId, "clinic-logos");
9157
9203
  const coverPhotoUrl = await this.processMedia(
9158
9204
  validatedData.coverPhoto,
9159
9205
  clinicId,
@@ -9243,11 +9289,7 @@ var ClinicService = class extends BaseService {
9243
9289
  const validatedData = updateClinicSchema.parse(data);
9244
9290
  const updatePayload = {};
9245
9291
  if (validatedData.logo !== void 0) {
9246
- updatePayload.logo = await this.processMedia(
9247
- validatedData.logo,
9248
- clinicId,
9249
- "clinic-logos"
9250
- );
9292
+ updatePayload.logo = await this.processMedia(validatedData.logo, clinicId, "clinic-logos");
9251
9293
  }
9252
9294
  if (validatedData.coverPhoto !== void 0) {
9253
9295
  updatePayload.coverPhoto = await this.processMedia(
@@ -9347,22 +9389,10 @@ var ClinicService = class extends BaseService {
9347
9389
  * Pretražuje klinike u određenom radijusu
9348
9390
  */
9349
9391
  async findClinicsInRadius(center, radiusInKm, filters) {
9350
- return findClinicsInRadius(
9351
- this.db,
9352
- center,
9353
- radiusInKm,
9354
- filters
9355
- );
9392
+ return findClinicsInRadius(this.db, center, radiusInKm, filters);
9356
9393
  }
9357
9394
  async addTags(clinicId, adminId, newTags) {
9358
- return addTags(
9359
- this.db,
9360
- clinicId,
9361
- adminId,
9362
- newTags,
9363
- this.clinicAdminService,
9364
- this.app
9365
- );
9395
+ return addTags(this.db, clinicId, adminId, newTags, this.clinicAdminService, this.app);
9366
9396
  }
9367
9397
  async removeTags(clinicId, adminId, tagsToRemove) {
9368
9398
  return removeTags(
@@ -9400,9 +9430,7 @@ var ClinicService = class extends BaseService {
9400
9430
  clinicGroupId,
9401
9431
  adminId
9402
9432
  });
9403
- const clinicGroup = await this.clinicGroupService.getClinicGroup(
9404
- clinicGroupId
9405
- );
9433
+ const clinicGroup = await this.clinicGroupService.getClinicGroup(clinicGroupId);
9406
9434
  if (!clinicGroup) {
9407
9435
  console.error("[CLINIC_SERVICE] Clinic group not found", {
9408
9436
  clinicGroupId
@@ -9448,13 +9476,7 @@ var ClinicService = class extends BaseService {
9448
9476
  return getAllClinics(this.db, pagination, lastDoc);
9449
9477
  }
9450
9478
  async getAllClinicsInRange(center, rangeInKm, pagination, lastDoc) {
9451
- return getAllClinicsInRange(
9452
- this.db,
9453
- center,
9454
- rangeInKm,
9455
- pagination,
9456
- lastDoc
9457
- );
9479
+ return getAllClinicsInRange(this.db, center, rangeInKm, pagination, lastDoc);
9458
9480
  }
9459
9481
  /**
9460
9482
  * Get clinics based on multiple filtering criteria
@@ -14886,7 +14908,7 @@ var procedureSchema = createProcedureSchema.extend({
14886
14908
  });
14887
14909
 
14888
14910
  // src/services/procedure/procedure.service.ts
14889
- import { distanceBetween as distanceBetween6 } from "geofire-common";
14911
+ import { distanceBetween as distanceBetween6, geohashQueryBounds as geohashQueryBounds5 } from "geofire-common";
14890
14912
  var ProcedureService = class extends BaseService {
14891
14913
  constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService, mediaService) {
14892
14914
  super(db, auth, app);
@@ -14909,9 +14931,7 @@ var ProcedureService = class extends BaseService {
14909
14931
  return media;
14910
14932
  }
14911
14933
  if (media instanceof File || media instanceof Blob) {
14912
- console.log(
14913
- `[ProcedureService] Uploading ${collectionName} media for ${ownerId}`
14914
- );
14934
+ console.log(`[ProcedureService] Uploading ${collectionName} media for ${ownerId}`);
14915
14935
  const metadata = await this.mediaService.uploadMedia(
14916
14936
  media,
14917
14937
  ownerId,
@@ -14933,11 +14953,7 @@ var ProcedureService = class extends BaseService {
14933
14953
  if (!mediaArray || mediaArray.length === 0) return [];
14934
14954
  const result = [];
14935
14955
  for (const media of mediaArray) {
14936
- const processedUrl = await this.processMedia(
14937
- media,
14938
- ownerId,
14939
- collectionName
14940
- );
14956
+ const processedUrl = await this.processMedia(media, ownerId, collectionName);
14941
14957
  if (processedUrl) {
14942
14958
  result.push(processedUrl);
14943
14959
  }
@@ -14955,41 +14971,23 @@ var ProcedureService = class extends BaseService {
14955
14971
  const procedureId = this.generateId();
14956
14972
  const [category, subcategory, technology, product] = await Promise.all([
14957
14973
  this.categoryService.getById(validatedData.categoryId),
14958
- this.subcategoryService.getById(
14959
- validatedData.categoryId,
14960
- validatedData.subcategoryId
14961
- ),
14974
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
14962
14975
  this.technologyService.getById(validatedData.technologyId),
14963
- this.productService.getById(
14964
- validatedData.technologyId,
14965
- validatedData.productId
14966
- )
14976
+ this.productService.getById(validatedData.technologyId, validatedData.productId)
14967
14977
  ]);
14968
14978
  if (!category || !subcategory || !technology || !product) {
14969
14979
  throw new Error("One or more required base entities not found");
14970
14980
  }
14971
- const clinicRef = doc30(
14972
- this.db,
14973
- CLINICS_COLLECTION,
14974
- validatedData.clinicBranchId
14975
- );
14981
+ const clinicRef = doc30(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
14976
14982
  const clinicSnapshot = await getDoc32(clinicRef);
14977
14983
  if (!clinicSnapshot.exists()) {
14978
- throw new Error(
14979
- `Clinic with ID ${validatedData.clinicBranchId} not found`
14980
- );
14984
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
14981
14985
  }
14982
14986
  const clinic = clinicSnapshot.data();
14983
- const practitionerRef = doc30(
14984
- this.db,
14985
- PRACTITIONERS_COLLECTION,
14986
- validatedData.practitionerId
14987
- );
14987
+ const practitionerRef = doc30(this.db, PRACTITIONERS_COLLECTION, validatedData.practitionerId);
14988
14988
  const practitionerSnapshot = await getDoc32(practitionerRef);
14989
14989
  if (!practitionerSnapshot.exists()) {
14990
- throw new Error(
14991
- `Practitioner with ID ${validatedData.practitionerId} not found`
14992
- );
14990
+ throw new Error(`Practitioner with ID ${validatedData.practitionerId} not found`);
14993
14991
  }
14994
14992
  const practitioner = practitionerSnapshot.data();
14995
14993
  let processedPhotos = [];
@@ -15078,24 +15076,16 @@ var ProcedureService = class extends BaseService {
15078
15076
  const validatedData = createProcedureSchema.parse(validationData);
15079
15077
  const [category, subcategory, technology, product, clinicSnapshot] = await Promise.all([
15080
15078
  this.categoryService.getById(validatedData.categoryId),
15081
- this.subcategoryService.getById(
15082
- validatedData.categoryId,
15083
- validatedData.subcategoryId
15084
- ),
15079
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
15085
15080
  this.technologyService.getById(validatedData.technologyId),
15086
- this.productService.getById(
15087
- validatedData.technologyId,
15088
- validatedData.productId
15089
- ),
15081
+ this.productService.getById(validatedData.technologyId, validatedData.productId),
15090
15082
  getDoc32(doc30(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
15091
15083
  ]);
15092
15084
  if (!category || !subcategory || !technology || !product) {
15093
15085
  throw new Error("One or more required base entities not found");
15094
15086
  }
15095
15087
  if (!clinicSnapshot.exists()) {
15096
- throw new Error(
15097
- `Clinic with ID ${validatedData.clinicBranchId} not found`
15098
- );
15088
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
15099
15089
  }
15100
15090
  const clinic = clinicSnapshot.data();
15101
15091
  let processedPhotos = [];
@@ -15121,12 +15111,8 @@ var ProcedureService = class extends BaseService {
15121
15111
  }
15122
15112
  if (practitionersMap.size !== practitionerIds.length) {
15123
15113
  const foundIds = Array.from(practitionersMap.keys());
15124
- const notFoundIds = practitionerIds.filter(
15125
- (id) => !foundIds.includes(id)
15126
- );
15127
- throw new Error(
15128
- `The following practitioners were not found: ${notFoundIds.join(", ")}`
15129
- );
15114
+ const notFoundIds = practitionerIds.filter((id) => !foundIds.includes(id));
15115
+ throw new Error(`The following practitioners were not found: ${notFoundIds.join(", ")}`);
15130
15116
  }
15131
15117
  const batch = writeBatch6(this.db);
15132
15118
  const createdProcedureIds = [];
@@ -15194,10 +15180,7 @@ var ProcedureService = class extends BaseService {
15194
15180
  const fetchedProcedures = [];
15195
15181
  for (let i = 0; i < createdProcedureIds.length; i += 30) {
15196
15182
  const chunk = createdProcedureIds.slice(i, i + 30);
15197
- const q = query29(
15198
- collection29(this.db, PROCEDURES_COLLECTION),
15199
- where29(documentId2(), "in", chunk)
15200
- );
15183
+ const q = query29(collection29(this.db, PROCEDURES_COLLECTION), where29(documentId2(), "in", chunk));
15201
15184
  const snapshot = await getDocs29(q);
15202
15185
  snapshot.forEach((doc37) => {
15203
15186
  fetchedProcedures.push(doc37.data());
@@ -15298,9 +15281,7 @@ var ProcedureService = class extends BaseService {
15298
15281
  );
15299
15282
  const newPractitionerSnap = await getDoc32(newPractitionerRef);
15300
15283
  if (!newPractitionerSnap.exists())
15301
- throw new Error(
15302
- `New Practitioner ${validatedData.practitionerId} not found`
15303
- );
15284
+ throw new Error(`New Practitioner ${validatedData.practitionerId} not found`);
15304
15285
  newPractitioner = newPractitionerSnap.data();
15305
15286
  updatedProcedureData.doctorInfo = {
15306
15287
  id: newPractitioner.id,
@@ -15314,11 +15295,7 @@ var ProcedureService = class extends BaseService {
15314
15295
  }
15315
15296
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
15316
15297
  clinicChanged = true;
15317
- const newClinicRef = doc30(
15318
- this.db,
15319
- CLINICS_COLLECTION,
15320
- validatedData.clinicBranchId
15321
- );
15298
+ const newClinicRef = doc30(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
15322
15299
  const newClinicSnap = await getDoc32(newClinicRef);
15323
15300
  if (!newClinicSnap.exists())
15324
15301
  throw new Error(`New Clinic ${validatedData.clinicBranchId} not found`);
@@ -15337,11 +15314,8 @@ var ProcedureService = class extends BaseService {
15337
15314
  updatedProcedureData.nameLower = validatedData.name.toLowerCase();
15338
15315
  }
15339
15316
  if (validatedData.categoryId) {
15340
- const category = await this.categoryService.getById(
15341
- validatedData.categoryId
15342
- );
15343
- if (!category)
15344
- throw new Error(`Category ${validatedData.categoryId} not found`);
15317
+ const category = await this.categoryService.getById(validatedData.categoryId);
15318
+ if (!category) throw new Error(`Category ${validatedData.categoryId} not found`);
15345
15319
  updatedProcedureData.category = category;
15346
15320
  finalCategoryId = category.id;
15347
15321
  }
@@ -15356,17 +15330,12 @@ var ProcedureService = class extends BaseService {
15356
15330
  );
15357
15331
  updatedProcedureData.subcategory = subcategory;
15358
15332
  } else if (validatedData.subcategoryId) {
15359
- console.warn(
15360
- "Attempted to update subcategory without a valid categoryId"
15361
- );
15333
+ console.warn("Attempted to update subcategory without a valid categoryId");
15362
15334
  }
15363
15335
  let finalTechnologyId = existingProcedure.technology.id;
15364
15336
  if (validatedData.technologyId) {
15365
- const technology = await this.technologyService.getById(
15366
- validatedData.technologyId
15367
- );
15368
- if (!technology)
15369
- throw new Error(`Technology ${validatedData.technologyId} not found`);
15337
+ const technology = await this.technologyService.getById(validatedData.technologyId);
15338
+ if (!technology) throw new Error(`Technology ${validatedData.technologyId} not found`);
15370
15339
  updatedProcedureData.technology = technology;
15371
15340
  finalTechnologyId = technology.id;
15372
15341
  updatedProcedureData.blockingConditions = technology.blockingConditions;
@@ -15377,10 +15346,7 @@ var ProcedureService = class extends BaseService {
15377
15346
  updatedProcedureData.documentationTemplates = technology.documentationTemplates || [];
15378
15347
  }
15379
15348
  if (validatedData.productId && finalTechnologyId) {
15380
- const product = await this.productService.getById(
15381
- finalTechnologyId,
15382
- validatedData.productId
15383
- );
15349
+ const product = await this.productService.getById(finalTechnologyId, validatedData.productId);
15384
15350
  if (!product)
15385
15351
  throw new Error(
15386
15352
  `Product ${validatedData.productId} not found for technology ${finalTechnologyId}`
@@ -15462,11 +15428,7 @@ var ProcedureService = class extends BaseService {
15462
15428
  limit16(pagination)
15463
15429
  );
15464
15430
  } else {
15465
- proceduresQuery = query29(
15466
- proceduresCollection,
15467
- orderBy17("name"),
15468
- limit16(pagination)
15469
- );
15431
+ proceduresQuery = query29(proceduresCollection, orderBy17("name"), limit16(pagination));
15470
15432
  }
15471
15433
  } else {
15472
15434
  proceduresQuery = query29(proceduresCollection, orderBy17("name"));
@@ -15589,7 +15551,9 @@ var ProcedureService = class extends BaseService {
15589
15551
  constraints.push(limit15(filters.pagination || 10));
15590
15552
  const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15591
15553
  const querySnapshot = await getDocs29(q);
15592
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15554
+ const procedures = querySnapshot.docs.map(
15555
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15556
+ );
15593
15557
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15594
15558
  console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15595
15559
  if (procedures.length < (filters.pagination || 10)) {
@@ -15620,7 +15584,9 @@ var ProcedureService = class extends BaseService {
15620
15584
  constraints.push(limit15(filters.pagination || 10));
15621
15585
  const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15622
15586
  const querySnapshot = await getDocs29(q);
15623
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15587
+ const procedures = querySnapshot.docs.map(
15588
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15589
+ );
15624
15590
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15625
15591
  console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15626
15592
  if (procedures.length < (filters.pagination || 10)) {
@@ -15632,7 +15598,9 @@ var ProcedureService = class extends BaseService {
15632
15598
  }
15633
15599
  }
15634
15600
  try {
15635
- console.log("[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering");
15601
+ console.log(
15602
+ "[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering"
15603
+ );
15636
15604
  const constraints = getBaseConstraints();
15637
15605
  constraints.push(orderBy17("createdAt", "desc"));
15638
15606
  if (filters.lastDoc) {
@@ -15647,7 +15615,9 @@ var ProcedureService = class extends BaseService {
15647
15615
  constraints.push(limit15(filters.pagination || 10));
15648
15616
  const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15649
15617
  const querySnapshot = await getDocs29(q);
15650
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15618
+ let procedures = querySnapshot.docs.map(
15619
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15620
+ );
15651
15621
  procedures = this.applyInMemoryFilters(procedures, filters);
15652
15622
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15653
15623
  console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
@@ -15667,7 +15637,9 @@ var ProcedureService = class extends BaseService {
15667
15637
  ];
15668
15638
  const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15669
15639
  const querySnapshot = await getDocs29(q);
15670
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15640
+ let procedures = querySnapshot.docs.map(
15641
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15642
+ );
15671
15643
  procedures = this.applyInMemoryFilters(procedures, filters);
15672
15644
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15673
15645
  console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
@@ -15707,7 +15679,9 @@ var ProcedureService = class extends BaseService {
15707
15679
  if (filters.maxPrice !== void 0 && price > filters.maxPrice) return false;
15708
15680
  return true;
15709
15681
  });
15710
- console.log(`[PROCEDURE_SERVICE] Applied price filter (${filters.minPrice}-${filters.maxPrice}), results: ${filteredProcedures.length}`);
15682
+ console.log(
15683
+ `[PROCEDURE_SERVICE] Applied price filter (${filters.minPrice}-${filters.maxPrice}), results: ${filteredProcedures.length}`
15684
+ );
15711
15685
  }
15712
15686
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
15713
15687
  filteredProcedures = filteredProcedures.filter((procedure) => {
@@ -15717,7 +15691,9 @@ var ProcedureService = class extends BaseService {
15717
15691
  if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
15718
15692
  return true;
15719
15693
  });
15720
- console.log(`[PROCEDURE_SERVICE] Applied rating filter, results: ${filteredProcedures.length}`);
15694
+ console.log(
15695
+ `[PROCEDURE_SERVICE] Applied rating filter, results: ${filteredProcedures.length}`
15696
+ );
15721
15697
  }
15722
15698
  if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15723
15699
  const benefitsToMatch = filters.treatmentBenefits;
@@ -15725,32 +15701,50 @@ var ProcedureService = class extends BaseService {
15725
15701
  const procedureBenefits = procedure.treatmentBenefits || [];
15726
15702
  return benefitsToMatch.some((benefit) => procedureBenefits.includes(benefit));
15727
15703
  });
15728
- console.log(`[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`);
15704
+ console.log(
15705
+ `[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`
15706
+ );
15729
15707
  }
15730
15708
  if (filters.procedureFamily) {
15731
- filteredProcedures = filteredProcedures.filter((procedure) => procedure.family === filters.procedureFamily);
15732
- console.log(`[PROCEDURE_SERVICE] Applied family filter, results: ${filteredProcedures.length}`);
15709
+ filteredProcedures = filteredProcedures.filter(
15710
+ (procedure) => procedure.family === filters.procedureFamily
15711
+ );
15712
+ console.log(
15713
+ `[PROCEDURE_SERVICE] Applied family filter, results: ${filteredProcedures.length}`
15714
+ );
15733
15715
  }
15734
15716
  if (filters.procedureCategory) {
15735
- filteredProcedures = filteredProcedures.filter((procedure) => {
15736
- var _a;
15737
- return ((_a = procedure.category) == null ? void 0 : _a.id) === filters.procedureCategory;
15738
- });
15739
- console.log(`[PROCEDURE_SERVICE] Applied category filter, results: ${filteredProcedures.length}`);
15717
+ filteredProcedures = filteredProcedures.filter(
15718
+ (procedure) => {
15719
+ var _a;
15720
+ return ((_a = procedure.category) == null ? void 0 : _a.id) === filters.procedureCategory;
15721
+ }
15722
+ );
15723
+ console.log(
15724
+ `[PROCEDURE_SERVICE] Applied category filter, results: ${filteredProcedures.length}`
15725
+ );
15740
15726
  }
15741
15727
  if (filters.procedureSubcategory) {
15742
- filteredProcedures = filteredProcedures.filter((procedure) => {
15743
- var _a;
15744
- return ((_a = procedure.subcategory) == null ? void 0 : _a.id) === filters.procedureSubcategory;
15745
- });
15746
- console.log(`[PROCEDURE_SERVICE] Applied subcategory filter, results: ${filteredProcedures.length}`);
15728
+ filteredProcedures = filteredProcedures.filter(
15729
+ (procedure) => {
15730
+ var _a;
15731
+ return ((_a = procedure.subcategory) == null ? void 0 : _a.id) === filters.procedureSubcategory;
15732
+ }
15733
+ );
15734
+ console.log(
15735
+ `[PROCEDURE_SERVICE] Applied subcategory filter, results: ${filteredProcedures.length}`
15736
+ );
15747
15737
  }
15748
15738
  if (filters.procedureTechnology) {
15749
- filteredProcedures = filteredProcedures.filter((procedure) => {
15750
- var _a;
15751
- return ((_a = procedure.technology) == null ? void 0 : _a.id) === filters.procedureTechnology;
15752
- });
15753
- console.log(`[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`);
15739
+ filteredProcedures = filteredProcedures.filter(
15740
+ (procedure) => {
15741
+ var _a;
15742
+ return ((_a = procedure.technology) == null ? void 0 : _a.id) === filters.procedureTechnology;
15743
+ }
15744
+ );
15745
+ console.log(
15746
+ `[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`
15747
+ );
15754
15748
  }
15755
15749
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
15756
15750
  const location = filters.location;
@@ -15774,29 +15768,48 @@ var ProcedureService = class extends BaseService {
15774
15768
  return filteredProcedures;
15775
15769
  }
15776
15770
  handleGeoQuery(filters) {
15777
- console.log("[PROCEDURE_SERVICE] Executing geo query with enhanced debugging");
15771
+ console.log("[PROCEDURE_SERVICE] Executing geo query with geohash bounds");
15778
15772
  try {
15779
15773
  const location = filters.location;
15780
15774
  const radiusInKm = filters.radiusInKm;
15781
- console.log("[PROCEDURE_SERVICE] Geo query parameters:", {
15782
- latitude: location.latitude,
15783
- longitude: location.longitude,
15784
- radiusInKm,
15785
- pagination: filters.pagination || 10
15775
+ if (!location || !radiusInKm) {
15776
+ return Promise.resolve({ procedures: [], lastDoc: null });
15777
+ }
15778
+ const bounds = geohashQueryBounds5([location.latitude, location.longitude], radiusInKm * 1e3);
15779
+ const fetches = bounds.map((b) => {
15780
+ const constraints = [
15781
+ where29("clinicInfo.location.geohash", ">=", b[0]),
15782
+ where29("clinicInfo.location.geohash", "<=", b[1]),
15783
+ where29("isActive", "==", filters.isActive !== void 0 ? filters.isActive : true)
15784
+ ];
15785
+ return getDocs29(query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints));
15786
15786
  });
15787
- const constraints = [
15788
- where29("isActive", "==", true),
15789
- orderBy17("createdAt", "desc"),
15790
- limit15((filters.pagination || 10) * 3)
15791
- // Get more results for geo filtering
15792
- ];
15793
- const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
15794
- return getDocs29(q).then((querySnapshot) => {
15795
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15787
+ return Promise.all(fetches).then((snaps) => {
15788
+ const collected = [];
15789
+ snaps.forEach((snap) => {
15790
+ snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
15791
+ });
15792
+ const uniqueMap = /* @__PURE__ */ new Map();
15793
+ for (const p of collected) {
15794
+ uniqueMap.set(p.id, p);
15795
+ }
15796
+ let procedures = Array.from(uniqueMap.values());
15796
15797
  procedures = this.applyInMemoryFilters(procedures, filters);
15797
- console.log(`[PROCEDURE_SERVICE] Geo query success: ${procedures.length} procedures within ${radiusInKm}km`);
15798
- const lastDoc = procedures.length < (filters.pagination || 10) ? null : querySnapshot.docs[querySnapshot.docs.length - 1];
15799
- return { procedures, lastDoc };
15798
+ const pageSize = filters.pagination || 10;
15799
+ let startIndex = 0;
15800
+ if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
15801
+ const idx = procedures.findIndex((p) => p.id === filters.lastDoc.id);
15802
+ if (idx >= 0) startIndex = idx + 1;
15803
+ }
15804
+ const page = procedures.slice(startIndex, startIndex + pageSize);
15805
+ const newLastDoc = page.length === pageSize ? page[page.length - 1] : null;
15806
+ console.log(
15807
+ `[PROCEDURE_SERVICE] Geo query success: ${page.length} (of ${procedures.length}) within ${radiusInKm}km`
15808
+ );
15809
+ return { procedures: page, lastDoc: newLastDoc };
15810
+ }).catch((err) => {
15811
+ console.error("[PROCEDURE_SERVICE] Geo bounds fetch failed:", err);
15812
+ return { procedures: [], lastDoc: null };
15800
15813
  });
15801
15814
  } catch (error) {
15802
15815
  console.error("[PROCEDURE_SERVICE] Geo query failed:", error);
@@ -15826,11 +15839,7 @@ var ProcedureService = class extends BaseService {
15826
15839
  throw new Error(`Clinic with ID ${data.clinicBranchId} not found`);
15827
15840
  }
15828
15841
  const clinic = clinicSnapshot.data();
15829
- const practitionerRef = doc30(
15830
- this.db,
15831
- PRACTITIONERS_COLLECTION,
15832
- data.practitionerId
15833
- );
15842
+ const practitionerRef = doc30(this.db, PRACTITIONERS_COLLECTION, data.practitionerId);
15834
15843
  const practitionerSnapshot = await getDoc32(practitionerRef);
15835
15844
  if (!practitionerSnapshot.exists()) {
15836
15845
  throw new Error(`Practitioner with ID ${data.practitionerId} not found`);
@@ -15838,11 +15847,7 @@ var ProcedureService = class extends BaseService {
15838
15847
  const practitioner = practitionerSnapshot.data();
15839
15848
  let processedPhotos = [];
15840
15849
  if (data.photos && data.photos.length > 0) {
15841
- processedPhotos = await this.processMediaArray(
15842
- data.photos,
15843
- procedureId,
15844
- "procedure-photos"
15845
- );
15850
+ processedPhotos = await this.processMediaArray(data.photos, procedureId, "procedure-photos");
15846
15851
  }
15847
15852
  const clinicInfo = {
15848
15853
  id: clinicSnapshot.id,