@blackcode_sa/metaestetics-api 1.13.8 → 1.13.11

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.
@@ -843,6 +843,131 @@ interface ProcedureSummaryInfo {
843
843
  practitionerName: string;
844
844
  }
845
845
 
846
+ /**
847
+ * Osnovne informacije o zdravstvenom radniku
848
+ */
849
+ interface PractitionerBasicInfo {
850
+ firstName: string;
851
+ lastName: string;
852
+ title: string;
853
+ email: string;
854
+ phoneNumber: string | null;
855
+ dateOfBirth: Timestamp | Date | null;
856
+ gender: "male" | "female" | "other";
857
+ profileImageUrl?: MediaResource | null;
858
+ bio?: string;
859
+ languages: string[];
860
+ }
861
+ /**
862
+ * Sertifikacija zdravstvenog radnika
863
+ */
864
+ interface PractitionerCertification {
865
+ level: CertificationLevel;
866
+ specialties: CertificationSpecialty[];
867
+ licenseNumber: string;
868
+ issuingAuthority: string;
869
+ issueDate: Timestamp | Date;
870
+ expiryDate?: Timestamp | Date | null;
871
+ verificationStatus: "pending" | "verified" | "rejected";
872
+ }
873
+ /**
874
+ * Interfejs za radno vreme zdravstvenog radnika u klinici
875
+ */
876
+ interface PractitionerClinicWorkingHours {
877
+ clinicId: string;
878
+ workingHours: {
879
+ monday: {
880
+ start: string;
881
+ end: string;
882
+ } | null;
883
+ tuesday: {
884
+ start: string;
885
+ end: string;
886
+ } | null;
887
+ wednesday: {
888
+ start: string;
889
+ end: string;
890
+ } | null;
891
+ thursday: {
892
+ start: string;
893
+ end: string;
894
+ } | null;
895
+ friday: {
896
+ start: string;
897
+ end: string;
898
+ } | null;
899
+ saturday: {
900
+ start: string;
901
+ end: string;
902
+ } | null;
903
+ sunday: {
904
+ start: string;
905
+ end: string;
906
+ } | null;
907
+ };
908
+ isActive: boolean;
909
+ createdAt: Timestamp | Date;
910
+ updatedAt: Timestamp | Date;
911
+ }
912
+ /**
913
+ * Status of practitioner profile
914
+ */
915
+ declare enum PractitionerStatus {
916
+ DRAFT = "draft",
917
+ ACTIVE = "active"
918
+ }
919
+ /**
920
+ * Token status for practitioner invitations
921
+ */
922
+ declare enum PractitionerTokenStatus {
923
+ ACTIVE = "active",
924
+ USED = "used",
925
+ EXPIRED = "expired",
926
+ REVOKED = "revoked"
927
+ }
928
+ /**
929
+ * Interfejs za zdravstvenog radnika
930
+ */
931
+ interface Practitioner {
932
+ id: string;
933
+ userRef: string;
934
+ basicInfo: PractitionerBasicInfo;
935
+ fullNameLower: string;
936
+ certification: PractitionerCertification;
937
+ clinics: string[];
938
+ clinicWorkingHours: PractitionerClinicWorkingHours[];
939
+ clinicsInfo: ClinicInfo[];
940
+ procedures: string[];
941
+ freeConsultations?: Record<string, string> | null;
942
+ proceduresInfo: ProcedureSummaryInfo[];
943
+ reviewInfo: PractitionerReviewInfo;
944
+ isActive: boolean;
945
+ isVerified: boolean;
946
+ status: PractitionerStatus;
947
+ createdAt: Timestamp;
948
+ updatedAt: Timestamp;
949
+ }
950
+ /**
951
+ * Token za pozivanje zdravstvenog radnika
952
+ */
953
+ interface PractitionerToken {
954
+ id: string;
955
+ token: string;
956
+ practitionerId: string;
957
+ email: string;
958
+ clinicId: string;
959
+ status: PractitionerTokenStatus;
960
+ createdBy: string;
961
+ createdAt: Timestamp;
962
+ expiresAt: Timestamp;
963
+ usedBy?: string;
964
+ usedAt?: Timestamp;
965
+ emailSent?: boolean;
966
+ emailSentAt?: Timestamp;
967
+ emailError?: string;
968
+ emailErrorAt?: Timestamp;
969
+ }
970
+
846
971
  /**
847
972
  * Enum for all possible clinic tags
848
973
  */
@@ -1141,6 +1266,8 @@ interface DoctorInfo {
1141
1266
  photo: string | null;
1142
1267
  rating: number;
1143
1268
  services: string[];
1269
+ status?: PractitionerStatus;
1270
+ isActive?: boolean;
1144
1271
  }
1145
1272
  /**
1146
1273
  * Interface for clinic
@@ -1174,131 +1301,6 @@ interface Clinic {
1174
1301
  logo?: MediaResource | null;
1175
1302
  }
1176
1303
 
1177
- /**
1178
- * Osnovne informacije o zdravstvenom radniku
1179
- */
1180
- interface PractitionerBasicInfo {
1181
- firstName: string;
1182
- lastName: string;
1183
- title: string;
1184
- email: string;
1185
- phoneNumber: string | null;
1186
- dateOfBirth: Timestamp | Date | null;
1187
- gender: "male" | "female" | "other";
1188
- profileImageUrl?: MediaResource | null;
1189
- bio?: string;
1190
- languages: string[];
1191
- }
1192
- /**
1193
- * Sertifikacija zdravstvenog radnika
1194
- */
1195
- interface PractitionerCertification {
1196
- level: CertificationLevel;
1197
- specialties: CertificationSpecialty[];
1198
- licenseNumber: string;
1199
- issuingAuthority: string;
1200
- issueDate: Timestamp | Date;
1201
- expiryDate?: Timestamp | Date | null;
1202
- verificationStatus: "pending" | "verified" | "rejected";
1203
- }
1204
- /**
1205
- * Interfejs za radno vreme zdravstvenog radnika u klinici
1206
- */
1207
- interface PractitionerClinicWorkingHours {
1208
- clinicId: string;
1209
- workingHours: {
1210
- monday: {
1211
- start: string;
1212
- end: string;
1213
- } | null;
1214
- tuesday: {
1215
- start: string;
1216
- end: string;
1217
- } | null;
1218
- wednesday: {
1219
- start: string;
1220
- end: string;
1221
- } | null;
1222
- thursday: {
1223
- start: string;
1224
- end: string;
1225
- } | null;
1226
- friday: {
1227
- start: string;
1228
- end: string;
1229
- } | null;
1230
- saturday: {
1231
- start: string;
1232
- end: string;
1233
- } | null;
1234
- sunday: {
1235
- start: string;
1236
- end: string;
1237
- } | null;
1238
- };
1239
- isActive: boolean;
1240
- createdAt: Timestamp | Date;
1241
- updatedAt: Timestamp | Date;
1242
- }
1243
- /**
1244
- * Status of practitioner profile
1245
- */
1246
- declare enum PractitionerStatus {
1247
- DRAFT = "draft",
1248
- ACTIVE = "active"
1249
- }
1250
- /**
1251
- * Token status for practitioner invitations
1252
- */
1253
- declare enum PractitionerTokenStatus {
1254
- ACTIVE = "active",
1255
- USED = "used",
1256
- EXPIRED = "expired",
1257
- REVOKED = "revoked"
1258
- }
1259
- /**
1260
- * Interfejs za zdravstvenog radnika
1261
- */
1262
- interface Practitioner {
1263
- id: string;
1264
- userRef: string;
1265
- basicInfo: PractitionerBasicInfo;
1266
- fullNameLower: string;
1267
- certification: PractitionerCertification;
1268
- clinics: string[];
1269
- clinicWorkingHours: PractitionerClinicWorkingHours[];
1270
- clinicsInfo: ClinicInfo[];
1271
- procedures: string[];
1272
- freeConsultations?: Record<string, string> | null;
1273
- proceduresInfo: ProcedureSummaryInfo[];
1274
- reviewInfo: PractitionerReviewInfo;
1275
- isActive: boolean;
1276
- isVerified: boolean;
1277
- status: PractitionerStatus;
1278
- createdAt: Timestamp;
1279
- updatedAt: Timestamp;
1280
- }
1281
- /**
1282
- * Token za pozivanje zdravstvenog radnika
1283
- */
1284
- interface PractitionerToken {
1285
- id: string;
1286
- token: string;
1287
- practitionerId: string;
1288
- email: string;
1289
- clinicId: string;
1290
- status: PractitionerTokenStatus;
1291
- createdBy: string;
1292
- createdAt: Timestamp;
1293
- expiresAt: Timestamp;
1294
- usedBy?: string;
1295
- usedAt?: Timestamp;
1296
- emailSent?: boolean;
1297
- emailSentAt?: Timestamp;
1298
- emailError?: string;
1299
- emailErrorAt?: Timestamp;
1300
- }
1301
-
1302
1304
  declare enum AllergyType {
1303
1305
  MEDICATION = "medication",
1304
1306
  FOOD = "food",
@@ -843,6 +843,131 @@ interface ProcedureSummaryInfo {
843
843
  practitionerName: string;
844
844
  }
845
845
 
846
+ /**
847
+ * Osnovne informacije o zdravstvenom radniku
848
+ */
849
+ interface PractitionerBasicInfo {
850
+ firstName: string;
851
+ lastName: string;
852
+ title: string;
853
+ email: string;
854
+ phoneNumber: string | null;
855
+ dateOfBirth: Timestamp | Date | null;
856
+ gender: "male" | "female" | "other";
857
+ profileImageUrl?: MediaResource | null;
858
+ bio?: string;
859
+ languages: string[];
860
+ }
861
+ /**
862
+ * Sertifikacija zdravstvenog radnika
863
+ */
864
+ interface PractitionerCertification {
865
+ level: CertificationLevel;
866
+ specialties: CertificationSpecialty[];
867
+ licenseNumber: string;
868
+ issuingAuthority: string;
869
+ issueDate: Timestamp | Date;
870
+ expiryDate?: Timestamp | Date | null;
871
+ verificationStatus: "pending" | "verified" | "rejected";
872
+ }
873
+ /**
874
+ * Interfejs za radno vreme zdravstvenog radnika u klinici
875
+ */
876
+ interface PractitionerClinicWorkingHours {
877
+ clinicId: string;
878
+ workingHours: {
879
+ monday: {
880
+ start: string;
881
+ end: string;
882
+ } | null;
883
+ tuesday: {
884
+ start: string;
885
+ end: string;
886
+ } | null;
887
+ wednesday: {
888
+ start: string;
889
+ end: string;
890
+ } | null;
891
+ thursday: {
892
+ start: string;
893
+ end: string;
894
+ } | null;
895
+ friday: {
896
+ start: string;
897
+ end: string;
898
+ } | null;
899
+ saturday: {
900
+ start: string;
901
+ end: string;
902
+ } | null;
903
+ sunday: {
904
+ start: string;
905
+ end: string;
906
+ } | null;
907
+ };
908
+ isActive: boolean;
909
+ createdAt: Timestamp | Date;
910
+ updatedAt: Timestamp | Date;
911
+ }
912
+ /**
913
+ * Status of practitioner profile
914
+ */
915
+ declare enum PractitionerStatus {
916
+ DRAFT = "draft",
917
+ ACTIVE = "active"
918
+ }
919
+ /**
920
+ * Token status for practitioner invitations
921
+ */
922
+ declare enum PractitionerTokenStatus {
923
+ ACTIVE = "active",
924
+ USED = "used",
925
+ EXPIRED = "expired",
926
+ REVOKED = "revoked"
927
+ }
928
+ /**
929
+ * Interfejs za zdravstvenog radnika
930
+ */
931
+ interface Practitioner {
932
+ id: string;
933
+ userRef: string;
934
+ basicInfo: PractitionerBasicInfo;
935
+ fullNameLower: string;
936
+ certification: PractitionerCertification;
937
+ clinics: string[];
938
+ clinicWorkingHours: PractitionerClinicWorkingHours[];
939
+ clinicsInfo: ClinicInfo[];
940
+ procedures: string[];
941
+ freeConsultations?: Record<string, string> | null;
942
+ proceduresInfo: ProcedureSummaryInfo[];
943
+ reviewInfo: PractitionerReviewInfo;
944
+ isActive: boolean;
945
+ isVerified: boolean;
946
+ status: PractitionerStatus;
947
+ createdAt: Timestamp;
948
+ updatedAt: Timestamp;
949
+ }
950
+ /**
951
+ * Token za pozivanje zdravstvenog radnika
952
+ */
953
+ interface PractitionerToken {
954
+ id: string;
955
+ token: string;
956
+ practitionerId: string;
957
+ email: string;
958
+ clinicId: string;
959
+ status: PractitionerTokenStatus;
960
+ createdBy: string;
961
+ createdAt: Timestamp;
962
+ expiresAt: Timestamp;
963
+ usedBy?: string;
964
+ usedAt?: Timestamp;
965
+ emailSent?: boolean;
966
+ emailSentAt?: Timestamp;
967
+ emailError?: string;
968
+ emailErrorAt?: Timestamp;
969
+ }
970
+
846
971
  /**
847
972
  * Enum for all possible clinic tags
848
973
  */
@@ -1141,6 +1266,8 @@ interface DoctorInfo {
1141
1266
  photo: string | null;
1142
1267
  rating: number;
1143
1268
  services: string[];
1269
+ status?: PractitionerStatus;
1270
+ isActive?: boolean;
1144
1271
  }
1145
1272
  /**
1146
1273
  * Interface for clinic
@@ -1174,131 +1301,6 @@ interface Clinic {
1174
1301
  logo?: MediaResource | null;
1175
1302
  }
1176
1303
 
1177
- /**
1178
- * Osnovne informacije o zdravstvenom radniku
1179
- */
1180
- interface PractitionerBasicInfo {
1181
- firstName: string;
1182
- lastName: string;
1183
- title: string;
1184
- email: string;
1185
- phoneNumber: string | null;
1186
- dateOfBirth: Timestamp | Date | null;
1187
- gender: "male" | "female" | "other";
1188
- profileImageUrl?: MediaResource | null;
1189
- bio?: string;
1190
- languages: string[];
1191
- }
1192
- /**
1193
- * Sertifikacija zdravstvenog radnika
1194
- */
1195
- interface PractitionerCertification {
1196
- level: CertificationLevel;
1197
- specialties: CertificationSpecialty[];
1198
- licenseNumber: string;
1199
- issuingAuthority: string;
1200
- issueDate: Timestamp | Date;
1201
- expiryDate?: Timestamp | Date | null;
1202
- verificationStatus: "pending" | "verified" | "rejected";
1203
- }
1204
- /**
1205
- * Interfejs za radno vreme zdravstvenog radnika u klinici
1206
- */
1207
- interface PractitionerClinicWorkingHours {
1208
- clinicId: string;
1209
- workingHours: {
1210
- monday: {
1211
- start: string;
1212
- end: string;
1213
- } | null;
1214
- tuesday: {
1215
- start: string;
1216
- end: string;
1217
- } | null;
1218
- wednesday: {
1219
- start: string;
1220
- end: string;
1221
- } | null;
1222
- thursday: {
1223
- start: string;
1224
- end: string;
1225
- } | null;
1226
- friday: {
1227
- start: string;
1228
- end: string;
1229
- } | null;
1230
- saturday: {
1231
- start: string;
1232
- end: string;
1233
- } | null;
1234
- sunday: {
1235
- start: string;
1236
- end: string;
1237
- } | null;
1238
- };
1239
- isActive: boolean;
1240
- createdAt: Timestamp | Date;
1241
- updatedAt: Timestamp | Date;
1242
- }
1243
- /**
1244
- * Status of practitioner profile
1245
- */
1246
- declare enum PractitionerStatus {
1247
- DRAFT = "draft",
1248
- ACTIVE = "active"
1249
- }
1250
- /**
1251
- * Token status for practitioner invitations
1252
- */
1253
- declare enum PractitionerTokenStatus {
1254
- ACTIVE = "active",
1255
- USED = "used",
1256
- EXPIRED = "expired",
1257
- REVOKED = "revoked"
1258
- }
1259
- /**
1260
- * Interfejs za zdravstvenog radnika
1261
- */
1262
- interface Practitioner {
1263
- id: string;
1264
- userRef: string;
1265
- basicInfo: PractitionerBasicInfo;
1266
- fullNameLower: string;
1267
- certification: PractitionerCertification;
1268
- clinics: string[];
1269
- clinicWorkingHours: PractitionerClinicWorkingHours[];
1270
- clinicsInfo: ClinicInfo[];
1271
- procedures: string[];
1272
- freeConsultations?: Record<string, string> | null;
1273
- proceduresInfo: ProcedureSummaryInfo[];
1274
- reviewInfo: PractitionerReviewInfo;
1275
- isActive: boolean;
1276
- isVerified: boolean;
1277
- status: PractitionerStatus;
1278
- createdAt: Timestamp;
1279
- updatedAt: Timestamp;
1280
- }
1281
- /**
1282
- * Token za pozivanje zdravstvenog radnika
1283
- */
1284
- interface PractitionerToken {
1285
- id: string;
1286
- token: string;
1287
- practitionerId: string;
1288
- email: string;
1289
- clinicId: string;
1290
- status: PractitionerTokenStatus;
1291
- createdBy: string;
1292
- createdAt: Timestamp;
1293
- expiresAt: Timestamp;
1294
- usedBy?: string;
1295
- usedAt?: Timestamp;
1296
- emailSent?: boolean;
1297
- emailSentAt?: Timestamp;
1298
- emailError?: string;
1299
- emailErrorAt?: Timestamp;
1300
- }
1301
-
1302
1304
  declare enum AllergyType {
1303
1305
  MEDICATION = "medication",
1304
1306
  FOOD = "food",
@@ -1307,29 +1307,6 @@ interface ProcedureSummaryInfo {
1307
1307
  practitionerName: string;
1308
1308
  }
1309
1309
 
1310
- /**
1311
- * Interface for clinic contact information
1312
- */
1313
- interface ClinicContactInfo {
1314
- email: string;
1315
- phoneNumber: string;
1316
- alternativePhoneNumber?: string | null;
1317
- website?: string | null;
1318
- }
1319
- /**
1320
- * Interface for clinic location
1321
- */
1322
- interface ClinicLocation {
1323
- address: string;
1324
- city: string;
1325
- country: string;
1326
- postalCode: string;
1327
- latitude: number;
1328
- longitude: number;
1329
- geohash?: string | null;
1330
- tz?: string | null;
1331
- }
1332
-
1333
1310
  /**
1334
1311
  * Osnovne informacije o zdravstvenom radniku
1335
1312
  */
@@ -1426,6 +1403,29 @@ interface Practitioner {
1426
1403
  updatedAt: Timestamp;
1427
1404
  }
1428
1405
 
1406
+ /**
1407
+ * Interface for clinic contact information
1408
+ */
1409
+ interface ClinicContactInfo {
1410
+ email: string;
1411
+ phoneNumber: string;
1412
+ alternativePhoneNumber?: string | null;
1413
+ website?: string | null;
1414
+ }
1415
+ /**
1416
+ * Interface for clinic location
1417
+ */
1418
+ interface ClinicLocation {
1419
+ address: string;
1420
+ city: string;
1421
+ country: string;
1422
+ postalCode: string;
1423
+ latitude: number;
1424
+ longitude: number;
1425
+ geohash?: string | null;
1426
+ tz?: string | null;
1427
+ }
1428
+
1429
1429
  /**
1430
1430
  * Interface for clinic profile information
1431
1431
  */
@@ -1307,29 +1307,6 @@ interface ProcedureSummaryInfo {
1307
1307
  practitionerName: string;
1308
1308
  }
1309
1309
 
1310
- /**
1311
- * Interface for clinic contact information
1312
- */
1313
- interface ClinicContactInfo {
1314
- email: string;
1315
- phoneNumber: string;
1316
- alternativePhoneNumber?: string | null;
1317
- website?: string | null;
1318
- }
1319
- /**
1320
- * Interface for clinic location
1321
- */
1322
- interface ClinicLocation {
1323
- address: string;
1324
- city: string;
1325
- country: string;
1326
- postalCode: string;
1327
- latitude: number;
1328
- longitude: number;
1329
- geohash?: string | null;
1330
- tz?: string | null;
1331
- }
1332
-
1333
1310
  /**
1334
1311
  * Osnovne informacije o zdravstvenom radniku
1335
1312
  */
@@ -1426,6 +1403,29 @@ interface Practitioner {
1426
1403
  updatedAt: Timestamp;
1427
1404
  }
1428
1405
 
1406
+ /**
1407
+ * Interface for clinic contact information
1408
+ */
1409
+ interface ClinicContactInfo {
1410
+ email: string;
1411
+ phoneNumber: string;
1412
+ alternativePhoneNumber?: string | null;
1413
+ website?: string | null;
1414
+ }
1415
+ /**
1416
+ * Interface for clinic location
1417
+ */
1418
+ interface ClinicLocation {
1419
+ address: string;
1420
+ city: string;
1421
+ country: string;
1422
+ postalCode: string;
1423
+ latitude: number;
1424
+ longitude: number;
1425
+ geohash?: string | null;
1426
+ tz?: string | null;
1427
+ }
1428
+
1429
1429
  /**
1430
1430
  * Interface for clinic profile information
1431
1431
  */
package/dist/index.d.mts CHANGED
@@ -5300,6 +5300,8 @@ interface DoctorInfo {
5300
5300
  photo: string | null;
5301
5301
  rating: number;
5302
5302
  services: string[];
5303
+ status?: PractitionerStatus;
5304
+ isActive?: boolean;
5303
5305
  }
5304
5306
  /**
5305
5307
  * Interface for clinic
@@ -6697,9 +6699,17 @@ declare class ProcedureService extends BaseService {
6697
6699
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, categoryService: CategoryService, subcategoryService: SubcategoryService, technologyService: TechnologyService, productService: ProductService, mediaService: MediaService);
6698
6700
  setPractitionerService(practitionerService: PractitionerService): void;
6699
6701
  /**
6700
- * Filters out procedures from draft practitioners
6702
+ * Filters out procedures that should not be visible to patients:
6703
+ * 1. Procedures with no practitioner (missing practitionerId)
6704
+ * 2. Procedures where practitioner doesn't exist
6705
+ * 3. Procedures from draft practitioners
6706
+ * 4. Procedures from inactive practitioners (isActive === false)
6707
+ *
6708
+ * Note: Each procedure has ONE practitionerId. If that practitioner is inactive/draft/missing,
6709
+ * the procedure is filtered out.
6710
+ *
6701
6711
  * @param procedures - Array of procedures to filter
6702
- * @returns Filtered array of procedures (excluding those from draft practitioners)
6712
+ * @returns Filtered array of procedures (excluding invalid/inactive/draft practitioners)
6703
6713
  */
6704
6714
  private filterDraftPractitionerProcedures;
6705
6715
  /**
package/dist/index.d.ts CHANGED
@@ -5300,6 +5300,8 @@ interface DoctorInfo {
5300
5300
  photo: string | null;
5301
5301
  rating: number;
5302
5302
  services: string[];
5303
+ status?: PractitionerStatus;
5304
+ isActive?: boolean;
5303
5305
  }
5304
5306
  /**
5305
5307
  * Interface for clinic
@@ -6697,9 +6699,17 @@ declare class ProcedureService extends BaseService {
6697
6699
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, categoryService: CategoryService, subcategoryService: SubcategoryService, technologyService: TechnologyService, productService: ProductService, mediaService: MediaService);
6698
6700
  setPractitionerService(practitionerService: PractitionerService): void;
6699
6701
  /**
6700
- * Filters out procedures from draft practitioners
6702
+ * Filters out procedures that should not be visible to patients:
6703
+ * 1. Procedures with no practitioner (missing practitionerId)
6704
+ * 2. Procedures where practitioner doesn't exist
6705
+ * 3. Procedures from draft practitioners
6706
+ * 4. Procedures from inactive practitioners (isActive === false)
6707
+ *
6708
+ * Note: Each procedure has ONE practitionerId. If that practitioner is inactive/draft/missing,
6709
+ * the procedure is filtered out.
6710
+ *
6701
6711
  * @param procedures - Array of procedures to filter
6702
- * @returns Filtered array of procedures (excluding those from draft practitioners)
6712
+ * @returns Filtered array of procedures (excluding invalid/inactive/draft practitioners)
6703
6713
  */
6704
6714
  private filterDraftPractitionerProcedures;
6705
6715
  /**
package/dist/index.js CHANGED
@@ -20022,44 +20022,82 @@ var ProcedureService = class extends BaseService {
20022
20022
  this.practitionerService = practitionerService;
20023
20023
  }
20024
20024
  /**
20025
- * Filters out procedures from draft practitioners
20025
+ * Filters out procedures that should not be visible to patients:
20026
+ * 1. Procedures with no practitioner (missing practitionerId)
20027
+ * 2. Procedures where practitioner doesn't exist
20028
+ * 3. Procedures from draft practitioners
20029
+ * 4. Procedures from inactive practitioners (isActive === false)
20030
+ *
20031
+ * Note: Each procedure has ONE practitionerId. If that practitioner is inactive/draft/missing,
20032
+ * the procedure is filtered out.
20033
+ *
20026
20034
  * @param procedures - Array of procedures to filter
20027
- * @returns Filtered array of procedures (excluding those from draft practitioners)
20035
+ * @returns Filtered array of procedures (excluding invalid/inactive/draft practitioners)
20028
20036
  */
20029
20037
  async filterDraftPractitionerProcedures(procedures) {
20030
20038
  if (!this.practitionerService || procedures.length === 0) {
20031
20039
  return procedures;
20032
20040
  }
20033
20041
  try {
20042
+ const proceduresWithPractitioner = procedures.filter(
20043
+ (p) => p.practitionerId && p.practitionerId.trim() !== ""
20044
+ );
20045
+ if (proceduresWithPractitioner.length === 0) {
20046
+ console.log(
20047
+ `[ProcedureService] All ${procedures.length} procedures have no practitionerId - filtering out`
20048
+ );
20049
+ return [];
20050
+ }
20034
20051
  const practitionerIds = Array.from(
20035
- new Set(procedures.map((p) => p.practitionerId).filter(Boolean))
20052
+ new Set(proceduresWithPractitioner.map((p) => p.practitionerId).filter(Boolean))
20036
20053
  );
20037
20054
  if (practitionerIds.length === 0) {
20038
- return procedures;
20055
+ return [];
20039
20056
  }
20040
20057
  const practitionerPromises = practitionerIds.map(
20041
20058
  (id) => this.practitionerService.getPractitioner(id).catch(() => null)
20042
20059
  );
20043
20060
  const practitioners = await Promise.all(practitionerPromises);
20044
- const practitionerStatusMap = /* @__PURE__ */ new Map();
20061
+ const practitionerMap = /* @__PURE__ */ new Map();
20045
20062
  practitioners.forEach((practitioner, index) => {
20046
20063
  if (practitioner) {
20047
- practitionerStatusMap.set(practitionerIds[index], practitioner.status);
20064
+ practitionerMap.set(practitionerIds[index], practitioner);
20048
20065
  }
20049
20066
  });
20050
- const filteredProcedures = procedures.filter((procedure) => {
20051
- const practitionerStatus = practitionerStatusMap.get(procedure.practitionerId);
20052
- return practitionerStatus !== "draft" /* DRAFT */;
20067
+ const filteredProcedures = proceduresWithPractitioner.filter((procedure) => {
20068
+ const practitioner = practitionerMap.get(procedure.practitionerId);
20069
+ if (!practitioner) {
20070
+ console.log(
20071
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} not found`
20072
+ );
20073
+ return false;
20074
+ }
20075
+ if (practitioner.status === "draft" /* DRAFT */) {
20076
+ console.log(
20077
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is DRAFT`
20078
+ );
20079
+ return false;
20080
+ }
20081
+ if (!practitioner.isActive) {
20082
+ console.log(
20083
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is not active`
20084
+ );
20085
+ return false;
20086
+ }
20087
+ return true;
20053
20088
  });
20054
- if (filteredProcedures.length !== procedures.length) {
20089
+ const filteredCount = procedures.length - filteredProcedures.length;
20090
+ if (filteredCount > 0) {
20091
+ const noPractitionerCount = procedures.length - proceduresWithPractitioner.length;
20092
+ const invalidPractitionerCount = proceduresWithPractitioner.length - filteredProcedures.length;
20055
20093
  console.log(
20056
- `[ProcedureService] Filtered out ${procedures.length - filteredProcedures.length} procedures from draft practitioners`
20094
+ `[ProcedureService] Filtered out ${filteredCount} procedures: ${noPractitionerCount} with no practitionerId, ${invalidPractitionerCount} with missing/draft/inactive practitioners`
20057
20095
  );
20058
20096
  }
20059
20097
  return filteredProcedures;
20060
20098
  } catch (error) {
20061
20099
  console.error(
20062
- "[ProcedureService] Error filtering draft practitioner procedures:",
20100
+ "[ProcedureService] Error filtering practitioner procedures:",
20063
20101
  error
20064
20102
  );
20065
20103
  return procedures;
@@ -20233,7 +20271,11 @@ var ProcedureService = class extends BaseService {
20233
20271
  photo: typeof practitioner.basicInfo.profileImageUrl === "string" ? practitioner.basicInfo.profileImageUrl : "",
20234
20272
  // Default to empty string if not a processed URL
20235
20273
  rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
20236
- services: practitioner.procedures || []
20274
+ services: practitioner.procedures || [],
20275
+ status: practitioner.status,
20276
+ // Include practitioner status for client-side filtering
20277
+ isActive: practitioner.isActive
20278
+ // Include isActive flag for client-side filtering
20237
20279
  };
20238
20280
  const { productsMetadata: _, productId: __, photos: ___, ...validatedDataWithoutProductsMetadata } = validatedData;
20239
20281
  const newProcedure = {
@@ -20392,7 +20434,9 @@ var ProcedureService = class extends BaseService {
20392
20434
  description: practitioner.basicInfo.bio || "",
20393
20435
  photo: typeof practitioner.basicInfo.profileImageUrl === "string" ? practitioner.basicInfo.profileImageUrl : "",
20394
20436
  rating: ((_c = practitioner.reviewInfo) == null ? void 0 : _c.averageRating) || 0,
20395
- services: practitioner.procedures || []
20437
+ services: practitioner.procedures || [],
20438
+ status: practitioner.status,
20439
+ isActive: practitioner.isActive
20396
20440
  };
20397
20441
  const newProcedure = {
20398
20442
  ...sourceProcedure,
@@ -20769,7 +20813,8 @@ var ProcedureService = class extends BaseService {
20769
20813
  (0, import_firestore58.where)("isActive", "==", true)
20770
20814
  );
20771
20815
  const snapshot = await (0, import_firestore58.getDocs)(q);
20772
- return snapshot.docs.map((doc47) => doc47.data());
20816
+ const procedures = snapshot.docs.map((doc47) => doc47.data());
20817
+ return await this.filterDraftPractitionerProcedures(procedures);
20773
20818
  }
20774
20819
  /**
20775
20820
  * Gets all procedures for a practitioner
@@ -20888,7 +20933,9 @@ var ProcedureService = class extends BaseService {
20888
20933
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
20889
20934
  // Default to empty string if not a processed URL
20890
20935
  rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
20891
- services: newPractitioner.procedures || []
20936
+ services: newPractitioner.procedures || [],
20937
+ status: newPractitioner.status,
20938
+ isActive: newPractitioner.isActive
20892
20939
  };
20893
20940
  }
20894
20941
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
@@ -21172,6 +21219,7 @@ var ProcedureService = class extends BaseService {
21172
21219
  if (hasNestedFilters) {
21173
21220
  procedures = this.applyInMemoryFilters(procedures, filters);
21174
21221
  }
21222
+ procedures = await this.filterDraftPractitionerProcedures(procedures);
21175
21223
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
21176
21224
  console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
21177
21225
  if (procedures.length < (filters.pagination || 10)) {
package/dist/index.mjs CHANGED
@@ -20258,44 +20258,82 @@ var ProcedureService = class extends BaseService {
20258
20258
  this.practitionerService = practitionerService;
20259
20259
  }
20260
20260
  /**
20261
- * Filters out procedures from draft practitioners
20261
+ * Filters out procedures that should not be visible to patients:
20262
+ * 1. Procedures with no practitioner (missing practitionerId)
20263
+ * 2. Procedures where practitioner doesn't exist
20264
+ * 3. Procedures from draft practitioners
20265
+ * 4. Procedures from inactive practitioners (isActive === false)
20266
+ *
20267
+ * Note: Each procedure has ONE practitionerId. If that practitioner is inactive/draft/missing,
20268
+ * the procedure is filtered out.
20269
+ *
20262
20270
  * @param procedures - Array of procedures to filter
20263
- * @returns Filtered array of procedures (excluding those from draft practitioners)
20271
+ * @returns Filtered array of procedures (excluding invalid/inactive/draft practitioners)
20264
20272
  */
20265
20273
  async filterDraftPractitionerProcedures(procedures) {
20266
20274
  if (!this.practitionerService || procedures.length === 0) {
20267
20275
  return procedures;
20268
20276
  }
20269
20277
  try {
20278
+ const proceduresWithPractitioner = procedures.filter(
20279
+ (p) => p.practitionerId && p.practitionerId.trim() !== ""
20280
+ );
20281
+ if (proceduresWithPractitioner.length === 0) {
20282
+ console.log(
20283
+ `[ProcedureService] All ${procedures.length} procedures have no practitionerId - filtering out`
20284
+ );
20285
+ return [];
20286
+ }
20270
20287
  const practitionerIds = Array.from(
20271
- new Set(procedures.map((p) => p.practitionerId).filter(Boolean))
20288
+ new Set(proceduresWithPractitioner.map((p) => p.practitionerId).filter(Boolean))
20272
20289
  );
20273
20290
  if (practitionerIds.length === 0) {
20274
- return procedures;
20291
+ return [];
20275
20292
  }
20276
20293
  const practitionerPromises = practitionerIds.map(
20277
20294
  (id) => this.practitionerService.getPractitioner(id).catch(() => null)
20278
20295
  );
20279
20296
  const practitioners = await Promise.all(practitionerPromises);
20280
- const practitionerStatusMap = /* @__PURE__ */ new Map();
20297
+ const practitionerMap = /* @__PURE__ */ new Map();
20281
20298
  practitioners.forEach((practitioner, index) => {
20282
20299
  if (practitioner) {
20283
- practitionerStatusMap.set(practitionerIds[index], practitioner.status);
20300
+ practitionerMap.set(practitionerIds[index], practitioner);
20284
20301
  }
20285
20302
  });
20286
- const filteredProcedures = procedures.filter((procedure) => {
20287
- const practitionerStatus = practitionerStatusMap.get(procedure.practitionerId);
20288
- return practitionerStatus !== "draft" /* DRAFT */;
20303
+ const filteredProcedures = proceduresWithPractitioner.filter((procedure) => {
20304
+ const practitioner = practitionerMap.get(procedure.practitionerId);
20305
+ if (!practitioner) {
20306
+ console.log(
20307
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} not found`
20308
+ );
20309
+ return false;
20310
+ }
20311
+ if (practitioner.status === "draft" /* DRAFT */) {
20312
+ console.log(
20313
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is DRAFT`
20314
+ );
20315
+ return false;
20316
+ }
20317
+ if (!practitioner.isActive) {
20318
+ console.log(
20319
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is not active`
20320
+ );
20321
+ return false;
20322
+ }
20323
+ return true;
20289
20324
  });
20290
- if (filteredProcedures.length !== procedures.length) {
20325
+ const filteredCount = procedures.length - filteredProcedures.length;
20326
+ if (filteredCount > 0) {
20327
+ const noPractitionerCount = procedures.length - proceduresWithPractitioner.length;
20328
+ const invalidPractitionerCount = proceduresWithPractitioner.length - filteredProcedures.length;
20291
20329
  console.log(
20292
- `[ProcedureService] Filtered out ${procedures.length - filteredProcedures.length} procedures from draft practitioners`
20330
+ `[ProcedureService] Filtered out ${filteredCount} procedures: ${noPractitionerCount} with no practitionerId, ${invalidPractitionerCount} with missing/draft/inactive practitioners`
20293
20331
  );
20294
20332
  }
20295
20333
  return filteredProcedures;
20296
20334
  } catch (error) {
20297
20335
  console.error(
20298
- "[ProcedureService] Error filtering draft practitioner procedures:",
20336
+ "[ProcedureService] Error filtering practitioner procedures:",
20299
20337
  error
20300
20338
  );
20301
20339
  return procedures;
@@ -20469,7 +20507,11 @@ var ProcedureService = class extends BaseService {
20469
20507
  photo: typeof practitioner.basicInfo.profileImageUrl === "string" ? practitioner.basicInfo.profileImageUrl : "",
20470
20508
  // Default to empty string if not a processed URL
20471
20509
  rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
20472
- services: practitioner.procedures || []
20510
+ services: practitioner.procedures || [],
20511
+ status: practitioner.status,
20512
+ // Include practitioner status for client-side filtering
20513
+ isActive: practitioner.isActive
20514
+ // Include isActive flag for client-side filtering
20473
20515
  };
20474
20516
  const { productsMetadata: _, productId: __, photos: ___, ...validatedDataWithoutProductsMetadata } = validatedData;
20475
20517
  const newProcedure = {
@@ -20628,7 +20670,9 @@ var ProcedureService = class extends BaseService {
20628
20670
  description: practitioner.basicInfo.bio || "",
20629
20671
  photo: typeof practitioner.basicInfo.profileImageUrl === "string" ? practitioner.basicInfo.profileImageUrl : "",
20630
20672
  rating: ((_c = practitioner.reviewInfo) == null ? void 0 : _c.averageRating) || 0,
20631
- services: practitioner.procedures || []
20673
+ services: practitioner.procedures || [],
20674
+ status: practitioner.status,
20675
+ isActive: practitioner.isActive
20632
20676
  };
20633
20677
  const newProcedure = {
20634
20678
  ...sourceProcedure,
@@ -21005,7 +21049,8 @@ var ProcedureService = class extends BaseService {
21005
21049
  where33("isActive", "==", true)
21006
21050
  );
21007
21051
  const snapshot = await getDocs33(q);
21008
- return snapshot.docs.map((doc47) => doc47.data());
21052
+ const procedures = snapshot.docs.map((doc47) => doc47.data());
21053
+ return await this.filterDraftPractitionerProcedures(procedures);
21009
21054
  }
21010
21055
  /**
21011
21056
  * Gets all procedures for a practitioner
@@ -21124,7 +21169,9 @@ var ProcedureService = class extends BaseService {
21124
21169
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
21125
21170
  // Default to empty string if not a processed URL
21126
21171
  rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
21127
- services: newPractitioner.procedures || []
21172
+ services: newPractitioner.procedures || [],
21173
+ status: newPractitioner.status,
21174
+ isActive: newPractitioner.isActive
21128
21175
  };
21129
21176
  }
21130
21177
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
@@ -21408,6 +21455,7 @@ var ProcedureService = class extends BaseService {
21408
21455
  if (hasNestedFilters) {
21409
21456
  procedures = this.applyInMemoryFilters(procedures, filters);
21410
21457
  }
21458
+ procedures = await this.filterDraftPractitionerProcedures(procedures);
21411
21459
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
21412
21460
  console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
21413
21461
  if (procedures.length < (filters.pagination || 10)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.13.8",
4
+ "version": "1.13.11",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -90,9 +90,17 @@ export class ProcedureService extends BaseService {
90
90
  }
91
91
 
92
92
  /**
93
- * Filters out procedures from draft practitioners
93
+ * Filters out procedures that should not be visible to patients:
94
+ * 1. Procedures with no practitioner (missing practitionerId)
95
+ * 2. Procedures where practitioner doesn't exist
96
+ * 3. Procedures from draft practitioners
97
+ * 4. Procedures from inactive practitioners (isActive === false)
98
+ *
99
+ * Note: Each procedure has ONE practitionerId. If that practitioner is inactive/draft/missing,
100
+ * the procedure is filtered out.
101
+ *
94
102
  * @param procedures - Array of procedures to filter
95
- * @returns Filtered array of procedures (excluding those from draft practitioners)
103
+ * @returns Filtered array of procedures (excluding invalid/inactive/draft practitioners)
96
104
  */
97
105
  private async filterDraftPractitionerProcedures(
98
106
  procedures: Procedure[]
@@ -102,13 +110,25 @@ export class ProcedureService extends BaseService {
102
110
  }
103
111
 
104
112
  try {
113
+ // First, filter out procedures with no practitionerId
114
+ const proceduresWithPractitioner = procedures.filter((p) =>
115
+ p.practitionerId && p.practitionerId.trim() !== ''
116
+ );
117
+
118
+ if (proceduresWithPractitioner.length === 0) {
119
+ console.log(
120
+ `[ProcedureService] All ${procedures.length} procedures have no practitionerId - filtering out`
121
+ );
122
+ return [];
123
+ }
124
+
105
125
  // Get unique practitioner IDs from procedures
106
126
  const practitionerIds = Array.from(
107
- new Set(procedures.map((p) => p.practitionerId).filter(Boolean))
127
+ new Set(proceduresWithPractitioner.map((p) => p.practitionerId).filter(Boolean))
108
128
  );
109
129
 
110
130
  if (practitionerIds.length === 0) {
111
- return procedures;
131
+ return [];
112
132
  }
113
133
 
114
134
  // Fetch all practitioners in parallel
@@ -117,32 +137,64 @@ export class ProcedureService extends BaseService {
117
137
  );
118
138
  const practitioners = await Promise.all(practitionerPromises);
119
139
 
120
- // Create a map of practitioner ID to status
121
- const practitionerStatusMap = new Map<string, PractitionerStatus>();
140
+ // Create a map of practitioner ID to practitioner data
141
+ const practitionerMap = new Map<string, Practitioner>();
122
142
  practitioners.forEach((practitioner, index) => {
123
143
  if (practitioner) {
124
- practitionerStatusMap.set(practitionerIds[index], practitioner.status);
144
+ practitionerMap.set(practitionerIds[index], practitioner);
125
145
  }
126
146
  });
127
147
 
128
- // Filter out procedures from draft practitioners
129
- const filteredProcedures = procedures.filter((procedure) => {
130
- const practitionerStatus = practitionerStatusMap.get(procedure.practitionerId);
131
- return practitionerStatus !== PractitionerStatus.DRAFT;
148
+ // Filter out procedures that:
149
+ // 1. Have no practitionerId (already filtered above, but double-check)
150
+ // 2. Have a practitioner that doesn't exist
151
+ // 3. Have a practitioner with DRAFT status
152
+ // 4. Have a practitioner that is not active (isActive === false)
153
+ const filteredProcedures = proceduresWithPractitioner.filter((procedure) => {
154
+ // Check if practitioner exists
155
+ const practitioner = practitionerMap.get(procedure.practitionerId);
156
+
157
+ if (!practitioner) {
158
+ console.log(
159
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} not found`
160
+ );
161
+ return false;
162
+ }
163
+
164
+ // Check if practitioner is DRAFT
165
+ if (practitioner.status === PractitionerStatus.DRAFT) {
166
+ console.log(
167
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is DRAFT`
168
+ );
169
+ return false;
170
+ }
171
+
172
+ // Check if practitioner is active (must be true to show procedure)
173
+ if (!practitioner.isActive) {
174
+ console.log(
175
+ `[ProcedureService] Filtering out procedure ${procedure.id} - practitioner ${procedure.practitionerId} is not active`
176
+ );
177
+ return false;
178
+ }
179
+
180
+ return true;
132
181
  });
133
182
 
134
- if (filteredProcedures.length !== procedures.length) {
183
+ const filteredCount = procedures.length - filteredProcedures.length;
184
+ if (filteredCount > 0) {
185
+ const noPractitionerCount = procedures.length - proceduresWithPractitioner.length;
186
+ const invalidPractitionerCount = proceduresWithPractitioner.length - filteredProcedures.length;
135
187
  console.log(
136
- `[ProcedureService] Filtered out ${
137
- procedures.length - filteredProcedures.length
138
- } procedures from draft practitioners`
188
+ `[ProcedureService] Filtered out ${filteredCount} procedures: ` +
189
+ `${noPractitionerCount} with no practitionerId, ` +
190
+ `${invalidPractitionerCount} with missing/draft/inactive practitioners`
139
191
  );
140
192
  }
141
193
 
142
194
  return filteredProcedures;
143
195
  } catch (error) {
144
196
  console.error(
145
- '[ProcedureService] Error filtering draft practitioner procedures:',
197
+ '[ProcedureService] Error filtering practitioner procedures:',
146
198
  error
147
199
  );
148
200
  // On error, return original procedures to avoid breaking functionality
@@ -387,6 +439,8 @@ export class ProcedureService extends BaseService {
387
439
  : '', // Default to empty string if not a processed URL
388
440
  rating: practitioner.reviewInfo?.averageRating || 0,
389
441
  services: practitioner.procedures || [],
442
+ status: practitioner.status, // Include practitioner status for client-side filtering
443
+ isActive: practitioner.isActive, // Include isActive flag for client-side filtering
390
444
  };
391
445
 
392
446
  // Create the procedure object
@@ -576,6 +630,8 @@ export class ProcedureService extends BaseService {
576
630
  : '',
577
631
  rating: practitioner.reviewInfo?.averageRating || 0,
578
632
  services: practitioner.procedures || [],
633
+ status: practitioner.status,
634
+ isActive: practitioner.isActive,
579
635
  };
580
636
 
581
637
  // Construct the new procedure object
@@ -1062,7 +1118,10 @@ export class ProcedureService extends BaseService {
1062
1118
  where('isActive', '==', true),
1063
1119
  );
1064
1120
  const snapshot = await getDocs(q);
1065
- return snapshot.docs.map(doc => doc.data() as Procedure);
1121
+ const procedures = snapshot.docs.map(doc => doc.data() as Procedure);
1122
+
1123
+ // Filter out procedures from draft practitioners
1124
+ return await this.filterDraftPractitionerProcedures(procedures);
1066
1125
  }
1067
1126
 
1068
1127
  /**
@@ -1210,6 +1269,8 @@ export class ProcedureService extends BaseService {
1210
1269
  : '', // Default to empty string if not a processed URL
1211
1270
  rating: newPractitioner.reviewInfo?.averageRating || 0,
1212
1271
  services: newPractitioner.procedures || [],
1272
+ status: newPractitioner.status,
1273
+ isActive: newPractitioner.isActive,
1213
1274
  };
1214
1275
  }
1215
1276
 
@@ -1591,6 +1652,9 @@ export class ProcedureService extends BaseService {
1591
1652
  procedures = this.applyInMemoryFilters(procedures, filters);
1592
1653
  }
1593
1654
 
1655
+ // Filter out procedures from draft practitioners
1656
+ procedures = await this.filterDraftPractitionerProcedures(procedures);
1657
+
1594
1658
  const lastDoc =
1595
1659
  querySnapshot.docs.length > 0
1596
1660
  ? querySnapshot.docs[querySnapshot.docs.length - 1]
@@ -3,6 +3,7 @@ import { Timestamp, FieldValue } from 'firebase/firestore';
3
3
  import type { ClinicInfo } from '../profile';
4
4
  import { ClinicReviewInfo } from '../reviews';
5
5
  import { ProcedureSummaryInfo } from '../procedure';
6
+ import { PractitionerStatus } from '../practitioner';
6
7
 
7
8
  export const CLINIC_GROUPS_COLLECTION = 'clinic_groups';
8
9
  export const CLINIC_ADMINS_COLLECTION = 'clinic_admins';
@@ -351,6 +352,8 @@ export interface DoctorInfo {
351
352
  photo: string | null;
352
353
  rating: number;
353
354
  services: string[]; // Used for search and filtering
355
+ status?: PractitionerStatus; // Practitioner status (DRAFT, ACTIVE, etc.)
356
+ isActive?: boolean; // Whether practitioner is active
354
357
  // TODO: Add aggregated fields, like rating, reviews, services this doctor provides in this clinic and similar
355
358
  }
356
359