@blackcode_sa/metaestetics-api 1.14.56 → 1.14.58

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.js CHANGED
@@ -3970,7 +3970,10 @@ var zoneItemDataSchema = import_zod3.z.object({
3970
3970
  notes: import_zod3.z.string().max(MAX_STRING_LENGTH_LONG, "Notes too long").optional(),
3971
3971
  notesVisibleToPatient: import_zod3.z.boolean().optional().default(false),
3972
3972
  subtotal: import_zod3.z.number().min(0, "Subtotal must be non-negative").optional(),
3973
- ionNumber: import_zod3.z.string().optional(),
3973
+ ionNumber: import_zod3.z.string().nullable().optional(),
3974
+ // Batch/Lot number - can be null to clear/delete
3975
+ expiryDate: import_zod3.z.string().nullable().optional(),
3976
+ // ISO date string (YYYY-MM-DD) - can be null to clear/delete
3974
3977
  createdAt: import_zod3.z.string().optional(),
3975
3978
  updatedAt: import_zod3.z.string().optional()
3976
3979
  }).refine(
@@ -4900,6 +4903,7 @@ async function removeItemFromZoneUtil(db, appointmentId, zoneId, itemIndex) {
4900
4903
  return getAppointmentOrThrow(db, appointmentId);
4901
4904
  }
4902
4905
  async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates) {
4906
+ var _a, _b, _c, _d;
4903
4907
  validateZoneKeyFormat(zoneId);
4904
4908
  const appointment = await getAppointmentOrThrow(db, appointmentId);
4905
4909
  const metadata = initializeMetadata(appointment);
@@ -4910,17 +4914,37 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
4910
4914
  if (itemIndex < 0 || itemIndex >= items.length) {
4911
4915
  throw new Error(`Invalid item index ${itemIndex} for zone ${zoneId}`);
4912
4916
  }
4917
+ const cleanUpdates = Object.fromEntries(
4918
+ Object.entries(updates).filter(([_, value]) => value !== void 0).map(([key, value]) => [
4919
+ key,
4920
+ value === "" ? null : value
4921
+ // Convert empty strings to null
4922
+ ])
4923
+ );
4924
+ console.log(`[updateZoneItemUtil] Updates received:`, {
4925
+ itemIndex,
4926
+ zoneId,
4927
+ rawUpdates: updates,
4928
+ cleanUpdates,
4929
+ hasIonNumber: "ionNumber" in cleanUpdates,
4930
+ hasExpiryDate: "expiryDate" in cleanUpdates,
4931
+ ionNumberValue: cleanUpdates.ionNumber,
4932
+ expiryDateValue: cleanUpdates.expiryDate
4933
+ });
4913
4934
  items[itemIndex] = {
4914
4935
  ...items[itemIndex],
4915
- ...updates,
4936
+ ...cleanUpdates,
4916
4937
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4917
4938
  };
4918
- console.log(`[updateZoneItemUtil] BEFORE recalculation:`, {
4939
+ console.log(`[updateZoneItemUtil] Item after update:`, {
4919
4940
  itemIndex,
4941
+ ionNumber: items[itemIndex].ionNumber,
4942
+ expiryDate: items[itemIndex].expiryDate,
4920
4943
  quantity: items[itemIndex].quantity,
4921
4944
  priceOverrideAmount: items[itemIndex].priceOverrideAmount,
4922
4945
  price: items[itemIndex].price,
4923
- oldSubtotal: items[itemIndex].subtotal
4946
+ oldSubtotal: items[itemIndex].subtotal,
4947
+ allItemKeys: Object.keys(items[itemIndex])
4924
4948
  });
4925
4949
  items[itemIndex].subtotal = calculateItemSubtotal(items[itemIndex]);
4926
4950
  console.log(`[updateZoneItemUtil] AFTER recalculation:`, {
@@ -4928,13 +4952,30 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
4928
4952
  newSubtotal: items[itemIndex].subtotal
4929
4953
  });
4930
4954
  const finalbilling = calculateFinalBilling(metadata.zonesData, 0.081);
4955
+ console.log(`[updateZoneItemUtil] Saving to Firestore:`, {
4956
+ appointmentId,
4957
+ zoneId,
4958
+ itemIndex,
4959
+ itemToSave: items[itemIndex],
4960
+ itemIonNumber: items[itemIndex].ionNumber,
4961
+ itemExpiryDate: items[itemIndex].expiryDate,
4962
+ zonesDataKeys: Object.keys(metadata.zonesData),
4963
+ zoneItemsCount: (_a = metadata.zonesData[zoneId]) == null ? void 0 : _a.length
4964
+ });
4931
4965
  const appointmentRef = (0, import_firestore8.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
4932
4966
  await (0, import_firestore7.updateDoc)(appointmentRef, {
4933
4967
  "metadata.zonesData": metadata.zonesData,
4934
4968
  "metadata.finalbilling": finalbilling,
4935
4969
  updatedAt: (0, import_firestore7.serverTimestamp)()
4936
4970
  });
4937
- return getAppointmentOrThrow(db, appointmentId);
4971
+ const savedAppointment = await getAppointmentOrThrow(db, appointmentId);
4972
+ const savedItem = (_d = (_c = (_b = savedAppointment.metadata) == null ? void 0 : _b.zonesData) == null ? void 0 : _c[zoneId]) == null ? void 0 : _d[itemIndex];
4973
+ console.log(`[updateZoneItemUtil] Verification after save:`, {
4974
+ savedItemIonNumber: savedItem == null ? void 0 : savedItem.ionNumber,
4975
+ savedItemExpiryDate: savedItem == null ? void 0 : savedItem.expiryDate,
4976
+ savedItemKeys: savedItem ? Object.keys(savedItem) : []
4977
+ });
4978
+ return savedAppointment;
4938
4979
  }
4939
4980
  async function overridePriceForZoneItemUtil(db, appointmentId, zoneId, itemIndex, newPrice) {
4940
4981
  return updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, {
@@ -5064,7 +5105,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
5064
5105
  isRequired,
5065
5106
  sortingOrder: templateRef.sortingOrder,
5066
5107
  status: existingForm.status || "pending" /* PENDING */,
5067
- path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}`
5108
+ path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}`,
5109
+ procedureId
5110
+ // Track which procedure this form belongs to
5068
5111
  };
5069
5112
  initializedFormsInfo.push(linkedForm);
5070
5113
  if (!allLinkedFormIds.includes(existingForm.id)) {
@@ -5118,7 +5161,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
5118
5161
  isRequired,
5119
5162
  sortingOrder: templateRef.sortingOrder,
5120
5163
  status: "pending" /* PENDING */,
5121
- path: docRef.path
5164
+ path: docRef.path,
5165
+ procedureId
5166
+ // Track which procedure this form belongs to
5122
5167
  };
5123
5168
  initializedFormsInfo.push(linkedForm);
5124
5169
  const formType = isProcedureSpecific ? "procedure-specific" : "general/shared";
@@ -5311,6 +5356,7 @@ async function createExtendedProcedureInfo(db, procedureId) {
5311
5356
  procedureId,
5312
5357
  procedureName: data.name,
5313
5358
  procedureDescription: data.description || "",
5359
+ procedurePrice: data.price || 0,
5314
5360
  procedureFamily: data.family,
5315
5361
  // Use embedded family object
5316
5362
  procedureCategoryId: data.category.id,
@@ -5638,16 +5684,37 @@ async function getZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex) {
5638
5684
  return zoneArray[photoIndex];
5639
5685
  }
5640
5686
  async function updateZonePhotoVisibilityUtil(db, appointmentId, zoneId, photoIndex, showToPatient, doctorId) {
5687
+ const updates = { showToPatient };
5688
+ if (!showToPatient) {
5689
+ updates.beforeNoteVisibleToPatient = false;
5690
+ updates.afterNoteVisibleToPatient = false;
5691
+ }
5641
5692
  return updateZonePhotoEntryUtil(
5642
5693
  db,
5643
5694
  appointmentId,
5644
5695
  zoneId,
5645
5696
  photoIndex,
5646
- { showToPatient },
5697
+ updates,
5647
5698
  doctorId
5648
5699
  );
5649
5700
  }
5650
5701
  async function updateZonePhotoNoteVisibilityUtil(db, appointmentId, zoneId, photoIndex, noteType, visibleToPatient, doctorId) {
5702
+ var _a;
5703
+ const appointment = await getAppointmentOrThrow(db, appointmentId);
5704
+ const zonePhotos = (_a = appointment.metadata) == null ? void 0 : _a.zonePhotos;
5705
+ if (!zonePhotos || !zonePhotos[zoneId] || !Array.isArray(zonePhotos[zoneId])) {
5706
+ throw new Error(`No photos found for zone ${zoneId} in appointment ${appointmentId}`);
5707
+ }
5708
+ const zoneArray = zonePhotos[zoneId];
5709
+ if (photoIndex < 0 || photoIndex >= zoneArray.length) {
5710
+ throw new Error(`Invalid photo index ${photoIndex} for zone ${zoneId}. Must be between 0 and ${zoneArray.length - 1}`);
5711
+ }
5712
+ const photoEntry = zoneArray[photoIndex];
5713
+ if (visibleToPatient && !photoEntry.showToPatient) {
5714
+ throw new Error(
5715
+ 'Cannot make note visible to patient: The photo pair must be visible to the patient first. Please enable "Show to Patient" for the photo pair before making notes visible.'
5716
+ );
5717
+ }
5651
5718
  const updates = noteType === "before" ? { beforeNoteVisibleToPatient: visibleToPatient } : { afterNoteVisibleToPatient: visibleToPatient };
5652
5719
  return updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates, doctorId);
5653
5720
  }
@@ -7291,6 +7358,8 @@ var AppointmentService = class extends BaseService {
7291
7358
  finalizationNotesInternal: currentMetadata.finalizationNotesInternal,
7292
7359
  finalizationNotes: currentMetadata.finalizationNotes
7293
7360
  });
7361
+ const normalizedSharedNotes = sharedNotes !== void 0 ? sharedNotes === "" || sharedNotes === null ? null : sharedNotes : currentMetadata.finalizationNotesShared;
7362
+ const normalizedInternalNotes = internalNotes !== void 0 ? internalNotes === "" || internalNotes === null ? null : internalNotes : currentMetadata.finalizationNotesInternal;
7294
7363
  const metadataUpdate = {
7295
7364
  selectedZones: currentMetadata.selectedZones,
7296
7365
  zonePhotos: currentMetadata.zonePhotos,
@@ -7299,21 +7368,38 @@ var AppointmentService = class extends BaseService {
7299
7368
  extendedProcedures: currentMetadata.extendedProcedures || [],
7300
7369
  recommendedProcedures: currentMetadata.recommendedProcedures || [],
7301
7370
  finalbilling: currentMetadata.finalbilling,
7302
- finalizationNotesShared: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotesShared,
7303
- finalizationNotesInternal: internalNotes !== void 0 ? internalNotes : currentMetadata.finalizationNotesInternal,
7371
+ finalizationNotesShared: normalizedSharedNotes,
7372
+ finalizationNotesInternal: normalizedInternalNotes,
7304
7373
  // Keep deprecated field for backward compatibility during migration
7305
- finalizationNotes: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
7374
+ finalizationNotes: normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
7306
7375
  };
7307
7376
  console.log("\u{1F50D} [APPOINTMENT_SERVICE] Update data metadata:", {
7308
7377
  finalizationNotesShared: metadataUpdate.finalizationNotesShared,
7309
7378
  finalizationNotesInternal: metadataUpdate.finalizationNotesInternal,
7310
- finalizationNotes: metadataUpdate.finalizationNotes
7379
+ finalizationNotes: metadataUpdate.finalizationNotes,
7380
+ normalizedSharedNotes,
7381
+ normalizedInternalNotes
7311
7382
  });
7312
- const updateData = {
7313
- metadata: metadataUpdate,
7383
+ const appointmentRef = (0, import_firestore14.doc)(this.db, APPOINTMENTS_COLLECTION, appointmentId);
7384
+ const updateFields = {
7385
+ "metadata.finalizationNotesShared": normalizedSharedNotes,
7386
+ "metadata.finalizationNotesInternal": normalizedInternalNotes,
7387
+ "metadata.finalizationNotes": normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared,
7314
7388
  updatedAt: (0, import_firestore14.serverTimestamp)()
7315
7389
  };
7316
- const result = await this.updateAppointment(appointmentId, updateData);
7390
+ console.log("\u{1F50D} [APPOINTMENT_SERVICE] Direct Firestore update with dot notation:", {
7391
+ appointmentId,
7392
+ updateFields: {
7393
+ "metadata.finalizationNotesShared": updateFields["metadata.finalizationNotesShared"],
7394
+ "metadata.finalizationNotesInternal": updateFields["metadata.finalizationNotesInternal"],
7395
+ "metadata.finalizationNotes": updateFields["metadata.finalizationNotes"]
7396
+ }
7397
+ });
7398
+ await (0, import_firestore14.updateDoc)(appointmentRef, updateFields);
7399
+ const result = await this.getAppointmentById(appointmentId);
7400
+ if (!result) {
7401
+ throw new Error(`Failed to retrieve updated appointment ${appointmentId}`);
7402
+ }
7317
7403
  console.log("\u{1F50D} [APPOINTMENT_SERVICE] After update, result metadata:", {
7318
7404
  finalizationNotesShared: (_a = result.metadata) == null ? void 0 : _a.finalizationNotesShared,
7319
7405
  finalizationNotesInternal: (_b = result.metadata) == null ? void 0 : _b.finalizationNotesInternal,
@@ -22515,10 +22601,72 @@ var ProcedureService = class extends BaseService {
22515
22601
  throw error;
22516
22602
  }
22517
22603
  }
22604
+ /**
22605
+ * Creates a serializable cursor from a DocumentSnapshot or returns the cursor values.
22606
+ * This format can be passed through React Native state/Redux without losing data.
22607
+ *
22608
+ * @param doc - The Firestore DocumentSnapshot
22609
+ * @param orderByField - The field used in orderBy clause
22610
+ * @returns Serializable cursor object with values needed for startAfter
22611
+ */
22612
+ createSerializableCursor(doc47, orderByField = "createdAt") {
22613
+ if (!doc47) return null;
22614
+ const data = typeof doc47.data === "function" ? doc47.data() : doc47;
22615
+ const docId = doc47.id || (data == null ? void 0 : data.id);
22616
+ if (!docId) return null;
22617
+ let orderByValue = data == null ? void 0 : data[orderByField];
22618
+ if (orderByValue && typeof orderByValue.toDate === "function") {
22619
+ orderByValue = orderByValue.toMillis();
22620
+ } else if (orderByValue && orderByValue.seconds) {
22621
+ orderByValue = orderByValue.seconds * 1e3 + (orderByValue.nanoseconds || 0) / 1e6;
22622
+ }
22623
+ return {
22624
+ __cursor: true,
22625
+ values: [orderByValue],
22626
+ id: docId,
22627
+ orderByField
22628
+ };
22629
+ }
22630
+ /**
22631
+ * Converts a serializable cursor back to values for startAfter.
22632
+ * Handles both native DocumentSnapshots and serialized cursor objects.
22633
+ *
22634
+ * @param lastDoc - Either a DocumentSnapshot or a serializable cursor object
22635
+ * @param orderByField - The field used in orderBy clause (for validation)
22636
+ * @returns Values to spread into startAfter, or null if invalid
22637
+ */
22638
+ getCursorValuesForStartAfter(lastDoc, orderByField = "createdAt") {
22639
+ if (!lastDoc) return null;
22640
+ if (typeof lastDoc.data === "function") {
22641
+ return [lastDoc];
22642
+ }
22643
+ if (lastDoc.__cursor && Array.isArray(lastDoc.values)) {
22644
+ if (orderByField === "createdAt" && typeof lastDoc.values[0] === "number") {
22645
+ const timestamp = import_firestore58.Timestamp.fromMillis(lastDoc.values[0]);
22646
+ return [timestamp];
22647
+ }
22648
+ return lastDoc.values;
22649
+ }
22650
+ if (Array.isArray(lastDoc)) {
22651
+ return lastDoc;
22652
+ }
22653
+ if (lastDoc[orderByField]) {
22654
+ let value = lastDoc[orderByField];
22655
+ if (typeof value === "number" && orderByField === "createdAt") {
22656
+ value = import_firestore58.Timestamp.fromMillis(value);
22657
+ } else if (value.seconds && orderByField === "createdAt") {
22658
+ value = new import_firestore58.Timestamp(value.seconds, value.nanoseconds || 0);
22659
+ }
22660
+ return [value];
22661
+ }
22662
+ console.warn("[PROCEDURE_SERVICE] Could not parse lastDoc cursor:", typeof lastDoc);
22663
+ return null;
22664
+ }
22518
22665
  /**
22519
22666
  * Searches and filters procedures based on multiple criteria
22520
22667
  *
22521
- * @note Frontend MORA da šalje ceo snapshot (ili barem sva polja po kojima sortiraš, npr. nameLower) kao lastDoc za paginaciju, a ne samo id!
22668
+ * @note Frontend can now send either a DocumentSnapshot or a serializable cursor object.
22669
+ * The serializable cursor format is: { __cursor: true, values: [...], id: string, orderByField: string }
22522
22670
  *
22523
22671
  * @param filters - Various filters to apply
22524
22672
  * @param filters.nameSearch - Optional search text for procedure name
@@ -22614,12 +22762,10 @@ var ProcedureService = class extends BaseService {
22614
22762
  constraints.push((0, import_firestore58.where)("nameLower", "<=", searchTerm + "\uF8FF"));
22615
22763
  constraints.push((0, import_firestore58.orderBy)("nameLower"));
22616
22764
  if (filters.lastDoc) {
22617
- if (typeof filters.lastDoc.data === "function") {
22618
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22619
- } else if (Array.isArray(filters.lastDoc)) {
22620
- constraints.push((0, import_firestore58.startAfter)(...filters.lastDoc));
22621
- } else {
22622
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22765
+ const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "nameLower");
22766
+ if (cursorValues) {
22767
+ constraints.push((0, import_firestore58.startAfter)(...cursorValues));
22768
+ console.log("[PROCEDURE_SERVICE] Strategy 1: Using cursor for pagination");
22623
22769
  }
22624
22770
  }
22625
22771
  constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
@@ -22638,8 +22784,9 @@ var ProcedureService = class extends BaseService {
22638
22784
  if (querySnapshot.docs.length < (filters.pagination || 10)) {
22639
22785
  return { procedures, lastDoc: null };
22640
22786
  }
22641
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22642
- return { procedures, lastDoc };
22787
+ const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22788
+ const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "nameLower");
22789
+ return { procedures, lastDoc: serializableCursor };
22643
22790
  } catch (error) {
22644
22791
  console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
22645
22792
  }
@@ -22657,12 +22804,10 @@ var ProcedureService = class extends BaseService {
22657
22804
  constraints.push((0, import_firestore58.where)("name", "<=", searchTerm + "\uF8FF"));
22658
22805
  constraints.push((0, import_firestore58.orderBy)("name"));
22659
22806
  if (filters.lastDoc) {
22660
- if (typeof filters.lastDoc.data === "function") {
22661
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22662
- } else if (Array.isArray(filters.lastDoc)) {
22663
- constraints.push((0, import_firestore58.startAfter)(...filters.lastDoc));
22664
- } else {
22665
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22807
+ const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "name");
22808
+ if (cursorValues) {
22809
+ constraints.push((0, import_firestore58.startAfter)(...cursorValues));
22810
+ console.log("[PROCEDURE_SERVICE] Strategy 2: Using cursor for pagination");
22666
22811
  }
22667
22812
  }
22668
22813
  constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
@@ -22681,8 +22826,9 @@ var ProcedureService = class extends BaseService {
22681
22826
  if (querySnapshot.docs.length < (filters.pagination || 10)) {
22682
22827
  return { procedures, lastDoc: null };
22683
22828
  }
22684
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22685
- return { procedures, lastDoc };
22829
+ const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22830
+ const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "name");
22831
+ return { procedures, lastDoc: serializableCursor };
22686
22832
  } catch (error) {
22687
22833
  console.log("[PROCEDURE_SERVICE] Strategy 2 failed:", error);
22688
22834
  }
@@ -22732,12 +22878,10 @@ var ProcedureService = class extends BaseService {
22732
22878
  );
22733
22879
  constraints.push((0, import_firestore58.orderBy)("createdAt", "desc"));
22734
22880
  if (filters.lastDoc) {
22735
- if (typeof filters.lastDoc.data === "function") {
22736
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22737
- } else if (Array.isArray(filters.lastDoc)) {
22738
- constraints.push((0, import_firestore58.startAfter)(...filters.lastDoc));
22739
- } else {
22740
- constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
22881
+ const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "createdAt");
22882
+ if (cursorValues) {
22883
+ constraints.push((0, import_firestore58.startAfter)(...cursorValues));
22884
+ console.log("[PROCEDURE_SERVICE] Strategy 3: Using cursor for pagination");
22741
22885
  }
22742
22886
  }
22743
22887
  constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
@@ -22768,8 +22912,9 @@ var ProcedureService = class extends BaseService {
22768
22912
  if (querySnapshot.docs.length < (filters.pagination || 10)) {
22769
22913
  return { procedures, lastDoc: null };
22770
22914
  }
22771
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22772
- return { procedures, lastDoc };
22915
+ const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22916
+ const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "createdAt");
22917
+ return { procedures, lastDoc: serializableCursor };
22773
22918
  } catch (error) {
22774
22919
  console.log("[PROCEDURE_SERVICE] Strategy 3 failed:", error);
22775
22920
  }
@@ -22785,6 +22930,13 @@ var ProcedureService = class extends BaseService {
22785
22930
  if (filters.clinicId) {
22786
22931
  constraints.push((0, import_firestore58.where)("clinicBranchId", "==", filters.clinicId));
22787
22932
  }
22933
+ if (filters.lastDoc) {
22934
+ const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "createdAt");
22935
+ if (cursorValues) {
22936
+ constraints.push((0, import_firestore58.startAfter)(...cursorValues));
22937
+ console.log("[PROCEDURE_SERVICE] Strategy 4: Using cursor for pagination");
22938
+ }
22939
+ }
22788
22940
  constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
22789
22941
  const q = (0, import_firestore58.query)((0, import_firestore58.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
22790
22942
  const querySnapshot = await (0, import_firestore58.getDocs)(q);
@@ -22799,8 +22951,9 @@ var ProcedureService = class extends BaseService {
22799
22951
  if (querySnapshot.docs.length < (filters.pagination || 10)) {
22800
22952
  return { procedures, lastDoc: null };
22801
22953
  }
22802
- const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22803
- return { procedures, lastDoc };
22954
+ const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
22955
+ const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "createdAt");
22956
+ return { procedures, lastDoc: serializableCursor };
22804
22957
  } catch (error) {
22805
22958
  console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
22806
22959
  }