@blackcode_sa/metaestetics-api 1.5.29 → 1.5.30

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
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/config/firebase.ts
9
2
  import { initializeApp } from "firebase/app";
10
3
  import { getFirestore } from "firebase/firestore";
@@ -3451,7 +3444,6 @@ import {
3451
3444
  limit as limit2,
3452
3445
  startAfter as startAfter2,
3453
3446
  orderBy,
3454
- writeBatch as writeBatch2,
3455
3447
  arrayUnion as arrayUnion5,
3456
3448
  arrayRemove as arrayRemove4
3457
3449
  } from "firebase/firestore";
@@ -3464,86 +3456,21 @@ var PractitionerService = class extends BaseService {
3464
3456
  }
3465
3457
  getClinicService() {
3466
3458
  if (!this.clinicService) {
3467
- throw new Error("ClinicService nije inicijalizovan");
3459
+ throw new Error("Clinic service not initialized!");
3468
3460
  }
3469
3461
  return this.clinicService;
3470
3462
  }
3471
- /**
3472
- * Postavlja referencu na ClinicService nakon inicijalizacije
3473
- */
3474
3463
  setClinicService(clinicService) {
3475
3464
  this.clinicService = clinicService;
3476
3465
  }
3477
3466
  /**
3478
- * Aggregates clinic information for a practitioner
3479
- * @param clinicIds Array of clinic IDs the practitioner works at
3480
- * @returns Array of ClinicInfo objects
3481
- */
3482
- async aggregateClinicInfo(clinicIds) {
3483
- const clinicsInfo = [];
3484
- for (const clinicId of clinicIds) {
3485
- const clinic = await this.getClinicService().getClinic(clinicId);
3486
- if (!clinic) continue;
3487
- clinicsInfo.push({
3488
- id: clinic.id,
3489
- featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
3490
- name: clinic.name,
3491
- description: clinic.description || "",
3492
- location: clinic.location,
3493
- contactInfo: clinic.contactInfo
3494
- });
3495
- }
3496
- return clinicsInfo;
3497
- }
3498
- /**
3499
- * @deprecated Aggregation of procedure info is now handled by ProcedureService.
3500
- */
3501
- async aggregateProcedureInfo(clinicIds, practitionerId) {
3502
- console.warn("PractitionerService.aggregateProcedureInfo is deprecated.");
3503
- return [];
3504
- }
3505
- /**
3506
- * Updates aggregated data (clinics and procedures) for a practitioner
3507
- * @param practitionerId ID of the practitioner to update
3508
- * @returns Updated practitioner
3509
- */
3510
- async updateAggregatedData(practitionerId) {
3511
- const practitioner = await this.getPractitioner(practitionerId);
3512
- if (!practitioner) {
3513
- return null;
3514
- }
3515
- const clinicsInfo = await this.aggregateClinicInfo(practitioner.clinics);
3516
- const proceduresInfo = await this.aggregateProcedureInfo(
3517
- practitioner.clinics,
3518
- practitionerId
3519
- );
3520
- const updatedPractitioner = await this.updatePractitioner(practitionerId, {
3521
- clinicsInfo,
3522
- proceduresInfo
3523
- });
3524
- return updatedPractitioner;
3525
- }
3526
- /**
3527
- * Kreira novog zdravstvenog radnika
3467
+ * Creates a new practitioner
3528
3468
  */
3529
3469
  async createPractitioner(data) {
3530
3470
  try {
3531
- const validatedData = createPractitionerSchema.parse(data);
3532
- const existingPractitioner = await this.getPractitionerByUserRef(
3533
- validatedData.userRef
3534
- );
3535
- if (existingPractitioner) {
3536
- throw new Error("User already has a practitioner profile");
3537
- }
3538
- if (validatedData.clinics) {
3539
- for (const clinicId of validatedData.clinics) {
3540
- const clinic = await this.getClinicService().getClinic(clinicId);
3541
- if (!clinic) {
3542
- throw new Error(`Clinic ${clinicId} not found`);
3543
- }
3544
- }
3545
- }
3546
- const defaultReviewInfo = {
3471
+ const validData = createPractitionerSchema.parse(data);
3472
+ const practitionerId = this.generateId();
3473
+ const reviewInfo = {
3547
3474
  totalReviews: 0,
3548
3475
  averageRating: 0,
3549
3476
  knowledgeAndExpertise: 0,
@@ -3553,50 +3480,46 @@ var PractitionerService = class extends BaseService {
3553
3480
  trustworthiness: 0,
3554
3481
  recommendationPercentage: 0
3555
3482
  };
3556
- const practitionerId = this.generateId();
3557
- let clinicsInfo = validatedData.clinicsInfo || [];
3558
- if (clinicsInfo.length === 0 && validatedData.clinics && validatedData.clinics.length > 0) {
3559
- clinicsInfo = await this.aggregateClinicInfo(validatedData.clinics);
3560
- }
3561
- const proceduresInfo = [];
3562
- const practitionerData = {
3483
+ const practitioner = {
3563
3484
  id: practitionerId,
3564
- userRef: validatedData.userRef,
3565
- basicInfo: validatedData.basicInfo,
3566
- certification: validatedData.certification,
3567
- clinics: validatedData.clinics || [],
3568
- clinicWorkingHours: validatedData.clinicWorkingHours || [],
3569
- clinicsInfo,
3485
+ userRef: validData.userRef,
3486
+ basicInfo: validData.basicInfo,
3487
+ certification: validData.certification,
3488
+ clinics: validData.clinics || [],
3489
+ clinicWorkingHours: validData.clinicWorkingHours || [],
3490
+ clinicsInfo: [],
3570
3491
  procedures: [],
3571
- proceduresInfo,
3572
- reviewInfo: defaultReviewInfo,
3573
- isActive: validatedData.isActive,
3574
- isVerified: validatedData.isVerified,
3575
- status: validatedData.status || "active" /* ACTIVE */,
3492
+ proceduresInfo: [],
3493
+ reviewInfo,
3494
+ isActive: validData.isActive !== void 0 ? validData.isActive : true,
3495
+ isVerified: validData.isVerified !== void 0 ? validData.isVerified : false,
3496
+ status: validData.status || "active" /* ACTIVE */,
3576
3497
  createdAt: serverTimestamp9(),
3577
3498
  updatedAt: serverTimestamp9()
3578
3499
  };
3579
3500
  practitionerSchema.parse({
3580
- ...practitionerData,
3501
+ ...practitioner,
3581
3502
  createdAt: Timestamp8.now(),
3582
3503
  updatedAt: Timestamp8.now()
3583
3504
  });
3584
- await setDoc7(
3585
- doc6(this.db, PRACTITIONERS_COLLECTION, practitionerData.id),
3586
- practitionerData
3505
+ const practitionerRef = doc6(
3506
+ this.db,
3507
+ PRACTITIONERS_COLLECTION,
3508
+ practitionerId
3587
3509
  );
3588
- let savedPractitioner = await this.getPractitioner(practitionerData.id);
3589
- if (!savedPractitioner) {
3590
- throw new Error("Failed to create practitioner profile");
3591
- }
3592
- if (proceduresInfo.length === 0 && validatedData.clinics && validatedData.clinics.length > 0) {
3593
- savedPractitioner = await this.updateAggregatedData(savedPractitioner.id) || savedPractitioner;
3510
+ await setDoc7(practitionerRef, practitioner);
3511
+ const createdPractitioner = await this.getPractitioner(practitionerId);
3512
+ if (!createdPractitioner) {
3513
+ throw new Error(
3514
+ `Failed to retrieve created practitioner ${practitionerId}`
3515
+ );
3594
3516
  }
3595
- return savedPractitioner;
3517
+ return createdPractitioner;
3596
3518
  } catch (error) {
3597
3519
  if (error instanceof z12.ZodError) {
3598
- throw new Error("Invalid practitioner data: " + error.message);
3520
+ throw new Error(`Invalid practitioner data: ${error.message}`);
3599
3521
  }
3522
+ console.error("Error creating practitioner:", error);
3600
3523
  throw error;
3601
3524
  }
3602
3525
  }
@@ -3637,10 +3560,7 @@ var PractitionerService = class extends BaseService {
3637
3560
  recommendationPercentage: 0
3638
3561
  };
3639
3562
  const practitionerId = this.generateId();
3640
- let clinicsInfo = validatedData.clinicsInfo || [];
3641
- if (clinicsInfo.length === 0 && clinics.length > 0) {
3642
- clinicsInfo = await this.aggregateClinicInfo(clinics);
3643
- }
3563
+ const clinicsInfo = validatedData.clinicsInfo || [];
3644
3564
  const proceduresInfo = [];
3645
3565
  const practitionerData = {
3646
3566
  id: practitionerId,
@@ -3877,113 +3797,100 @@ var PractitionerService = class extends BaseService {
3877
3797
  return querySnapshot.docs.map((doc28) => doc28.data());
3878
3798
  }
3879
3799
  /**
3880
- * Ažurira profil zdravstvenog radnika
3800
+ * Updates a practitioner
3881
3801
  */
3882
3802
  async updatePractitioner(practitionerId, data) {
3883
- const practitionerRef = doc6(
3884
- this.db,
3885
- PRACTITIONERS_COLLECTION,
3886
- practitionerId
3887
- );
3888
- const practitionerDoc = await getDoc9(practitionerRef);
3889
- if (!practitionerDoc.exists()) {
3890
- throw new Error("Practitioner not found");
3891
- }
3892
3803
  try {
3893
- const currentPractitioner = practitionerDoc.data();
3894
- if (data.clinics) {
3895
- for (const clinicId of data.clinics) {
3896
- const clinic = await this.getClinicService().getClinic(clinicId);
3897
- if (!clinic) {
3898
- throw new Error(`Clinic ${clinicId} not found`);
3899
- }
3900
- }
3901
- if (!data.clinicsInfo) {
3902
- data.clinicsInfo = await this.aggregateClinicInfo(data.clinics);
3903
- }
3904
- if (!data.proceduresInfo) {
3905
- data.proceduresInfo = await this.aggregateProcedureInfo(
3906
- data.clinics,
3907
- practitionerId
3908
- );
3909
- }
3804
+ const validData = data;
3805
+ const practitionerRef = doc6(
3806
+ this.db,
3807
+ PRACTITIONERS_COLLECTION,
3808
+ practitionerId
3809
+ );
3810
+ const practitionerDoc = await getDoc9(practitionerRef);
3811
+ if (!practitionerDoc.exists()) {
3812
+ throw new Error(`Practitioner ${practitionerId} not found`);
3910
3813
  }
3814
+ const currentPractitioner = practitionerDoc.data();
3911
3815
  const updateData = {
3912
- ...data,
3816
+ ...validData,
3913
3817
  updatedAt: serverTimestamp9()
3914
3818
  };
3915
- practitionerSchema.parse({
3916
- ...currentPractitioner,
3917
- ...data,
3918
- updatedAt: Timestamp8.now()
3919
- });
3920
3819
  await updateDoc8(practitionerRef, updateData);
3921
3820
  const updatedPractitioner = await this.getPractitioner(practitionerId);
3922
3821
  if (!updatedPractitioner) {
3923
- throw new Error("Failed to retrieve updated practitioner profile");
3822
+ throw new Error(
3823
+ `Failed to retrieve updated practitioner ${practitionerId}`
3824
+ );
3924
3825
  }
3925
3826
  return updatedPractitioner;
3926
3827
  } catch (error) {
3927
3828
  if (error instanceof z12.ZodError) {
3928
- throw new Error("Invalid practitioner data: " + error.message);
3829
+ throw new Error(`Invalid practitioner update data: ${error.message}`);
3929
3830
  }
3831
+ console.error(`Error updating practitioner ${practitionerId}:`, error);
3930
3832
  throw error;
3931
3833
  }
3932
3834
  }
3933
3835
  /**
3934
- * Dodaje kliniku zdravstvenom radniku
3836
+ * Adds a clinic to a practitioner
3935
3837
  */
3936
3838
  async addClinic(practitionerId, clinicId) {
3937
- const practitioner = await this.getPractitioner(practitionerId);
3938
- if (!practitioner) {
3939
- throw new Error("Practitioner not found");
3940
- }
3941
- const clinic = await this.getClinicService().getClinic(clinicId);
3942
- if (!clinic) {
3943
- throw new Error("Clinic not found");
3944
- }
3945
- if (practitioner.clinics.includes(clinicId)) {
3946
- throw new Error("Practitioner is already associated with this clinic");
3839
+ var _a;
3840
+ try {
3841
+ const practitionerRef = doc6(
3842
+ this.db,
3843
+ PRACTITIONERS_COLLECTION,
3844
+ practitionerId
3845
+ );
3846
+ const practitionerDoc = await getDoc9(practitionerRef);
3847
+ if (!practitionerDoc.exists()) {
3848
+ throw new Error(`Practitioner ${practitionerId} not found`);
3849
+ }
3850
+ const practitioner = practitionerDoc.data();
3851
+ if ((_a = practitioner.clinics) == null ? void 0 : _a.includes(clinicId)) {
3852
+ console.log(
3853
+ `Clinic ${clinicId} already added to practitioner ${practitionerId}`
3854
+ );
3855
+ return;
3856
+ }
3857
+ await updateDoc8(practitionerRef, {
3858
+ clinics: arrayUnion5(clinicId),
3859
+ updatedAt: serverTimestamp9()
3860
+ });
3861
+ } catch (error) {
3862
+ console.error(
3863
+ `Error adding clinic ${clinicId} to practitioner ${practitionerId}:`,
3864
+ error
3865
+ );
3866
+ throw error;
3947
3867
  }
3948
- const updatedClinics = [...practitioner.clinics, clinicId];
3949
- const clinicInfo = {
3950
- id: clinic.id,
3951
- name: clinic.name,
3952
- description: clinic.description || "",
3953
- featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
3954
- location: clinic.location,
3955
- contactInfo: clinic.contactInfo
3956
- };
3957
- const updatedClinicsInfo = [...practitioner.clinicsInfo, clinicInfo];
3958
- await this.updatePractitioner(practitionerId, {
3959
- clinics: updatedClinics,
3960
- clinicsInfo: updatedClinicsInfo
3961
- });
3962
- await this.updateAggregatedData(practitionerId);
3963
3868
  }
3964
3869
  /**
3965
- * Uklanja kliniku iz liste klinika zdravstvenog radnika
3870
+ * Removes a clinic from a practitioner
3966
3871
  */
3967
3872
  async removeClinic(practitionerId, clinicId) {
3968
- const practitioner = await this.getPractitioner(practitionerId);
3969
- if (!practitioner) {
3970
- throw new Error("Practitioner not found");
3971
- }
3972
- if (!practitioner.clinics.includes(clinicId)) {
3973
- throw new Error("Practitioner is not associated with this clinic");
3873
+ try {
3874
+ const practitionerRef = doc6(
3875
+ this.db,
3876
+ PRACTITIONERS_COLLECTION,
3877
+ practitionerId
3878
+ );
3879
+ const practitionerDoc = await getDoc9(practitionerRef);
3880
+ if (!practitionerDoc.exists()) {
3881
+ throw new Error(`Practitioner ${practitionerId} not found`);
3882
+ }
3883
+ await updateDoc8(practitionerRef, {
3884
+ clinics: arrayRemove4(clinicId),
3885
+ updatedAt: serverTimestamp9()
3886
+ });
3887
+ } catch (error) {
3888
+ console.error(
3889
+ `Error removing clinic ${clinicId} from practitioner ${practitionerId}:`,
3890
+ error
3891
+ );
3892
+ throw error;
3974
3893
  }
3975
- const updatedClinics = practitioner.clinics.filter((id) => id !== clinicId);
3976
- const updatedClinicsInfo = practitioner.clinicsInfo.filter(
3977
- (clinic) => clinic.id !== clinicId
3978
- );
3979
- const updatedProceduresInfo = practitioner.proceduresInfo.filter(
3980
- (procedure) => procedure.clinicId !== clinicId
3981
- );
3982
- await this.updatePractitioner(practitionerId, {
3983
- clinics: updatedClinics,
3984
- clinicsInfo: updatedClinicsInfo,
3985
- proceduresInfo: updatedProceduresInfo
3986
- });
3987
3894
  }
3988
3895
  /**
3989
3896
  * Deaktivira profil zdravstvenog radnika
@@ -4221,112 +4128,6 @@ var PractitionerService = class extends BaseService {
4221
4128
  throw error;
4222
4129
  }
4223
4130
  }
4224
- // --- Helper Functions ---
4225
- /**
4226
- * Aggregates essential clinic information for embedding in Practitioner.
4227
- * @param clinicIds Array of clinic IDs the practitioner works at
4228
- * @returns Array of ClinicInfo objects
4229
- */
4230
- async _aggregateClinicInfoForPractitioner(clinicIds) {
4231
- const clinicsInfo = [];
4232
- const clinicService = this.getClinicService();
4233
- for (const clinicId of clinicIds) {
4234
- try {
4235
- const clinic = await clinicService.getClinic(clinicId);
4236
- if (!clinic) {
4237
- console.warn(
4238
- `Clinic ${clinicId} not found during practitioner aggregation.`
4239
- );
4240
- continue;
4241
- }
4242
- clinicsInfo.push({
4243
- id: clinic.id,
4244
- featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
4245
- name: clinic.name,
4246
- description: clinic.description || "",
4247
- location: clinic.location,
4248
- contactInfo: clinic.contactInfo
4249
- });
4250
- } catch (error) {
4251
- console.error(
4252
- `Error fetching clinic ${clinicId} for practitioner aggregation:`,
4253
- error
4254
- );
4255
- }
4256
- }
4257
- return clinicsInfo;
4258
- }
4259
- /**
4260
- * Creates an aggregated DoctorInfo object from Practitioner data.
4261
- * @param practitioner The practitioner object
4262
- * @returns DoctorInfo object
4263
- */
4264
- _createDoctorInfoForClinic(practitioner) {
4265
- var _a;
4266
- return {
4267
- id: practitioner.id,
4268
- name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
4269
- description: practitioner.basicInfo.bio || "",
4270
- photo: practitioner.basicInfo.profileImageUrl || "",
4271
- rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
4272
- services: practitioner.procedures || []
4273
- // List of procedure IDs
4274
- };
4275
- }
4276
- /**
4277
- * Updates the DoctorInfo within the doctorsInfo array for multiple clinics.
4278
- * @param clinicIds IDs of clinics to update
4279
- * @param doctorInfo The updated DoctorInfo object
4280
- */
4281
- async _updateDoctorInfoInClinics(clinicIds, doctorInfo) {
4282
- const batch = writeBatch2(this.db);
4283
- const practitionerId = doctorInfo.id;
4284
- for (const clinicId of clinicIds) {
4285
- const clinicRef = doc6(this.db, CLINICS_COLLECTION, clinicId);
4286
- batch.update(clinicRef, {
4287
- doctorsInfo: arrayRemove4(...[{ id: practitionerId }]),
4288
- updatedAt: serverTimestamp9()
4289
- });
4290
- batch.update(clinicRef, {
4291
- doctorsInfo: arrayUnion5(doctorInfo),
4292
- updatedAt: serverTimestamp9()
4293
- });
4294
- }
4295
- try {
4296
- await batch.commit();
4297
- } catch (error) {
4298
- console.error(
4299
- `Error updating doctor info in clinics for practitioner ${practitionerId}:`,
4300
- error
4301
- );
4302
- }
4303
- }
4304
- /**
4305
- * Removes DoctorInfo from the doctorsInfo array for multiple clinics.
4306
- * @param clinicIds IDs of clinics to update
4307
- * @param practitionerId ID of the practitioner whose info should be removed
4308
- */
4309
- async _removeDoctorInfoFromClinics(clinicIds, practitionerId) {
4310
- const batch = writeBatch2(this.db);
4311
- for (const clinicId of clinicIds) {
4312
- const clinicRef = doc6(this.db, CLINICS_COLLECTION, clinicId);
4313
- batch.update(clinicRef, {
4314
- doctors: arrayRemove4(practitionerId),
4315
- // Also remove from simple ID list
4316
- doctorsInfo: arrayRemove4(...[{ id: practitionerId }]),
4317
- // Remove by ID matcher
4318
- updatedAt: serverTimestamp9()
4319
- });
4320
- }
4321
- try {
4322
- await batch.commit();
4323
- } catch (error) {
4324
- console.error(
4325
- `Error removing doctor info from clinics for practitioner ${practitionerId}:`,
4326
- error
4327
- );
4328
- }
4329
- }
4330
4131
  };
4331
4132
 
4332
4133
  // src/services/user.service.ts
@@ -5263,8 +5064,7 @@ import {
5263
5064
  Timestamp as Timestamp12,
5264
5065
  serverTimestamp as serverTimestamp12,
5265
5066
  writeBatch as writeBatch4,
5266
- arrayUnion as arrayUnion6,
5267
- arrayRemove as arrayRemove5
5067
+ arrayUnion as arrayUnion6
5268
5068
  } from "firebase/firestore";
5269
5069
  import {
5270
5070
  geohashForLocation as geohashForLocation4
@@ -5281,7 +5081,9 @@ import {
5281
5081
  where as where7,
5282
5082
  updateDoc as updateDoc11,
5283
5083
  setDoc as setDoc10,
5284
- Timestamp as Timestamp11
5084
+ Timestamp as Timestamp11,
5085
+ limit as limit3,
5086
+ startAfter as startAfter3
5285
5087
  } from "firebase/firestore";
5286
5088
  import {
5287
5089
  geohashForLocation as geohashForLocation3,
@@ -5531,15 +5333,14 @@ async function getAllClinics(db, pagination, lastDoc) {
5531
5333
  const clinicsCollection = collection7(db, CLINICS_COLLECTION);
5532
5334
  let clinicsQuery = query7(clinicsCollection);
5533
5335
  if (pagination && pagination > 0) {
5534
- const { limit: limit6, startAfter: startAfter6 } = __require("firebase/firestore");
5535
5336
  if (lastDoc) {
5536
5337
  clinicsQuery = query7(
5537
5338
  clinicsCollection,
5538
- startAfter6(lastDoc),
5539
- limit6(pagination)
5339
+ startAfter3(lastDoc),
5340
+ limit3(pagination)
5540
5341
  );
5541
5342
  } else {
5542
- clinicsQuery = query7(clinicsCollection, limit6(pagination));
5343
+ clinicsQuery = query7(clinicsCollection, limit3(pagination));
5543
5344
  }
5544
5345
  }
5545
5346
  const clinicsSnapshot = await getDocs7(clinicsQuery);
@@ -5729,8 +5530,8 @@ import {
5729
5530
  query as query9,
5730
5531
  where as where9,
5731
5532
  getDocs as getDocs9,
5732
- startAfter as startAfter3,
5733
- limit as limit3,
5533
+ startAfter as startAfter4,
5534
+ limit as limit4,
5734
5535
  documentId,
5735
5536
  orderBy as orderBy2
5736
5537
  } from "firebase/firestore";
@@ -5768,10 +5569,10 @@ async function getClinicsByFilters(db, filters) {
5768
5569
  );
5769
5570
  }
5770
5571
  if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
5771
- constraints.push(startAfter3(filters.lastDoc));
5772
- constraints.push(limit3(filters.pagination));
5572
+ constraints.push(startAfter4(filters.lastDoc));
5573
+ constraints.push(limit4(filters.pagination));
5773
5574
  } else if (filters.pagination && filters.pagination > 0) {
5774
- constraints.push(limit3(filters.pagination));
5575
+ constraints.push(limit4(filters.pagination));
5775
5576
  }
5776
5577
  constraints.push(orderBy2(documentId()));
5777
5578
  let clinicsResult = [];
@@ -5888,59 +5689,8 @@ var ClinicService = class extends BaseService {
5888
5689
  this.clinicAdminService = clinicAdminService;
5889
5690
  this.clinicGroupService = clinicGroupService;
5890
5691
  }
5891
- // --- Helper Functions ---
5892
- /**
5893
- * Creates an aggregated ClinicInfo object from Clinic data.
5894
- * @param clinic The clinic object
5895
- * @returns ClinicInfo object
5896
- */
5897
- _createClinicInfoForAggregation(clinic) {
5898
- return {
5899
- id: clinic.id,
5900
- featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
5901
- name: clinic.name,
5902
- description: clinic.description || "",
5903
- location: clinic.location,
5904
- contactInfo: clinic.contactInfo
5905
- };
5906
- }
5907
- /**
5908
- * Updates the ClinicInfo within the clinicsInfo array for multiple practitioners.
5909
- * @param practitionerIds IDs of practitioners to update
5910
- * @param clinicInfo The updated ClinicInfo object
5911
- */
5912
- async _updateClinicInfoInPractitioners(practitionerIds, clinicInfo) {
5913
- const batch = writeBatch4(this.db);
5914
- const clinicId = clinicInfo.id;
5915
- for (const practitionerId of practitionerIds) {
5916
- const practitionerRef = doc10(
5917
- this.db,
5918
- PRACTITIONERS_COLLECTION,
5919
- practitionerId
5920
- );
5921
- batch.update(practitionerRef, {
5922
- clinicsInfo: arrayRemove5(...[{ id: clinicId }]),
5923
- updatedAt: serverTimestamp12()
5924
- });
5925
- batch.update(practitionerRef, {
5926
- clinicsInfo: arrayUnion6(clinicInfo),
5927
- updatedAt: serverTimestamp12()
5928
- });
5929
- }
5930
- try {
5931
- await batch.commit();
5932
- } catch (error) {
5933
- console.error(
5934
- `Error updating clinic info in practitioners for clinic ${clinicId}:`,
5935
- error
5936
- );
5937
- }
5938
- }
5939
- // --- Core Service Methods (Updated) ---
5940
5692
  /**
5941
5693
  * Creates a new clinic.
5942
- * Initializes empty doctorsInfo and proceduresInfo.
5943
- * Aggregation into Clinic happens via PractitionerService and ProcedureService.
5944
5694
  */
5945
5695
  async createClinic(data, creatorAdminId) {
5946
5696
  try {
@@ -5997,20 +5747,6 @@ var ClinicService = class extends BaseService {
5997
5747
  const batch = writeBatch4(this.db);
5998
5748
  const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
5999
5749
  batch.set(clinicRef, clinicData);
6000
- const groupRef = doc10(
6001
- this.db,
6002
- CLINIC_GROUPS_COLLECTION,
6003
- validatedData.clinicGroupId
6004
- );
6005
- const newClinicInfoForGroup = this._createClinicInfoForAggregation({
6006
- ...clinicData,
6007
- id: clinicId
6008
- });
6009
- batch.update(groupRef, {
6010
- clinics: arrayUnion6(clinicId),
6011
- clinicsInfo: arrayUnion6(newClinicInfoForGroup),
6012
- updatedAt: serverTimestamp12()
6013
- });
6014
5750
  const adminRef = doc10(this.db, CLINIC_ADMINS_COLLECTION, creatorAdminId);
6015
5751
  batch.update(adminRef, {
6016
5752
  clinicsManaged: arrayUnion6(clinicId),
@@ -6029,7 +5765,7 @@ var ClinicService = class extends BaseService {
6029
5765
  }
6030
5766
  }
6031
5767
  /**
6032
- * Updates a clinic and propagates changes (ClinicInfo) to associated practitioners.
5768
+ * Updates a clinic.
6033
5769
  */
6034
5770
  async updateClinic(clinicId, data, adminId) {
6035
5771
  const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
@@ -6064,32 +5800,7 @@ var ClinicService = class extends BaseService {
6064
5800
  ...updatePayload,
6065
5801
  updatedAt: serverTimestamp12()
6066
5802
  };
6067
- const batch = writeBatch4(this.db);
6068
- batch.update(clinicRef, updateDataForFirestore);
6069
- const groupRef = doc10(
6070
- this.db,
6071
- CLINIC_GROUPS_COLLECTION,
6072
- currentClinic.clinicGroupId
6073
- );
6074
- const updatedClinicInfoForGroup = this._createClinicInfoForAggregation(
6075
- finalStateForValidation
6076
- );
6077
- batch.update(groupRef, {
6078
- clinicsInfo: arrayRemove5(...[{ id: clinicId }]),
6079
- updatedAt: serverTimestamp12()
6080
- });
6081
- batch.update(groupRef, {
6082
- clinicsInfo: arrayUnion6(updatedClinicInfoForGroup),
6083
- updatedAt: serverTimestamp12()
6084
- });
6085
- const practitionerIds = currentClinic.doctors || [];
6086
- if (practitionerIds.length > 0) {
6087
- await this._updateClinicInfoInPractitioners(
6088
- practitionerIds,
6089
- updatedClinicInfoForGroup
6090
- );
6091
- }
6092
- await batch.commit();
5803
+ await updateDoc12(clinicRef, updateDataForFirestore);
6093
5804
  const updatedClinic = await this.getClinic(clinicId);
6094
5805
  if (!updatedClinic) throw new Error("Failed to retrieve updated clinic");
6095
5806
  return updatedClinic;
@@ -6105,7 +5816,6 @@ var ClinicService = class extends BaseService {
6105
5816
  }
6106
5817
  /**
6107
5818
  * Deactivates a clinic.
6108
- * Note: Does not currently remove ClinicInfo from practitioners (might be desired).
6109
5819
  */
6110
5820
  async deactivateClinic(clinicId, adminId) {
6111
5821
  const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
@@ -6114,10 +5824,6 @@ var ClinicService = class extends BaseService {
6114
5824
  updatedAt: serverTimestamp12()
6115
5825
  });
6116
5826
  }
6117
- // --- Other Methods ---
6118
- // (getClinic, getClinicsByGroup, findClinicsInRadius, addTags, removeTags, getClinicsByAdmin, etc.)
6119
- // Review these methods to ensure they don't rely on outdated aggregation logic (e.g., filtering ServiceInfo)
6120
- // and update them to use proceduresInfo if necessary for filtering.
6121
5827
  /**
6122
5828
  * Dohvata kliniku po ID-u
6123
5829
  */
@@ -6132,12 +5838,8 @@ var ClinicService = class extends BaseService {
6132
5838
  }
6133
5839
  /**
6134
5840
  * Pretražuje klinike u određenom radijusu
6135
- * REVIEW: SearchUtils.findClinicsInRadius might need updating for filters.
6136
5841
  */
6137
5842
  async findClinicsInRadius(center, radiusInKm, filters) {
6138
- console.warn(
6139
- "SearchUtils.findClinicsInRadius filter logic might need updating for proceduresInfo."
6140
- );
6141
5843
  return findClinicsInRadius(
6142
5844
  this.db,
6143
5845
  center,
@@ -7111,11 +6813,14 @@ import {
7111
6813
  getDocs as getDocs13,
7112
6814
  query as query13,
7113
6815
  where as where13,
6816
+ updateDoc as updateDoc15,
6817
+ setDoc as setDoc13,
6818
+ deleteDoc as deleteDoc8,
7114
6819
  serverTimestamp as serverTimestamp14,
7115
- writeBatch as writeBatch6,
7116
- arrayUnion as arrayUnion7,
7117
- arrayRemove as arrayRemove6,
7118
- orderBy as orderBy4
6820
+ orderBy as orderBy4,
6821
+ limit as limit5,
6822
+ startAfter as startAfter5,
6823
+ documentId as documentId2
7119
6824
  } from "firebase/firestore";
7120
6825
 
7121
6826
  // src/types/procedure/index.ts
@@ -7188,6 +6893,7 @@ var procedureSchema = createProcedureSchema.extend({
7188
6893
  });
7189
6894
 
7190
6895
  // src/services/procedure/procedure.service.ts
6896
+ import { distanceBetween as distanceBetween6, geohashQueryBounds as geohashQueryBounds5 } from "geofire-common";
7191
6897
  var ProcedureService = class extends BaseService {
7192
6898
  constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService) {
7193
6899
  super(db, auth, app);
@@ -7196,108 +6902,8 @@ var ProcedureService = class extends BaseService {
7196
6902
  this.technologyService = technologyService;
7197
6903
  this.productService = productService;
7198
6904
  }
7199
- // Helper function to create ProcedureSummaryInfo
7200
- _createProcedureSummaryInfo(procedure) {
7201
- var _a, _b, _c, _d, _e;
7202
- const categoryName = ((_a = procedure.category) == null ? void 0 : _a.name) || "N/A";
7203
- const subcategoryName = ((_b = procedure.subcategory) == null ? void 0 : _b.name) || "N/A";
7204
- const technologyName = ((_c = procedure.technology) == null ? void 0 : _c.name) || "N/A";
7205
- const clinicName = ((_d = procedure.clinicInfo) == null ? void 0 : _d.name) || "N/A";
7206
- const practitionerName = ((_e = procedure.doctorInfo) == null ? void 0 : _e.name) || "N/A";
7207
- return {
7208
- id: procedure.id,
7209
- name: procedure.name,
7210
- description: procedure.description || "",
7211
- photo: "",
7212
- // No photo source identified yet
7213
- family: procedure.family,
7214
- categoryName,
7215
- subcategoryName,
7216
- technologyName,
7217
- price: procedure.price,
7218
- pricingMeasure: procedure.pricingMeasure,
7219
- currency: procedure.currency,
7220
- duration: procedure.duration,
7221
- clinicId: procedure.clinicBranchId,
7222
- clinicName,
7223
- practitionerId: procedure.practitionerId,
7224
- practitionerName
7225
- };
7226
- }
7227
- // Helper to update practitioner's procedures
7228
- async _updatePractitionerProcedures(practitionerId, procedureSummary, procedureIdToRemove) {
7229
- const practitionerRef = doc13(
7230
- this.db,
7231
- PRACTITIONERS_COLLECTION,
7232
- practitionerId
7233
- );
7234
- const updateData = {};
7235
- if (procedureSummary) {
7236
- updateData["procedures"] = arrayUnion7(procedureSummary.id);
7237
- updateData["proceduresInfo"] = arrayRemove6(
7238
- ...[
7239
- // Need to spread the arrayRemove arguments
7240
- // Create a 'matcher' object with only the ID for removal
7241
- { id: procedureSummary.id }
7242
- ]
7243
- );
7244
- } else if (procedureIdToRemove) {
7245
- updateData["procedures"] = arrayRemove6(procedureIdToRemove);
7246
- updateData["proceduresInfo"] = arrayRemove6(
7247
- ...[{ id: procedureIdToRemove }]
7248
- // Use matcher for removal
7249
- );
7250
- } else {
7251
- return;
7252
- }
7253
- updateData["updatedAt"] = serverTimestamp14();
7254
- const batch = writeBatch6(this.db);
7255
- batch.update(practitionerRef, updateData);
7256
- if (procedureSummary) {
7257
- batch.update(practitionerRef, {
7258
- proceduresInfo: arrayUnion7(procedureSummary)
7259
- });
7260
- }
7261
- await batch.commit();
7262
- }
7263
- // Helper to update clinic's procedures
7264
- async _updateClinicProcedures(clinicId, procedureSummary, procedureIdToRemove) {
7265
- const clinicRef = doc13(this.db, CLINICS_COLLECTION, clinicId);
7266
- const clinicSnap = await getDoc16(clinicRef);
7267
- if (!clinicSnap.exists()) {
7268
- console.warn(
7269
- `Clinic ${clinicId} not found, skipping procedure aggregation update.`
7270
- );
7271
- return;
7272
- }
7273
- const updateData = {};
7274
- if (procedureSummary) {
7275
- updateData["services"] = arrayUnion7(procedureSummary.id);
7276
- updateData["proceduresInfo"] = arrayRemove6(
7277
- ...[{ id: procedureSummary.id }]
7278
- // Use matcher for removal
7279
- );
7280
- } else if (procedureIdToRemove) {
7281
- updateData["services"] = arrayRemove6(procedureIdToRemove);
7282
- updateData["proceduresInfo"] = arrayRemove6(
7283
- ...[{ id: procedureIdToRemove }]
7284
- // Use matcher for removal
7285
- );
7286
- } else {
7287
- return;
7288
- }
7289
- updateData["updatedAt"] = serverTimestamp14();
7290
- const batch = writeBatch6(this.db);
7291
- batch.update(clinicRef, updateData);
7292
- if (procedureSummary) {
7293
- batch.update(clinicRef, {
7294
- proceduresInfo: arrayUnion7(procedureSummary)
7295
- });
7296
- }
7297
- await batch.commit();
7298
- }
7299
6905
  /**
7300
- * Creates a new procedure and updates related practitioner/clinic aggregates
6906
+ * Creates a new procedure
7301
6907
  * @param data - The data for creating a new procedure
7302
6908
  * @returns The created procedure
7303
6909
  */
@@ -7357,9 +6963,7 @@ var ProcedureService = class extends BaseService {
7357
6963
  description: practitioner.basicInfo.bio || "",
7358
6964
  photo: practitioner.basicInfo.profileImageUrl || "",
7359
6965
  rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
7360
- // Example rating source
7361
6966
  services: practitioner.procedures || []
7362
- // Link services to practitioner's procedures
7363
6967
  };
7364
6968
  const procedureId = this.generateId();
7365
6969
  const newProcedure = {
@@ -7394,37 +6998,12 @@ var ProcedureService = class extends BaseService {
7394
6998
  isActive: true
7395
6999
  // Default to active
7396
7000
  };
7397
- const batch = writeBatch6(this.db);
7398
7001
  const procedureRef = doc13(this.db, PROCEDURES_COLLECTION, procedureId);
7399
- batch.set(procedureRef, {
7002
+ await setDoc13(procedureRef, {
7400
7003
  ...newProcedure,
7401
7004
  createdAt: serverTimestamp14(),
7402
7005
  updatedAt: serverTimestamp14()
7403
7006
  });
7404
- const procedureSummary = this._createProcedureSummaryInfo({
7405
- ...newProcedure,
7406
- createdAt: /* @__PURE__ */ new Date(),
7407
- // Use placeholder date for summary creation
7408
- updatedAt: /* @__PURE__ */ new Date()
7409
- });
7410
- const practitionerUpdateData = {
7411
- procedures: arrayUnion7(procedureId),
7412
- proceduresInfo: arrayUnion7(procedureSummary),
7413
- updatedAt: serverTimestamp14()
7414
- };
7415
- batch.update(practitionerRef, practitionerUpdateData);
7416
- const clinicUpdateData = {
7417
- // services: arrayUnion(procedureId), // Decide if 'services' array is still needed
7418
- proceduresInfo: arrayUnion7(procedureSummary),
7419
- // Potentially update clinic.doctors array if not already present
7420
- doctors: arrayUnion7(validatedData.practitionerId),
7421
- // Potentially update clinic.doctorsInfo array
7422
- // This requires fetching existing doctorsInfo and adding/updating
7423
- // For simplicity now, we'll just add the procedure summary
7424
- updatedAt: serverTimestamp14()
7425
- };
7426
- batch.update(clinicRef, clinicUpdateData);
7427
- await batch.commit();
7428
7007
  const savedDoc = await getDoc16(procedureRef);
7429
7008
  return savedDoc.data();
7430
7009
  }
@@ -7470,7 +7049,7 @@ var ProcedureService = class extends BaseService {
7470
7049
  return snapshot.docs.map((doc28) => doc28.data());
7471
7050
  }
7472
7051
  /**
7473
- * Updates a procedure and its related aggregates in Practitioner and Clinic docs
7052
+ * Updates a procedure
7474
7053
  * @param id - The ID of the procedure to update
7475
7054
  * @param data - The data to update the procedure with
7476
7055
  * @returns The updated procedure
@@ -7587,104 +7166,15 @@ var ProcedureService = class extends BaseService {
7587
7166
  } else if (validatedData.productId) {
7588
7167
  console.warn("Attempted to update product without a valid technologyId");
7589
7168
  }
7590
- const batch = writeBatch6(this.db);
7591
- batch.update(procedureRef, {
7169
+ await updateDoc15(procedureRef, {
7592
7170
  ...updatedProcedureData,
7593
7171
  updatedAt: serverTimestamp14()
7594
7172
  });
7595
- const finalProcedureStateForSummary = {
7596
- ...existingProcedure,
7597
- ...updatedProcedureData,
7598
- // Apply updates
7599
- // Ensure nested objects needed for summary are present
7600
- category: updatedProcedureData.category || existingProcedure.category,
7601
- subcategory: updatedProcedureData.subcategory || existingProcedure.subcategory,
7602
- technology: updatedProcedureData.technology || existingProcedure.technology,
7603
- product: updatedProcedureData.product || existingProcedure.product,
7604
- clinicInfo: updatedProcedureData.clinicInfo || existingProcedure.clinicInfo,
7605
- doctorInfo: updatedProcedureData.doctorInfo || existingProcedure.doctorInfo,
7606
- practitionerId: validatedData.practitionerId || existingProcedure.practitionerId,
7607
- // Use potentially updated IDs
7608
- clinicBranchId: validatedData.clinicBranchId || existingProcedure.clinicBranchId
7609
- };
7610
- const updatedProcedureSummary = this._createProcedureSummaryInfo(
7611
- finalProcedureStateForSummary
7612
- );
7613
- if (practitionerChanged) {
7614
- const oldPractitionerRef = doc13(
7615
- this.db,
7616
- PRACTITIONERS_COLLECTION,
7617
- oldPractitionerId
7618
- );
7619
- batch.update(oldPractitionerRef, {
7620
- procedures: arrayRemove6(id),
7621
- proceduresInfo: arrayRemove6(...[{ id }]),
7622
- // Matcher for removal
7623
- updatedAt: serverTimestamp14()
7624
- });
7625
- const newPractitionerRef = doc13(
7626
- this.db,
7627
- PRACTITIONERS_COLLECTION,
7628
- updatedProcedureSummary.practitionerId
7629
- );
7630
- batch.update(newPractitionerRef, {
7631
- procedures: arrayUnion7(id),
7632
- proceduresInfo: arrayUnion7(updatedProcedureSummary),
7633
- updatedAt: serverTimestamp14()
7634
- });
7635
- } else {
7636
- const currentPractitionerRef = doc13(
7637
- this.db,
7638
- PRACTITIONERS_COLLECTION,
7639
- oldPractitionerId
7640
- );
7641
- batch.update(currentPractitionerRef, {
7642
- proceduresInfo: arrayRemove6(...[{ id }]),
7643
- updatedAt: serverTimestamp14()
7644
- });
7645
- batch.update(currentPractitionerRef, {
7646
- proceduresInfo: arrayUnion7(updatedProcedureSummary),
7647
- updatedAt: serverTimestamp14()
7648
- });
7649
- }
7650
- if (clinicChanged) {
7651
- const oldClinicRef = doc13(this.db, CLINICS_COLLECTION, oldClinicId);
7652
- batch.update(oldClinicRef, {
7653
- // services: arrayRemove(id),
7654
- proceduresInfo: arrayRemove6(...[{ id }]),
7655
- // Matcher for removal
7656
- updatedAt: serverTimestamp14()
7657
- // Potentially remove from clinic.doctors and clinic.doctorsInfo if practitioner also changed or was last one for this clinic
7658
- });
7659
- const newClinicRef = doc13(
7660
- this.db,
7661
- CLINICS_COLLECTION,
7662
- updatedProcedureSummary.clinicId
7663
- );
7664
- batch.update(newClinicRef, {
7665
- // services: arrayUnion(id),
7666
- proceduresInfo: arrayUnion7(updatedProcedureSummary),
7667
- doctors: arrayUnion7(updatedProcedureSummary.practitionerId),
7668
- // Ensure practitioner is listed
7669
- updatedAt: serverTimestamp14()
7670
- });
7671
- } else {
7672
- const currentClinicRef = doc13(this.db, CLINICS_COLLECTION, oldClinicId);
7673
- batch.update(currentClinicRef, {
7674
- proceduresInfo: arrayRemove6(...[{ id }]),
7675
- updatedAt: serverTimestamp14()
7676
- });
7677
- batch.update(currentClinicRef, {
7678
- proceduresInfo: arrayUnion7(updatedProcedureSummary),
7679
- updatedAt: serverTimestamp14()
7680
- });
7681
- }
7682
- await batch.commit();
7683
7173
  const updatedSnapshot = await getDoc16(procedureRef);
7684
7174
  return updatedSnapshot.data();
7685
7175
  }
7686
7176
  /**
7687
- * Deactivates a procedure (soft delete) and updates aggregates
7177
+ * Deactivates a procedure (soft delete)
7688
7178
  * @param id - The ID of the procedure to deactivate
7689
7179
  */
7690
7180
  async deactivateProcedure(id) {
@@ -7694,39 +7184,13 @@ var ProcedureService = class extends BaseService {
7694
7184
  console.warn(`Procedure ${id} not found for deactivation.`);
7695
7185
  return;
7696
7186
  }
7697
- const procedure = procedureSnap.data();
7698
- const batch = writeBatch6(this.db);
7699
- batch.update(procedureRef, {
7187
+ await updateDoc15(procedureRef, {
7700
7188
  isActive: false,
7701
7189
  updatedAt: serverTimestamp14()
7702
7190
  });
7703
- const practitionerRef = doc13(
7704
- this.db,
7705
- PRACTITIONERS_COLLECTION,
7706
- procedure.practitionerId
7707
- );
7708
- batch.update(practitionerRef, {
7709
- procedures: arrayRemove6(id),
7710
- proceduresInfo: arrayRemove6(...[{ id }]),
7711
- // Matcher for removal
7712
- updatedAt: serverTimestamp14()
7713
- });
7714
- const clinicRef = doc13(
7715
- this.db,
7716
- CLINICS_COLLECTION,
7717
- procedure.clinicBranchId
7718
- );
7719
- batch.update(clinicRef, {
7720
- // services: arrayRemove(id),
7721
- proceduresInfo: arrayRemove6(...[{ id }]),
7722
- // Matcher for removal
7723
- updatedAt: serverTimestamp14()
7724
- // Potentially update clinic.doctors/doctorsInfo if this was the last active procedure for this doctor at this clinic
7725
- });
7726
- await batch.commit();
7727
7191
  }
7728
7192
  /**
7729
- * Deletes a procedure permanently and updates related aggregates
7193
+ * Deletes a procedure permanently
7730
7194
  * @param id - The ID of the procedure to delete
7731
7195
  * @returns A boolean indicating if the deletion was successful
7732
7196
  */
@@ -7736,37 +7200,7 @@ var ProcedureService = class extends BaseService {
7736
7200
  if (!procedureSnapshot.exists()) {
7737
7201
  return false;
7738
7202
  }
7739
- const procedure = procedureSnapshot.data();
7740
- const batch = writeBatch6(this.db);
7741
- if (procedure.practitionerId) {
7742
- const practitionerRef = doc13(
7743
- this.db,
7744
- PRACTITIONERS_COLLECTION,
7745
- procedure.practitionerId
7746
- );
7747
- batch.update(practitionerRef, {
7748
- procedures: arrayRemove6(id),
7749
- proceduresInfo: arrayRemove6(...[{ id }]),
7750
- // Matcher for removal
7751
- updatedAt: serverTimestamp14()
7752
- });
7753
- }
7754
- if (procedure.clinicBranchId) {
7755
- const clinicRef = doc13(
7756
- this.db,
7757
- CLINICS_COLLECTION,
7758
- procedure.clinicBranchId
7759
- );
7760
- batch.update(clinicRef, {
7761
- // services: arrayRemove(id),
7762
- proceduresInfo: arrayRemove6(...[{ id }]),
7763
- // Matcher for removal
7764
- updatedAt: serverTimestamp14()
7765
- // Potentially update clinic.doctors/doctorsInfo
7766
- });
7767
- }
7768
- batch.delete(procedureRef);
7769
- await batch.commit();
7203
+ await deleteDoc8(procedureRef);
7770
7204
  return true;
7771
7205
  }
7772
7206
  /**
@@ -7795,20 +7229,20 @@ var ProcedureService = class extends BaseService {
7795
7229
  const proceduresCollection = collection13(this.db, PROCEDURES_COLLECTION);
7796
7230
  let proceduresQuery = query13(proceduresCollection);
7797
7231
  if (pagination && pagination > 0) {
7798
- const { limit: limit6, startAfter: startAfter6 } = await import("firebase/firestore");
7232
+ const { limit: limit8, startAfter: startAfter8 } = await import("firebase/firestore");
7799
7233
  if (lastDoc) {
7800
7234
  proceduresQuery = query13(
7801
7235
  proceduresCollection,
7802
7236
  orderBy4("name"),
7803
7237
  // Use imported orderBy
7804
- startAfter6(lastDoc),
7805
- limit6(pagination)
7238
+ startAfter8(lastDoc),
7239
+ limit8(pagination)
7806
7240
  );
7807
7241
  } else {
7808
7242
  proceduresQuery = query13(
7809
7243
  proceduresCollection,
7810
7244
  orderBy4("name"),
7811
- limit6(pagination)
7245
+ limit8(pagination)
7812
7246
  );
7813
7247
  }
7814
7248
  } else {
@@ -7833,6 +7267,203 @@ var ProcedureService = class extends BaseService {
7833
7267
  throw error;
7834
7268
  }
7835
7269
  }
7270
+ /**
7271
+ * Searches and filters procedures based on multiple criteria
7272
+ *
7273
+ * @param filters - Various filters to apply
7274
+ * @param filters.nameSearch - Optional search text for procedure name
7275
+ * @param filters.treatmentBenefits - Optional array of treatment benefits to filter by
7276
+ * @param filters.procedureFamily - Optional procedure family to filter by
7277
+ * @param filters.procedureCategory - Optional procedure category to filter by
7278
+ * @param filters.procedureSubcategory - Optional procedure subcategory to filter by
7279
+ * @param filters.procedureTechnology - Optional procedure technology to filter by
7280
+ * @param filters.location - Optional location for distance-based search
7281
+ * @param filters.radiusInKm - Optional radius in kilometers (required if location is provided)
7282
+ * @param filters.minPrice - Optional minimum price
7283
+ * @param filters.maxPrice - Optional maximum price
7284
+ * @param filters.minRating - Optional minimum rating (0-5)
7285
+ * @param filters.maxRating - Optional maximum rating (0-5)
7286
+ * @param filters.pagination - Optional number of results per page
7287
+ * @param filters.lastDoc - Optional last document for pagination
7288
+ * @param filters.isActive - Optional filter for active procedures only
7289
+ * @returns Filtered procedures and the last document for pagination
7290
+ */
7291
+ async getProceduresByFilters(filters) {
7292
+ try {
7293
+ console.log(
7294
+ "[PROCEDURE_SERVICE] Starting procedure filtering with criteria:",
7295
+ filters
7296
+ );
7297
+ const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
7298
+ const constraints = [];
7299
+ if (filters.isActive !== void 0) {
7300
+ constraints.push(where13("isActive", "==", filters.isActive));
7301
+ } else {
7302
+ constraints.push(where13("isActive", "==", true));
7303
+ }
7304
+ if (filters.procedureFamily) {
7305
+ constraints.push(where13("family", "==", filters.procedureFamily));
7306
+ }
7307
+ constraints.push(orderBy4(documentId2()));
7308
+ if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
7309
+ constraints.push(startAfter5(filters.lastDoc));
7310
+ constraints.push(limit5(filters.pagination));
7311
+ } else if (filters.pagination && filters.pagination > 0) {
7312
+ constraints.push(limit5(filters.pagination));
7313
+ }
7314
+ let proceduresResult = [];
7315
+ let lastVisibleDoc = null;
7316
+ if (isGeoQuery) {
7317
+ const center = filters.location;
7318
+ const radiusInKm = filters.radiusInKm;
7319
+ const bounds = geohashQueryBounds5(
7320
+ [center.latitude, center.longitude],
7321
+ radiusInKm * 1e3
7322
+ // Convert to meters
7323
+ );
7324
+ const matchingProcedures = [];
7325
+ for (const bound of bounds) {
7326
+ const geoConstraints = [
7327
+ ...constraints,
7328
+ where13("clinicInfo.location.geohash", ">=", bound[0]),
7329
+ where13("clinicInfo.location.geohash", "<=", bound[1])
7330
+ ];
7331
+ const q = query13(
7332
+ collection13(this.db, PROCEDURES_COLLECTION),
7333
+ ...geoConstraints
7334
+ );
7335
+ const querySnapshot = await getDocs13(q);
7336
+ console.log(
7337
+ `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
7338
+ );
7339
+ for (const doc28 of querySnapshot.docs) {
7340
+ const procedure = { ...doc28.data(), id: doc28.id };
7341
+ const distance = distanceBetween6(
7342
+ [center.latitude, center.longitude],
7343
+ [
7344
+ procedure.clinicInfo.location.latitude,
7345
+ procedure.clinicInfo.location.longitude
7346
+ ]
7347
+ );
7348
+ const distanceInKm = distance / 1e3;
7349
+ if (distanceInKm <= radiusInKm) {
7350
+ matchingProcedures.push({
7351
+ ...procedure,
7352
+ distance: distanceInKm
7353
+ });
7354
+ }
7355
+ }
7356
+ }
7357
+ let filteredProcedures = matchingProcedures;
7358
+ filteredProcedures = this.applyInMemoryFilters(
7359
+ filteredProcedures,
7360
+ filters
7361
+ );
7362
+ filteredProcedures.sort((a, b) => a.distance - b.distance);
7363
+ if (filters.pagination && filters.pagination > 0) {
7364
+ let startIndex = 0;
7365
+ if (filters.lastDoc) {
7366
+ const lastDocIndex = filteredProcedures.findIndex(
7367
+ (procedure) => procedure.id === filters.lastDoc.id
7368
+ );
7369
+ if (lastDocIndex !== -1) {
7370
+ startIndex = lastDocIndex + 1;
7371
+ }
7372
+ }
7373
+ const paginatedProcedures = filteredProcedures.slice(
7374
+ startIndex,
7375
+ startIndex + filters.pagination
7376
+ );
7377
+ lastVisibleDoc = paginatedProcedures.length > 0 ? paginatedProcedures[paginatedProcedures.length - 1] : null;
7378
+ proceduresResult = paginatedProcedures;
7379
+ } else {
7380
+ proceduresResult = filteredProcedures;
7381
+ }
7382
+ } else {
7383
+ const q = query13(
7384
+ collection13(this.db, PROCEDURES_COLLECTION),
7385
+ ...constraints
7386
+ );
7387
+ const querySnapshot = await getDocs13(q);
7388
+ console.log(
7389
+ `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
7390
+ );
7391
+ const procedures = querySnapshot.docs.map((doc28) => {
7392
+ return { ...doc28.data(), id: doc28.id };
7393
+ });
7394
+ let filteredProcedures = this.applyInMemoryFilters(procedures, filters);
7395
+ lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7396
+ proceduresResult = filteredProcedures;
7397
+ }
7398
+ return {
7399
+ procedures: proceduresResult,
7400
+ lastDoc: lastVisibleDoc
7401
+ };
7402
+ } catch (error) {
7403
+ console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
7404
+ throw error;
7405
+ }
7406
+ }
7407
+ /**
7408
+ * Helper method to apply in-memory filters to procedures
7409
+ * Used by getProceduresByFilters to apply filters that can't be done in Firestore queries
7410
+ *
7411
+ * @param procedures - The procedures to filter
7412
+ * @param filters - The filters to apply
7413
+ * @returns Filtered procedures
7414
+ */
7415
+ applyInMemoryFilters(procedures, filters) {
7416
+ let filteredProcedures = procedures;
7417
+ if (filters.nameSearch && filters.nameSearch.trim() !== "") {
7418
+ const searchTerm = filters.nameSearch.toLowerCase().trim();
7419
+ filteredProcedures = filteredProcedures.filter((procedure) => {
7420
+ return procedure.name.toLowerCase().includes(searchTerm);
7421
+ });
7422
+ }
7423
+ if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
7424
+ filteredProcedures = filteredProcedures.filter((procedure) => {
7425
+ return filters.treatmentBenefits.every(
7426
+ (benefit) => procedure.treatmentBenefits.includes(benefit)
7427
+ );
7428
+ });
7429
+ }
7430
+ if (filters.procedureCategory) {
7431
+ filteredProcedures = filteredProcedures.filter(
7432
+ (procedure) => procedure.category.id === filters.procedureCategory
7433
+ );
7434
+ }
7435
+ if (filters.procedureSubcategory) {
7436
+ filteredProcedures = filteredProcedures.filter(
7437
+ (procedure) => procedure.subcategory.id === filters.procedureSubcategory
7438
+ );
7439
+ }
7440
+ if (filters.procedureTechnology) {
7441
+ filteredProcedures = filteredProcedures.filter(
7442
+ (procedure) => procedure.technology.id === filters.procedureTechnology
7443
+ );
7444
+ }
7445
+ if (filters.minPrice !== void 0) {
7446
+ filteredProcedures = filteredProcedures.filter(
7447
+ (procedure) => procedure.price >= filters.minPrice
7448
+ );
7449
+ }
7450
+ if (filters.maxPrice !== void 0) {
7451
+ filteredProcedures = filteredProcedures.filter(
7452
+ (procedure) => procedure.price <= filters.maxPrice
7453
+ );
7454
+ }
7455
+ if (filters.minRating !== void 0) {
7456
+ filteredProcedures = filteredProcedures.filter(
7457
+ (procedure) => procedure.reviewInfo.averageRating >= filters.minRating
7458
+ );
7459
+ }
7460
+ if (filters.maxRating !== void 0) {
7461
+ filteredProcedures = filteredProcedures.filter(
7462
+ (procedure) => procedure.reviewInfo.averageRating <= filters.maxRating
7463
+ );
7464
+ }
7465
+ return filteredProcedures;
7466
+ }
7836
7467
  };
7837
7468
 
7838
7469
  // src/services/documentation-templates/documentation-template.service.ts
@@ -7847,8 +7478,8 @@ import {
7847
7478
  query as query14,
7848
7479
  where as where14,
7849
7480
  orderBy as orderBy5,
7850
- limit as limit4,
7851
- startAfter as startAfter4
7481
+ limit as limit6,
7482
+ startAfter as startAfter6
7852
7483
  } from "firebase/firestore";
7853
7484
  var DocumentationTemplateService = class extends BaseService {
7854
7485
  constructor() {
@@ -7952,10 +7583,10 @@ var DocumentationTemplateService = class extends BaseService {
7952
7583
  this.collectionRef,
7953
7584
  where14("isActive", "==", true),
7954
7585
  orderBy5("updatedAt", "desc"),
7955
- limit4(pageSize)
7586
+ limit6(pageSize)
7956
7587
  );
7957
7588
  if (lastDoc) {
7958
- q = query14(q, startAfter4(lastDoc));
7589
+ q = query14(q, startAfter6(lastDoc));
7959
7590
  }
7960
7591
  const querySnapshot = await getDocs14(q);
7961
7592
  const templates = [];
@@ -7982,10 +7613,10 @@ var DocumentationTemplateService = class extends BaseService {
7982
7613
  where14("isActive", "==", true),
7983
7614
  where14("tags", "array-contains-any", tags),
7984
7615
  orderBy5("updatedAt", "desc"),
7985
- limit4(pageSize)
7616
+ limit6(pageSize)
7986
7617
  );
7987
7618
  if (lastDoc) {
7988
- q = query14(q, startAfter4(lastDoc));
7619
+ q = query14(q, startAfter6(lastDoc));
7989
7620
  }
7990
7621
  const querySnapshot = await getDocs14(q);
7991
7622
  const templates = [];
@@ -8011,10 +7642,10 @@ var DocumentationTemplateService = class extends BaseService {
8011
7642
  this.collectionRef,
8012
7643
  where14("createdBy", "==", userId),
8013
7644
  orderBy5("updatedAt", "desc"),
8014
- limit4(pageSize)
7645
+ limit6(pageSize)
8015
7646
  );
8016
7647
  if (lastDoc) {
8017
- q = query14(q, startAfter4(lastDoc));
7648
+ q = query14(q, startAfter6(lastDoc));
8018
7649
  }
8019
7650
  const querySnapshot = await getDocs14(q);
8020
7651
  const templates = [];
@@ -8041,8 +7672,8 @@ import {
8041
7672
  query as query15,
8042
7673
  where as where15,
8043
7674
  orderBy as orderBy6,
8044
- limit as limit5,
8045
- startAfter as startAfter5
7675
+ limit as limit7,
7676
+ startAfter as startAfter7
8046
7677
  } from "firebase/firestore";
8047
7678
  var FilledDocumentService = class extends BaseService {
8048
7679
  constructor(...args) {
@@ -8066,10 +7697,10 @@ var FilledDocumentService = class extends BaseService {
8066
7697
  if (!template) {
8067
7698
  throw new Error(`Template with ID ${templateId} not found`);
8068
7699
  }
8069
- const documentId2 = this.generateId();
7700
+ const documentId3 = this.generateId();
8070
7701
  const now = Date.now();
8071
7702
  const filledDocument = {
8072
- id: documentId2,
7703
+ id: documentId3,
8073
7704
  templateId,
8074
7705
  templateVersion: template.version,
8075
7706
  patientId,
@@ -8080,7 +7711,7 @@ var FilledDocumentService = class extends BaseService {
8080
7711
  values: {},
8081
7712
  status: "draft" /* DRAFT */
8082
7713
  };
8083
- const docRef = doc15(this.collectionRef, documentId2);
7714
+ const docRef = doc15(this.collectionRef, documentId3);
8084
7715
  await setDoc15(docRef, filledDocument);
8085
7716
  return filledDocument;
8086
7717
  }
@@ -8089,8 +7720,8 @@ var FilledDocumentService = class extends BaseService {
8089
7720
  * @param documentId - ID of the filled document to retrieve
8090
7721
  * @returns The filled document or null if not found
8091
7722
  */
8092
- async getFilledDocumentById(documentId2) {
8093
- const docRef = doc15(this.collectionRef, documentId2);
7723
+ async getFilledDocumentById(documentId3) {
7724
+ const docRef = doc15(this.collectionRef, documentId3);
8094
7725
  const docSnap = await getDoc18(docRef);
8095
7726
  if (!docSnap.exists()) {
8096
7727
  return null;
@@ -8104,10 +7735,10 @@ var FilledDocumentService = class extends BaseService {
8104
7735
  * @param status - Optional new status for the document
8105
7736
  * @returns The updated filled document
8106
7737
  */
8107
- async updateFilledDocument(documentId2, values, status) {
8108
- const filledDocument = await this.getFilledDocumentById(documentId2);
7738
+ async updateFilledDocument(documentId3, values, status) {
7739
+ const filledDocument = await this.getFilledDocumentById(documentId3);
8109
7740
  if (!filledDocument) {
8110
- throw new Error(`Filled document with ID ${documentId2} not found`);
7741
+ throw new Error(`Filled document with ID ${documentId3} not found`);
8111
7742
  }
8112
7743
  const updateData = {
8113
7744
  values: {
@@ -8119,7 +7750,7 @@ var FilledDocumentService = class extends BaseService {
8119
7750
  if (status) {
8120
7751
  updateData.status = status;
8121
7752
  }
8122
- const docRef = doc15(this.collectionRef, documentId2);
7753
+ const docRef = doc15(this.collectionRef, documentId3);
8123
7754
  await updateDoc17(docRef, updateData);
8124
7755
  return {
8125
7756
  ...filledDocument,
@@ -8138,10 +7769,10 @@ var FilledDocumentService = class extends BaseService {
8138
7769
  this.collectionRef,
8139
7770
  where15("patientId", "==", patientId),
8140
7771
  orderBy6("updatedAt", "desc"),
8141
- limit5(pageSize)
7772
+ limit7(pageSize)
8142
7773
  );
8143
7774
  if (lastDoc) {
8144
- q = query15(q, startAfter5(lastDoc));
7775
+ q = query15(q, startAfter7(lastDoc));
8145
7776
  }
8146
7777
  const querySnapshot = await getDocs15(q);
8147
7778
  const documents = [];
@@ -8167,10 +7798,10 @@ var FilledDocumentService = class extends BaseService {
8167
7798
  this.collectionRef,
8168
7799
  where15("practitionerId", "==", practitionerId),
8169
7800
  orderBy6("updatedAt", "desc"),
8170
- limit5(pageSize)
7801
+ limit7(pageSize)
8171
7802
  );
8172
7803
  if (lastDoc) {
8173
- q = query15(q, startAfter5(lastDoc));
7804
+ q = query15(q, startAfter7(lastDoc));
8174
7805
  }
8175
7806
  const querySnapshot = await getDocs15(q);
8176
7807
  const documents = [];
@@ -8196,10 +7827,10 @@ var FilledDocumentService = class extends BaseService {
8196
7827
  this.collectionRef,
8197
7828
  where15("clinicId", "==", clinicId),
8198
7829
  orderBy6("updatedAt", "desc"),
8199
- limit5(pageSize)
7830
+ limit7(pageSize)
8200
7831
  );
8201
7832
  if (lastDoc) {
8202
- q = query15(q, startAfter5(lastDoc));
7833
+ q = query15(q, startAfter7(lastDoc));
8203
7834
  }
8204
7835
  const querySnapshot = await getDocs15(q);
8205
7836
  const documents = [];
@@ -8225,10 +7856,10 @@ var FilledDocumentService = class extends BaseService {
8225
7856
  this.collectionRef,
8226
7857
  where15("templateId", "==", templateId),
8227
7858
  orderBy6("updatedAt", "desc"),
8228
- limit5(pageSize)
7859
+ limit7(pageSize)
8229
7860
  );
8230
7861
  if (lastDoc) {
8231
- q = query15(q, startAfter5(lastDoc));
7862
+ q = query15(q, startAfter7(lastDoc));
8232
7863
  }
8233
7864
  const querySnapshot = await getDocs15(q);
8234
7865
  const documents = [];
@@ -8254,10 +7885,10 @@ var FilledDocumentService = class extends BaseService {
8254
7885
  this.collectionRef,
8255
7886
  where15("status", "==", status),
8256
7887
  orderBy6("updatedAt", "desc"),
8257
- limit5(pageSize)
7888
+ limit7(pageSize)
8258
7889
  );
8259
7890
  if (lastDoc) {
8260
- q = query15(q, startAfter5(lastDoc));
7891
+ q = query15(q, startAfter7(lastDoc));
8261
7892
  }
8262
7893
  const querySnapshot = await getDocs15(q);
8263
7894
  const documents = [];