@blackcode_sa/metaestetics-api 1.8.12 → 1.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +2 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/backoffice/index.d.mts +1 -0
- package/dist/backoffice/index.d.ts +1 -0
- package/dist/index.d.mts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +140 -222
- package/dist/index.mjs +143 -223
- package/package.json +1 -1
- package/src/admin/scripts/migrateProcedures.js +23 -0
- package/src/admin/scripts/serviceAccountKey.json +13 -0
- package/src/services/clinic/clinic.service.ts +33 -0
- package/src/services/clinic/utils/filter.utils.ts +54 -225
- package/src/services/practitioner/practitioner.service.ts +47 -115
- package/src/services/procedure/procedure.service.ts +43 -3
- package/src/types/clinic/index.ts +1 -0
- package/src/types/practitioner/index.ts +1 -0
package/dist/admin/index.d.mts
CHANGED
|
@@ -788,6 +788,7 @@ interface Clinic {
|
|
|
788
788
|
id: string;
|
|
789
789
|
clinicGroupId: string;
|
|
790
790
|
name: string;
|
|
791
|
+
nameLower: string;
|
|
791
792
|
description?: string;
|
|
792
793
|
location: ClinicLocation;
|
|
793
794
|
contactInfo: ClinicContactInfo;
|
|
@@ -901,6 +902,7 @@ interface Practitioner {
|
|
|
901
902
|
id: string;
|
|
902
903
|
userRef: string;
|
|
903
904
|
basicInfo: PractitionerBasicInfo;
|
|
905
|
+
fullNameLower: string;
|
|
904
906
|
certification: PractitionerCertification;
|
|
905
907
|
clinics: string[];
|
|
906
908
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
package/dist/admin/index.d.ts
CHANGED
|
@@ -788,6 +788,7 @@ interface Clinic {
|
|
|
788
788
|
id: string;
|
|
789
789
|
clinicGroupId: string;
|
|
790
790
|
name: string;
|
|
791
|
+
nameLower: string;
|
|
791
792
|
description?: string;
|
|
792
793
|
location: ClinicLocation;
|
|
793
794
|
contactInfo: ClinicContactInfo;
|
|
@@ -901,6 +902,7 @@ interface Practitioner {
|
|
|
901
902
|
id: string;
|
|
902
903
|
userRef: string;
|
|
903
904
|
basicInfo: PractitionerBasicInfo;
|
|
905
|
+
fullNameLower: string;
|
|
904
906
|
certification: PractitionerCertification;
|
|
905
907
|
clinics: string[];
|
|
906
908
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
|
@@ -1187,6 +1187,7 @@ interface Practitioner {
|
|
|
1187
1187
|
id: string;
|
|
1188
1188
|
userRef: string;
|
|
1189
1189
|
basicInfo: PractitionerBasicInfo;
|
|
1190
|
+
fullNameLower: string;
|
|
1190
1191
|
certification: PractitionerCertification;
|
|
1191
1192
|
clinics: string[];
|
|
1192
1193
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
|
@@ -1187,6 +1187,7 @@ interface Practitioner {
|
|
|
1187
1187
|
id: string;
|
|
1188
1188
|
userRef: string;
|
|
1189
1189
|
basicInfo: PractitionerBasicInfo;
|
|
1190
|
+
fullNameLower: string;
|
|
1190
1191
|
certification: PractitionerCertification;
|
|
1191
1192
|
clinics: string[];
|
|
1192
1193
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
package/dist/index.d.mts
CHANGED
|
@@ -1207,6 +1207,7 @@ interface Clinic {
|
|
|
1207
1207
|
id: string;
|
|
1208
1208
|
clinicGroupId: string;
|
|
1209
1209
|
name: string;
|
|
1210
|
+
nameLower: string;
|
|
1210
1211
|
description?: string;
|
|
1211
1212
|
location: ClinicLocation;
|
|
1212
1213
|
contactInfo: ClinicContactInfo;
|
|
@@ -1432,6 +1433,7 @@ interface Practitioner {
|
|
|
1432
1433
|
id: string;
|
|
1433
1434
|
userRef: string;
|
|
1434
1435
|
basicInfo: PractitionerBasicInfo;
|
|
1436
|
+
fullNameLower: string;
|
|
1435
1437
|
certification: PractitionerCertification;
|
|
1436
1438
|
clinics: string[];
|
|
1437
1439
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
|
@@ -4100,6 +4102,18 @@ declare class ClinicService extends BaseService {
|
|
|
4100
4102
|
})[];
|
|
4101
4103
|
lastDoc: any;
|
|
4102
4104
|
}>;
|
|
4105
|
+
/**
|
|
4106
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
4107
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
4108
|
+
* @returns Array of minimal clinic info for map
|
|
4109
|
+
*/
|
|
4110
|
+
getClinicsForMap(): Promise<{
|
|
4111
|
+
id: string;
|
|
4112
|
+
name: string;
|
|
4113
|
+
address: string;
|
|
4114
|
+
latitude: number | undefined;
|
|
4115
|
+
longitude: number | undefined;
|
|
4116
|
+
}[]>;
|
|
4103
4117
|
}
|
|
4104
4118
|
|
|
4105
4119
|
declare class ProcedureService extends BaseService {
|
|
@@ -4259,6 +4273,20 @@ declare class ProcedureService extends BaseService {
|
|
|
4259
4273
|
* @returns The created procedure
|
|
4260
4274
|
*/
|
|
4261
4275
|
createConsultationProcedure(data: Omit<CreateProcedureData, "productId">): Promise<Procedure>;
|
|
4276
|
+
/**
|
|
4277
|
+
* Gets all procedures with minimal info for map display (id, name, clinicId, clinicName, address, latitude, longitude)
|
|
4278
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
4279
|
+
* @returns Array of minimal procedure info for map
|
|
4280
|
+
*/
|
|
4281
|
+
getProceduresForMap(): Promise<{
|
|
4282
|
+
id: string;
|
|
4283
|
+
name: string;
|
|
4284
|
+
clinicId: string | undefined;
|
|
4285
|
+
clinicName: string | undefined;
|
|
4286
|
+
address: string;
|
|
4287
|
+
latitude: number | undefined;
|
|
4288
|
+
longitude: number | undefined;
|
|
4289
|
+
}[]>;
|
|
4262
4290
|
}
|
|
4263
4291
|
|
|
4264
4292
|
declare class PractitionerService extends BaseService {
|
package/dist/index.d.ts
CHANGED
|
@@ -1207,6 +1207,7 @@ interface Clinic {
|
|
|
1207
1207
|
id: string;
|
|
1208
1208
|
clinicGroupId: string;
|
|
1209
1209
|
name: string;
|
|
1210
|
+
nameLower: string;
|
|
1210
1211
|
description?: string;
|
|
1211
1212
|
location: ClinicLocation;
|
|
1212
1213
|
contactInfo: ClinicContactInfo;
|
|
@@ -1432,6 +1433,7 @@ interface Practitioner {
|
|
|
1432
1433
|
id: string;
|
|
1433
1434
|
userRef: string;
|
|
1434
1435
|
basicInfo: PractitionerBasicInfo;
|
|
1436
|
+
fullNameLower: string;
|
|
1435
1437
|
certification: PractitionerCertification;
|
|
1436
1438
|
clinics: string[];
|
|
1437
1439
|
clinicWorkingHours: PractitionerClinicWorkingHours[];
|
|
@@ -4100,6 +4102,18 @@ declare class ClinicService extends BaseService {
|
|
|
4100
4102
|
})[];
|
|
4101
4103
|
lastDoc: any;
|
|
4102
4104
|
}>;
|
|
4105
|
+
/**
|
|
4106
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
4107
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
4108
|
+
* @returns Array of minimal clinic info for map
|
|
4109
|
+
*/
|
|
4110
|
+
getClinicsForMap(): Promise<{
|
|
4111
|
+
id: string;
|
|
4112
|
+
name: string;
|
|
4113
|
+
address: string;
|
|
4114
|
+
latitude: number | undefined;
|
|
4115
|
+
longitude: number | undefined;
|
|
4116
|
+
}[]>;
|
|
4103
4117
|
}
|
|
4104
4118
|
|
|
4105
4119
|
declare class ProcedureService extends BaseService {
|
|
@@ -4259,6 +4273,20 @@ declare class ProcedureService extends BaseService {
|
|
|
4259
4273
|
* @returns The created procedure
|
|
4260
4274
|
*/
|
|
4261
4275
|
createConsultationProcedure(data: Omit<CreateProcedureData, "productId">): Promise<Procedure>;
|
|
4276
|
+
/**
|
|
4277
|
+
* Gets all procedures with minimal info for map display (id, name, clinicId, clinicName, address, latitude, longitude)
|
|
4278
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
4279
|
+
* @returns Array of minimal procedure info for map
|
|
4280
|
+
*/
|
|
4281
|
+
getProceduresForMap(): Promise<{
|
|
4282
|
+
id: string;
|
|
4283
|
+
name: string;
|
|
4284
|
+
clinicId: string | undefined;
|
|
4285
|
+
clinicName: string | undefined;
|
|
4286
|
+
address: string;
|
|
4287
|
+
latitude: number | undefined;
|
|
4288
|
+
longitude: number | undefined;
|
|
4289
|
+
}[]>;
|
|
4262
4290
|
}
|
|
4263
4291
|
|
|
4264
4292
|
declare class PractitionerService extends BaseService {
|
package/dist/index.js
CHANGED
|
@@ -6211,6 +6211,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6211
6211
|
trustworthiness: 0,
|
|
6212
6212
|
recommendationPercentage: 0
|
|
6213
6213
|
};
|
|
6214
|
+
const fullNameLower = `${validData.basicInfo.firstName} ${validData.basicInfo.lastName}`.toLowerCase();
|
|
6214
6215
|
const practitioner = {
|
|
6215
6216
|
id: practitionerId,
|
|
6216
6217
|
userRef: validData.userRef,
|
|
@@ -6218,6 +6219,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6218
6219
|
validData.basicInfo,
|
|
6219
6220
|
practitionerId
|
|
6220
6221
|
),
|
|
6222
|
+
fullNameLower,
|
|
6223
|
+
// Ensure this is present
|
|
6221
6224
|
certification: validData.certification,
|
|
6222
6225
|
clinics: validData.clinics || [],
|
|
6223
6226
|
clinicWorkingHours: validData.clinicWorkingHours || [],
|
|
@@ -6313,6 +6316,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6313
6316
|
}
|
|
6314
6317
|
const finalClinicsInfo = validatedData.clinicsInfo && validatedData.clinicsInfo.length > 0 ? validatedData.clinicsInfo : clinicsInfo;
|
|
6315
6318
|
const proceduresInfo = [];
|
|
6319
|
+
const fullNameLowerDraft = `${validatedData.basicInfo.firstName} ${validatedData.basicInfo.lastName}`.toLowerCase();
|
|
6316
6320
|
const practitionerData = {
|
|
6317
6321
|
id: practitionerId,
|
|
6318
6322
|
userRef: "",
|
|
@@ -6321,6 +6325,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6321
6325
|
validatedData.basicInfo,
|
|
6322
6326
|
practitionerId
|
|
6323
6327
|
),
|
|
6328
|
+
fullNameLower: fullNameLowerDraft,
|
|
6329
|
+
// Ensure this is present
|
|
6324
6330
|
certification: validatedData.certification,
|
|
6325
6331
|
clinics,
|
|
6326
6332
|
clinicWorkingHours: validatedData.clinicWorkingHours || [],
|
|
@@ -6826,10 +6832,6 @@ var PractitionerService = class extends BaseService {
|
|
|
6826
6832
|
*/
|
|
6827
6833
|
async getPractitionersByFilters(filters) {
|
|
6828
6834
|
try {
|
|
6829
|
-
console.log(
|
|
6830
|
-
"[PRACTITIONER_SERVICE] Starting practitioner filtering with criteria:",
|
|
6831
|
-
filters
|
|
6832
|
-
);
|
|
6833
6835
|
const constraints = [];
|
|
6834
6836
|
if (!filters.includeDraftPractitioners) {
|
|
6835
6837
|
constraints.push((0, import_firestore21.where)("status", "==", "active" /* ACTIVE */));
|
|
@@ -6844,60 +6846,40 @@ var PractitionerService = class extends BaseService {
|
|
|
6844
6846
|
)
|
|
6845
6847
|
);
|
|
6846
6848
|
}
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
constraints.push((0, import_firestore21.startAfter)(filters.lastDoc));
|
|
6852
|
-
}
|
|
6853
|
-
constraints.push((0, import_firestore21.limit)(filters.pagination));
|
|
6849
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
6850
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
6851
|
+
constraints.push((0, import_firestore21.where)("fullNameLower", ">=", searchTerm));
|
|
6852
|
+
constraints.push((0, import_firestore21.where)("fullNameLower", "<=", searchTerm + "\uF8FF"));
|
|
6854
6853
|
}
|
|
6855
|
-
|
|
6856
|
-
(0, import_firestore21.
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
let practitioners = querySnapshot.docs.map((doc37) => {
|
|
6864
|
-
return { ...doc37.data(), id: doc37.id };
|
|
6865
|
-
});
|
|
6866
|
-
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6867
|
-
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
6868
|
-
const searchTerm = filters.nameSearch.toLowerCase().trim();
|
|
6869
|
-
practitioners = practitioners.filter((practitioner) => {
|
|
6870
|
-
const fullName = `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`.toLowerCase();
|
|
6871
|
-
return fullName.includes(searchTerm);
|
|
6872
|
-
});
|
|
6854
|
+
if (filters.procedureTechnology) {
|
|
6855
|
+
constraints.push((0, import_firestore21.where)("proceduresInfo.technologyName", "==", filters.procedureTechnology));
|
|
6856
|
+
} else if (filters.procedureSubcategory) {
|
|
6857
|
+
constraints.push((0, import_firestore21.where)("proceduresInfo.subcategoryName", "==", filters.procedureSubcategory));
|
|
6858
|
+
} else if (filters.procedureCategory) {
|
|
6859
|
+
constraints.push((0, import_firestore21.where)("proceduresInfo.categoryName", "==", filters.procedureCategory));
|
|
6860
|
+
} else if (filters.procedureFamily) {
|
|
6861
|
+
constraints.push((0, import_firestore21.where)("proceduresInfo.family", "==", filters.procedureFamily));
|
|
6873
6862
|
}
|
|
6874
|
-
if (filters.
|
|
6875
|
-
|
|
6876
|
-
return filters.specialties.every(
|
|
6877
|
-
(specialty) => practitioner.certification.specialties.includes(specialty)
|
|
6878
|
-
);
|
|
6879
|
-
});
|
|
6863
|
+
if (filters.minRating !== void 0) {
|
|
6864
|
+
constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", ">=", filters.minRating));
|
|
6880
6865
|
}
|
|
6881
|
-
if (filters.
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
}
|
|
6894
|
-
if (filters.procedureFamily) {
|
|
6895
|
-
return procedure.family === filters.procedureFamily;
|
|
6896
|
-
}
|
|
6897
|
-
return false;
|
|
6898
|
-
});
|
|
6899
|
-
});
|
|
6866
|
+
if (filters.maxRating !== void 0) {
|
|
6867
|
+
constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
6868
|
+
}
|
|
6869
|
+
constraints.push((0, import_firestore21.orderBy)("fullNameLower"));
|
|
6870
|
+
if (filters.lastDoc) {
|
|
6871
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
6872
|
+
constraints.push((0, import_firestore21.startAfter)(filters.lastDoc));
|
|
6873
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
6874
|
+
constraints.push((0, import_firestore21.startAfter)(...filters.lastDoc));
|
|
6875
|
+
} else {
|
|
6876
|
+
constraints.push((0, import_firestore21.startAfter)(filters.lastDoc));
|
|
6877
|
+
}
|
|
6900
6878
|
}
|
|
6879
|
+
constraints.push((0, import_firestore21.limit)(filters.pagination || 5));
|
|
6880
|
+
const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
|
|
6881
|
+
const querySnapshot = await (0, import_firestore21.getDocs)(q);
|
|
6882
|
+
let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
6901
6883
|
if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
|
|
6902
6884
|
const location = filters.location;
|
|
6903
6885
|
const radiusInKm = filters.radiusInKm;
|
|
@@ -6913,22 +6895,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6913
6895
|
});
|
|
6914
6896
|
});
|
|
6915
6897
|
}
|
|
6916
|
-
|
|
6917
|
-
practitioners = practitioners.filter(
|
|
6918
|
-
(p) => p.reviewInfo.averageRating >= filters.minRating
|
|
6919
|
-
);
|
|
6920
|
-
}
|
|
6921
|
-
if (filters.maxRating !== void 0) {
|
|
6922
|
-
practitioners = practitioners.filter(
|
|
6923
|
-
(p) => p.reviewInfo.averageRating <= filters.maxRating
|
|
6924
|
-
);
|
|
6925
|
-
}
|
|
6926
|
-
console.log(
|
|
6927
|
-
`[PRACTITIONER_SERVICE] Filtered to ${practitioners.length} practitioners`
|
|
6928
|
-
);
|
|
6929
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
6930
|
-
practitioners = practitioners.slice(0, filters.pagination);
|
|
6931
|
-
}
|
|
6898
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6932
6899
|
return {
|
|
6933
6900
|
practitioners,
|
|
6934
6901
|
lastDoc
|
|
@@ -8567,168 +8534,64 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
|
|
|
8567
8534
|
var import_firestore26 = require("firebase/firestore");
|
|
8568
8535
|
var import_geofire_common6 = require("geofire-common");
|
|
8569
8536
|
async function getClinicsByFilters(db, filters) {
|
|
8570
|
-
|
|
8571
|
-
"[FILTER_UTILS] Starting clinic filtering with criteria:",
|
|
8572
|
-
filters
|
|
8573
|
-
);
|
|
8574
|
-
const isGeoQuery = filters.center && filters.radiusInKm && filters.radiusInKm > 0;
|
|
8537
|
+
var _a;
|
|
8575
8538
|
const constraints = [];
|
|
8576
|
-
|
|
8577
|
-
constraints.push((0, import_firestore26.where)("isActive", "==", filters.isActive));
|
|
8578
|
-
} else {
|
|
8579
|
-
constraints.push((0, import_firestore26.where)("isActive", "==", true));
|
|
8580
|
-
}
|
|
8539
|
+
constraints.push((0, import_firestore26.where)("isActive", "==", (_a = filters.isActive) != null ? _a : true));
|
|
8581
8540
|
if (filters.tags && filters.tags.length > 0) {
|
|
8582
8541
|
constraints.push((0, import_firestore26.where)("tags", "array-contains", filters.tags[0]));
|
|
8583
8542
|
}
|
|
8584
8543
|
if (filters.procedureTechnology) {
|
|
8585
|
-
constraints.push(
|
|
8586
|
-
(0, import_firestore26.where)("servicesInfo.technology", "==", filters.procedureTechnology)
|
|
8587
|
-
);
|
|
8544
|
+
constraints.push((0, import_firestore26.where)("servicesInfo.technology", "==", filters.procedureTechnology));
|
|
8588
8545
|
} else if (filters.procedureSubcategory) {
|
|
8589
|
-
constraints.push(
|
|
8590
|
-
(0, import_firestore26.where)("servicesInfo.subCategory", "==", filters.procedureSubcategory)
|
|
8591
|
-
);
|
|
8546
|
+
constraints.push((0, import_firestore26.where)("servicesInfo.subCategory", "==", filters.procedureSubcategory));
|
|
8592
8547
|
} else if (filters.procedureCategory) {
|
|
8593
|
-
constraints.push(
|
|
8594
|
-
(0, import_firestore26.where)("servicesInfo.category", "==", filters.procedureCategory)
|
|
8595
|
-
);
|
|
8548
|
+
constraints.push((0, import_firestore26.where)("servicesInfo.category", "==", filters.procedureCategory));
|
|
8596
8549
|
} else if (filters.procedureFamily) {
|
|
8597
|
-
constraints.push(
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
if (filters.
|
|
8602
|
-
|
|
8603
|
-
constraints.push((0, import_firestore26.
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
}
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
if (
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
)
|
|
8618
|
-
|
|
8619
|
-
for (const bound of bounds) {
|
|
8620
|
-
const geoConstraints = [
|
|
8621
|
-
...constraints,
|
|
8622
|
-
(0, import_firestore26.where)("location.geohash", ">=", bound[0]),
|
|
8623
|
-
(0, import_firestore26.where)("location.geohash", "<=", bound[1])
|
|
8624
|
-
];
|
|
8625
|
-
const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...geoConstraints);
|
|
8626
|
-
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8627
|
-
console.log(
|
|
8628
|
-
`[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
|
|
8629
|
-
);
|
|
8630
|
-
for (const doc37 of querySnapshot.docs) {
|
|
8631
|
-
const clinic = { ...doc37.data(), id: doc37.id };
|
|
8632
|
-
const distance = (0, import_geofire_common6.distanceBetween)(
|
|
8633
|
-
[center.latitude, center.longitude],
|
|
8634
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8635
|
-
);
|
|
8636
|
-
const distanceInKm = distance / 1e3;
|
|
8637
|
-
if (distanceInKm <= radiusInKm) {
|
|
8638
|
-
matchingClinics.push({
|
|
8639
|
-
...clinic,
|
|
8640
|
-
distance: distanceInKm
|
|
8641
|
-
});
|
|
8642
|
-
}
|
|
8643
|
-
}
|
|
8644
|
-
}
|
|
8645
|
-
let filteredClinics = matchingClinics;
|
|
8646
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8647
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8648
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8649
|
-
});
|
|
8650
|
-
}
|
|
8651
|
-
if (filters.minRating !== void 0) {
|
|
8652
|
-
filteredClinics = filteredClinics.filter(
|
|
8653
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8654
|
-
);
|
|
8655
|
-
}
|
|
8656
|
-
if (filters.maxRating !== void 0) {
|
|
8657
|
-
filteredClinics = filteredClinics.filter(
|
|
8658
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8659
|
-
);
|
|
8660
|
-
}
|
|
8661
|
-
filteredClinics.sort((a, b) => a.distance - b.distance);
|
|
8662
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
8663
|
-
let startIndex = 0;
|
|
8664
|
-
if (filters.lastDoc) {
|
|
8665
|
-
const lastDocIndex = filteredClinics.findIndex(
|
|
8666
|
-
(clinic) => clinic.id === filters.lastDoc.id
|
|
8667
|
-
);
|
|
8668
|
-
if (lastDocIndex !== -1) {
|
|
8669
|
-
startIndex = lastDocIndex + 1;
|
|
8670
|
-
}
|
|
8671
|
-
}
|
|
8672
|
-
const paginatedClinics = filteredClinics.slice(
|
|
8673
|
-
startIndex,
|
|
8674
|
-
startIndex + filters.pagination
|
|
8675
|
-
);
|
|
8676
|
-
lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
|
|
8677
|
-
clinicsResult = paginatedClinics;
|
|
8550
|
+
constraints.push((0, import_firestore26.where)("servicesInfo.procedureFamily", "==", filters.procedureFamily));
|
|
8551
|
+
}
|
|
8552
|
+
let useNameLower = false;
|
|
8553
|
+
let searchTerm = "";
|
|
8554
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8555
|
+
searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8556
|
+
constraints.push((0, import_firestore26.where)("nameLower", ">=", searchTerm));
|
|
8557
|
+
constraints.push((0, import_firestore26.where)("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
8558
|
+
useNameLower = true;
|
|
8559
|
+
}
|
|
8560
|
+
if (filters.minRating !== void 0) {
|
|
8561
|
+
constraints.push((0, import_firestore26.where)("reviewInfo.averageRating", ">=", filters.minRating));
|
|
8562
|
+
}
|
|
8563
|
+
if (filters.maxRating !== void 0) {
|
|
8564
|
+
constraints.push((0, import_firestore26.where)("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
8565
|
+
}
|
|
8566
|
+
constraints.push((0, import_firestore26.orderBy)("nameLower"));
|
|
8567
|
+
if (filters.lastDoc) {
|
|
8568
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
8569
|
+
constraints.push((0, import_firestore26.startAfter)(filters.lastDoc));
|
|
8570
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
8571
|
+
constraints.push((0, import_firestore26.startAfter)(...filters.lastDoc));
|
|
8678
8572
|
} else {
|
|
8679
|
-
|
|
8573
|
+
constraints.push((0, import_firestore26.startAfter)(filters.lastDoc));
|
|
8680
8574
|
}
|
|
8681
|
-
}
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8575
|
+
}
|
|
8576
|
+
constraints.push((0, import_firestore26.limit)(filters.pagination || 5));
|
|
8577
|
+
const q = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
|
|
8578
|
+
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8579
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8580
|
+
if (filters.tags && filters.tags.length > 1) {
|
|
8581
|
+
clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
|
|
8582
|
+
}
|
|
8583
|
+
if (filters.center && filters.radiusInKm) {
|
|
8584
|
+
clinics = clinics.filter((clinic) => {
|
|
8585
|
+
const distance = (0, import_geofire_common6.distanceBetween)(
|
|
8586
|
+
[filters.center.latitude, filters.center.longitude],
|
|
8587
|
+
[clinic.location.latitude, clinic.location.longitude]
|
|
8588
|
+
) / 1e3;
|
|
8589
|
+
clinic.distance = distance;
|
|
8590
|
+
return distance <= filters.radiusInKm;
|
|
8689
8591
|
});
|
|
8690
|
-
let filteredClinics = clinics;
|
|
8691
|
-
if (filters.center) {
|
|
8692
|
-
const center = filters.center;
|
|
8693
|
-
const clinicsWithDistance = [];
|
|
8694
|
-
filteredClinics.forEach((clinic) => {
|
|
8695
|
-
const distance = (0, import_geofire_common6.distanceBetween)(
|
|
8696
|
-
[center.latitude, center.longitude],
|
|
8697
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8698
|
-
);
|
|
8699
|
-
clinicsWithDistance.push({
|
|
8700
|
-
...clinic,
|
|
8701
|
-
distance: distance / 1e3
|
|
8702
|
-
// Convert to kilometers
|
|
8703
|
-
});
|
|
8704
|
-
});
|
|
8705
|
-
filteredClinics = clinicsWithDistance;
|
|
8706
|
-
filteredClinics.sort(
|
|
8707
|
-
(a, b) => a.distance - b.distance
|
|
8708
|
-
);
|
|
8709
|
-
}
|
|
8710
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8711
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8712
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8713
|
-
});
|
|
8714
|
-
}
|
|
8715
|
-
if (filters.minRating !== void 0) {
|
|
8716
|
-
filteredClinics = filteredClinics.filter(
|
|
8717
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8718
|
-
);
|
|
8719
|
-
}
|
|
8720
|
-
if (filters.maxRating !== void 0) {
|
|
8721
|
-
filteredClinics = filteredClinics.filter(
|
|
8722
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8723
|
-
);
|
|
8724
|
-
}
|
|
8725
|
-
lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8726
|
-
clinicsResult = filteredClinics;
|
|
8727
8592
|
}
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
lastDoc: lastVisibleDoc
|
|
8731
|
-
};
|
|
8593
|
+
const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8594
|
+
return { clinics, lastDoc: lastVisibleDoc };
|
|
8732
8595
|
}
|
|
8733
8596
|
|
|
8734
8597
|
// src/services/clinic/clinic.service.ts
|
|
@@ -8864,6 +8727,8 @@ var ClinicService = class extends BaseService {
|
|
|
8864
8727
|
id: clinicId,
|
|
8865
8728
|
clinicGroupId: validatedData.clinicGroupId,
|
|
8866
8729
|
name: validatedData.name,
|
|
8730
|
+
nameLower: validatedData.name.toLowerCase(),
|
|
8731
|
+
// Add this line
|
|
8867
8732
|
description: validatedData.description,
|
|
8868
8733
|
location: { ...location, geohash: hash },
|
|
8869
8734
|
contactInfo: validatedData.contactInfo,
|
|
@@ -8964,6 +8829,9 @@ var ClinicService = class extends BaseService {
|
|
|
8964
8829
|
updatePayload[field] = validatedData[field];
|
|
8965
8830
|
}
|
|
8966
8831
|
}
|
|
8832
|
+
if (validatedData.name) {
|
|
8833
|
+
updatePayload.nameLower = validatedData.name.toLowerCase();
|
|
8834
|
+
}
|
|
8967
8835
|
if (validatedData.location) {
|
|
8968
8836
|
const loc = validatedData.location;
|
|
8969
8837
|
updatePayload.location = {
|
|
@@ -9139,6 +9007,27 @@ var ClinicService = class extends BaseService {
|
|
|
9139
9007
|
async getClinicsByFilters(filters) {
|
|
9140
9008
|
return getClinicsByFilters(this.db, filters);
|
|
9141
9009
|
}
|
|
9010
|
+
/**
|
|
9011
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
9012
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
9013
|
+
* @returns Array of minimal clinic info for map
|
|
9014
|
+
*/
|
|
9015
|
+
async getClinicsForMap() {
|
|
9016
|
+
const clinicsRef = (0, import_firestore27.collection)(this.db, CLINICS_COLLECTION);
|
|
9017
|
+
const snapshot = await (0, import_firestore27.getDocs)(clinicsRef);
|
|
9018
|
+
const clinicsForMap = snapshot.docs.map((doc37) => {
|
|
9019
|
+
var _a, _b, _c;
|
|
9020
|
+
const data = doc37.data();
|
|
9021
|
+
return {
|
|
9022
|
+
id: doc37.id,
|
|
9023
|
+
name: data.name,
|
|
9024
|
+
address: ((_a = data.location) == null ? void 0 : _a.address) || "",
|
|
9025
|
+
latitude: (_b = data.location) == null ? void 0 : _b.latitude,
|
|
9026
|
+
longitude: (_c = data.location) == null ? void 0 : _c.longitude
|
|
9027
|
+
};
|
|
9028
|
+
});
|
|
9029
|
+
return clinicsForMap;
|
|
9030
|
+
}
|
|
9142
9031
|
};
|
|
9143
9032
|
|
|
9144
9033
|
// src/services/auth/utils/firebase.utils.ts
|
|
@@ -14838,7 +14727,7 @@ var ProcedureService = class extends BaseService {
|
|
|
14838
14727
|
}
|
|
14839
14728
|
let finalCategoryId = existingProcedure.category.id;
|
|
14840
14729
|
if (validatedData.name) {
|
|
14841
|
-
updatedProcedureData.nameLower = validatedData.
|
|
14730
|
+
updatedProcedureData.nameLower = validatedData.name.toLowerCase();
|
|
14842
14731
|
}
|
|
14843
14732
|
if (validatedData.categoryId) {
|
|
14844
14733
|
const category = await this.categoryService.getById(
|
|
@@ -15065,7 +14954,13 @@ var ProcedureService = class extends BaseService {
|
|
|
15065
14954
|
constraints.push((0, import_firestore45.orderBy)("nameLower"));
|
|
15066
14955
|
}
|
|
15067
14956
|
if (filters.lastDoc) {
|
|
15068
|
-
|
|
14957
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
14958
|
+
constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
|
|
14959
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
14960
|
+
constraints.push((0, import_firestore45.startAfter)(...filters.lastDoc));
|
|
14961
|
+
} else {
|
|
14962
|
+
constraints.push((0, import_firestore45.startAfter)(filters.lastDoc));
|
|
14963
|
+
}
|
|
15069
14964
|
}
|
|
15070
14965
|
if (filters.pagination && filters.pagination > 0) {
|
|
15071
14966
|
constraints.push((0, import_firestore45.limit)(filters.pagination));
|
|
@@ -15244,6 +15139,29 @@ var ProcedureService = class extends BaseService {
|
|
|
15244
15139
|
const savedDoc = await (0, import_firestore45.getDoc)(procedureRef);
|
|
15245
15140
|
return savedDoc.data();
|
|
15246
15141
|
}
|
|
15142
|
+
/**
|
|
15143
|
+
* Gets all procedures with minimal info for map display (id, name, clinicId, clinicName, address, latitude, longitude)
|
|
15144
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
15145
|
+
* @returns Array of minimal procedure info for map
|
|
15146
|
+
*/
|
|
15147
|
+
async getProceduresForMap() {
|
|
15148
|
+
const proceduresRef = (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION);
|
|
15149
|
+
const snapshot = await (0, import_firestore45.getDocs)(proceduresRef);
|
|
15150
|
+
const proceduresForMap = snapshot.docs.map((doc37) => {
|
|
15151
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
15152
|
+
const data = doc37.data();
|
|
15153
|
+
return {
|
|
15154
|
+
id: doc37.id,
|
|
15155
|
+
name: data.name,
|
|
15156
|
+
clinicId: (_a = data.clinicInfo) == null ? void 0 : _a.id,
|
|
15157
|
+
clinicName: (_b = data.clinicInfo) == null ? void 0 : _b.name,
|
|
15158
|
+
address: ((_d = (_c = data.clinicInfo) == null ? void 0 : _c.location) == null ? void 0 : _d.address) || "",
|
|
15159
|
+
latitude: (_f = (_e = data.clinicInfo) == null ? void 0 : _e.location) == null ? void 0 : _f.latitude,
|
|
15160
|
+
longitude: (_h = (_g = data.clinicInfo) == null ? void 0 : _g.location) == null ? void 0 : _h.longitude
|
|
15161
|
+
};
|
|
15162
|
+
});
|
|
15163
|
+
return proceduresForMap;
|
|
15164
|
+
}
|
|
15247
15165
|
};
|
|
15248
15166
|
|
|
15249
15167
|
// src/services/reviews/reviews.service.ts
|