@blackcode_sa/metaestetics-api 1.7.19 → 1.7.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1096,7 +1096,7 @@ var BaseService = class {
1096
1096
  };
1097
1097
 
1098
1098
  // src/services/user.service.ts
1099
- var import_firestore17 = require("firebase/firestore");
1099
+ var import_firestore19 = require("firebase/firestore");
1100
1100
 
1101
1101
  // src/errors/user.errors.ts
1102
1102
  var USER_ERRORS = {
@@ -1194,419 +1194,770 @@ var USER_ERRORS = {
1194
1194
  var import_zod16 = require("zod");
1195
1195
 
1196
1196
  // src/services/patient/patient.service.ts
1197
- var import_firestore12 = require("firebase/firestore");
1197
+ var import_firestore14 = require("firebase/firestore");
1198
1198
 
1199
- // src/services/patient/utils/profile.utils.ts
1200
- var import_firestore8 = require("firebase/firestore");
1199
+ // src/services/media/media.service.ts
1200
+ var import_firestore2 = require("firebase/firestore");
1201
1201
  var import_storage3 = require("firebase/storage");
1202
- var import_zod8 = require("zod");
1203
-
1204
- // src/types/patient/medical-info.types.ts
1205
- var PATIENT_MEDICAL_INFO_COLLECTION = "medical_info";
1206
- var DEFAULT_MEDICAL_INFO = {
1207
- vitalStats: {},
1208
- blockingConditions: [],
1209
- contraindications: [],
1210
- allergies: [],
1211
- currentMedications: []
1212
- };
1213
-
1214
- // src/types/patient/index.ts
1215
- var PATIENTS_COLLECTION = "patients";
1216
- var PATIENT_SENSITIVE_INFO_COLLECTION = "sensitive-info";
1217
- var PATIENT_MEDICAL_HISTORY_COLLECTION = "medical-history";
1218
- var PATIENT_APPOINTMENTS_COLLECTION = "appointments";
1219
- var PATIENT_LOCATION_INFO_COLLECTION = "location-info";
1220
- var Gender = /* @__PURE__ */ ((Gender2) => {
1221
- Gender2["MALE"] = "male";
1222
- Gender2["FEMALE"] = "female";
1223
- Gender2["TRANSGENDER_MALE"] = "transgender_male";
1224
- Gender2["TRANSGENDER_FEMALE"] = "transgender_female";
1225
- Gender2["PREFER_NOT_TO_SAY"] = "prefer_not_to_say";
1226
- Gender2["OTHER"] = "other";
1227
- return Gender2;
1228
- })(Gender || {});
1229
-
1230
- // src/validations/patient.schema.ts
1231
- var import_zod6 = require("zod");
1232
1202
  var import_firestore3 = require("firebase/firestore");
1233
-
1234
- // src/validations/patient/medical-info.schema.ts
1235
- var import_zod5 = require("zod");
1236
-
1237
- // src/types/patient/allergies.ts
1238
- var AllergyType = /* @__PURE__ */ ((AllergyType2) => {
1239
- AllergyType2["MEDICATION"] = "medication";
1240
- AllergyType2["FOOD"] = "food";
1241
- AllergyType2["ENVIRONMENTAL"] = "environmental";
1242
- AllergyType2["LATEX"] = "latex";
1243
- AllergyType2["COSMETIC"] = "cosmetic";
1244
- AllergyType2["OTHER"] = "other";
1245
- return AllergyType2;
1246
- })(AllergyType || {});
1247
- var MedicationAllergySubtype = /* @__PURE__ */ ((MedicationAllergySubtype2) => {
1248
- MedicationAllergySubtype2["ANTIBIOTICS"] = "antibiotics";
1249
- MedicationAllergySubtype2["NSAIDS"] = "nsaids";
1250
- MedicationAllergySubtype2["OPIOIDS"] = "opioids";
1251
- MedicationAllergySubtype2["ANESTHETICS"] = "anesthetics";
1252
- MedicationAllergySubtype2["VACCINES"] = "vaccines";
1253
- MedicationAllergySubtype2["OTHER"] = "other";
1254
- return MedicationAllergySubtype2;
1255
- })(MedicationAllergySubtype || {});
1256
- var FoodAllergySubtype = /* @__PURE__ */ ((FoodAllergySubtype2) => {
1257
- FoodAllergySubtype2["NUTS"] = "nuts";
1258
- FoodAllergySubtype2["SHELLFISH"] = "shellfish";
1259
- FoodAllergySubtype2["DAIRY"] = "dairy";
1260
- FoodAllergySubtype2["EGGS"] = "eggs";
1261
- FoodAllergySubtype2["WHEAT"] = "wheat";
1262
- FoodAllergySubtype2["SOY"] = "soy";
1263
- FoodAllergySubtype2["FISH"] = "fish";
1264
- FoodAllergySubtype2["FRUITS"] = "fruits";
1265
- FoodAllergySubtype2["OTHER"] = "other";
1266
- return FoodAllergySubtype2;
1267
- })(FoodAllergySubtype || {});
1268
- var EnvironmentalAllergySubtype = /* @__PURE__ */ ((EnvironmentalAllergySubtype2) => {
1269
- EnvironmentalAllergySubtype2["POLLEN"] = "pollen";
1270
- EnvironmentalAllergySubtype2["DUST"] = "dust";
1271
- EnvironmentalAllergySubtype2["MOLD"] = "mold";
1272
- EnvironmentalAllergySubtype2["PET_DANDER"] = "pet_dander";
1273
- EnvironmentalAllergySubtype2["INSECTS"] = "insects";
1274
- EnvironmentalAllergySubtype2["OTHER"] = "other";
1275
- return EnvironmentalAllergySubtype2;
1276
- })(EnvironmentalAllergySubtype || {});
1277
- var CosmeticAllergySubtype = /* @__PURE__ */ ((CosmeticAllergySubtype2) => {
1278
- CosmeticAllergySubtype2["FRAGRANCES"] = "fragrances";
1279
- CosmeticAllergySubtype2["PRESERVATIVES"] = "preservatives";
1280
- CosmeticAllergySubtype2["DYES"] = "dyes";
1281
- CosmeticAllergySubtype2["METALS"] = "metals";
1282
- CosmeticAllergySubtype2["OTHER"] = "other";
1283
- return CosmeticAllergySubtype2;
1284
- })(CosmeticAllergySubtype || {});
1285
-
1286
- // src/backoffice/types/static/blocking-condition.types.ts
1287
- var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
1288
- BlockingCondition2["PREGNANCY"] = "pregnancy";
1289
- BlockingCondition2["BREASTFEEDING"] = "breastfeeding";
1290
- BlockingCondition2["ACTIVE_INFECTION"] = "active_infection";
1291
- BlockingCondition2["SKIN_CONDITION"] = "skin_condition";
1292
- BlockingCondition2["AUTOIMMUNE_DISEASE"] = "autoimmune_disease";
1293
- BlockingCondition2["BLOOD_THINNERS"] = "blood_thinners";
1294
- BlockingCondition2["RECENT_SURGERY"] = "recent_surgery";
1295
- BlockingCondition2["DIABETES"] = "diabetes";
1296
- BlockingCondition2["HEART_CONDITION"] = "heart_condition";
1297
- BlockingCondition2["HIGH_BLOOD_PRESSURE"] = "high_blood_pressure";
1298
- BlockingCondition2["KELOID_SCARRING"] = "keloid_scarring";
1299
- BlockingCondition2["METAL_IMPLANTS"] = "metal_implants";
1300
- BlockingCondition2["PACEMAKER"] = "pacemaker";
1301
- BlockingCondition2["CANCER"] = "cancer";
1302
- BlockingCondition2["EPILEPSY"] = "epilepsy";
1303
- return BlockingCondition2;
1304
- })(BlockingCondition || {});
1305
-
1306
- // src/backoffice/types/static/contraindication.types.ts
1307
- var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
1308
- Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
1309
- Contraindication2["RECENT_TANNING"] = "recent_tanning";
1310
- Contraindication2["RECENT_BOTOX"] = "recent_botox";
1311
- Contraindication2["RECENT_FILLERS"] = "recent_fillers";
1312
- Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
1313
- Contraindication2["MEDICATIONS"] = "medications";
1314
- Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
1315
- Contraindication2["RECENT_LASER"] = "recent_laser";
1316
- Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
1317
- Contraindication2["OPEN_WOUNDS"] = "open_wounds";
1318
- Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
1319
- Contraindication2["COLD_SORES"] = "cold_sores";
1320
- return Contraindication2;
1321
- })(Contraindication || {});
1322
-
1323
- // src/validations/common.schema.ts
1324
- var import_zod4 = require("zod");
1325
- var import_firestore2 = require("firebase/firestore");
1326
- var timestampSchema2 = import_zod4.z.union([
1327
- import_zod4.z.object({
1328
- seconds: import_zod4.z.number(),
1329
- nanoseconds: import_zod4.z.number()
1330
- }),
1331
- import_zod4.z.instanceof(import_firestore2.Timestamp)
1332
- ]).transform((data) => {
1333
- if (data instanceof import_firestore2.Timestamp) {
1334
- return data;
1335
- }
1336
- return new import_firestore2.Timestamp(data.seconds, data.nanoseconds);
1337
- });
1338
-
1339
- // src/validations/patient/medical-info.schema.ts
1340
- var allergySubtypeSchema = import_zod5.z.union([
1341
- import_zod5.z.nativeEnum(MedicationAllergySubtype),
1342
- import_zod5.z.nativeEnum(FoodAllergySubtype),
1343
- import_zod5.z.nativeEnum(EnvironmentalAllergySubtype),
1344
- import_zod5.z.nativeEnum(CosmeticAllergySubtype),
1345
- import_zod5.z.literal("other")
1346
- ]);
1347
- var allergySchema = import_zod5.z.object({
1348
- type: import_zod5.z.nativeEnum(AllergyType),
1349
- subtype: allergySubtypeSchema,
1350
- name: import_zod5.z.string().optional().nullable(),
1351
- severity: import_zod5.z.enum(["mild", "moderate", "severe"]).optional(),
1352
- reaction: import_zod5.z.string().optional().nullable(),
1353
- diagnosed: timestampSchema2.optional().nullable(),
1354
- notes: import_zod5.z.string().optional().nullable()
1355
- });
1356
- var vitalStatsSchema = import_zod5.z.object({
1357
- height: import_zod5.z.number().positive().optional(),
1358
- weight: import_zod5.z.number().positive().optional(),
1359
- bloodType: import_zod5.z.enum(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]).optional(),
1360
- bloodPressure: import_zod5.z.object({
1361
- systolic: import_zod5.z.number().min(70).max(200),
1362
- diastolic: import_zod5.z.number().min(40).max(130),
1363
- lastMeasured: timestampSchema2
1364
- }).optional()
1365
- });
1366
- var blockingConditionSchema = import_zod5.z.object({
1367
- condition: import_zod5.z.nativeEnum(BlockingCondition),
1368
- diagnosedAt: timestampSchema2,
1369
- notes: import_zod5.z.string().optional().nullable(),
1370
- isActive: import_zod5.z.boolean()
1371
- });
1372
- var contraindicationSchema = import_zod5.z.object({
1373
- condition: import_zod5.z.nativeEnum(Contraindication),
1374
- lastOccurrence: timestampSchema2,
1375
- frequency: import_zod5.z.enum(["rare", "occasional", "frequent"]),
1376
- notes: import_zod5.z.string().optional().nullable(),
1377
- isActive: import_zod5.z.boolean()
1378
- });
1379
- var medicationSchema = import_zod5.z.object({
1380
- name: import_zod5.z.string().min(1),
1381
- dosage: import_zod5.z.string().min(1),
1382
- frequency: import_zod5.z.string().min(1),
1383
- startDate: timestampSchema2.optional().nullable(),
1384
- endDate: timestampSchema2.optional().nullable(),
1385
- prescribedBy: import_zod5.z.string().optional().nullable()
1386
- });
1387
- var patientMedicalInfoSchema = import_zod5.z.object({
1388
- patientId: import_zod5.z.string(),
1389
- vitalStats: vitalStatsSchema,
1390
- blockingConditions: import_zod5.z.array(blockingConditionSchema),
1391
- contraindications: import_zod5.z.array(contraindicationSchema),
1392
- allergies: import_zod5.z.array(allergySchema),
1393
- currentMedications: import_zod5.z.array(medicationSchema),
1394
- emergencyNotes: import_zod5.z.string().optional(),
1395
- lastUpdated: timestampSchema2,
1396
- updatedBy: import_zod5.z.string(),
1397
- verifiedBy: import_zod5.z.string().optional(),
1398
- verifiedAt: timestampSchema2.optional()
1399
- });
1400
- var createPatientMedicalInfoSchema = patientMedicalInfoSchema.omit({
1401
- patientId: true,
1402
- lastUpdated: true,
1403
- updatedBy: true,
1404
- verifiedBy: true,
1405
- verifiedAt: true
1406
- });
1407
- var updatePatientMedicalInfoSchema = createPatientMedicalInfoSchema.partial();
1408
- var updateVitalStatsSchema = vitalStatsSchema;
1409
- var addAllergySchema = allergySchema;
1410
- var updateAllergySchema = allergySchema.partial().extend({
1411
- allergyIndex: import_zod5.z.number().min(0)
1412
- });
1413
- var addBlockingConditionSchema = blockingConditionSchema;
1414
- var updateBlockingConditionSchema = blockingConditionSchema.partial().extend({
1415
- conditionIndex: import_zod5.z.number().min(0)
1416
- });
1417
- var addContraindicationSchema = contraindicationSchema;
1418
- var updateContraindicationSchema = contraindicationSchema.partial().extend({
1419
- contraindicationIndex: import_zod5.z.number().min(0)
1420
- });
1421
- var addMedicationSchema = medicationSchema;
1422
- var updateMedicationSchema = medicationSchema.partial().extend({
1423
- medicationIndex: import_zod5.z.number().min(0)
1424
- });
1425
-
1426
- // src/validations/patient.schema.ts
1427
- var locationDataSchema = import_zod6.z.object({
1428
- latitude: import_zod6.z.number().min(-90).max(90),
1429
- longitude: import_zod6.z.number().min(-180).max(180),
1430
- geohash: import_zod6.z.string().optional()
1431
- });
1432
- var addressDataSchema = import_zod6.z.object({
1433
- address: import_zod6.z.string(),
1434
- city: import_zod6.z.string(),
1435
- country: import_zod6.z.string(),
1436
- postalCode: import_zod6.z.string()
1437
- });
1438
- var emergencyContactSchema = import_zod6.z.object({
1439
- name: import_zod6.z.string(),
1440
- relationship: import_zod6.z.string(),
1441
- phoneNumber: import_zod6.z.string(),
1442
- isNotifiable: import_zod6.z.boolean()
1443
- });
1444
- var gamificationSchema = import_zod6.z.object({
1445
- level: import_zod6.z.number(),
1446
- points: import_zod6.z.number()
1447
- });
1448
- var patientLocationInfoSchema = import_zod6.z.object({
1449
- patientId: import_zod6.z.string(),
1450
- userRef: import_zod6.z.string(),
1451
- locationData: locationDataSchema,
1452
- createdAt: import_zod6.z.instanceof(import_firestore3.Timestamp),
1453
- updatedAt: import_zod6.z.instanceof(import_firestore3.Timestamp)
1454
- });
1455
- var createPatientLocationInfoSchema = import_zod6.z.object({
1456
- patientId: import_zod6.z.string(),
1457
- userRef: import_zod6.z.string(),
1458
- locationData: locationDataSchema
1459
- });
1460
- var patientSensitiveInfoSchema = import_zod6.z.object({
1461
- patientId: import_zod6.z.string(),
1462
- userRef: import_zod6.z.string(),
1463
- photoUrl: import_zod6.z.string().optional(),
1464
- firstName: import_zod6.z.string().min(2),
1465
- lastName: import_zod6.z.string().min(2),
1466
- dateOfBirth: import_zod6.z.instanceof(import_firestore3.Timestamp).nullable(),
1467
- gender: import_zod6.z.nativeEnum(Gender),
1468
- email: import_zod6.z.string().email().optional(),
1469
- phoneNumber: import_zod6.z.string().optional(),
1470
- alternativePhoneNumber: import_zod6.z.string().optional(),
1471
- addressData: addressDataSchema.optional(),
1472
- emergencyContacts: import_zod6.z.array(emergencyContactSchema).optional(),
1473
- createdAt: import_zod6.z.instanceof(import_firestore3.Timestamp),
1474
- updatedAt: import_zod6.z.instanceof(import_firestore3.Timestamp)
1475
- });
1476
- var patientDoctorSchema = import_zod6.z.object({
1477
- userRef: import_zod6.z.string(),
1478
- assignedAt: import_zod6.z.instanceof(import_firestore3.Timestamp),
1479
- assignedBy: import_zod6.z.string().optional(),
1480
- isActive: import_zod6.z.boolean(),
1481
- notes: import_zod6.z.string().optional()
1482
- });
1483
- var patientClinicSchema = import_zod6.z.object({
1484
- clinicId: import_zod6.z.string(),
1485
- assignedAt: import_zod6.z.instanceof(import_firestore3.Timestamp),
1486
- assignedBy: import_zod6.z.string().optional(),
1487
- isActive: import_zod6.z.boolean(),
1488
- notes: import_zod6.z.string().optional()
1489
- });
1490
- var patientProfileSchema = import_zod6.z.object({
1491
- id: import_zod6.z.string(),
1492
- userRef: import_zod6.z.string(),
1493
- displayName: import_zod6.z.string(),
1494
- profilePhoto: import_zod6.z.string().url().nullable(),
1495
- gamification: gamificationSchema,
1496
- expoTokens: import_zod6.z.array(import_zod6.z.string()),
1497
- isActive: import_zod6.z.boolean(),
1498
- isVerified: import_zod6.z.boolean(),
1499
- doctors: import_zod6.z.array(patientDoctorSchema),
1500
- clinics: import_zod6.z.array(patientClinicSchema),
1501
- doctorIds: import_zod6.z.array(import_zod6.z.string()),
1502
- clinicIds: import_zod6.z.array(import_zod6.z.string()),
1503
- createdAt: import_zod6.z.instanceof(import_firestore3.Timestamp),
1504
- updatedAt: import_zod6.z.instanceof(import_firestore3.Timestamp)
1505
- });
1506
- var createPatientProfileSchema = import_zod6.z.object({
1507
- userRef: import_zod6.z.string(),
1508
- displayName: import_zod6.z.string(),
1509
- profilePhoto: import_zod6.z.string().url().nullable().optional(),
1510
- expoTokens: import_zod6.z.array(import_zod6.z.string()),
1511
- gamification: gamificationSchema.optional(),
1512
- isActive: import_zod6.z.boolean(),
1513
- isVerified: import_zod6.z.boolean(),
1514
- doctors: import_zod6.z.array(patientDoctorSchema).optional(),
1515
- clinics: import_zod6.z.array(patientClinicSchema).optional(),
1516
- doctorIds: import_zod6.z.array(import_zod6.z.string()).optional(),
1517
- clinicIds: import_zod6.z.array(import_zod6.z.string()).optional()
1518
- });
1519
- var createPatientSensitiveInfoSchema = import_zod6.z.object({
1520
- patientId: import_zod6.z.string(),
1521
- userRef: import_zod6.z.string(),
1522
- photoUrl: import_zod6.z.string().optional(),
1523
- firstName: import_zod6.z.string().min(2),
1524
- lastName: import_zod6.z.string().min(2),
1525
- dateOfBirth: import_zod6.z.instanceof(import_firestore3.Timestamp).nullable(),
1526
- gender: import_zod6.z.nativeEnum(Gender),
1527
- email: import_zod6.z.string().email().optional(),
1528
- phoneNumber: import_zod6.z.string().optional(),
1529
- alternativePhoneNumber: import_zod6.z.string().optional(),
1530
- addressData: addressDataSchema.optional(),
1531
- emergencyContacts: import_zod6.z.array(emergencyContactSchema).optional()
1532
- });
1533
- var searchPatientsSchema = import_zod6.z.object({
1534
- clinicId: import_zod6.z.string().optional(),
1535
- practitionerId: import_zod6.z.string().optional()
1536
- }).refine((data) => data.clinicId || data.practitionerId, {
1537
- message: "At least one of clinicId or practitionerId must be provided",
1538
- path: []
1539
- // Optional: specify a path like ['clinicId'] or ['practitionerId']
1540
- });
1541
- var requesterInfoSchema = import_zod6.z.object({
1542
- id: import_zod6.z.string(),
1543
- role: import_zod6.z.enum(["clinic_admin", "practitioner"]),
1544
- associatedClinicId: import_zod6.z.string().optional(),
1545
- associatedPractitionerId: import_zod6.z.string().optional()
1546
- }).refine(
1547
- (data) => {
1548
- if (data.role === "clinic_admin") {
1549
- return !!data.associatedClinicId;
1550
- } else if (data.role === "practitioner") {
1551
- return !!data.associatedPractitionerId;
1552
- }
1553
- return false;
1554
- },
1555
- {
1556
- message: "Associated ID (clinic or practitioner) is required based on role",
1557
- path: ["associatedClinicId", "associatedPractitionerId"]
1203
+ var MediaAccessLevel = /* @__PURE__ */ ((MediaAccessLevel2) => {
1204
+ MediaAccessLevel2["PUBLIC"] = "public";
1205
+ MediaAccessLevel2["PRIVATE"] = "private";
1206
+ MediaAccessLevel2["CONFIDENTIAL"] = "confidential";
1207
+ return MediaAccessLevel2;
1208
+ })(MediaAccessLevel || {});
1209
+ var MEDIA_METADATA_COLLECTION = "media_metadata";
1210
+ var MediaService = class extends BaseService {
1211
+ constructor(db, auth, app) {
1212
+ super(db, auth, app);
1558
1213
  }
1559
- );
1560
-
1561
- // src/services/patient/utils/docs.utils.ts
1562
- var import_firestore5 = require("firebase/firestore");
1563
-
1564
- // src/services/patient/utils/sensitive.utils.ts
1565
- var import_firestore4 = require("firebase/firestore");
1566
- var import_zod7 = require("zod");
1567
- var createSensitiveInfoUtil = async (db, data, requesterUserId) => {
1568
- try {
1569
- if (data.userRef !== requesterUserId) {
1570
- throw new Error("Only patient can create their sensitive information");
1571
- }
1572
- const validatedData = createPatientSensitiveInfoSchema.parse(data);
1573
- const sensitiveDoc = await (0, import_firestore4.getDoc)(
1574
- getSensitiveInfoDocRef(db, data.patientId)
1575
- );
1576
- if (sensitiveDoc.exists()) {
1577
- throw new Error("Sensitive information already exists for this patient");
1578
- }
1579
- const sensitiveInfoData = {
1580
- ...validatedData,
1581
- createdAt: (0, import_firestore4.serverTimestamp)(),
1582
- updatedAt: (0, import_firestore4.serverTimestamp)()
1583
- };
1584
- await (0, import_firestore4.setDoc)(getSensitiveInfoDocRef(db, data.patientId), sensitiveInfoData);
1585
- const createdDoc = await (0, import_firestore4.getDoc)(getSensitiveInfoDocRef(db, data.patientId));
1586
- if (!createdDoc.exists()) {
1587
- throw new Error("Failed to create sensitive information");
1588
- }
1589
- return createdDoc.data();
1590
- } catch (error) {
1591
- if (error instanceof import_zod7.z.ZodError) {
1592
- throw new Error("Invalid sensitive info data: " + error.message);
1593
- }
1214
+ /**
1215
+ * Upload a media file, store its metadata, and return the metadata including the URL.
1216
+ * @param file - The file to upload.
1217
+ * @param ownerId - ID of the owner (user, patient, clinic, etc.).
1218
+ * @param accessLevel - Access level (public, private, confidential).
1219
+ * @param collectionName - The logical collection name this media belongs to (e.g., 'patient_profile_pictures', 'clinic_logos').
1220
+ * @param originalFileName - Optional: the original name of the file, if not using file.name.
1221
+ * @returns Promise with the media metadata.
1222
+ */
1223
+ async uploadMedia(file, ownerId, accessLevel, collectionName, originalFileName) {
1224
+ const mediaId = this.generateId();
1225
+ const fileNameToUse = originalFileName || (file instanceof File ? file.name : file.toString());
1226
+ const uniqueFileName = `${mediaId}-${fileNameToUse}`;
1227
+ const filePath = `media/${accessLevel}/${ownerId}/${collectionName}/${uniqueFileName}`;
1228
+ console.log(`[MediaService] Uploading file to: ${filePath}`);
1229
+ const storageRef = (0, import_storage3.ref)(this.storage, filePath);
1230
+ try {
1231
+ const uploadResult = await (0, import_storage3.uploadBytes)(storageRef, file, {
1232
+ contentType: file.type
1233
+ });
1234
+ console.log("[MediaService] File uploaded successfully", uploadResult);
1235
+ const downloadURL = await (0, import_storage3.getDownloadURL)(uploadResult.ref);
1236
+ console.log("[MediaService] Got download URL:", downloadURL);
1237
+ const metadata = {
1238
+ id: mediaId,
1239
+ name: fileNameToUse,
1240
+ url: downloadURL,
1241
+ contentType: file.type,
1242
+ size: file.size,
1243
+ createdAt: import_firestore2.Timestamp.now(),
1244
+ accessLevel,
1245
+ ownerId,
1246
+ collectionName,
1247
+ path: filePath
1248
+ };
1249
+ const metadataDocRef = (0, import_firestore3.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1250
+ await (0, import_firestore3.setDoc)(metadataDocRef, metadata);
1251
+ console.log("[MediaService] Metadata stored in Firestore:", mediaId);
1252
+ return metadata;
1253
+ } catch (error) {
1254
+ console.error("[MediaService] Error during media upload:", error);
1255
+ throw error;
1256
+ }
1257
+ }
1258
+ /**
1259
+ * Get media metadata from Firestore by its ID.
1260
+ * @param mediaId - ID of the media.
1261
+ * @returns Promise with the media metadata or null if not found.
1262
+ */
1263
+ async getMediaMetadata(mediaId) {
1264
+ console.log(`[MediaService] Getting media metadata for ID: ${mediaId}`);
1265
+ const docRef = (0, import_firestore3.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1266
+ const docSnap = await (0, import_firestore3.getDoc)(docRef);
1267
+ if (docSnap.exists()) {
1268
+ console.log("[MediaService] Metadata found:", docSnap.data());
1269
+ return docSnap.data();
1270
+ }
1271
+ console.log("[MediaService] No metadata found for ID:", mediaId);
1272
+ return null;
1273
+ }
1274
+ /**
1275
+ * Get media metadata from Firestore by its public URL.
1276
+ * @param url - The public URL of the media file.
1277
+ * @returns Promise with the media metadata or null if not found.
1278
+ */
1279
+ async getMediaMetadataByUrl(url) {
1280
+ console.log(`[MediaService] Getting media metadata by URL: ${url}`);
1281
+ const q = (0, import_firestore3.query)(
1282
+ (0, import_firestore3.collection)(this.db, MEDIA_METADATA_COLLECTION),
1283
+ (0, import_firestore3.where)("url", "==", url),
1284
+ (0, import_firestore3.limit)(1)
1285
+ );
1286
+ try {
1287
+ const querySnapshot = await (0, import_firestore3.getDocs)(q);
1288
+ if (!querySnapshot.empty) {
1289
+ const metadata = querySnapshot.docs[0].data();
1290
+ console.log("[MediaService] Metadata found by URL:", metadata);
1291
+ return metadata;
1292
+ }
1293
+ console.log("[MediaService] No metadata found for URL:", url);
1294
+ return null;
1295
+ } catch (error) {
1296
+ console.error("[MediaService] Error fetching metadata by URL:", error);
1297
+ throw error;
1298
+ }
1299
+ }
1300
+ /**
1301
+ * Delete media from storage and remove metadata from Firestore.
1302
+ * @param mediaId - ID of the media to delete.
1303
+ */
1304
+ async deleteMedia(mediaId) {
1305
+ console.log(`[MediaService] Deleting media with ID: ${mediaId}`);
1306
+ const metadata = await this.getMediaMetadata(mediaId);
1307
+ if (!metadata) {
1308
+ console.warn(
1309
+ `[MediaService] Metadata not found for media ID ${mediaId}. Cannot delete.`
1310
+ );
1311
+ return;
1312
+ }
1313
+ const storageFileRef = (0, import_storage3.ref)(this.storage, metadata.path);
1314
+ try {
1315
+ await (0, import_storage3.deleteObject)(storageFileRef);
1316
+ console.log(`[MediaService] File deleted from Storage: ${metadata.path}`);
1317
+ const metadataDocRef = (0, import_firestore3.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1318
+ await (0, import_firestore3.deleteDoc)(metadataDocRef);
1319
+ console.log(
1320
+ `[MediaService] Metadata deleted from Firestore for ID: ${mediaId}`
1321
+ );
1322
+ } catch (error) {
1323
+ console.error(`[MediaService] Error deleting media ${mediaId}:`, error);
1324
+ throw error;
1325
+ }
1326
+ }
1327
+ /**
1328
+ * Update media access level. This involves moving the file in Firebase Storage
1329
+ * to a new path reflecting the new access level, and updating its metadata.
1330
+ * @param mediaId - ID of the media to update.
1331
+ * @param newAccessLevel - New access level.
1332
+ * @returns Promise with the updated media metadata, or null if metadata not found.
1333
+ */
1334
+ async updateMediaAccessLevel(mediaId, newAccessLevel) {
1335
+ var _a;
1336
+ console.log(
1337
+ `[MediaService] Attempting to update access level for media ID: ${mediaId} to ${newAccessLevel}`
1338
+ );
1339
+ const metadata = await this.getMediaMetadata(mediaId);
1340
+ if (!metadata) {
1341
+ console.warn(
1342
+ `[MediaService] Metadata not found for media ID ${mediaId}. Cannot update access level.`
1343
+ );
1344
+ return null;
1345
+ }
1346
+ if (metadata.accessLevel === newAccessLevel) {
1347
+ console.log(
1348
+ `[MediaService] Media ID ${mediaId} already has access level ${newAccessLevel}. Updating timestamp only.`
1349
+ );
1350
+ const metadataDocRef = (0, import_firestore3.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1351
+ try {
1352
+ await (0, import_firestore3.updateDoc)(metadataDocRef, { updatedAt: import_firestore2.Timestamp.now() });
1353
+ return { ...metadata, updatedAt: import_firestore2.Timestamp.now() };
1354
+ } catch (error) {
1355
+ console.error(
1356
+ `[MediaService] Error updating timestamp for media ID ${mediaId}:`,
1357
+ error
1358
+ );
1359
+ throw error;
1360
+ }
1361
+ }
1362
+ const oldStoragePath = metadata.path;
1363
+ const fileNamePart = `${metadata.id}-${metadata.name}`;
1364
+ const newStoragePath = `media/${newAccessLevel}/${metadata.ownerId}/${metadata.collectionName}/${fileNamePart}`;
1365
+ console.log(
1366
+ `[MediaService] Moving file for ${mediaId} from ${oldStoragePath} to ${newStoragePath}`
1367
+ );
1368
+ const oldStorageFileRef = (0, import_storage3.ref)(this.storage, oldStoragePath);
1369
+ const newStorageFileRef = (0, import_storage3.ref)(this.storage, newStoragePath);
1370
+ try {
1371
+ console.log(`[MediaService] Downloading bytes from ${oldStoragePath}`);
1372
+ const fileBytes = await (0, import_storage3.getBytes)(oldStorageFileRef);
1373
+ console.log(
1374
+ `[MediaService] Successfully downloaded ${fileBytes.byteLength} bytes from ${oldStoragePath}`
1375
+ );
1376
+ console.log(`[MediaService] Uploading bytes to ${newStoragePath}`);
1377
+ await (0, import_storage3.uploadBytes)(newStorageFileRef, fileBytes, {
1378
+ contentType: metadata.contentType
1379
+ });
1380
+ console.log(
1381
+ `[MediaService] Successfully uploaded bytes to ${newStoragePath}`
1382
+ );
1383
+ const newDownloadURL = await (0, import_storage3.getDownloadURL)(newStorageFileRef);
1384
+ console.log(
1385
+ `[MediaService] Got new download URL for ${newStoragePath}: ${newDownloadURL}`
1386
+ );
1387
+ const updateData = {
1388
+ accessLevel: newAccessLevel,
1389
+ path: newStoragePath,
1390
+ url: newDownloadURL,
1391
+ updatedAt: import_firestore2.Timestamp.now()
1392
+ };
1393
+ const metadataDocRef = (0, import_firestore3.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1394
+ console.log(
1395
+ `[MediaService] Updating Firestore metadata for ${mediaId} with new data:`,
1396
+ updateData
1397
+ );
1398
+ await (0, import_firestore3.updateDoc)(metadataDocRef, updateData);
1399
+ console.log(
1400
+ `[MediaService] Successfully updated Firestore metadata for ${mediaId}`
1401
+ );
1402
+ try {
1403
+ console.log(`[MediaService] Deleting old file from ${oldStoragePath}`);
1404
+ await (0, import_storage3.deleteObject)(oldStorageFileRef);
1405
+ console.log(
1406
+ `[MediaService] Successfully deleted old file from ${oldStoragePath}`
1407
+ );
1408
+ } catch (deleteError) {
1409
+ console.error(
1410
+ `[MediaService] Failed to delete old file from ${oldStoragePath} for media ID ${mediaId}. This file is now orphaned. Error:`,
1411
+ deleteError
1412
+ );
1413
+ }
1414
+ return { ...metadata, ...updateData };
1415
+ } catch (error) {
1416
+ console.error(
1417
+ `[MediaService] Error updating media access level and moving file for ${mediaId}:`,
1418
+ error
1419
+ );
1420
+ if (newStorageFileRef && error.code !== "storage/object-not-found" && ((_a = error.message) == null ? void 0 : _a.includes("uploadBytes"))) {
1421
+ console.warn(
1422
+ `[MediaService] Attempting to delete partially uploaded file at ${newStoragePath} due to error.`
1423
+ );
1424
+ try {
1425
+ await (0, import_storage3.deleteObject)(newStorageFileRef);
1426
+ console.warn(
1427
+ `[MediaService] Cleaned up partially uploaded file at ${newStoragePath}.`
1428
+ );
1429
+ } catch (cleanupError) {
1430
+ console.error(
1431
+ `[MediaService] Failed to cleanup partially uploaded file at ${newStoragePath}:`,
1432
+ cleanupError
1433
+ );
1434
+ }
1435
+ }
1436
+ throw error;
1437
+ }
1438
+ }
1439
+ /**
1440
+ * List all media for an owner, optionally filtered by collection and access level.
1441
+ * @param ownerId - ID of the owner.
1442
+ * @param collectionName - Optional: Filter by collection name.
1443
+ * @param accessLevel - Optional: Filter by access level.
1444
+ * @param count - Optional: Number of items to fetch.
1445
+ * @param startAfterId - Optional: ID of the document to start after (for pagination).
1446
+ */
1447
+ async listMedia(ownerId, collectionName, accessLevel, count, startAfterId) {
1448
+ console.log(`[MediaService] Listing media for owner: ${ownerId}`);
1449
+ let qConstraints = [(0, import_firestore3.where)("ownerId", "==", ownerId)];
1450
+ if (collectionName) {
1451
+ qConstraints.push((0, import_firestore3.where)("collectionName", "==", collectionName));
1452
+ }
1453
+ if (accessLevel) {
1454
+ qConstraints.push((0, import_firestore3.where)("accessLevel", "==", accessLevel));
1455
+ }
1456
+ qConstraints.push((0, import_firestore3.orderBy)("createdAt", "desc"));
1457
+ if (count) {
1458
+ qConstraints.push((0, import_firestore3.limit)(count));
1459
+ }
1460
+ if (startAfterId) {
1461
+ const startAfterDoc = await this.getMediaMetadata(startAfterId);
1462
+ if (startAfterDoc) {
1463
+ }
1464
+ }
1465
+ const finalQuery = (0, import_firestore3.query)(
1466
+ (0, import_firestore3.collection)(this.db, MEDIA_METADATA_COLLECTION),
1467
+ ...qConstraints
1468
+ );
1469
+ try {
1470
+ const querySnapshot = await (0, import_firestore3.getDocs)(finalQuery);
1471
+ const mediaList = querySnapshot.docs.map(
1472
+ (doc34) => doc34.data()
1473
+ );
1474
+ console.log(`[MediaService] Found ${mediaList.length} media items.`);
1475
+ return mediaList;
1476
+ } catch (error) {
1477
+ console.error("[MediaService] Error listing media:", error);
1478
+ throw error;
1479
+ }
1480
+ }
1481
+ /**
1482
+ * Get download URL for media. (Convenience, as URL is in metadata)
1483
+ * @param mediaId - ID of the media.
1484
+ */
1485
+ async getMediaDownloadUrl(mediaId) {
1486
+ console.log(`[MediaService] Getting download URL for media ID: ${mediaId}`);
1487
+ const metadata = await this.getMediaMetadata(mediaId);
1488
+ if (metadata && metadata.url) {
1489
+ console.log(`[MediaService] URL found: ${metadata.url}`);
1490
+ return metadata.url;
1491
+ }
1492
+ console.log(`[MediaService] URL not found for media ID: ${mediaId}`);
1493
+ return null;
1494
+ }
1495
+ };
1496
+
1497
+ // src/services/patient/utils/profile.utils.ts
1498
+ var import_firestore10 = require("firebase/firestore");
1499
+ var import_zod9 = require("zod");
1500
+
1501
+ // src/types/patient/medical-info.types.ts
1502
+ var PATIENT_MEDICAL_INFO_COLLECTION = "medical_info";
1503
+ var DEFAULT_MEDICAL_INFO = {
1504
+ vitalStats: {},
1505
+ blockingConditions: [],
1506
+ contraindications: [],
1507
+ allergies: [],
1508
+ currentMedications: []
1509
+ };
1510
+
1511
+ // src/types/patient/index.ts
1512
+ var PATIENTS_COLLECTION = "patients";
1513
+ var PATIENT_SENSITIVE_INFO_COLLECTION = "sensitive-info";
1514
+ var PATIENT_MEDICAL_HISTORY_COLLECTION = "medical-history";
1515
+ var PATIENT_APPOINTMENTS_COLLECTION = "appointments";
1516
+ var PATIENT_LOCATION_INFO_COLLECTION = "location-info";
1517
+ var Gender = /* @__PURE__ */ ((Gender2) => {
1518
+ Gender2["MALE"] = "male";
1519
+ Gender2["FEMALE"] = "female";
1520
+ Gender2["TRANSGENDER_MALE"] = "transgender_male";
1521
+ Gender2["TRANSGENDER_FEMALE"] = "transgender_female";
1522
+ Gender2["PREFER_NOT_TO_SAY"] = "prefer_not_to_say";
1523
+ Gender2["OTHER"] = "other";
1524
+ return Gender2;
1525
+ })(Gender || {});
1526
+
1527
+ // src/validations/patient.schema.ts
1528
+ var import_zod7 = require("zod");
1529
+ var import_firestore5 = require("firebase/firestore");
1530
+
1531
+ // src/validations/media.schema.ts
1532
+ var import_zod4 = require("zod");
1533
+ var mediaResourceSchema = import_zod4.z.union([
1534
+ import_zod4.z.string().url(),
1535
+ import_zod4.z.instanceof(File),
1536
+ import_zod4.z.instanceof(Blob)
1537
+ ]);
1538
+
1539
+ // src/validations/patient/medical-info.schema.ts
1540
+ var import_zod6 = require("zod");
1541
+
1542
+ // src/types/patient/allergies.ts
1543
+ var AllergyType = /* @__PURE__ */ ((AllergyType2) => {
1544
+ AllergyType2["MEDICATION"] = "medication";
1545
+ AllergyType2["FOOD"] = "food";
1546
+ AllergyType2["ENVIRONMENTAL"] = "environmental";
1547
+ AllergyType2["LATEX"] = "latex";
1548
+ AllergyType2["COSMETIC"] = "cosmetic";
1549
+ AllergyType2["OTHER"] = "other";
1550
+ return AllergyType2;
1551
+ })(AllergyType || {});
1552
+ var MedicationAllergySubtype = /* @__PURE__ */ ((MedicationAllergySubtype2) => {
1553
+ MedicationAllergySubtype2["ANTIBIOTICS"] = "antibiotics";
1554
+ MedicationAllergySubtype2["NSAIDS"] = "nsaids";
1555
+ MedicationAllergySubtype2["OPIOIDS"] = "opioids";
1556
+ MedicationAllergySubtype2["ANESTHETICS"] = "anesthetics";
1557
+ MedicationAllergySubtype2["VACCINES"] = "vaccines";
1558
+ MedicationAllergySubtype2["OTHER"] = "other";
1559
+ return MedicationAllergySubtype2;
1560
+ })(MedicationAllergySubtype || {});
1561
+ var FoodAllergySubtype = /* @__PURE__ */ ((FoodAllergySubtype2) => {
1562
+ FoodAllergySubtype2["NUTS"] = "nuts";
1563
+ FoodAllergySubtype2["SHELLFISH"] = "shellfish";
1564
+ FoodAllergySubtype2["DAIRY"] = "dairy";
1565
+ FoodAllergySubtype2["EGGS"] = "eggs";
1566
+ FoodAllergySubtype2["WHEAT"] = "wheat";
1567
+ FoodAllergySubtype2["SOY"] = "soy";
1568
+ FoodAllergySubtype2["FISH"] = "fish";
1569
+ FoodAllergySubtype2["FRUITS"] = "fruits";
1570
+ FoodAllergySubtype2["OTHER"] = "other";
1571
+ return FoodAllergySubtype2;
1572
+ })(FoodAllergySubtype || {});
1573
+ var EnvironmentalAllergySubtype = /* @__PURE__ */ ((EnvironmentalAllergySubtype2) => {
1574
+ EnvironmentalAllergySubtype2["POLLEN"] = "pollen";
1575
+ EnvironmentalAllergySubtype2["DUST"] = "dust";
1576
+ EnvironmentalAllergySubtype2["MOLD"] = "mold";
1577
+ EnvironmentalAllergySubtype2["PET_DANDER"] = "pet_dander";
1578
+ EnvironmentalAllergySubtype2["INSECTS"] = "insects";
1579
+ EnvironmentalAllergySubtype2["OTHER"] = "other";
1580
+ return EnvironmentalAllergySubtype2;
1581
+ })(EnvironmentalAllergySubtype || {});
1582
+ var CosmeticAllergySubtype = /* @__PURE__ */ ((CosmeticAllergySubtype2) => {
1583
+ CosmeticAllergySubtype2["FRAGRANCES"] = "fragrances";
1584
+ CosmeticAllergySubtype2["PRESERVATIVES"] = "preservatives";
1585
+ CosmeticAllergySubtype2["DYES"] = "dyes";
1586
+ CosmeticAllergySubtype2["METALS"] = "metals";
1587
+ CosmeticAllergySubtype2["OTHER"] = "other";
1588
+ return CosmeticAllergySubtype2;
1589
+ })(CosmeticAllergySubtype || {});
1590
+
1591
+ // src/backoffice/types/static/blocking-condition.types.ts
1592
+ var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
1593
+ BlockingCondition2["PREGNANCY"] = "pregnancy";
1594
+ BlockingCondition2["BREASTFEEDING"] = "breastfeeding";
1595
+ BlockingCondition2["ACTIVE_INFECTION"] = "active_infection";
1596
+ BlockingCondition2["SKIN_CONDITION"] = "skin_condition";
1597
+ BlockingCondition2["AUTOIMMUNE_DISEASE"] = "autoimmune_disease";
1598
+ BlockingCondition2["BLOOD_THINNERS"] = "blood_thinners";
1599
+ BlockingCondition2["RECENT_SURGERY"] = "recent_surgery";
1600
+ BlockingCondition2["DIABETES"] = "diabetes";
1601
+ BlockingCondition2["HEART_CONDITION"] = "heart_condition";
1602
+ BlockingCondition2["HIGH_BLOOD_PRESSURE"] = "high_blood_pressure";
1603
+ BlockingCondition2["KELOID_SCARRING"] = "keloid_scarring";
1604
+ BlockingCondition2["METAL_IMPLANTS"] = "metal_implants";
1605
+ BlockingCondition2["PACEMAKER"] = "pacemaker";
1606
+ BlockingCondition2["CANCER"] = "cancer";
1607
+ BlockingCondition2["EPILEPSY"] = "epilepsy";
1608
+ return BlockingCondition2;
1609
+ })(BlockingCondition || {});
1610
+
1611
+ // src/backoffice/types/static/contraindication.types.ts
1612
+ var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
1613
+ Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
1614
+ Contraindication2["RECENT_TANNING"] = "recent_tanning";
1615
+ Contraindication2["RECENT_BOTOX"] = "recent_botox";
1616
+ Contraindication2["RECENT_FILLERS"] = "recent_fillers";
1617
+ Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
1618
+ Contraindication2["MEDICATIONS"] = "medications";
1619
+ Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
1620
+ Contraindication2["RECENT_LASER"] = "recent_laser";
1621
+ Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
1622
+ Contraindication2["OPEN_WOUNDS"] = "open_wounds";
1623
+ Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
1624
+ Contraindication2["COLD_SORES"] = "cold_sores";
1625
+ return Contraindication2;
1626
+ })(Contraindication || {});
1627
+
1628
+ // src/validations/common.schema.ts
1629
+ var import_zod5 = require("zod");
1630
+ var import_firestore4 = require("firebase/firestore");
1631
+ var timestampSchema2 = import_zod5.z.union([
1632
+ import_zod5.z.object({
1633
+ seconds: import_zod5.z.number(),
1634
+ nanoseconds: import_zod5.z.number()
1635
+ }),
1636
+ import_zod5.z.instanceof(import_firestore4.Timestamp)
1637
+ ]).transform((data) => {
1638
+ if (data instanceof import_firestore4.Timestamp) {
1639
+ return data;
1640
+ }
1641
+ return new import_firestore4.Timestamp(data.seconds, data.nanoseconds);
1642
+ });
1643
+
1644
+ // src/validations/patient/medical-info.schema.ts
1645
+ var allergySubtypeSchema = import_zod6.z.union([
1646
+ import_zod6.z.nativeEnum(MedicationAllergySubtype),
1647
+ import_zod6.z.nativeEnum(FoodAllergySubtype),
1648
+ import_zod6.z.nativeEnum(EnvironmentalAllergySubtype),
1649
+ import_zod6.z.nativeEnum(CosmeticAllergySubtype),
1650
+ import_zod6.z.literal("other")
1651
+ ]);
1652
+ var allergySchema = import_zod6.z.object({
1653
+ type: import_zod6.z.nativeEnum(AllergyType),
1654
+ subtype: allergySubtypeSchema,
1655
+ name: import_zod6.z.string().optional().nullable(),
1656
+ severity: import_zod6.z.enum(["mild", "moderate", "severe"]).optional(),
1657
+ reaction: import_zod6.z.string().optional().nullable(),
1658
+ diagnosed: timestampSchema2.optional().nullable(),
1659
+ notes: import_zod6.z.string().optional().nullable()
1660
+ });
1661
+ var vitalStatsSchema = import_zod6.z.object({
1662
+ height: import_zod6.z.number().positive().optional(),
1663
+ weight: import_zod6.z.number().positive().optional(),
1664
+ bloodType: import_zod6.z.enum(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]).optional(),
1665
+ bloodPressure: import_zod6.z.object({
1666
+ systolic: import_zod6.z.number().min(70).max(200),
1667
+ diastolic: import_zod6.z.number().min(40).max(130),
1668
+ lastMeasured: timestampSchema2
1669
+ }).optional()
1670
+ });
1671
+ var blockingConditionSchema = import_zod6.z.object({
1672
+ condition: import_zod6.z.nativeEnum(BlockingCondition),
1673
+ diagnosedAt: timestampSchema2,
1674
+ notes: import_zod6.z.string().optional().nullable(),
1675
+ isActive: import_zod6.z.boolean()
1676
+ });
1677
+ var contraindicationSchema = import_zod6.z.object({
1678
+ condition: import_zod6.z.nativeEnum(Contraindication),
1679
+ lastOccurrence: timestampSchema2,
1680
+ frequency: import_zod6.z.enum(["rare", "occasional", "frequent"]),
1681
+ notes: import_zod6.z.string().optional().nullable(),
1682
+ isActive: import_zod6.z.boolean()
1683
+ });
1684
+ var medicationSchema = import_zod6.z.object({
1685
+ name: import_zod6.z.string().min(1),
1686
+ dosage: import_zod6.z.string().min(1),
1687
+ frequency: import_zod6.z.string().min(1),
1688
+ startDate: timestampSchema2.optional().nullable(),
1689
+ endDate: timestampSchema2.optional().nullable(),
1690
+ prescribedBy: import_zod6.z.string().optional().nullable()
1691
+ });
1692
+ var patientMedicalInfoSchema = import_zod6.z.object({
1693
+ patientId: import_zod6.z.string(),
1694
+ vitalStats: vitalStatsSchema,
1695
+ blockingConditions: import_zod6.z.array(blockingConditionSchema),
1696
+ contraindications: import_zod6.z.array(contraindicationSchema),
1697
+ allergies: import_zod6.z.array(allergySchema),
1698
+ currentMedications: import_zod6.z.array(medicationSchema),
1699
+ emergencyNotes: import_zod6.z.string().optional(),
1700
+ lastUpdated: timestampSchema2,
1701
+ updatedBy: import_zod6.z.string(),
1702
+ verifiedBy: import_zod6.z.string().optional(),
1703
+ verifiedAt: timestampSchema2.optional()
1704
+ });
1705
+ var createPatientMedicalInfoSchema = patientMedicalInfoSchema.omit({
1706
+ patientId: true,
1707
+ lastUpdated: true,
1708
+ updatedBy: true,
1709
+ verifiedBy: true,
1710
+ verifiedAt: true
1711
+ });
1712
+ var updatePatientMedicalInfoSchema = createPatientMedicalInfoSchema.partial();
1713
+ var updateVitalStatsSchema = vitalStatsSchema;
1714
+ var addAllergySchema = allergySchema;
1715
+ var updateAllergySchema = allergySchema.partial().extend({
1716
+ allergyIndex: import_zod6.z.number().min(0)
1717
+ });
1718
+ var addBlockingConditionSchema = blockingConditionSchema;
1719
+ var updateBlockingConditionSchema = blockingConditionSchema.partial().extend({
1720
+ conditionIndex: import_zod6.z.number().min(0)
1721
+ });
1722
+ var addContraindicationSchema = contraindicationSchema;
1723
+ var updateContraindicationSchema = contraindicationSchema.partial().extend({
1724
+ contraindicationIndex: import_zod6.z.number().min(0)
1725
+ });
1726
+ var addMedicationSchema = medicationSchema;
1727
+ var updateMedicationSchema = medicationSchema.partial().extend({
1728
+ medicationIndex: import_zod6.z.number().min(0)
1729
+ });
1730
+
1731
+ // src/validations/patient.schema.ts
1732
+ var locationDataSchema = import_zod7.z.object({
1733
+ latitude: import_zod7.z.number().min(-90).max(90),
1734
+ longitude: import_zod7.z.number().min(-180).max(180),
1735
+ geohash: import_zod7.z.string().optional()
1736
+ });
1737
+ var addressDataSchema = import_zod7.z.object({
1738
+ address: import_zod7.z.string(),
1739
+ city: import_zod7.z.string(),
1740
+ country: import_zod7.z.string(),
1741
+ postalCode: import_zod7.z.string()
1742
+ });
1743
+ var emergencyContactSchema = import_zod7.z.object({
1744
+ name: import_zod7.z.string(),
1745
+ relationship: import_zod7.z.string(),
1746
+ phoneNumber: import_zod7.z.string(),
1747
+ isNotifiable: import_zod7.z.boolean()
1748
+ });
1749
+ var gamificationSchema = import_zod7.z.object({
1750
+ level: import_zod7.z.number(),
1751
+ points: import_zod7.z.number()
1752
+ });
1753
+ var patientLocationInfoSchema = import_zod7.z.object({
1754
+ patientId: import_zod7.z.string(),
1755
+ userRef: import_zod7.z.string(),
1756
+ locationData: locationDataSchema,
1757
+ createdAt: import_zod7.z.instanceof(import_firestore5.Timestamp),
1758
+ updatedAt: import_zod7.z.instanceof(import_firestore5.Timestamp)
1759
+ });
1760
+ var createPatientLocationInfoSchema = import_zod7.z.object({
1761
+ patientId: import_zod7.z.string(),
1762
+ userRef: import_zod7.z.string(),
1763
+ locationData: locationDataSchema
1764
+ });
1765
+ var patientSensitiveInfoSchema = import_zod7.z.object({
1766
+ patientId: import_zod7.z.string(),
1767
+ userRef: import_zod7.z.string(),
1768
+ firstName: import_zod7.z.string().min(2),
1769
+ lastName: import_zod7.z.string().min(2),
1770
+ dateOfBirth: import_zod7.z.instanceof(import_firestore5.Timestamp).nullable(),
1771
+ gender: import_zod7.z.nativeEnum(Gender),
1772
+ email: import_zod7.z.string().email().optional(),
1773
+ phoneNumber: import_zod7.z.string().optional(),
1774
+ alternativePhoneNumber: import_zod7.z.string().optional(),
1775
+ addressData: addressDataSchema.optional(),
1776
+ emergencyContacts: import_zod7.z.array(emergencyContactSchema).optional(),
1777
+ createdAt: import_zod7.z.instanceof(import_firestore5.Timestamp),
1778
+ updatedAt: import_zod7.z.instanceof(import_firestore5.Timestamp)
1779
+ });
1780
+ var patientDoctorSchema = import_zod7.z.object({
1781
+ userRef: import_zod7.z.string(),
1782
+ assignedAt: import_zod7.z.instanceof(import_firestore5.Timestamp),
1783
+ assignedBy: import_zod7.z.string().optional(),
1784
+ isActive: import_zod7.z.boolean(),
1785
+ notes: import_zod7.z.string().optional()
1786
+ });
1787
+ var patientClinicSchema = import_zod7.z.object({
1788
+ clinicId: import_zod7.z.string(),
1789
+ assignedAt: import_zod7.z.instanceof(import_firestore5.Timestamp),
1790
+ assignedBy: import_zod7.z.string().optional(),
1791
+ isActive: import_zod7.z.boolean(),
1792
+ notes: import_zod7.z.string().optional()
1793
+ });
1794
+ var patientProfileSchema = import_zod7.z.object({
1795
+ id: import_zod7.z.string(),
1796
+ userRef: import_zod7.z.string(),
1797
+ displayName: import_zod7.z.string(),
1798
+ gamification: gamificationSchema,
1799
+ expoTokens: import_zod7.z.array(import_zod7.z.string()),
1800
+ isActive: import_zod7.z.boolean(),
1801
+ isVerified: import_zod7.z.boolean(),
1802
+ phoneNumber: import_zod7.z.string().nullable().optional(),
1803
+ dateOfBirth: import_zod7.z.instanceof(import_firestore5.Timestamp).nullable().optional(),
1804
+ doctors: import_zod7.z.array(patientDoctorSchema),
1805
+ clinics: import_zod7.z.array(patientClinicSchema),
1806
+ doctorIds: import_zod7.z.array(import_zod7.z.string()),
1807
+ clinicIds: import_zod7.z.array(import_zod7.z.string()),
1808
+ createdAt: import_zod7.z.instanceof(import_firestore5.Timestamp),
1809
+ updatedAt: import_zod7.z.instanceof(import_firestore5.Timestamp)
1810
+ });
1811
+ var createPatientProfileSchema = import_zod7.z.object({
1812
+ userRef: import_zod7.z.string(),
1813
+ displayName: import_zod7.z.string(),
1814
+ expoTokens: import_zod7.z.array(import_zod7.z.string()),
1815
+ gamification: gamificationSchema.optional(),
1816
+ isActive: import_zod7.z.boolean(),
1817
+ isVerified: import_zod7.z.boolean(),
1818
+ doctors: import_zod7.z.array(patientDoctorSchema).optional(),
1819
+ clinics: import_zod7.z.array(patientClinicSchema).optional(),
1820
+ doctorIds: import_zod7.z.array(import_zod7.z.string()).optional(),
1821
+ clinicIds: import_zod7.z.array(import_zod7.z.string()).optional()
1822
+ });
1823
+ var createPatientSensitiveInfoSchema = import_zod7.z.object({
1824
+ patientId: import_zod7.z.string(),
1825
+ userRef: import_zod7.z.string(),
1826
+ photoUrl: mediaResourceSchema.nullable().optional(),
1827
+ firstName: import_zod7.z.string().min(2),
1828
+ lastName: import_zod7.z.string().min(2),
1829
+ dateOfBirth: import_zod7.z.instanceof(import_firestore5.Timestamp).nullable(),
1830
+ gender: import_zod7.z.nativeEnum(Gender),
1831
+ email: import_zod7.z.string().email().optional(),
1832
+ phoneNumber: import_zod7.z.string().optional(),
1833
+ alternativePhoneNumber: import_zod7.z.string().optional(),
1834
+ addressData: addressDataSchema.optional(),
1835
+ emergencyContacts: import_zod7.z.array(emergencyContactSchema).optional()
1836
+ });
1837
+ var searchPatientsSchema = import_zod7.z.object({
1838
+ clinicId: import_zod7.z.string().optional(),
1839
+ practitionerId: import_zod7.z.string().optional()
1840
+ }).refine((data) => data.clinicId || data.practitionerId, {
1841
+ message: "At least one of clinicId or practitionerId must be provided",
1842
+ path: []
1843
+ // Optional: specify a path like ['clinicId'] or ['practitionerId']
1844
+ });
1845
+ var requesterInfoSchema = import_zod7.z.object({
1846
+ id: import_zod7.z.string(),
1847
+ role: import_zod7.z.enum(["clinic_admin", "practitioner"]),
1848
+ associatedClinicId: import_zod7.z.string().optional(),
1849
+ associatedPractitionerId: import_zod7.z.string().optional()
1850
+ }).refine(
1851
+ (data) => {
1852
+ if (data.role === "clinic_admin") {
1853
+ return !!data.associatedClinicId;
1854
+ } else if (data.role === "practitioner") {
1855
+ return !!data.associatedPractitionerId;
1856
+ }
1857
+ return false;
1858
+ },
1859
+ {
1860
+ message: "Associated ID (clinic or practitioner) is required based on role",
1861
+ path: ["associatedClinicId", "associatedPractitionerId"]
1862
+ }
1863
+ );
1864
+
1865
+ // src/services/patient/utils/docs.utils.ts
1866
+ var import_firestore7 = require("firebase/firestore");
1867
+
1868
+ // src/services/patient/utils/sensitive.utils.ts
1869
+ var import_firestore6 = require("firebase/firestore");
1870
+ var import_zod8 = require("zod");
1871
+ var handlePhotoUrlUpload = async (photoUrl, patientId, mediaService) => {
1872
+ if (!photoUrl) {
1873
+ return null;
1874
+ }
1875
+ if (typeof photoUrl === "string") {
1876
+ return photoUrl;
1877
+ }
1878
+ if (photoUrl instanceof File || photoUrl instanceof Blob) {
1879
+ const mediaMetadata = await mediaService.uploadMedia(
1880
+ photoUrl,
1881
+ patientId,
1882
+ // Using patientId as ownerId
1883
+ "private" /* PRIVATE */,
1884
+ // Sensitive info should be private
1885
+ "patient_sensitive_photos",
1886
+ photoUrl instanceof File ? photoUrl.name : `sensitive_photo_${patientId}`
1887
+ );
1888
+ return mediaMetadata.url;
1889
+ }
1890
+ return null;
1891
+ };
1892
+ var createSensitiveInfoUtil = async (db, data, requesterUserId, mediaService) => {
1893
+ try {
1894
+ if (data.userRef !== requesterUserId) {
1895
+ throw new Error("Only patient can create their sensitive information");
1896
+ }
1897
+ const validatedData = createPatientSensitiveInfoSchema.parse(data);
1898
+ const sensitiveDoc = await (0, import_firestore6.getDoc)(
1899
+ getSensitiveInfoDocRef(db, data.patientId)
1900
+ );
1901
+ if (sensitiveDoc.exists()) {
1902
+ throw new Error("Sensitive information already exists for this patient");
1903
+ }
1904
+ let processedPhotoUrl = null;
1905
+ if (validatedData.photoUrl && mediaService) {
1906
+ processedPhotoUrl = await handlePhotoUrlUpload(
1907
+ validatedData.photoUrl,
1908
+ data.patientId,
1909
+ mediaService
1910
+ );
1911
+ } else if (typeof validatedData.photoUrl === "string") {
1912
+ processedPhotoUrl = validatedData.photoUrl;
1913
+ }
1914
+ const sensitiveInfoData = {
1915
+ ...validatedData,
1916
+ photoUrl: processedPhotoUrl,
1917
+ createdAt: (0, import_firestore6.serverTimestamp)(),
1918
+ updatedAt: (0, import_firestore6.serverTimestamp)()
1919
+ };
1920
+ await (0, import_firestore6.setDoc)(getSensitiveInfoDocRef(db, data.patientId), sensitiveInfoData);
1921
+ const createdDoc = await (0, import_firestore6.getDoc)(getSensitiveInfoDocRef(db, data.patientId));
1922
+ if (!createdDoc.exists()) {
1923
+ throw new Error("Failed to create sensitive information");
1924
+ }
1925
+ return createdDoc.data();
1926
+ } catch (error) {
1927
+ if (error instanceof import_zod8.z.ZodError) {
1928
+ throw new Error("Invalid sensitive info data: " + error.message);
1929
+ }
1594
1930
  throw error;
1595
1931
  }
1596
1932
  };
1597
1933
  var getSensitiveInfoUtil = async (db, patientId, requesterUserId) => {
1598
1934
  await initSensitiveInfoDocIfNotExists(db, patientId, requesterUserId);
1599
- const sensitiveDoc = await (0, import_firestore4.getDoc)(getSensitiveInfoDocRef(db, patientId));
1935
+ const sensitiveDoc = await (0, import_firestore6.getDoc)(getSensitiveInfoDocRef(db, patientId));
1600
1936
  return sensitiveDoc.exists() ? sensitiveDoc.data() : null;
1601
1937
  };
1602
- var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId) => {
1938
+ var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId, mediaService) => {
1603
1939
  await initSensitiveInfoDocIfNotExists(db, patientId, requesterUserId);
1940
+ let processedPhotoUrl = void 0;
1941
+ if (data.photoUrl !== void 0) {
1942
+ if (mediaService) {
1943
+ processedPhotoUrl = await handlePhotoUrlUpload(
1944
+ data.photoUrl,
1945
+ patientId,
1946
+ mediaService
1947
+ );
1948
+ } else if (typeof data.photoUrl === "string" || data.photoUrl === null) {
1949
+ processedPhotoUrl = data.photoUrl;
1950
+ } else {
1951
+ throw new Error("MediaService required to process photo upload");
1952
+ }
1953
+ }
1604
1954
  const updateData = {
1605
1955
  ...data,
1606
- updatedAt: (0, import_firestore4.serverTimestamp)()
1956
+ photoUrl: processedPhotoUrl,
1957
+ updatedAt: (0, import_firestore6.serverTimestamp)()
1607
1958
  };
1608
- await (0, import_firestore4.updateDoc)(getSensitiveInfoDocRef(db, patientId), updateData);
1609
- const updatedDoc = await (0, import_firestore4.getDoc)(getSensitiveInfoDocRef(db, patientId));
1959
+ await (0, import_firestore6.updateDoc)(getSensitiveInfoDocRef(db, patientId), updateData);
1960
+ const updatedDoc = await (0, import_firestore6.getDoc)(getSensitiveInfoDocRef(db, patientId));
1610
1961
  if (!updatedDoc.exists()) {
1611
1962
  throw new Error("Failed to retrieve updated sensitive information");
1612
1963
  }
@@ -1615,21 +1966,21 @@ var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId) => {
1615
1966
 
1616
1967
  // src/services/patient/utils/docs.utils.ts
1617
1968
  var getPatientDocRef = (db, patientId) => {
1618
- return (0, import_firestore5.doc)(db, PATIENTS_COLLECTION, patientId);
1969
+ return (0, import_firestore7.doc)(db, PATIENTS_COLLECTION, patientId);
1619
1970
  };
1620
1971
  var getPatientDocRefByUserRef = async (db, userRef) => {
1621
- const patientsRef = (0, import_firestore5.collection)(db, PATIENTS_COLLECTION);
1622
- const q = (0, import_firestore5.query)(patientsRef, (0, import_firestore5.where)("userRef", "==", userRef));
1623
- const querySnapshot = await (0, import_firestore5.getDocs)(q);
1972
+ const patientsRef = (0, import_firestore7.collection)(db, PATIENTS_COLLECTION);
1973
+ const q = (0, import_firestore7.query)(patientsRef, (0, import_firestore7.where)("userRef", "==", userRef));
1974
+ const querySnapshot = await (0, import_firestore7.getDocs)(q);
1624
1975
  if (querySnapshot.empty) {
1625
1976
  throw new Error("Patient profile not found");
1626
1977
  }
1627
- return (0, import_firestore5.doc)(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
1978
+ return (0, import_firestore7.doc)(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
1628
1979
  };
1629
1980
  var getSensitiveInfoDocRef = (db, patientId) => {
1630
1981
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_SENSITIVE_INFO_COLLECTION}/${patientId}`;
1631
1982
  console.log(`[getSensitiveInfoDocRef] Creating reference with path: ${path}`);
1632
- return (0, import_firestore5.doc)(
1983
+ return (0, import_firestore7.doc)(
1633
1984
  db,
1634
1985
  PATIENTS_COLLECTION,
1635
1986
  patientId,
@@ -1640,7 +1991,7 @@ var getSensitiveInfoDocRef = (db, patientId) => {
1640
1991
  var getLocationInfoDocRef = (db, patientId) => {
1641
1992
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_LOCATION_INFO_COLLECTION}/${patientId}`;
1642
1993
  console.log(`[getLocationInfoDocRef] Creating reference with path: ${path}`);
1643
- return (0, import_firestore5.doc)(
1994
+ return (0, import_firestore7.doc)(
1644
1995
  db,
1645
1996
  PATIENTS_COLLECTION,
1646
1997
  patientId,
@@ -1651,7 +2002,7 @@ var getLocationInfoDocRef = (db, patientId) => {
1651
2002
  var getMedicalInfoDocRef = (db, patientId) => {
1652
2003
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_MEDICAL_INFO_COLLECTION}/${patientId}`;
1653
2004
  console.log(`[getMedicalInfoDocRef] Creating reference with path: ${path}`);
1654
- return (0, import_firestore5.doc)(
2005
+ return (0, import_firestore7.doc)(
1655
2006
  db,
1656
2007
  PATIENTS_COLLECTION,
1657
2008
  patientId,
@@ -1668,7 +2019,7 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1668
2019
  console.log(
1669
2020
  `[initSensitiveInfoDocIfNotExists] Got document reference: ${sensitiveInfoRef.path}`
1670
2021
  );
1671
- const sensitiveDoc = await (0, import_firestore5.getDoc)(sensitiveInfoRef);
2022
+ const sensitiveDoc = await (0, import_firestore7.getDoc)(sensitiveInfoRef);
1672
2023
  console.log(
1673
2024
  `[initSensitiveInfoDocIfNotExists] Document exists: ${sensitiveDoc.exists()}`
1674
2025
  );
@@ -1692,7 +2043,7 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1692
2043
  )
1693
2044
  );
1694
2045
  await createSensitiveInfoUtil(db, defaultSensitiveInfo, userRef);
1695
- const verifyDoc = await (0, import_firestore5.getDoc)(sensitiveInfoRef);
2046
+ const verifyDoc = await (0, import_firestore7.getDoc)(sensitiveInfoRef);
1696
2047
  console.log(
1697
2048
  `[initSensitiveInfoDocIfNotExists] Verification - document exists: ${verifyDoc.exists()}`
1698
2049
  );
@@ -1709,10 +2060,10 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1709
2060
  };
1710
2061
 
1711
2062
  // src/services/patient/utils/medical.utils.ts
1712
- var import_firestore7 = require("firebase/firestore");
2063
+ var import_firestore9 = require("firebase/firestore");
1713
2064
 
1714
2065
  // src/services/patient/utils/practitioner.utils.ts
1715
- var import_firestore6 = require("firebase/firestore");
2066
+ var import_firestore8 = require("firebase/firestore");
1716
2067
 
1717
2068
  // src/types/practitioner/index.ts
1718
2069
  var PRACTITIONERS_COLLECTION = "practitioners";
@@ -1737,23 +2088,23 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
1737
2088
  `[getPatientsByPractitionerUtil] Fetching patients for practitioner ID: ${practitionerId} with options:`,
1738
2089
  options
1739
2090
  );
1740
- const patientsCollection = (0, import_firestore6.collection)(db, PATIENTS_COLLECTION);
2091
+ const patientsCollection = (0, import_firestore8.collection)(db, PATIENTS_COLLECTION);
1741
2092
  const constraints = [
1742
- (0, import_firestore6.where)("doctorIds", "array-contains", practitionerId)
2093
+ (0, import_firestore8.where)("doctorIds", "array-contains", practitionerId)
1743
2094
  ];
1744
- let q = (0, import_firestore6.query)(patientsCollection, ...constraints);
2095
+ let q = (0, import_firestore8.query)(patientsCollection, ...constraints);
1745
2096
  if (options == null ? void 0 : options.limit) {
1746
- q = (0, import_firestore6.query)(q, (0, import_firestore6.limit)(options.limit));
2097
+ q = (0, import_firestore8.query)(q, (0, import_firestore8.limit)(options.limit));
1747
2098
  }
1748
2099
  if (options == null ? void 0 : options.startAfter) {
1749
- const startAfterDoc = await (0, import_firestore6.getDoc)(
1750
- (0, import_firestore6.doc)(db, PATIENTS_COLLECTION, options.startAfter)
2100
+ const startAfterDoc = await (0, import_firestore8.getDoc)(
2101
+ (0, import_firestore8.doc)(db, PATIENTS_COLLECTION, options.startAfter)
1751
2102
  );
1752
2103
  if (startAfterDoc.exists()) {
1753
- q = (0, import_firestore6.query)(q, (0, import_firestore6.startAfter)(startAfterDoc));
2104
+ q = (0, import_firestore8.query)(q, (0, import_firestore8.startAfter)(startAfterDoc));
1754
2105
  }
1755
2106
  }
1756
- const patientsSnapshot = await (0, import_firestore6.getDocs)(q);
2107
+ const patientsSnapshot = await (0, import_firestore8.getDocs)(q);
1757
2108
  const patients = [];
1758
2109
  patientsSnapshot.forEach((doc34) => {
1759
2110
  patients.push(doc34.data());
@@ -1786,7 +2137,7 @@ var getPatientsByPractitionerWithDetailsUtil = async (db, practitionerId, option
1786
2137
  const patientProfilesWithDetails = await Promise.all(
1787
2138
  patientProfiles.map(async (profile) => {
1788
2139
  try {
1789
- const sensitiveInfoDoc = await (0, import_firestore6.getDoc)(
2140
+ const sensitiveInfoDoc = await (0, import_firestore8.getDoc)(
1790
2141
  getSensitiveInfoDocRef(db, profile.id)
1791
2142
  );
1792
2143
  const sensitiveInfo = sensitiveInfoDoc.exists() ? sensitiveInfoDoc.data() : void 0;
@@ -1822,13 +2173,13 @@ var getPractitionerProfileByUserRef = async (db, userRef) => {
1822
2173
  console.log(
1823
2174
  `[getPractitionerProfileByUserRef] Fetching practitioner with userRef: ${userRef}`
1824
2175
  );
1825
- const practitionersCollection = (0, import_firestore6.collection)(db, PRACTITIONERS_COLLECTION);
1826
- const q = (0, import_firestore6.query)(
2176
+ const practitionersCollection = (0, import_firestore8.collection)(db, PRACTITIONERS_COLLECTION);
2177
+ const q = (0, import_firestore8.query)(
1827
2178
  practitionersCollection,
1828
- (0, import_firestore6.where)("userRef", "==", userRef),
1829
- (0, import_firestore6.limit)(1)
2179
+ (0, import_firestore8.where)("userRef", "==", userRef),
2180
+ (0, import_firestore8.limit)(1)
1830
2181
  );
1831
- const querySnapshot = await (0, import_firestore6.getDocs)(q);
2182
+ const querySnapshot = await (0, import_firestore8.getDocs)(q);
1832
2183
  if (querySnapshot.empty) {
1833
2184
  console.log(
1834
2185
  `[getPractitionerProfileByUserRef] No practitioner found with userRef: ${userRef}`
@@ -1862,7 +2213,7 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1862
2213
  console.log(
1863
2214
  `[ensureMedicalInfoExists] Got document reference: ${medicalInfoRef.path}`
1864
2215
  );
1865
- const medicalInfoDoc = await (0, import_firestore7.getDoc)(medicalInfoRef);
2216
+ const medicalInfoDoc = await (0, import_firestore9.getDoc)(medicalInfoRef);
1866
2217
  console.log(
1867
2218
  `[ensureMedicalInfoExists] Document exists: ${medicalInfoDoc.exists()}`
1868
2219
  );
@@ -1870,7 +2221,7 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1870
2221
  const defaultData = {
1871
2222
  ...DEFAULT_MEDICAL_INFO,
1872
2223
  patientId,
1873
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2224
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
1874
2225
  updatedBy: userRef
1875
2226
  };
1876
2227
  console.log(
@@ -1880,9 +2231,9 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1880
2231
  (key, value) => value && typeof value === "object" && value.constructor && value.constructor.name === "Object" ? "[serverTimestamp]" : value
1881
2232
  )
1882
2233
  );
1883
- await (0, import_firestore7.setDoc)(medicalInfoRef, defaultData);
2234
+ await (0, import_firestore9.setDoc)(medicalInfoRef, defaultData);
1884
2235
  console.log(`[ensureMedicalInfoExists] Document created successfully`);
1885
- const verifyDoc = await (0, import_firestore7.getDoc)(medicalInfoRef);
2236
+ const verifyDoc = await (0, import_firestore9.getDoc)(medicalInfoRef);
1886
2237
  console.log(
1887
2238
  `[ensureMedicalInfoExists] Verification - document exists: ${verifyDoc.exists()}`
1888
2239
  );
@@ -1898,7 +2249,7 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1898
2249
  };
1899
2250
  var checkMedicalAccessUtil = async (db, patientId, userRef, userRoles) => {
1900
2251
  var _a;
1901
- const patientDoc = await (0, import_firestore7.getDoc)(getPatientDocRef(db, patientId));
2252
+ const patientDoc = await (0, import_firestore9.getDoc)(getPatientDocRef(db, patientId));
1902
2253
  if (!patientDoc.exists()) {
1903
2254
  throw new Error("Patient profile not found");
1904
2255
  }
@@ -1931,17 +2282,17 @@ var checkMedicalAccessUtil = async (db, patientId, userRef, userRoles) => {
1931
2282
  var createMedicalInfoUtil = async (db, patientId, data, userRef, userRoles) => {
1932
2283
  await checkMedicalAccessUtil(db, patientId, userRef, userRoles);
1933
2284
  const validatedData = createPatientMedicalInfoSchema.parse(data);
1934
- await (0, import_firestore7.setDoc)(getMedicalInfoDocRef(db, patientId), {
2285
+ await (0, import_firestore9.setDoc)(getMedicalInfoDocRef(db, patientId), {
1935
2286
  ...validatedData,
1936
2287
  patientId,
1937
- lastUpdated: import_firestore7.Timestamp.now(),
2288
+ lastUpdated: import_firestore9.Timestamp.now(),
1938
2289
  updatedBy: userRef
1939
2290
  });
1940
2291
  };
1941
2292
  var getMedicalInfoUtil = async (db, patientId, userRef, userRoles) => {
1942
2293
  await checkMedicalAccessUtil(db, patientId, userRef, userRoles);
1943
2294
  const docRef = getMedicalInfoDocRef(db, patientId);
1944
- const snapshot = await (0, import_firestore7.getDoc)(docRef);
2295
+ const snapshot = await (0, import_firestore9.getDoc)(docRef);
1945
2296
  if (!snapshot.exists()) {
1946
2297
  throw new Error("Medicinske informacije nisu prona\u0111ene");
1947
2298
  }
@@ -1950,25 +2301,25 @@ var getMedicalInfoUtil = async (db, patientId, userRef, userRoles) => {
1950
2301
  var updateVitalStatsUtil = async (db, patientId, data, userRef) => {
1951
2302
  await ensureMedicalInfoExists(db, patientId, userRef);
1952
2303
  const validatedData = updateVitalStatsSchema.parse(data);
1953
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2304
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
1954
2305
  vitalStats: validatedData,
1955
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2306
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
1956
2307
  updatedBy: userRef
1957
2308
  });
1958
2309
  };
1959
2310
  var addAllergyUtil = async (db, patientId, data, userRef) => {
1960
2311
  await ensureMedicalInfoExists(db, patientId, userRef);
1961
2312
  const validatedData = addAllergySchema.parse(data);
1962
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
1963
- allergies: (0, import_firestore7.arrayUnion)(validatedData),
1964
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2313
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2314
+ allergies: (0, import_firestore9.arrayUnion)(validatedData),
2315
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
1965
2316
  updatedBy: userRef
1966
2317
  });
1967
2318
  };
1968
2319
  var updateAllergyUtil = async (db, patientId, data, userRef) => {
1969
2320
  const validatedData = updateAllergySchema.parse(data);
1970
2321
  const { allergyIndex, ...updateData } = validatedData;
1971
- const docSnapshot = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2322
+ const docSnapshot = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
1972
2323
  if (!docSnapshot.exists()) throw new Error("Medical info not found");
1973
2324
  const medicalInfo = patientMedicalInfoSchema.parse(docSnapshot.data());
1974
2325
  if (allergyIndex >= medicalInfo.allergies.length) {
@@ -1979,14 +2330,14 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
1979
2330
  ...updatedAllergies[allergyIndex],
1980
2331
  ...updateData
1981
2332
  };
1982
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2333
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
1983
2334
  allergies: updatedAllergies,
1984
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2335
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
1985
2336
  updatedBy: userRef
1986
2337
  });
1987
2338
  };
1988
2339
  var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1989
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2340
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
1990
2341
  if (!doc34.exists()) throw new Error("Medical info not found");
1991
2342
  const medicalInfo = doc34.data();
1992
2343
  if (allergyIndex >= medicalInfo.allergies.length) {
@@ -1995,25 +2346,25 @@ var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1995
2346
  const updatedAllergies = medicalInfo.allergies.filter(
1996
2347
  (_, index) => index !== allergyIndex
1997
2348
  );
1998
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2349
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
1999
2350
  allergies: updatedAllergies,
2000
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2351
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2001
2352
  updatedBy: userRef
2002
2353
  });
2003
2354
  };
2004
2355
  var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
2005
2356
  await ensureMedicalInfoExists(db, patientId, userRef);
2006
2357
  const validatedData = addBlockingConditionSchema.parse(data);
2007
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2008
- blockingConditions: (0, import_firestore7.arrayUnion)(validatedData),
2009
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2358
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2359
+ blockingConditions: (0, import_firestore9.arrayUnion)(validatedData),
2360
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2010
2361
  updatedBy: userRef
2011
2362
  });
2012
2363
  };
2013
2364
  var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
2014
2365
  const validatedData = updateBlockingConditionSchema.parse(data);
2015
2366
  const { conditionIndex, ...updateData } = validatedData;
2016
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2367
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2017
2368
  if (!doc34.exists()) throw new Error("Medical info not found");
2018
2369
  const medicalInfo = doc34.data();
2019
2370
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
@@ -2024,14 +2375,14 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
2024
2375
  ...updatedConditions[conditionIndex],
2025
2376
  ...updateData
2026
2377
  };
2027
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2378
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2028
2379
  blockingConditions: updatedConditions,
2029
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2380
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2030
2381
  updatedBy: userRef
2031
2382
  });
2032
2383
  };
2033
2384
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
2034
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2385
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2035
2386
  if (!doc34.exists()) throw new Error("Medical info not found");
2036
2387
  const medicalInfo = doc34.data();
2037
2388
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
@@ -2040,25 +2391,25 @@ var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef)
2040
2391
  const updatedConditions = medicalInfo.blockingConditions.filter(
2041
2392
  (_, index) => index !== conditionIndex
2042
2393
  );
2043
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2394
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2044
2395
  blockingConditions: updatedConditions,
2045
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2396
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2046
2397
  updatedBy: userRef
2047
2398
  });
2048
2399
  };
2049
2400
  var addContraindicationUtil = async (db, patientId, data, userRef) => {
2050
2401
  await ensureMedicalInfoExists(db, patientId, userRef);
2051
2402
  const validatedData = addContraindicationSchema.parse(data);
2052
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2053
- contraindications: (0, import_firestore7.arrayUnion)(validatedData),
2054
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2403
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2404
+ contraindications: (0, import_firestore9.arrayUnion)(validatedData),
2405
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2055
2406
  updatedBy: userRef
2056
2407
  });
2057
2408
  };
2058
2409
  var updateContraindicationUtil = async (db, patientId, data, userRef) => {
2059
2410
  const validatedData = updateContraindicationSchema.parse(data);
2060
2411
  const { contraindicationIndex, ...updateData } = validatedData;
2061
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2412
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2062
2413
  if (!doc34.exists()) throw new Error("Medical info not found");
2063
2414
  const medicalInfo = doc34.data();
2064
2415
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
@@ -2069,14 +2420,14 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
2069
2420
  ...updatedContraindications[contraindicationIndex],
2070
2421
  ...updateData
2071
2422
  };
2072
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2423
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2073
2424
  contraindications: updatedContraindications,
2074
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2425
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2075
2426
  updatedBy: userRef
2076
2427
  });
2077
2428
  };
2078
2429
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
2079
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2430
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2080
2431
  if (!doc34.exists()) throw new Error("Medical info not found");
2081
2432
  const medicalInfo = doc34.data();
2082
2433
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
@@ -2085,25 +2436,25 @@ var removeContraindicationUtil = async (db, patientId, contraindicationIndex, us
2085
2436
  const updatedContraindications = medicalInfo.contraindications.filter(
2086
2437
  (_, index) => index !== contraindicationIndex
2087
2438
  );
2088
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2439
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2089
2440
  contraindications: updatedContraindications,
2090
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2441
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2091
2442
  updatedBy: userRef
2092
2443
  });
2093
2444
  };
2094
2445
  var addMedicationUtil = async (db, patientId, data, userRef) => {
2095
2446
  await ensureMedicalInfoExists(db, patientId, userRef);
2096
2447
  const validatedData = addMedicationSchema.parse(data);
2097
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2098
- currentMedications: (0, import_firestore7.arrayUnion)(validatedData),
2099
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2448
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2449
+ currentMedications: (0, import_firestore9.arrayUnion)(validatedData),
2450
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2100
2451
  updatedBy: userRef
2101
2452
  });
2102
2453
  };
2103
2454
  var updateMedicationUtil = async (db, patientId, data, userRef) => {
2104
2455
  const validatedData = updateMedicationSchema.parse(data);
2105
2456
  const { medicationIndex, ...updateData } = validatedData;
2106
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2457
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2107
2458
  if (!doc34.exists()) throw new Error("Medical info not found");
2108
2459
  const medicalInfo = doc34.data();
2109
2460
  if (medicationIndex >= medicalInfo.currentMedications.length) {
@@ -2114,14 +2465,14 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
2114
2465
  ...updatedMedications[medicationIndex],
2115
2466
  ...updateData
2116
2467
  };
2117
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2468
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2118
2469
  currentMedications: updatedMedications,
2119
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2470
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2120
2471
  updatedBy: userRef
2121
2472
  });
2122
2473
  };
2123
2474
  var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
2124
- const doc34 = await (0, import_firestore7.getDoc)(getMedicalInfoDocRef(db, patientId));
2475
+ const doc34 = await (0, import_firestore9.getDoc)(getMedicalInfoDocRef(db, patientId));
2125
2476
  if (!doc34.exists()) throw new Error("Medical info not found");
2126
2477
  const medicalInfo = doc34.data();
2127
2478
  if (medicationIndex >= medicalInfo.currentMedications.length) {
@@ -2130,9 +2481,9 @@ var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
2130
2481
  const updatedMedications = medicalInfo.currentMedications.filter(
2131
2482
  (_, index) => index !== medicationIndex
2132
2483
  );
2133
- await (0, import_firestore7.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2484
+ await (0, import_firestore9.updateDoc)(getMedicalInfoDocRef(db, patientId), {
2134
2485
  currentMedications: updatedMedications,
2135
- lastUpdated: (0, import_firestore7.serverTimestamp)(),
2486
+ lastUpdated: (0, import_firestore9.serverTimestamp)(),
2136
2487
  updatedBy: userRef
2137
2488
  });
2138
2489
  };
@@ -2149,7 +2500,6 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
2149
2500
  id: patientId,
2150
2501
  userRef: validatedData.userRef,
2151
2502
  displayName: validatedData.displayName,
2152
- profilePhoto: validatedData.profilePhoto || null,
2153
2503
  expoTokens: validatedData.expoTokens,
2154
2504
  gamification: validatedData.gamification || {
2155
2505
  level: 1,
@@ -2161,15 +2511,15 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
2161
2511
  clinics: validatedData.clinics || [],
2162
2512
  doctorIds: ((_a = validatedData.doctors) == null ? void 0 : _a.map((d) => d.userRef)) || [],
2163
2513
  clinicIds: ((_b = validatedData.clinics) == null ? void 0 : _b.map((c) => c.clinicId)) || [],
2164
- createdAt: (0, import_firestore8.serverTimestamp)(),
2165
- updatedAt: (0, import_firestore8.serverTimestamp)()
2514
+ createdAt: (0, import_firestore10.serverTimestamp)(),
2515
+ updatedAt: (0, import_firestore10.serverTimestamp)()
2166
2516
  };
2167
2517
  patientProfileSchema.parse({
2168
2518
  ...patientData,
2169
- createdAt: import_firestore8.Timestamp.now(),
2170
- updatedAt: import_firestore8.Timestamp.now()
2519
+ createdAt: import_firestore10.Timestamp.now(),
2520
+ updatedAt: import_firestore10.Timestamp.now()
2171
2521
  });
2172
- await (0, import_firestore8.setDoc)(getPatientDocRef(db, patientId), patientData);
2522
+ await (0, import_firestore10.setDoc)(getPatientDocRef(db, patientId), patientData);
2173
2523
  console.log(`[createPatientProfileUtil] Creating sensitive info document`);
2174
2524
  let sensitiveInfoSuccess = false;
2175
2525
  try {
@@ -2183,81 +2533,103 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
2183
2533
  );
2184
2534
  sensitiveInfoSuccess = true;
2185
2535
  } catch (sensitiveError) {
2186
- console.error(`[createPatientProfileUtil] Error creating sensitive info:`, sensitiveError);
2536
+ console.error(
2537
+ `[createPatientProfileUtil] Error creating sensitive info:`,
2538
+ sensitiveError
2539
+ );
2187
2540
  }
2188
2541
  console.log(`[createPatientProfileUtil] Creating medical info document`);
2189
2542
  let medicalInfoSuccess = false;
2190
2543
  try {
2191
2544
  await ensureMedicalInfoExists(db, patientId, validatedData.userRef);
2192
- console.log(`[createPatientProfileUtil] Medical info document created successfully`);
2545
+ console.log(
2546
+ `[createPatientProfileUtil] Medical info document created successfully`
2547
+ );
2193
2548
  medicalInfoSuccess = true;
2194
2549
  } catch (medicalError) {
2195
- console.error(`[createPatientProfileUtil] Error creating medical info:`, medicalError);
2550
+ console.error(
2551
+ `[createPatientProfileUtil] Error creating medical info:`,
2552
+ medicalError
2553
+ );
2196
2554
  }
2197
2555
  if (!sensitiveInfoSuccess || !medicalInfoSuccess) {
2198
- console.log(`[createPatientProfileUtil] Using fallback method to create documents`);
2556
+ console.log(
2557
+ `[createPatientProfileUtil] Using fallback method to create documents`
2558
+ );
2199
2559
  try {
2200
2560
  await testCreateSubDocuments(db, patientId, validatedData.userRef);
2201
- console.log(`[createPatientProfileUtil] Fallback method completed successfully`);
2561
+ console.log(
2562
+ `[createPatientProfileUtil] Fallback method completed successfully`
2563
+ );
2202
2564
  } catch (fallbackError) {
2203
- console.error(`[createPatientProfileUtil] Fallback method failed:`, fallbackError);
2565
+ console.error(
2566
+ `[createPatientProfileUtil] Fallback method failed:`,
2567
+ fallbackError
2568
+ );
2204
2569
  }
2205
2570
  }
2206
2571
  console.log(`[createPatientProfileUtil] Verifying patient document exists`);
2207
- const patientDoc = await (0, import_firestore8.getDoc)(getPatientDocRef(db, patientId));
2572
+ const patientDoc = await (0, import_firestore10.getDoc)(getPatientDocRef(db, patientId));
2208
2573
  if (!patientDoc.exists()) {
2209
- console.error(`[createPatientProfileUtil] Patient document not found after creation`);
2574
+ console.error(
2575
+ `[createPatientProfileUtil] Patient document not found after creation`
2576
+ );
2210
2577
  throw new Error("Failed to create patient profile");
2211
2578
  }
2212
- console.log(`[createPatientProfileUtil] Patient profile creation completed successfully`);
2579
+ console.log(
2580
+ `[createPatientProfileUtil] Patient profile creation completed successfully`
2581
+ );
2213
2582
  return patientDoc.data();
2214
2583
  } catch (error) {
2215
- console.error(`[createPatientProfileUtil] Error in patient profile creation:`, error);
2216
- if (error instanceof import_zod8.z.ZodError) {
2584
+ console.error(
2585
+ `[createPatientProfileUtil] Error in patient profile creation:`,
2586
+ error
2587
+ );
2588
+ if (error instanceof import_zod9.z.ZodError) {
2217
2589
  throw new Error("Invalid patient data: " + error.message);
2218
2590
  }
2219
2591
  throw error;
2220
2592
  }
2221
2593
  };
2222
2594
  var getPatientProfileUtil = async (db, patientId) => {
2223
- const patientDoc = await (0, import_firestore8.getDoc)(getPatientDocRef(db, patientId));
2595
+ const patientDoc = await (0, import_firestore10.getDoc)(getPatientDocRef(db, patientId));
2224
2596
  return patientDoc.exists() ? patientDoc.data() : null;
2225
2597
  };
2226
2598
  var getPatientProfileByUserRefUtil = async (db, userRef) => {
2227
2599
  try {
2228
2600
  const docRef = await getPatientDocRefByUserRef(db, userRef);
2229
- const patientDoc = await (0, import_firestore8.getDoc)(docRef);
2601
+ const patientDoc = await (0, import_firestore10.getDoc)(docRef);
2230
2602
  return patientDoc.exists() ? patientDoc.data() : null;
2231
2603
  } catch (error) {
2232
2604
  return null;
2233
2605
  }
2234
2606
  };
2235
2607
  var addExpoTokenUtil = async (db, patientId, token) => {
2236
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), {
2237
- expoTokens: (0, import_firestore8.arrayUnion)(token),
2238
- updatedAt: (0, import_firestore8.serverTimestamp)()
2608
+ await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), {
2609
+ expoTokens: (0, import_firestore10.arrayUnion)(token),
2610
+ updatedAt: (0, import_firestore10.serverTimestamp)()
2239
2611
  });
2240
2612
  };
2241
2613
  var removeExpoTokenUtil = async (db, patientId, token) => {
2242
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), {
2243
- expoTokens: (0, import_firestore8.arrayRemove)(token),
2244
- updatedAt: (0, import_firestore8.serverTimestamp)()
2614
+ await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), {
2615
+ expoTokens: (0, import_firestore10.arrayRemove)(token),
2616
+ updatedAt: (0, import_firestore10.serverTimestamp)()
2245
2617
  });
2246
2618
  };
2247
2619
  var addPointsUtil = async (db, patientId, points) => {
2248
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), {
2249
- "gamification.points": (0, import_firestore8.increment)(points),
2250
- updatedAt: (0, import_firestore8.serverTimestamp)()
2620
+ await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), {
2621
+ "gamification.points": (0, import_firestore10.increment)(points),
2622
+ updatedAt: (0, import_firestore10.serverTimestamp)()
2251
2623
  });
2252
2624
  };
2253
2625
  var updatePatientProfileUtil = async (db, patientId, data) => {
2254
2626
  try {
2255
2627
  const updateData = {
2256
2628
  ...data,
2257
- updatedAt: (0, import_firestore8.serverTimestamp)()
2629
+ updatedAt: (0, import_firestore10.serverTimestamp)()
2258
2630
  };
2259
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), updateData);
2260
- const updatedDoc = await (0, import_firestore8.getDoc)(getPatientDocRef(db, patientId));
2631
+ await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), updateData);
2632
+ const updatedDoc = await (0, import_firestore10.getDoc)(getPatientDocRef(db, patientId));
2261
2633
  if (!updatedDoc.exists()) {
2262
2634
  throw new Error("Patient profile not found after update");
2263
2635
  }
@@ -2270,7 +2642,7 @@ var updatePatientProfileUtil = async (db, patientId, data) => {
2270
2642
  var updatePatientProfileByUserRefUtil = async (db, userRef, data) => {
2271
2643
  try {
2272
2644
  const docRef = await getPatientDocRefByUserRef(db, userRef);
2273
- const patientDoc = await (0, import_firestore8.getDoc)(docRef);
2645
+ const patientDoc = await (0, import_firestore10.getDoc)(docRef);
2274
2646
  if (!patientDoc.exists()) {
2275
2647
  throw new Error("Patient profile not found");
2276
2648
  }
@@ -2278,49 +2650,10 @@ var updatePatientProfileByUserRefUtil = async (db, userRef, data) => {
2278
2650
  return updatePatientProfileUtil(db, patientData.id, data);
2279
2651
  } catch (error) {
2280
2652
  const errorMessage = error instanceof Error ? error.message : String(error);
2281
- throw new Error(`Failed to update patient profile by user ref: ${errorMessage}`);
2282
- }
2283
- };
2284
- var uploadProfilePhotoUtil = async (storage, patientId, file) => {
2285
- const photoRef = (0, import_storage3.ref)(storage, `patient-photos/${patientId}/profile-photo`);
2286
- await (0, import_storage3.uploadBytes)(photoRef, file);
2287
- return (0, import_storage3.getDownloadURL)(photoRef);
2288
- };
2289
- var updateProfilePhotoUtil = async (storage, db, patientId, file) => {
2290
- const patientDoc = await (0, import_firestore8.getDoc)(getPatientDocRef(db, patientId));
2291
- if (!patientDoc.exists()) throw new Error("Patient profile not found");
2292
- const patientData = patientDoc.data();
2293
- if (patientData.profilePhoto) {
2294
- try {
2295
- const oldPhotoRef = (0, import_storage3.ref)(storage, patientData.profilePhoto);
2296
- await (0, import_storage3.deleteObject)(oldPhotoRef);
2297
- } catch (error) {
2298
- console.warn("Failed to delete old profile photo:", error);
2299
- }
2300
- }
2301
- const newPhotoUrl = await uploadProfilePhotoUtil(storage, patientId, file);
2302
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), {
2303
- profilePhoto: newPhotoUrl,
2304
- updatedAt: (0, import_firestore8.serverTimestamp)()
2305
- });
2306
- return newPhotoUrl;
2307
- };
2308
- var deleteProfilePhotoUtil = async (storage, db, patientId) => {
2309
- const patientDoc = await (0, import_firestore8.getDoc)(getPatientDocRef(db, patientId));
2310
- if (!patientDoc.exists()) throw new Error("Patient profile not found");
2311
- const patientData = patientDoc.data();
2312
- if (patientData.profilePhoto) {
2313
- try {
2314
- const photoRef = (0, import_storage3.ref)(storage, patientData.profilePhoto);
2315
- await (0, import_storage3.deleteObject)(photoRef);
2316
- } catch (error) {
2317
- console.warn("Failed to delete profile photo:", error);
2318
- }
2653
+ throw new Error(
2654
+ `Failed to update patient profile by user ref: ${errorMessage}`
2655
+ );
2319
2656
  }
2320
- await (0, import_firestore8.updateDoc)(getPatientDocRef(db, patientId), {
2321
- profilePhoto: null,
2322
- updatedAt: (0, import_firestore8.serverTimestamp)()
2323
- });
2324
2657
  };
2325
2658
  var testCreateSubDocuments = async (db, patientId, userRef) => {
2326
2659
  console.log(
@@ -2329,33 +2662,41 @@ var testCreateSubDocuments = async (db, patientId, userRef) => {
2329
2662
  try {
2330
2663
  console.log(`[testCreateSubDocuments] Testing sensitive info creation`);
2331
2664
  const sensitiveInfoRef = getSensitiveInfoDocRef(db, patientId);
2332
- console.log(`[testCreateSubDocuments] Sensitive info path: ${sensitiveInfoRef.path}`);
2665
+ console.log(
2666
+ `[testCreateSubDocuments] Sensitive info path: ${sensitiveInfoRef.path}`
2667
+ );
2333
2668
  const defaultSensitiveInfo = {
2334
2669
  patientId,
2335
2670
  userRef,
2336
2671
  photoUrl: "",
2337
2672
  firstName: "Name",
2338
2673
  lastName: "Surname",
2339
- dateOfBirth: import_firestore8.Timestamp.now(),
2674
+ dateOfBirth: import_firestore10.Timestamp.now(),
2340
2675
  gender: "prefer_not_to_say" /* PREFER_NOT_TO_SAY */,
2341
2676
  email: "test@example.com",
2342
2677
  phoneNumber: "",
2343
- createdAt: import_firestore8.Timestamp.now(),
2344
- updatedAt: import_firestore8.Timestamp.now()
2678
+ createdAt: import_firestore10.Timestamp.now(),
2679
+ updatedAt: import_firestore10.Timestamp.now()
2345
2680
  };
2346
- await (0, import_firestore8.setDoc)(sensitiveInfoRef, defaultSensitiveInfo);
2347
- console.log(`[testCreateSubDocuments] Sensitive info document created directly`);
2681
+ await (0, import_firestore10.setDoc)(sensitiveInfoRef, defaultSensitiveInfo);
2682
+ console.log(
2683
+ `[testCreateSubDocuments] Sensitive info document created directly`
2684
+ );
2348
2685
  console.log(`[testCreateSubDocuments] Testing medical info creation`);
2349
2686
  const medicalInfoRef = getMedicalInfoDocRef(db, patientId);
2350
- console.log(`[testCreateSubDocuments] Medical info path: ${medicalInfoRef.path}`);
2687
+ console.log(
2688
+ `[testCreateSubDocuments] Medical info path: ${medicalInfoRef.path}`
2689
+ );
2351
2690
  const defaultMedicalInfo = {
2352
2691
  ...DEFAULT_MEDICAL_INFO,
2353
2692
  patientId,
2354
- lastUpdated: import_firestore8.Timestamp.now(),
2693
+ lastUpdated: import_firestore10.Timestamp.now(),
2355
2694
  updatedBy: userRef
2356
2695
  };
2357
- await (0, import_firestore8.setDoc)(medicalInfoRef, defaultMedicalInfo);
2358
- console.log(`[testCreateSubDocuments] Medical info document created directly`);
2696
+ await (0, import_firestore10.setDoc)(medicalInfoRef, defaultMedicalInfo);
2697
+ console.log(
2698
+ `[testCreateSubDocuments] Medical info document created directly`
2699
+ );
2359
2700
  console.log(`[testCreateSubDocuments] Test completed successfully`);
2360
2701
  } catch (error) {
2361
2702
  console.error(`[testCreateSubDocuments] Error:`, error);
@@ -2366,10 +2707,12 @@ var searchPatientsUtil = async (db, params, requester) => {
2366
2707
  searchPatientsSchema.parse(params);
2367
2708
  requesterInfoSchema.parse(requester);
2368
2709
  const constraints = [];
2369
- const patientsCollectionRef = (0, import_firestore8.collection)(db, PATIENTS_COLLECTION);
2710
+ const patientsCollectionRef = (0, import_firestore10.collection)(db, PATIENTS_COLLECTION);
2370
2711
  if (requester.role === "clinic_admin") {
2371
2712
  if (!requester.associatedClinicId) {
2372
- throw new Error("Associated clinic ID is required for clinic admin search.");
2713
+ throw new Error(
2714
+ "Associated clinic ID is required for clinic admin search."
2715
+ );
2373
2716
  }
2374
2717
  if (params.clinicId && params.clinicId !== requester.associatedClinicId) {
2375
2718
  console.warn(
@@ -2377,13 +2720,19 @@ var searchPatientsUtil = async (db, params, requester) => {
2377
2720
  );
2378
2721
  return [];
2379
2722
  }
2380
- constraints.push((0, import_firestore8.where)("clinicIds", "array-contains", requester.associatedClinicId));
2723
+ constraints.push(
2724
+ (0, import_firestore10.where)("clinicIds", "array-contains", requester.associatedClinicId)
2725
+ );
2381
2726
  if (params.practitionerId) {
2382
- constraints.push((0, import_firestore8.where)("doctorIds", "array-contains", params.practitionerId));
2727
+ constraints.push(
2728
+ (0, import_firestore10.where)("doctorIds", "array-contains", params.practitionerId)
2729
+ );
2383
2730
  }
2384
2731
  } else if (requester.role === "practitioner") {
2385
2732
  if (!requester.associatedPractitionerId) {
2386
- throw new Error("Associated practitioner ID is required for practitioner search.");
2733
+ throw new Error(
2734
+ "Associated practitioner ID is required for practitioner search."
2735
+ );
2387
2736
  }
2388
2737
  if (params.practitionerId && params.practitionerId !== requester.associatedPractitionerId) {
2389
2738
  console.warn(
@@ -2391,18 +2740,24 @@ var searchPatientsUtil = async (db, params, requester) => {
2391
2740
  );
2392
2741
  return [];
2393
2742
  }
2394
- constraints.push((0, import_firestore8.where)("doctorIds", "array-contains", requester.associatedPractitionerId));
2743
+ constraints.push(
2744
+ (0, import_firestore10.where)("doctorIds", "array-contains", requester.associatedPractitionerId)
2745
+ );
2395
2746
  if (params.clinicId) {
2396
- constraints.push((0, import_firestore8.where)("clinicIds", "array-contains", params.clinicId));
2747
+ constraints.push((0, import_firestore10.where)("clinicIds", "array-contains", params.clinicId));
2397
2748
  }
2398
2749
  } else {
2399
2750
  throw new Error("Invalid requester role.");
2400
2751
  }
2401
2752
  try {
2402
- const finalQuery = (0, import_firestore8.query)(patientsCollectionRef, ...constraints);
2403
- const querySnapshot = await (0, import_firestore8.getDocs)(finalQuery);
2404
- const patients = querySnapshot.docs.map((doc34) => doc34.data());
2405
- console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
2753
+ const finalQuery = (0, import_firestore10.query)(patientsCollectionRef, ...constraints);
2754
+ const querySnapshot = await (0, import_firestore10.getDocs)(finalQuery);
2755
+ const patients = querySnapshot.docs.map(
2756
+ (doc34) => doc34.data()
2757
+ );
2758
+ console.log(
2759
+ `[searchPatientsUtil] Found ${patients.length} patients matching criteria.`
2760
+ );
2406
2761
  return patients;
2407
2762
  } catch (error) {
2408
2763
  console.error("[searchPatientsUtil] Error searching patients:", error);
@@ -2411,19 +2766,24 @@ var searchPatientsUtil = async (db, params, requester) => {
2411
2766
  };
2412
2767
  var getAllPatientsUtil = async (db, options) => {
2413
2768
  try {
2414
- console.log(`[getAllPatientsUtil] Fetching patients with options:`, options);
2415
- const patientsCollection = (0, import_firestore8.collection)(db, PATIENTS_COLLECTION);
2416
- let q = (0, import_firestore8.query)(patientsCollection);
2769
+ console.log(
2770
+ `[getAllPatientsUtil] Fetching patients with options:`,
2771
+ options
2772
+ );
2773
+ const patientsCollection = (0, import_firestore10.collection)(db, PATIENTS_COLLECTION);
2774
+ let q = (0, import_firestore10.query)(patientsCollection);
2417
2775
  if (options == null ? void 0 : options.limit) {
2418
- q = (0, import_firestore8.query)(q, (0, import_firestore8.limit)(options.limit));
2776
+ q = (0, import_firestore10.query)(q, (0, import_firestore10.limit)(options.limit));
2419
2777
  }
2420
2778
  if (options == null ? void 0 : options.startAfter) {
2421
- const startAfterDoc = await (0, import_firestore8.getDoc)((0, import_firestore8.doc)(db, PATIENTS_COLLECTION, options.startAfter));
2779
+ const startAfterDoc = await (0, import_firestore10.getDoc)(
2780
+ (0, import_firestore10.doc)(db, PATIENTS_COLLECTION, options.startAfter)
2781
+ );
2422
2782
  if (startAfterDoc.exists()) {
2423
- q = (0, import_firestore8.query)(q, (0, import_firestore8.startAfter)(startAfterDoc));
2783
+ q = (0, import_firestore10.query)(q, (0, import_firestore10.startAfter)(startAfterDoc));
2424
2784
  }
2425
2785
  }
2426
- const patientsSnapshot = await (0, import_firestore8.getDocs)(q);
2786
+ const patientsSnapshot = await (0, import_firestore10.getDocs)(q);
2427
2787
  const patients = [];
2428
2788
  patientsSnapshot.forEach((doc34) => {
2429
2789
  patients.push(doc34.data());
@@ -2439,8 +2799,8 @@ var getAllPatientsUtil = async (db, options) => {
2439
2799
  };
2440
2800
 
2441
2801
  // src/services/patient/utils/location.utils.ts
2442
- var import_firestore9 = require("firebase/firestore");
2443
- var import_zod9 = require("zod");
2802
+ var import_firestore11 = require("firebase/firestore");
2803
+ var import_zod10 = require("zod");
2444
2804
  var import_geofire_common = require("geofire-common");
2445
2805
  var updatePatientLocationUtil = async (db, patientId, latitude, longitude) => {
2446
2806
  const locationData = {
@@ -2450,9 +2810,9 @@ var updatePatientLocationUtil = async (db, patientId, latitude, longitude) => {
2450
2810
  };
2451
2811
  const updateData = {
2452
2812
  locationData,
2453
- updatedAt: (0, import_firestore9.serverTimestamp)()
2813
+ updatedAt: (0, import_firestore11.serverTimestamp)()
2454
2814
  };
2455
- await (0, import_firestore9.updateDoc)(getLocationInfoDocRef(db, patientId), updateData);
2815
+ await (0, import_firestore11.updateDoc)(getLocationInfoDocRef(db, patientId), updateData);
2456
2816
  };
2457
2817
  var createLocationInfoUtil = async (db, data, requesterId) => {
2458
2818
  try {
@@ -2469,17 +2829,17 @@ var createLocationInfoUtil = async (db, data, requesterId) => {
2469
2829
  validatedData.locationData.longitude
2470
2830
  ])
2471
2831
  },
2472
- createdAt: (0, import_firestore9.serverTimestamp)(),
2473
- updatedAt: (0, import_firestore9.serverTimestamp)()
2832
+ createdAt: (0, import_firestore11.serverTimestamp)(),
2833
+ updatedAt: (0, import_firestore11.serverTimestamp)()
2474
2834
  };
2475
- await (0, import_firestore9.setDoc)(getLocationInfoDocRef(db, data.patientId), locationData);
2476
- const locationDoc = await (0, import_firestore9.getDoc)(getLocationInfoDocRef(db, data.patientId));
2835
+ await (0, import_firestore11.setDoc)(getLocationInfoDocRef(db, data.patientId), locationData);
2836
+ const locationDoc = await (0, import_firestore11.getDoc)(getLocationInfoDocRef(db, data.patientId));
2477
2837
  if (!locationDoc.exists()) {
2478
2838
  throw new Error("Failed to create location information");
2479
2839
  }
2480
2840
  return locationDoc.data();
2481
2841
  } catch (error) {
2482
- if (error instanceof import_zod9.z.ZodError) {
2842
+ if (error instanceof import_zod10.z.ZodError) {
2483
2843
  throw new Error("Invalid location data: " + error.message);
2484
2844
  }
2485
2845
  throw error;
@@ -2489,7 +2849,7 @@ var getLocationInfoUtil = async (db, patientId, requesterId) => {
2489
2849
  if (patientId !== requesterId) {
2490
2850
  throw new Error("Unauthorized access to location information");
2491
2851
  }
2492
- const locationDoc = await (0, import_firestore9.getDoc)(getLocationInfoDocRef(db, patientId));
2852
+ const locationDoc = await (0, import_firestore11.getDoc)(getLocationInfoDocRef(db, patientId));
2493
2853
  return locationDoc.exists() ? locationDoc.data() : null;
2494
2854
  };
2495
2855
  var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
@@ -2506,8 +2866,8 @@ var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
2506
2866
  ])
2507
2867
  };
2508
2868
  }
2509
- updateData.updatedAt = (0, import_firestore9.serverTimestamp)();
2510
- await (0, import_firestore9.updateDoc)(getLocationInfoDocRef(db, patientId), updateData);
2869
+ updateData.updatedAt = (0, import_firestore11.serverTimestamp)();
2870
+ await (0, import_firestore11.updateDoc)(getLocationInfoDocRef(db, patientId), updateData);
2511
2871
  const updatedInfo = await getLocationInfoUtil(db, patientId, requesterId);
2512
2872
  if (!updatedInfo) {
2513
2873
  throw new Error("Failed to retrieve updated location information");
@@ -2516,127 +2876,127 @@ var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
2516
2876
  };
2517
2877
 
2518
2878
  // src/services/patient/utils/medical-stuff.utils.ts
2519
- var import_firestore10 = require("firebase/firestore");
2879
+ var import_firestore12 = require("firebase/firestore");
2520
2880
  var addDoctorUtil = async (db, patientId, doctorRef, assignedBy) => {
2521
2881
  var _a;
2522
2882
  const newDoctor = {
2523
2883
  userRef: doctorRef,
2524
- assignedAt: import_firestore10.Timestamp.now(),
2884
+ assignedAt: import_firestore12.Timestamp.now(),
2525
2885
  assignedBy,
2526
2886
  isActive: true
2527
2887
  };
2528
- const patientDoc = await (0, import_firestore10.getDoc)(getPatientDocRef(db, patientId));
2888
+ const patientDoc = await (0, import_firestore12.getDoc)(getPatientDocRef(db, patientId));
2529
2889
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2530
2890
  const patientData = patientDoc.data();
2531
2891
  const existingDoctorIndex = (_a = patientData.doctors) == null ? void 0 : _a.findIndex(
2532
2892
  (d) => d.userRef === doctorRef
2533
2893
  );
2534
2894
  const updates = {
2535
- updatedAt: (0, import_firestore10.serverTimestamp)(),
2536
- doctorIds: (0, import_firestore10.arrayUnion)(doctorRef)
2895
+ updatedAt: (0, import_firestore12.serverTimestamp)(),
2896
+ doctorIds: (0, import_firestore12.arrayUnion)(doctorRef)
2537
2897
  };
2538
2898
  if (existingDoctorIndex !== void 0 && existingDoctorIndex > -1) {
2539
2899
  const updatedDoctors = [...patientData.doctors];
2540
2900
  updatedDoctors[existingDoctorIndex] = {
2541
2901
  ...updatedDoctors[existingDoctorIndex],
2542
2902
  isActive: true,
2543
- assignedAt: import_firestore10.Timestamp.now(),
2903
+ assignedAt: import_firestore12.Timestamp.now(),
2544
2904
  assignedBy
2545
2905
  };
2546
2906
  updates.doctors = updatedDoctors;
2547
2907
  } else {
2548
- updates.doctors = (0, import_firestore10.arrayUnion)(newDoctor);
2908
+ updates.doctors = (0, import_firestore12.arrayUnion)(newDoctor);
2549
2909
  }
2550
- await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), updates);
2910
+ await (0, import_firestore12.updateDoc)(getPatientDocRef(db, patientId), updates);
2551
2911
  };
2552
2912
  var removeDoctorUtil = async (db, patientId, doctorRef) => {
2553
2913
  var _a;
2554
2914
  const patientDocRef = getPatientDocRef(db, patientId);
2555
- const patientDoc = await (0, import_firestore10.getDoc)(patientDocRef);
2915
+ const patientDoc = await (0, import_firestore12.getDoc)(patientDocRef);
2556
2916
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2557
2917
  const patientData = patientDoc.data();
2558
2918
  const updatedDoctors = ((_a = patientData.doctors) == null ? void 0 : _a.filter((doctor) => doctor.userRef !== doctorRef)) || [];
2559
- await (0, import_firestore10.updateDoc)(patientDocRef, {
2919
+ await (0, import_firestore12.updateDoc)(patientDocRef, {
2560
2920
  doctors: updatedDoctors,
2561
2921
  // Set the filtered array
2562
- doctorIds: (0, import_firestore10.arrayRemove)(doctorRef),
2922
+ doctorIds: (0, import_firestore12.arrayRemove)(doctorRef),
2563
2923
  // Remove ID from the denormalized list
2564
- updatedAt: (0, import_firestore10.serverTimestamp)()
2924
+ updatedAt: (0, import_firestore12.serverTimestamp)()
2565
2925
  });
2566
2926
  };
2567
2927
  var addClinicUtil = async (db, patientId, clinicId, assignedBy) => {
2568
2928
  var _a;
2569
2929
  const newClinic = {
2570
2930
  clinicId,
2571
- assignedAt: import_firestore10.Timestamp.now(),
2931
+ assignedAt: import_firestore12.Timestamp.now(),
2572
2932
  assignedBy,
2573
2933
  isActive: true
2574
2934
  };
2575
- const patientDoc = await (0, import_firestore10.getDoc)(getPatientDocRef(db, patientId));
2935
+ const patientDoc = await (0, import_firestore12.getDoc)(getPatientDocRef(db, patientId));
2576
2936
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2577
2937
  const patientData = patientDoc.data();
2578
2938
  const existingClinicIndex = (_a = patientData.clinics) == null ? void 0 : _a.findIndex(
2579
2939
  (c) => c.clinicId === clinicId
2580
2940
  );
2581
2941
  const updates = {
2582
- updatedAt: (0, import_firestore10.serverTimestamp)(),
2583
- clinicIds: (0, import_firestore10.arrayUnion)(clinicId)
2942
+ updatedAt: (0, import_firestore12.serverTimestamp)(),
2943
+ clinicIds: (0, import_firestore12.arrayUnion)(clinicId)
2584
2944
  };
2585
2945
  if (existingClinicIndex !== void 0 && existingClinicIndex > -1) {
2586
2946
  const updatedClinics = [...patientData.clinics];
2587
2947
  updatedClinics[existingClinicIndex] = {
2588
2948
  ...updatedClinics[existingClinicIndex],
2589
2949
  isActive: true,
2590
- assignedAt: import_firestore10.Timestamp.now(),
2950
+ assignedAt: import_firestore12.Timestamp.now(),
2591
2951
  assignedBy
2592
2952
  };
2593
2953
  updates.clinics = updatedClinics;
2594
2954
  } else {
2595
- updates.clinics = (0, import_firestore10.arrayUnion)(newClinic);
2955
+ updates.clinics = (0, import_firestore12.arrayUnion)(newClinic);
2596
2956
  }
2597
- await (0, import_firestore10.updateDoc)(getPatientDocRef(db, patientId), updates);
2957
+ await (0, import_firestore12.updateDoc)(getPatientDocRef(db, patientId), updates);
2598
2958
  };
2599
2959
  var removeClinicUtil = async (db, patientId, clinicId) => {
2600
2960
  var _a;
2601
2961
  const patientDocRef = getPatientDocRef(db, patientId);
2602
- const patientDoc = await (0, import_firestore10.getDoc)(patientDocRef);
2962
+ const patientDoc = await (0, import_firestore12.getDoc)(patientDocRef);
2603
2963
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2604
2964
  const patientData = patientDoc.data();
2605
2965
  const updatedClinics = ((_a = patientData.clinics) == null ? void 0 : _a.filter((clinic) => clinic.clinicId !== clinicId)) || [];
2606
- await (0, import_firestore10.updateDoc)(patientDocRef, {
2966
+ await (0, import_firestore12.updateDoc)(patientDocRef, {
2607
2967
  clinics: updatedClinics,
2608
2968
  // Set the filtered array
2609
- clinicIds: (0, import_firestore10.arrayRemove)(clinicId),
2969
+ clinicIds: (0, import_firestore12.arrayRemove)(clinicId),
2610
2970
  // Remove ID from the denormalized list
2611
- updatedAt: (0, import_firestore10.serverTimestamp)()
2971
+ updatedAt: (0, import_firestore12.serverTimestamp)()
2612
2972
  });
2613
2973
  };
2614
2974
 
2615
2975
  // src/services/patient/utils/clinic.utils.ts
2616
- var import_firestore11 = require("firebase/firestore");
2976
+ var import_firestore13 = require("firebase/firestore");
2617
2977
  var getPatientsByClinicUtil = async (db, clinicId, options) => {
2618
2978
  try {
2619
2979
  console.log(
2620
2980
  `[getPatientsByClinicUtil] Fetching patients for clinic ID: ${clinicId} with options:`,
2621
2981
  options
2622
2982
  );
2623
- const patientsCollection = (0, import_firestore11.collection)(db, PATIENTS_COLLECTION);
2983
+ const patientsCollection = (0, import_firestore13.collection)(db, PATIENTS_COLLECTION);
2624
2984
  const constraints = [
2625
- (0, import_firestore11.where)("clinicIds", "array-contains", clinicId)
2985
+ (0, import_firestore13.where)("clinicIds", "array-contains", clinicId)
2626
2986
  ];
2627
- let q = (0, import_firestore11.query)(patientsCollection, ...constraints);
2987
+ let q = (0, import_firestore13.query)(patientsCollection, ...constraints);
2628
2988
  if (options == null ? void 0 : options.limit) {
2629
- q = (0, import_firestore11.query)(q, (0, import_firestore11.limit)(options.limit));
2989
+ q = (0, import_firestore13.query)(q, (0, import_firestore13.limit)(options.limit));
2630
2990
  }
2631
2991
  if (options == null ? void 0 : options.startAfter) {
2632
- const startAfterDoc = await (0, import_firestore11.getDoc)(
2633
- (0, import_firestore11.doc)(db, PATIENTS_COLLECTION, options.startAfter)
2992
+ const startAfterDoc = await (0, import_firestore13.getDoc)(
2993
+ (0, import_firestore13.doc)(db, PATIENTS_COLLECTION, options.startAfter)
2634
2994
  );
2635
2995
  if (startAfterDoc.exists()) {
2636
- q = (0, import_firestore11.query)(q, (0, import_firestore11.startAfter)(startAfterDoc));
2996
+ q = (0, import_firestore13.query)(q, (0, import_firestore13.startAfter)(startAfterDoc));
2637
2997
  }
2638
2998
  }
2639
- const patientsSnapshot = await (0, import_firestore11.getDocs)(q);
2999
+ const patientsSnapshot = await (0, import_firestore13.getDocs)(q);
2640
3000
  const patients = [];
2641
3001
  patientsSnapshot.forEach((doc34) => {
2642
3002
  patients.push(doc34.data());
@@ -2660,6 +3020,7 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2660
3020
  var PatientService = class extends BaseService {
2661
3021
  constructor(db, auth, app) {
2662
3022
  super(db, auth, app);
3023
+ this.mediaService = new MediaService(db, auth, app);
2663
3024
  }
2664
3025
  // Metode za rad sa profilom pacijenta
2665
3026
  async createPatientProfile(data) {
@@ -2696,7 +3057,12 @@ var PatientService = class extends BaseService {
2696
3057
  }
2697
3058
  // Metode za rad sa osetljivim informacijama
2698
3059
  async createSensitiveInfo(data, requesterUserId) {
2699
- return createSensitiveInfoUtil(this.db, data, requesterUserId);
3060
+ return createSensitiveInfoUtil(
3061
+ this.db,
3062
+ data,
3063
+ requesterUserId,
3064
+ this.mediaService
3065
+ );
2700
3066
  }
2701
3067
  async getSensitiveInfo(patientId, requesterUserId) {
2702
3068
  return getSensitiveInfoUtil(this.db, patientId, requesterUserId);
@@ -2707,7 +3073,13 @@ var PatientService = class extends BaseService {
2707
3073
  return this.getSensitiveInfo(profile.id, requesterUserId);
2708
3074
  }
2709
3075
  async updateSensitiveInfo(patientId, data, requesterUserId) {
2710
- return updateSensitiveInfoUtil(this.db, patientId, data, requesterUserId);
3076
+ return updateSensitiveInfoUtil(
3077
+ this.db,
3078
+ patientId,
3079
+ data,
3080
+ requesterUserId,
3081
+ this.mediaService
3082
+ );
2711
3083
  }
2712
3084
  // Metode za rad sa medicinskim informacijama
2713
3085
  async createMedicalInfo(patientId, data) {
@@ -2840,8 +3212,8 @@ var PatientService = class extends BaseService {
2840
3212
  if (!this.auth.currentUser) {
2841
3213
  throw new Error("No authenticated user");
2842
3214
  }
2843
- const userDoc = await (0, import_firestore12.getDoc)(
2844
- (0, import_firestore12.doc)(this.db, "users", this.auth.currentUser.uid)
3215
+ const userDoc = await (0, import_firestore14.getDoc)(
3216
+ (0, import_firestore14.doc)(this.db, "users", this.auth.currentUser.uid)
2845
3217
  );
2846
3218
  if (!userDoc.exists()) {
2847
3219
  throw new Error("User not found");
@@ -2852,7 +3224,7 @@ var PatientService = class extends BaseService {
2852
3224
  * Briše profil pacijenta i sve povezane subkolekcije
2853
3225
  */
2854
3226
  async deletePatientProfile(patientId) {
2855
- const batch = (0, import_firestore12.writeBatch)(this.db);
3227
+ const batch = (0, import_firestore14.writeBatch)(this.db);
2856
3228
  batch.delete(getSensitiveInfoDocRef(this.db, patientId));
2857
3229
  batch.delete(getLocationInfoDocRef(this.db, patientId));
2858
3230
  batch.delete(getMedicalInfoDocRef(this.db, patientId));
@@ -2876,14 +3248,113 @@ var PatientService = class extends BaseService {
2876
3248
  await removeClinicUtil(this.db, patientId, clinicId);
2877
3249
  }
2878
3250
  // Metode za rad sa profilnom slikom
3251
+ /**
3252
+ * Uploads a profile photo for a patient
3253
+ * @param patientId - ID of the patient
3254
+ * @param file - File or Blob to upload
3255
+ * @returns URL of the uploaded photo
3256
+ */
2879
3257
  async uploadProfilePhoto(patientId, file) {
2880
- return uploadProfilePhotoUtil(this.storage, patientId, file);
3258
+ console.log(
3259
+ `[PatientService] Uploading profile photo for patient ${patientId}`
3260
+ );
3261
+ const mediaMetadata = await this.mediaService.uploadMedia(
3262
+ file,
3263
+ patientId,
3264
+ // Using patientId as ownerId
3265
+ "private" /* PRIVATE */,
3266
+ // Profile photos should be private
3267
+ "patient_profile_photos",
3268
+ file instanceof File ? file.name : `profile_photo_${patientId}`
3269
+ );
3270
+ await (0, import_firestore14.updateDoc)(getSensitiveInfoDocRef(this.db, patientId), {
3271
+ photoUrl: mediaMetadata.url,
3272
+ updatedAt: (0, import_firestore14.serverTimestamp)()
3273
+ });
3274
+ return mediaMetadata.url;
2881
3275
  }
3276
+ /**
3277
+ * Updates a patient's profile photo (replaces existing one)
3278
+ * @param patientId - ID of the patient
3279
+ * @param file - New file or Blob to upload
3280
+ * @returns URL of the new uploaded photo
3281
+ */
2882
3282
  async updateProfilePhoto(patientId, file) {
2883
- return updateProfilePhotoUtil(this.storage, this.db, patientId, file);
3283
+ console.log(
3284
+ `[PatientService] Updating profile photo for patient ${patientId}`
3285
+ );
3286
+ const currentUser = await this.getCurrentUser();
3287
+ const currentSensitiveInfo = await this.getSensitiveInfo(
3288
+ patientId,
3289
+ currentUser.uid
3290
+ );
3291
+ if ((currentSensitiveInfo == null ? void 0 : currentSensitiveInfo.photoUrl) && typeof currentSensitiveInfo.photoUrl === "string") {
3292
+ try {
3293
+ const existingMediaMetadata = await this.mediaService.getMediaMetadataByUrl(
3294
+ currentSensitiveInfo.photoUrl
3295
+ );
3296
+ if (existingMediaMetadata) {
3297
+ await this.mediaService.deleteMedia(existingMediaMetadata.id);
3298
+ }
3299
+ } catch (error) {
3300
+ console.warn(
3301
+ `[PatientService] Could not delete old profile photo for patient ${patientId}:`,
3302
+ error
3303
+ );
3304
+ }
3305
+ }
3306
+ return this.uploadProfilePhoto(patientId, file);
2884
3307
  }
3308
+ /**
3309
+ * Deletes a patient's profile photo
3310
+ * @param patientId - ID of the patient
3311
+ */
2885
3312
  async deleteProfilePhoto(patientId) {
2886
- await deleteProfilePhotoUtil(this.storage, this.db, patientId);
3313
+ console.log(
3314
+ `[PatientService] Deleting profile photo for patient ${patientId}`
3315
+ );
3316
+ const currentUser = await this.getCurrentUser();
3317
+ const currentSensitiveInfo = await this.getSensitiveInfo(
3318
+ patientId,
3319
+ currentUser.uid
3320
+ );
3321
+ if ((currentSensitiveInfo == null ? void 0 : currentSensitiveInfo.photoUrl) && typeof currentSensitiveInfo.photoUrl === "string") {
3322
+ try {
3323
+ const existingMediaMetadata = await this.mediaService.getMediaMetadataByUrl(
3324
+ currentSensitiveInfo.photoUrl
3325
+ );
3326
+ if (existingMediaMetadata) {
3327
+ await this.mediaService.deleteMedia(existingMediaMetadata.id);
3328
+ }
3329
+ } catch (error) {
3330
+ console.warn(
3331
+ `[PatientService] Could not delete profile photo for patient ${patientId}:`,
3332
+ error
3333
+ );
3334
+ }
3335
+ await (0, import_firestore14.updateDoc)(getSensitiveInfoDocRef(this.db, patientId), {
3336
+ photoUrl: null,
3337
+ updatedAt: (0, import_firestore14.serverTimestamp)()
3338
+ });
3339
+ }
3340
+ }
3341
+ /**
3342
+ * Handles profile photo upload for patients (supports MediaResource)
3343
+ * @param photoUrl - MediaResource (File, Blob, or URL string) from CreatePatientSensitiveInfoData
3344
+ * @param patientId - ID of the patient
3345
+ * @returns URL string of the uploaded or existing photo
3346
+ */
3347
+ async handleProfilePhotoUpload(photoUrl, patientId) {
3348
+ if (!photoUrl) {
3349
+ return void 0;
3350
+ }
3351
+ if (typeof photoUrl === "string") {
3352
+ return photoUrl;
3353
+ }
3354
+ if (photoUrl instanceof File || photoUrl instanceof Blob) {
3355
+ return this.uploadProfilePhoto(patientId, photoUrl);
3356
+ }
3357
+ return void 0;
2887
3358
  }
2888
3359
  // Metode za ažuriranje profila
2889
3360
  async updatePatientProfile(patientId, data) {
@@ -2976,7 +3447,7 @@ var PatientService = class extends BaseService {
2976
3447
  };
2977
3448
 
2978
3449
  // src/services/clinic/utils/admin.utils.ts
2979
- var import_firestore14 = require("firebase/firestore");
3450
+ var import_firestore16 = require("firebase/firestore");
2980
3451
 
2981
3452
  // src/types/clinic/preferences.types.ts
2982
3453
  var PracticeType = /* @__PURE__ */ ((PracticeType2) => {
@@ -3103,131 +3574,131 @@ var SubscriptionModel = /* @__PURE__ */ ((SubscriptionModel2) => {
3103
3574
 
3104
3575
  // src/validations/clinic.schema.ts
3105
3576
  var import_zod13 = require("zod");
3106
- var import_firestore13 = require("firebase/firestore");
3577
+ var import_firestore15 = require("firebase/firestore");
3107
3578
 
3108
3579
  // src/validations/reviews.schema.ts
3109
- var import_zod10 = require("zod");
3110
- var baseReviewSchema = import_zod10.z.object({
3111
- id: import_zod10.z.string().min(1),
3112
- patientId: import_zod10.z.string().min(1),
3113
- fullReviewId: import_zod10.z.string().min(1),
3114
- createdAt: import_zod10.z.date(),
3115
- updatedAt: import_zod10.z.date(),
3116
- comment: import_zod10.z.string().min(1).max(2e3),
3117
- isVerified: import_zod10.z.boolean(),
3118
- isPublished: import_zod10.z.boolean()
3580
+ var import_zod11 = require("zod");
3581
+ var baseReviewSchema = import_zod11.z.object({
3582
+ id: import_zod11.z.string().min(1),
3583
+ patientId: import_zod11.z.string().min(1),
3584
+ fullReviewId: import_zod11.z.string().min(1),
3585
+ createdAt: import_zod11.z.date(),
3586
+ updatedAt: import_zod11.z.date(),
3587
+ comment: import_zod11.z.string().min(1).max(2e3),
3588
+ isVerified: import_zod11.z.boolean(),
3589
+ isPublished: import_zod11.z.boolean()
3119
3590
  });
3120
- var baseReviewCreateSchema = import_zod10.z.object({
3121
- patientId: import_zod10.z.string().min(1),
3122
- comment: import_zod10.z.string().min(1).max(2e3),
3123
- isVerified: import_zod10.z.boolean().default(false),
3124
- isPublished: import_zod10.z.boolean().default(true)
3591
+ var baseReviewCreateSchema = import_zod11.z.object({
3592
+ patientId: import_zod11.z.string().min(1),
3593
+ comment: import_zod11.z.string().min(1).max(2e3),
3594
+ isVerified: import_zod11.z.boolean().default(false),
3595
+ isPublished: import_zod11.z.boolean().default(true)
3125
3596
  });
3126
3597
  var clinicReviewSchema = baseReviewSchema.extend({
3127
- clinicId: import_zod10.z.string().min(1),
3128
- cleanliness: import_zod10.z.number().min(1).max(5),
3129
- facilities: import_zod10.z.number().min(1).max(5),
3130
- staffFriendliness: import_zod10.z.number().min(1).max(5),
3131
- waitingTime: import_zod10.z.number().min(1).max(5),
3132
- accessibility: import_zod10.z.number().min(1).max(5),
3133
- overallRating: import_zod10.z.number().min(1).max(5),
3134
- wouldRecommend: import_zod10.z.boolean()
3598
+ clinicId: import_zod11.z.string().min(1),
3599
+ cleanliness: import_zod11.z.number().min(1).max(5),
3600
+ facilities: import_zod11.z.number().min(1).max(5),
3601
+ staffFriendliness: import_zod11.z.number().min(1).max(5),
3602
+ waitingTime: import_zod11.z.number().min(1).max(5),
3603
+ accessibility: import_zod11.z.number().min(1).max(5),
3604
+ overallRating: import_zod11.z.number().min(1).max(5),
3605
+ wouldRecommend: import_zod11.z.boolean()
3135
3606
  });
3136
3607
  var createClinicReviewSchema = baseReviewCreateSchema.extend({
3137
- clinicId: import_zod10.z.string().min(1),
3138
- cleanliness: import_zod10.z.number().min(1).max(5),
3139
- facilities: import_zod10.z.number().min(1).max(5),
3140
- staffFriendliness: import_zod10.z.number().min(1).max(5),
3141
- waitingTime: import_zod10.z.number().min(1).max(5),
3142
- accessibility: import_zod10.z.number().min(1).max(5),
3143
- wouldRecommend: import_zod10.z.boolean()
3608
+ clinicId: import_zod11.z.string().min(1),
3609
+ cleanliness: import_zod11.z.number().min(1).max(5),
3610
+ facilities: import_zod11.z.number().min(1).max(5),
3611
+ staffFriendliness: import_zod11.z.number().min(1).max(5),
3612
+ waitingTime: import_zod11.z.number().min(1).max(5),
3613
+ accessibility: import_zod11.z.number().min(1).max(5),
3614
+ wouldRecommend: import_zod11.z.boolean()
3144
3615
  });
3145
3616
  var practitionerReviewSchema = baseReviewSchema.extend({
3146
- practitionerId: import_zod10.z.string().min(1),
3147
- knowledgeAndExpertise: import_zod10.z.number().min(1).max(5),
3148
- communicationSkills: import_zod10.z.number().min(1).max(5),
3149
- bedSideManner: import_zod10.z.number().min(1).max(5),
3150
- thoroughness: import_zod10.z.number().min(1).max(5),
3151
- trustworthiness: import_zod10.z.number().min(1).max(5),
3152
- overallRating: import_zod10.z.number().min(1).max(5),
3153
- wouldRecommend: import_zod10.z.boolean()
3617
+ practitionerId: import_zod11.z.string().min(1),
3618
+ knowledgeAndExpertise: import_zod11.z.number().min(1).max(5),
3619
+ communicationSkills: import_zod11.z.number().min(1).max(5),
3620
+ bedSideManner: import_zod11.z.number().min(1).max(5),
3621
+ thoroughness: import_zod11.z.number().min(1).max(5),
3622
+ trustworthiness: import_zod11.z.number().min(1).max(5),
3623
+ overallRating: import_zod11.z.number().min(1).max(5),
3624
+ wouldRecommend: import_zod11.z.boolean()
3154
3625
  });
3155
3626
  var createPractitionerReviewSchema = baseReviewCreateSchema.extend({
3156
- practitionerId: import_zod10.z.string().min(1),
3157
- knowledgeAndExpertise: import_zod10.z.number().min(1).max(5),
3158
- communicationSkills: import_zod10.z.number().min(1).max(5),
3159
- bedSideManner: import_zod10.z.number().min(1).max(5),
3160
- thoroughness: import_zod10.z.number().min(1).max(5),
3161
- trustworthiness: import_zod10.z.number().min(1).max(5),
3162
- wouldRecommend: import_zod10.z.boolean()
3627
+ practitionerId: import_zod11.z.string().min(1),
3628
+ knowledgeAndExpertise: import_zod11.z.number().min(1).max(5),
3629
+ communicationSkills: import_zod11.z.number().min(1).max(5),
3630
+ bedSideManner: import_zod11.z.number().min(1).max(5),
3631
+ thoroughness: import_zod11.z.number().min(1).max(5),
3632
+ trustworthiness: import_zod11.z.number().min(1).max(5),
3633
+ wouldRecommend: import_zod11.z.boolean()
3163
3634
  });
3164
3635
  var procedureReviewSchema = baseReviewSchema.extend({
3165
- procedureId: import_zod10.z.string().min(1),
3166
- effectivenessOfTreatment: import_zod10.z.number().min(1).max(5),
3167
- outcomeExplanation: import_zod10.z.number().min(1).max(5),
3168
- painManagement: import_zod10.z.number().min(1).max(5),
3169
- followUpCare: import_zod10.z.number().min(1).max(5),
3170
- valueForMoney: import_zod10.z.number().min(1).max(5),
3171
- overallRating: import_zod10.z.number().min(1).max(5),
3172
- wouldRecommend: import_zod10.z.boolean()
3636
+ procedureId: import_zod11.z.string().min(1),
3637
+ effectivenessOfTreatment: import_zod11.z.number().min(1).max(5),
3638
+ outcomeExplanation: import_zod11.z.number().min(1).max(5),
3639
+ painManagement: import_zod11.z.number().min(1).max(5),
3640
+ followUpCare: import_zod11.z.number().min(1).max(5),
3641
+ valueForMoney: import_zod11.z.number().min(1).max(5),
3642
+ overallRating: import_zod11.z.number().min(1).max(5),
3643
+ wouldRecommend: import_zod11.z.boolean()
3173
3644
  });
3174
3645
  var createProcedureReviewSchema = baseReviewCreateSchema.extend({
3175
- procedureId: import_zod10.z.string().min(1),
3176
- effectivenessOfTreatment: import_zod10.z.number().min(1).max(5),
3177
- outcomeExplanation: import_zod10.z.number().min(1).max(5),
3178
- painManagement: import_zod10.z.number().min(1).max(5),
3179
- followUpCare: import_zod10.z.number().min(1).max(5),
3180
- valueForMoney: import_zod10.z.number().min(1).max(5),
3181
- wouldRecommend: import_zod10.z.boolean()
3646
+ procedureId: import_zod11.z.string().min(1),
3647
+ effectivenessOfTreatment: import_zod11.z.number().min(1).max(5),
3648
+ outcomeExplanation: import_zod11.z.number().min(1).max(5),
3649
+ painManagement: import_zod11.z.number().min(1).max(5),
3650
+ followUpCare: import_zod11.z.number().min(1).max(5),
3651
+ valueForMoney: import_zod11.z.number().min(1).max(5),
3652
+ wouldRecommend: import_zod11.z.boolean()
3182
3653
  });
3183
- var clinicReviewInfoSchema = import_zod10.z.object({
3184
- totalReviews: import_zod10.z.number().min(0),
3185
- averageRating: import_zod10.z.number().min(0).max(5),
3186
- cleanliness: import_zod10.z.number().min(0).max(5),
3187
- facilities: import_zod10.z.number().min(0).max(5),
3188
- staffFriendliness: import_zod10.z.number().min(0).max(5),
3189
- waitingTime: import_zod10.z.number().min(0).max(5),
3190
- accessibility: import_zod10.z.number().min(0).max(5),
3191
- recommendationPercentage: import_zod10.z.number().min(0).max(100)
3654
+ var clinicReviewInfoSchema = import_zod11.z.object({
3655
+ totalReviews: import_zod11.z.number().min(0),
3656
+ averageRating: import_zod11.z.number().min(0).max(5),
3657
+ cleanliness: import_zod11.z.number().min(0).max(5),
3658
+ facilities: import_zod11.z.number().min(0).max(5),
3659
+ staffFriendliness: import_zod11.z.number().min(0).max(5),
3660
+ waitingTime: import_zod11.z.number().min(0).max(5),
3661
+ accessibility: import_zod11.z.number().min(0).max(5),
3662
+ recommendationPercentage: import_zod11.z.number().min(0).max(100)
3192
3663
  });
3193
- var practitionerReviewInfoSchema = import_zod10.z.object({
3194
- totalReviews: import_zod10.z.number().min(0),
3195
- averageRating: import_zod10.z.number().min(0).max(5),
3196
- knowledgeAndExpertise: import_zod10.z.number().min(0).max(5),
3197
- communicationSkills: import_zod10.z.number().min(0).max(5),
3198
- bedSideManner: import_zod10.z.number().min(0).max(5),
3199
- thoroughness: import_zod10.z.number().min(0).max(5),
3200
- trustworthiness: import_zod10.z.number().min(0).max(5),
3201
- recommendationPercentage: import_zod10.z.number().min(0).max(100)
3664
+ var practitionerReviewInfoSchema = import_zod11.z.object({
3665
+ totalReviews: import_zod11.z.number().min(0),
3666
+ averageRating: import_zod11.z.number().min(0).max(5),
3667
+ knowledgeAndExpertise: import_zod11.z.number().min(0).max(5),
3668
+ communicationSkills: import_zod11.z.number().min(0).max(5),
3669
+ bedSideManner: import_zod11.z.number().min(0).max(5),
3670
+ thoroughness: import_zod11.z.number().min(0).max(5),
3671
+ trustworthiness: import_zod11.z.number().min(0).max(5),
3672
+ recommendationPercentage: import_zod11.z.number().min(0).max(100)
3202
3673
  });
3203
- var procedureReviewInfoSchema = import_zod10.z.object({
3204
- totalReviews: import_zod10.z.number().min(0),
3205
- averageRating: import_zod10.z.number().min(0).max(5),
3206
- effectivenessOfTreatment: import_zod10.z.number().min(0).max(5),
3207
- outcomeExplanation: import_zod10.z.number().min(0).max(5),
3208
- painManagement: import_zod10.z.number().min(0).max(5),
3209
- followUpCare: import_zod10.z.number().min(0).max(5),
3210
- valueForMoney: import_zod10.z.number().min(0).max(5),
3211
- recommendationPercentage: import_zod10.z.number().min(0).max(100)
3674
+ var procedureReviewInfoSchema = import_zod11.z.object({
3675
+ totalReviews: import_zod11.z.number().min(0),
3676
+ averageRating: import_zod11.z.number().min(0).max(5),
3677
+ effectivenessOfTreatment: import_zod11.z.number().min(0).max(5),
3678
+ outcomeExplanation: import_zod11.z.number().min(0).max(5),
3679
+ painManagement: import_zod11.z.number().min(0).max(5),
3680
+ followUpCare: import_zod11.z.number().min(0).max(5),
3681
+ valueForMoney: import_zod11.z.number().min(0).max(5),
3682
+ recommendationPercentage: import_zod11.z.number().min(0).max(100)
3212
3683
  });
3213
- var reviewSchema = import_zod10.z.object({
3214
- id: import_zod10.z.string().min(1),
3215
- appointmentId: import_zod10.z.string().min(1),
3216
- patientId: import_zod10.z.string().min(1),
3217
- createdAt: import_zod10.z.date(),
3218
- updatedAt: import_zod10.z.date(),
3684
+ var reviewSchema = import_zod11.z.object({
3685
+ id: import_zod11.z.string().min(1),
3686
+ appointmentId: import_zod11.z.string().min(1),
3687
+ patientId: import_zod11.z.string().min(1),
3688
+ createdAt: import_zod11.z.date(),
3689
+ updatedAt: import_zod11.z.date(),
3219
3690
  clinicReview: clinicReviewSchema.optional(),
3220
3691
  practitionerReview: practitionerReviewSchema.optional(),
3221
3692
  procedureReview: procedureReviewSchema.optional(),
3222
- overallComment: import_zod10.z.string().min(1).max(2e3),
3223
- overallRating: import_zod10.z.number().min(1).max(5)
3693
+ overallComment: import_zod11.z.string().min(1).max(2e3),
3694
+ overallRating: import_zod11.z.number().min(1).max(5)
3224
3695
  });
3225
- var createReviewSchema = import_zod10.z.object({
3226
- patientId: import_zod10.z.string().min(1),
3696
+ var createReviewSchema = import_zod11.z.object({
3697
+ patientId: import_zod11.z.string().min(1),
3227
3698
  clinicReview: createClinicReviewSchema.optional(),
3228
3699
  practitionerReview: createPractitionerReviewSchema.optional(),
3229
3700
  procedureReview: createProcedureReviewSchema.optional(),
3230
- overallComment: import_zod10.z.string().min(1).max(2e3)
3701
+ overallComment: import_zod11.z.string().min(1).max(2e3)
3231
3702
  }).refine(
3232
3703
  (data) => {
3233
3704
  return data.clinicReview || data.practitionerReview || data.procedureReview;
@@ -3239,7 +3710,7 @@ var createReviewSchema = import_zod10.z.object({
3239
3710
  );
3240
3711
 
3241
3712
  // src/validations/shared.schema.ts
3242
- var import_zod11 = require("zod");
3713
+ var import_zod12 = require("zod");
3243
3714
 
3244
3715
  // src/backoffice/types/static/procedure-family.types.ts
3245
3716
  var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
@@ -3268,65 +3739,57 @@ var Currency = /* @__PURE__ */ ((Currency2) => {
3268
3739
  })(Currency || {});
3269
3740
 
3270
3741
  // src/validations/shared.schema.ts
3271
- var sharedClinicContactInfoSchema = import_zod11.z.object({
3272
- email: import_zod11.z.string().email(),
3273
- phoneNumber: import_zod11.z.string(),
3274
- alternativePhoneNumber: import_zod11.z.string().nullable().optional(),
3275
- website: import_zod11.z.string().nullable().optional()
3742
+ var sharedClinicContactInfoSchema = import_zod12.z.object({
3743
+ email: import_zod12.z.string().email(),
3744
+ phoneNumber: import_zod12.z.string(),
3745
+ alternativePhoneNumber: import_zod12.z.string().nullable().optional(),
3746
+ website: import_zod12.z.string().nullable().optional()
3276
3747
  });
3277
- var sharedClinicLocationSchema = import_zod11.z.object({
3278
- address: import_zod11.z.string(),
3279
- city: import_zod11.z.string(),
3280
- country: import_zod11.z.string(),
3281
- postalCode: import_zod11.z.string(),
3282
- latitude: import_zod11.z.number().min(-90).max(90),
3283
- longitude: import_zod11.z.number().min(-180).max(180),
3284
- geohash: import_zod11.z.string().nullable().optional()
3748
+ var sharedClinicLocationSchema = import_zod12.z.object({
3749
+ address: import_zod12.z.string(),
3750
+ city: import_zod12.z.string(),
3751
+ country: import_zod12.z.string(),
3752
+ postalCode: import_zod12.z.string(),
3753
+ latitude: import_zod12.z.number().min(-90).max(90),
3754
+ longitude: import_zod12.z.number().min(-180).max(180),
3755
+ geohash: import_zod12.z.string().nullable().optional()
3285
3756
  });
3286
- var procedureSummaryInfoSchema = import_zod11.z.object({
3287
- id: import_zod11.z.string().min(1),
3288
- name: import_zod11.z.string().min(1),
3289
- description: import_zod11.z.string().optional(),
3290
- photo: import_zod11.z.string().optional(),
3291
- family: import_zod11.z.nativeEnum(ProcedureFamily),
3292
- categoryName: import_zod11.z.string(),
3293
- subcategoryName: import_zod11.z.string(),
3294
- technologyName: import_zod11.z.string(),
3295
- price: import_zod11.z.number().nonnegative(),
3296
- pricingMeasure: import_zod11.z.nativeEnum(PricingMeasure),
3297
- currency: import_zod11.z.nativeEnum(Currency),
3298
- duration: import_zod11.z.number().int().positive(),
3299
- clinicId: import_zod11.z.string().min(1),
3300
- clinicName: import_zod11.z.string().min(1),
3301
- practitionerId: import_zod11.z.string().min(1),
3302
- practitionerName: import_zod11.z.string().min(1)
3757
+ var procedureSummaryInfoSchema = import_zod12.z.object({
3758
+ id: import_zod12.z.string().min(1),
3759
+ name: import_zod12.z.string().min(1),
3760
+ description: import_zod12.z.string().optional(),
3761
+ photo: import_zod12.z.string().optional(),
3762
+ family: import_zod12.z.nativeEnum(ProcedureFamily),
3763
+ categoryName: import_zod12.z.string(),
3764
+ subcategoryName: import_zod12.z.string(),
3765
+ technologyName: import_zod12.z.string(),
3766
+ price: import_zod12.z.number().nonnegative(),
3767
+ pricingMeasure: import_zod12.z.nativeEnum(PricingMeasure),
3768
+ currency: import_zod12.z.nativeEnum(Currency),
3769
+ duration: import_zod12.z.number().int().positive(),
3770
+ clinicId: import_zod12.z.string().min(1),
3771
+ clinicName: import_zod12.z.string().min(1),
3772
+ practitionerId: import_zod12.z.string().min(1),
3773
+ practitionerName: import_zod12.z.string().min(1)
3303
3774
  });
3304
- var clinicInfoSchema = import_zod11.z.object({
3305
- id: import_zod11.z.string(),
3306
- featuredPhoto: import_zod11.z.string(),
3307
- name: import_zod11.z.string(),
3308
- description: import_zod11.z.string().nullable().optional(),
3775
+ var clinicInfoSchema = import_zod12.z.object({
3776
+ id: import_zod12.z.string(),
3777
+ featuredPhoto: import_zod12.z.string(),
3778
+ name: import_zod12.z.string(),
3779
+ description: import_zod12.z.string().nullable().optional(),
3309
3780
  location: sharedClinicLocationSchema,
3310
3781
  contactInfo: sharedClinicContactInfoSchema
3311
3782
  });
3312
- var doctorInfoSchema = import_zod11.z.object({
3313
- id: import_zod11.z.string(),
3314
- name: import_zod11.z.string(),
3315
- description: import_zod11.z.string().nullable().optional(),
3316
- photo: import_zod11.z.string(),
3317
- rating: import_zod11.z.number().min(0).max(5),
3318
- services: import_zod11.z.array(import_zod11.z.string())
3783
+ var doctorInfoSchema = import_zod12.z.object({
3784
+ id: import_zod12.z.string(),
3785
+ name: import_zod12.z.string(),
3786
+ description: import_zod12.z.string().nullable().optional(),
3787
+ photo: import_zod12.z.string(),
3788
+ rating: import_zod12.z.number().min(0).max(5),
3789
+ services: import_zod12.z.array(import_zod12.z.string())
3319
3790
  // List of procedure IDs practitioner offers
3320
3791
  });
3321
3792
 
3322
- // src/validations/media.schema.ts
3323
- var import_zod12 = require("zod");
3324
- var mediaResourceSchema = import_zod12.z.union([
3325
- import_zod12.z.string(),
3326
- import_zod12.z.instanceof(File),
3327
- import_zod12.z.instanceof(Blob)
3328
- ]);
3329
-
3330
3793
  // src/validations/clinic.schema.ts
3331
3794
  var clinicContactInfoSchema = import_zod13.z.object({
3332
3795
  email: import_zod13.z.string().email(),
@@ -3386,8 +3849,8 @@ var clinicAdminSchema = import_zod13.z.object({
3386
3849
  clinicsManagedInfo: import_zod13.z.array(clinicInfoSchema),
3387
3850
  contactInfo: contactPersonSchema,
3388
3851
  roleTitle: import_zod13.z.string(),
3389
- createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3390
- updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3852
+ createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3853
+ updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3391
3854
  isActive: import_zod13.z.boolean()
3392
3855
  });
3393
3856
  var adminTokenSchema = import_zod13.z.object({
@@ -3396,9 +3859,9 @@ var adminTokenSchema = import_zod13.z.object({
3396
3859
  email: import_zod13.z.string().email().optional().nullable(),
3397
3860
  status: import_zod13.z.nativeEnum(AdminTokenStatus),
3398
3861
  usedByUserRef: import_zod13.z.string().optional(),
3399
- createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3862
+ createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3400
3863
  // Timestamp
3401
- expiresAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp))
3864
+ expiresAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp))
3402
3865
  // Timestamp
3403
3866
  });
3404
3867
  var createAdminTokenSchema = import_zod13.z.object({
@@ -3418,9 +3881,9 @@ var clinicGroupSchema = import_zod13.z.object({
3418
3881
  adminsInfo: import_zod13.z.array(adminInfoSchema),
3419
3882
  adminTokens: import_zod13.z.array(adminTokenSchema),
3420
3883
  ownerId: import_zod13.z.string().nullable(),
3421
- createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3884
+ createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3422
3885
  // Timestamp
3423
- updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3886
+ updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3424
3887
  // Timestamp
3425
3888
  isActive: import_zod13.z.boolean(),
3426
3889
  logo: mediaResourceSchema.optional().nullable(),
@@ -3462,9 +3925,9 @@ var clinicSchema = import_zod13.z.object({
3462
3925
  // Use the correct schema for aggregated procedure info
3463
3926
  reviewInfo: clinicReviewInfoSchema,
3464
3927
  admins: import_zod13.z.array(import_zod13.z.string()),
3465
- createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3928
+ createdAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3466
3929
  // Timestamp
3467
- updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore13.Timestamp)),
3930
+ updatedAt: import_zod13.z.instanceof(Date).or(import_zod13.z.instanceof(import_firestore15.Timestamp)),
3468
3931
  // Timestamp
3469
3932
  isActive: import_zod13.z.boolean(),
3470
3933
  isVerified: import_zod13.z.boolean(),
@@ -3686,7 +4149,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3686
4149
  }
3687
4150
  console.log("[CLINIC_ADMIN] Preparing admin data object");
3688
4151
  const adminData = {
3689
- id: (0, import_firestore14.doc)((0, import_firestore14.collection)(db, CLINIC_ADMINS_COLLECTION)).id,
4152
+ id: (0, import_firestore16.doc)((0, import_firestore16.collection)(db, CLINIC_ADMINS_COLLECTION)).id,
3690
4153
  // Generate a new ID for the admin document
3691
4154
  userRef: validatedData.userRef,
3692
4155
  clinicGroupId: clinicGroupId || "",
@@ -3699,15 +4162,15 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3699
4162
  contactInfo: validatedData.contactInfo,
3700
4163
  roleTitle: validatedData.roleTitle,
3701
4164
  isActive: validatedData.isActive,
3702
- createdAt: (0, import_firestore14.serverTimestamp)(),
3703
- updatedAt: (0, import_firestore14.serverTimestamp)()
4165
+ createdAt: (0, import_firestore16.serverTimestamp)(),
4166
+ updatedAt: (0, import_firestore16.serverTimestamp)()
3704
4167
  };
3705
4168
  console.log("[CLINIC_ADMIN] Validating complete admin object");
3706
4169
  try {
3707
4170
  clinicAdminSchema.parse({
3708
4171
  ...adminData,
3709
- createdAt: import_firestore14.Timestamp.now(),
3710
- updatedAt: import_firestore14.Timestamp.now()
4172
+ createdAt: import_firestore16.Timestamp.now(),
4173
+ updatedAt: import_firestore16.Timestamp.now()
3711
4174
  });
3712
4175
  console.log("[CLINIC_ADMIN] Admin object validation passed");
3713
4176
  } catch (schemaError) {
@@ -3721,7 +4184,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3721
4184
  adminId: adminData.id
3722
4185
  });
3723
4186
  try {
3724
- await (0, import_firestore14.setDoc)((0, import_firestore14.doc)(db, CLINIC_ADMINS_COLLECTION, adminData.id), adminData);
4187
+ await (0, import_firestore16.setDoc)((0, import_firestore16.doc)(db, CLINIC_ADMINS_COLLECTION, adminData.id), adminData);
3725
4188
  console.log("[CLINIC_ADMIN] Admin saved successfully");
3726
4189
  } catch (firestoreError) {
3727
4190
  console.error(
@@ -3770,30 +4233,30 @@ async function checkClinicGroupExists(db, groupId, clinicGroupService) {
3770
4233
  return !!group;
3771
4234
  }
3772
4235
  async function getClinicAdmin(db, adminId) {
3773
- const docRef = (0, import_firestore14.doc)(db, CLINIC_ADMINS_COLLECTION, adminId);
3774
- const docSnap = await (0, import_firestore14.getDoc)(docRef);
4236
+ const docRef = (0, import_firestore16.doc)(db, CLINIC_ADMINS_COLLECTION, adminId);
4237
+ const docSnap = await (0, import_firestore16.getDoc)(docRef);
3775
4238
  if (docSnap.exists()) {
3776
4239
  return docSnap.data();
3777
4240
  }
3778
4241
  return null;
3779
4242
  }
3780
4243
  async function getClinicAdminByUserRef(db, userRef) {
3781
- const q = (0, import_firestore14.query)(
3782
- (0, import_firestore14.collection)(db, CLINIC_ADMINS_COLLECTION),
3783
- (0, import_firestore14.where)("userRef", "==", userRef)
4244
+ const q = (0, import_firestore16.query)(
4245
+ (0, import_firestore16.collection)(db, CLINIC_ADMINS_COLLECTION),
4246
+ (0, import_firestore16.where)("userRef", "==", userRef)
3784
4247
  );
3785
- const querySnapshot = await (0, import_firestore14.getDocs)(q);
4248
+ const querySnapshot = await (0, import_firestore16.getDocs)(q);
3786
4249
  if (querySnapshot.empty) {
3787
4250
  return null;
3788
4251
  }
3789
4252
  return querySnapshot.docs[0].data();
3790
4253
  }
3791
4254
  async function getClinicAdminsByGroup(db, clinicGroupId) {
3792
- const q = (0, import_firestore14.query)(
3793
- (0, import_firestore14.collection)(db, CLINIC_ADMINS_COLLECTION),
3794
- (0, import_firestore14.where)("clinicGroupId", "==", clinicGroupId)
4255
+ const q = (0, import_firestore16.query)(
4256
+ (0, import_firestore16.collection)(db, CLINIC_ADMINS_COLLECTION),
4257
+ (0, import_firestore16.where)("clinicGroupId", "==", clinicGroupId)
3795
4258
  );
3796
- const querySnapshot = await (0, import_firestore14.getDocs)(q);
4259
+ const querySnapshot = await (0, import_firestore16.getDocs)(q);
3797
4260
  return querySnapshot.docs.map((doc34) => doc34.data());
3798
4261
  }
3799
4262
  async function updateClinicAdmin(db, adminId, data) {
@@ -3803,9 +4266,9 @@ async function updateClinicAdmin(db, adminId, data) {
3803
4266
  }
3804
4267
  const updatedData = {
3805
4268
  ...data,
3806
- updatedAt: (0, import_firestore14.serverTimestamp)()
4269
+ updatedAt: (0, import_firestore16.serverTimestamp)()
3807
4270
  };
3808
- await (0, import_firestore14.updateDoc)((0, import_firestore14.doc)(db, CLINIC_ADMINS_COLLECTION, adminId), updatedData);
4271
+ await (0, import_firestore16.updateDoc)((0, import_firestore16.doc)(db, CLINIC_ADMINS_COLLECTION, adminId), updatedData);
3809
4272
  const updatedAdmin = await getClinicAdmin(db, adminId);
3810
4273
  if (!updatedAdmin) {
3811
4274
  throw new Error("Failed to retrieve updated admin");
@@ -3817,7 +4280,7 @@ async function deleteClinicAdmin(db, adminId) {
3817
4280
  if (!admin) {
3818
4281
  throw new Error("Clinic admin not found");
3819
4282
  }
3820
- await (0, import_firestore14.deleteDoc)((0, import_firestore14.doc)(db, CLINIC_ADMINS_COLLECTION, adminId));
4283
+ await (0, import_firestore16.deleteDoc)((0, import_firestore16.doc)(db, CLINIC_ADMINS_COLLECTION, adminId));
3821
4284
  }
3822
4285
  async function addClinicToManaged(db, adminId, clinicId, requesterId, clinicService) {
3823
4286
  const admin = await getClinicAdmin(db, adminId);
@@ -4060,11 +4523,11 @@ var ClinicAdminService = class extends BaseService {
4060
4523
  };
4061
4524
 
4062
4525
  // src/services/practitioner/practitioner.service.ts
4063
- var import_firestore16 = require("firebase/firestore");
4526
+ var import_firestore18 = require("firebase/firestore");
4064
4527
 
4065
4528
  // src/validations/practitioner.schema.ts
4066
4529
  var import_zod14 = require("zod");
4067
- var import_firestore15 = require("firebase/firestore");
4530
+ var import_firestore17 = require("firebase/firestore");
4068
4531
 
4069
4532
  // src/backoffice/types/static/certification.types.ts
4070
4533
  var CertificationLevel = /* @__PURE__ */ ((CertificationLevel2) => {
@@ -4097,9 +4560,9 @@ var practitionerBasicInfoSchema = import_zod14.z.object({
4097
4560
  title: import_zod14.z.string().min(2).max(100),
4098
4561
  email: import_zod14.z.string().email(),
4099
4562
  phoneNumber: import_zod14.z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number"),
4100
- dateOfBirth: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4563
+ dateOfBirth: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4101
4564
  gender: import_zod14.z.enum(["male", "female", "other"]),
4102
- profileImageUrl: import_zod14.z.string().url().optional(),
4565
+ profileImageUrl: mediaResourceSchema.optional(),
4103
4566
  bio: import_zod14.z.string().max(1e3).optional(),
4104
4567
  languages: import_zod14.z.array(import_zod14.z.string()).min(1)
4105
4568
  });
@@ -4108,8 +4571,8 @@ var practitionerCertificationSchema = import_zod14.z.object({
4108
4571
  specialties: import_zod14.z.array(import_zod14.z.nativeEnum(CertificationSpecialty)),
4109
4572
  licenseNumber: import_zod14.z.string().min(3).max(50),
4110
4573
  issuingAuthority: import_zod14.z.string().min(2).max(100),
4111
- issueDate: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4112
- expiryDate: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()).optional(),
4574
+ issueDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4575
+ expiryDate: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).optional(),
4113
4576
  verificationStatus: import_zod14.z.enum(["pending", "verified", "rejected"])
4114
4577
  });
4115
4578
  var timeSlotSchema = import_zod14.z.object({
@@ -4126,8 +4589,8 @@ var practitionerWorkingHoursSchema = import_zod14.z.object({
4126
4589
  friday: timeSlotSchema,
4127
4590
  saturday: timeSlotSchema,
4128
4591
  sunday: timeSlotSchema,
4129
- createdAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4130
- updatedAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date())
4592
+ createdAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4593
+ updatedAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date())
4131
4594
  });
4132
4595
  var practitionerClinicWorkingHoursSchema = import_zod14.z.object({
4133
4596
  clinicId: import_zod14.z.string().min(1),
@@ -4141,8 +4604,8 @@ var practitionerClinicWorkingHoursSchema = import_zod14.z.object({
4141
4604
  sunday: timeSlotSchema
4142
4605
  }),
4143
4606
  isActive: import_zod14.z.boolean(),
4144
- createdAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4145
- updatedAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date())
4607
+ createdAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4608
+ updatedAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date())
4146
4609
  });
4147
4610
  var practitionerSchema = import_zod14.z.object({
4148
4611
  id: import_zod14.z.string().min(1),
@@ -4158,8 +4621,8 @@ var practitionerSchema = import_zod14.z.object({
4158
4621
  isActive: import_zod14.z.boolean(),
4159
4622
  isVerified: import_zod14.z.boolean(),
4160
4623
  status: import_zod14.z.nativeEnum(PractitionerStatus),
4161
- createdAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4162
- updatedAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date())
4624
+ createdAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4625
+ updatedAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date())
4163
4626
  });
4164
4627
  var createPractitionerSchema = import_zod14.z.object({
4165
4628
  userRef: import_zod14.z.string().min(1),
@@ -4191,10 +4654,10 @@ var practitionerTokenSchema = import_zod14.z.object({
4191
4654
  clinicId: import_zod14.z.string().min(1),
4192
4655
  status: import_zod14.z.nativeEnum(PractitionerTokenStatus),
4193
4656
  createdBy: import_zod14.z.string().min(1),
4194
- createdAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4195
- expiresAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()),
4657
+ createdAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4658
+ expiresAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()),
4196
4659
  usedBy: import_zod14.z.string().optional(),
4197
- usedAt: import_zod14.z.instanceof(import_firestore15.Timestamp).or(import_zod14.z.date()).optional()
4660
+ usedAt: import_zod14.z.instanceof(import_firestore17.Timestamp).or(import_zod14.z.date()).optional()
4198
4661
  });
4199
4662
  var createPractitionerTokenSchema = import_zod14.z.object({
4200
4663
  practitionerId: import_zod14.z.string().min(1),
@@ -4211,7 +4674,7 @@ var practitionerSignupSchema = import_zod14.z.object({
4211
4674
  profileData: import_zod14.z.object({
4212
4675
  basicInfo: import_zod14.z.object({
4213
4676
  phoneNumber: import_zod14.z.string().optional(),
4214
- profileImageUrl: import_zod14.z.string().optional(),
4677
+ profileImageUrl: mediaResourceSchema.optional(),
4215
4678
  gender: import_zod14.z.enum(["male", "female", "other"]).optional(),
4216
4679
  bio: import_zod14.z.string().optional()
4217
4680
  }).optional(),
@@ -4226,6 +4689,7 @@ var PractitionerService = class extends BaseService {
4226
4689
  constructor(db, auth, app, clinicService) {
4227
4690
  super(db, auth, app);
4228
4691
  this.clinicService = clinicService;
4692
+ this.mediaService = new MediaService(db, auth, app);
4229
4693
  }
4230
4694
  getClinicService() {
4231
4695
  if (!this.clinicService) {
@@ -4236,6 +4700,53 @@ var PractitionerService = class extends BaseService {
4236
4700
  setClinicService(clinicService) {
4237
4701
  this.clinicService = clinicService;
4238
4702
  }
4703
+ /**
4704
+ * Handles profile photo upload for practitioners
4705
+ * @param profilePhoto - MediaResource (File, Blob, or URL string)
4706
+ * @param practitionerId - ID of the practitioner
4707
+ * @returns URL string of the uploaded or existing photo
4708
+ */
4709
+ async handleProfilePhotoUpload(profilePhoto, practitionerId) {
4710
+ if (!profilePhoto) {
4711
+ return void 0;
4712
+ }
4713
+ if (typeof profilePhoto === "string") {
4714
+ return profilePhoto;
4715
+ }
4716
+ if (profilePhoto instanceof File || profilePhoto instanceof Blob) {
4717
+ console.log(
4718
+ `[PractitionerService] Uploading profile photo for practitioner ${practitionerId}`
4719
+ );
4720
+ const mediaMetadata = await this.mediaService.uploadMedia(
4721
+ profilePhoto,
4722
+ practitionerId,
4723
+ // Using practitionerId as ownerId
4724
+ "public" /* PUBLIC */,
4725
+ // Profile photos should be public
4726
+ "practitioner_profile_photos",
4727
+ profilePhoto instanceof File ? profilePhoto.name : `profile_photo_${practitionerId}`
4728
+ );
4729
+ return mediaMetadata.url;
4730
+ }
4731
+ return void 0;
4732
+ }
4733
+ /**
4734
+ * Processes BasicPractitionerInfo to handle profile photo uploads
4735
+ * @param basicInfo - The basic info containing potential MediaResource profile photo
4736
+ * @param practitionerId - ID of the practitioner
4737
+ * @returns Processed basic info with URL string for profileImageUrl
4738
+ */
4739
+ async processBasicInfo(basicInfo, practitionerId) {
4740
+ const processedBasicInfo = { ...basicInfo };
4741
+ if (basicInfo.profileImageUrl) {
4742
+ const uploadedUrl = await this.handleProfilePhotoUpload(
4743
+ basicInfo.profileImageUrl,
4744
+ practitionerId
4745
+ );
4746
+ processedBasicInfo.profileImageUrl = uploadedUrl;
4747
+ }
4748
+ return processedBasicInfo;
4749
+ }
4239
4750
  /**
4240
4751
  * Creates a new practitioner
4241
4752
  */
@@ -4256,7 +4767,10 @@ var PractitionerService = class extends BaseService {
4256
4767
  const practitioner = {
4257
4768
  id: practitionerId,
4258
4769
  userRef: validData.userRef,
4259
- basicInfo: validData.basicInfo,
4770
+ basicInfo: await this.processBasicInfo(
4771
+ validData.basicInfo,
4772
+ practitionerId
4773
+ ),
4260
4774
  certification: validData.certification,
4261
4775
  clinics: validData.clinics || [],
4262
4776
  clinicWorkingHours: validData.clinicWorkingHours || [],
@@ -4267,20 +4781,20 @@ var PractitionerService = class extends BaseService {
4267
4781
  isActive: validData.isActive !== void 0 ? validData.isActive : true,
4268
4782
  isVerified: validData.isVerified !== void 0 ? validData.isVerified : false,
4269
4783
  status: validData.status || "active" /* ACTIVE */,
4270
- createdAt: (0, import_firestore16.serverTimestamp)(),
4271
- updatedAt: (0, import_firestore16.serverTimestamp)()
4784
+ createdAt: (0, import_firestore18.serverTimestamp)(),
4785
+ updatedAt: (0, import_firestore18.serverTimestamp)()
4272
4786
  };
4273
4787
  practitionerSchema.parse({
4274
4788
  ...practitioner,
4275
- createdAt: import_firestore16.Timestamp.now(),
4276
- updatedAt: import_firestore16.Timestamp.now()
4789
+ createdAt: import_firestore18.Timestamp.now(),
4790
+ updatedAt: import_firestore18.Timestamp.now()
4277
4791
  });
4278
- const practitionerRef = (0, import_firestore16.doc)(
4792
+ const practitionerRef = (0, import_firestore18.doc)(
4279
4793
  this.db,
4280
4794
  PRACTITIONERS_COLLECTION,
4281
4795
  practitionerId
4282
4796
  );
4283
- await (0, import_firestore16.setDoc)(practitionerRef, practitioner);
4797
+ await (0, import_firestore18.setDoc)(practitionerRef, practitioner);
4284
4798
  const createdPractitioner = await this.getPractitioner(practitionerId);
4285
4799
  if (!createdPractitioner) {
4286
4800
  throw new Error(
@@ -4356,7 +4870,10 @@ var PractitionerService = class extends BaseService {
4356
4870
  id: practitionerId,
4357
4871
  userRef: "",
4358
4872
  // Prazno - biće popunjeno kada korisnik kreira nalog
4359
- basicInfo: validatedData.basicInfo,
4873
+ basicInfo: await this.processBasicInfo(
4874
+ validatedData.basicInfo,
4875
+ practitionerId
4876
+ ),
4360
4877
  certification: validatedData.certification,
4361
4878
  clinics,
4362
4879
  clinicWorkingHours: validatedData.clinicWorkingHours || [],
@@ -4367,17 +4884,17 @@ var PractitionerService = class extends BaseService {
4367
4884
  isActive: validatedData.isActive !== void 0 ? validatedData.isActive : false,
4368
4885
  isVerified: validatedData.isVerified !== void 0 ? validatedData.isVerified : false,
4369
4886
  status: "draft" /* DRAFT */,
4370
- createdAt: (0, import_firestore16.serverTimestamp)(),
4371
- updatedAt: (0, import_firestore16.serverTimestamp)()
4887
+ createdAt: (0, import_firestore18.serverTimestamp)(),
4888
+ updatedAt: (0, import_firestore18.serverTimestamp)()
4372
4889
  };
4373
4890
  practitionerSchema.parse({
4374
4891
  ...practitionerData,
4375
4892
  userRef: "temp-for-validation",
4376
- createdAt: import_firestore16.Timestamp.now(),
4377
- updatedAt: import_firestore16.Timestamp.now()
4893
+ createdAt: import_firestore18.Timestamp.now(),
4894
+ updatedAt: import_firestore18.Timestamp.now()
4378
4895
  });
4379
- await (0, import_firestore16.setDoc)(
4380
- (0, import_firestore16.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerData.id),
4896
+ await (0, import_firestore18.setDoc)(
4897
+ (0, import_firestore18.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerData.id),
4381
4898
  practitionerData
4382
4899
  );
4383
4900
  const savedPractitioner = await this.getPractitioner(practitionerData.id);
@@ -4394,12 +4911,12 @@ var PractitionerService = class extends BaseService {
4394
4911
  clinicId,
4395
4912
  status: "active" /* ACTIVE */,
4396
4913
  createdBy,
4397
- createdAt: import_firestore16.Timestamp.now(),
4398
- expiresAt: import_firestore16.Timestamp.fromDate(expiration)
4914
+ createdAt: import_firestore18.Timestamp.now(),
4915
+ expiresAt: import_firestore18.Timestamp.fromDate(expiration)
4399
4916
  };
4400
4917
  practitionerTokenSchema.parse(token);
4401
4918
  const tokenPath = `${PRACTITIONERS_COLLECTION}/${practitionerId}/${REGISTER_TOKENS_COLLECTION}/${token.id}`;
4402
- await (0, import_firestore16.setDoc)((0, import_firestore16.doc)(this.db, tokenPath), token);
4919
+ await (0, import_firestore18.setDoc)((0, import_firestore18.doc)(this.db, tokenPath), token);
4403
4920
  return { practitioner: savedPractitioner, token };
4404
4921
  } catch (error) {
4405
4922
  if (error instanceof import_zod15.z.ZodError) {
@@ -4447,12 +4964,12 @@ var PractitionerService = class extends BaseService {
4447
4964
  clinicId: validatedData.clinicId,
4448
4965
  status: "active" /* ACTIVE */,
4449
4966
  createdBy,
4450
- createdAt: import_firestore16.Timestamp.now(),
4451
- expiresAt: import_firestore16.Timestamp.fromDate(expiration)
4967
+ createdAt: import_firestore18.Timestamp.now(),
4968
+ expiresAt: import_firestore18.Timestamp.fromDate(expiration)
4452
4969
  };
4453
4970
  practitionerTokenSchema.parse(token);
4454
4971
  const tokenPath = `${PRACTITIONERS_COLLECTION}/${validatedData.practitionerId}/${REGISTER_TOKENS_COLLECTION}/${token.id}`;
4455
- await (0, import_firestore16.setDoc)((0, import_firestore16.doc)(this.db, tokenPath), token);
4972
+ await (0, import_firestore18.setDoc)((0, import_firestore18.doc)(this.db, tokenPath), token);
4456
4973
  return token;
4457
4974
  } catch (error) {
4458
4975
  if (error instanceof import_zod15.z.ZodError) {
@@ -4467,16 +4984,16 @@ var PractitionerService = class extends BaseService {
4467
4984
  * @returns Array of active tokens
4468
4985
  */
4469
4986
  async getPractitionerActiveTokens(practitionerId) {
4470
- const tokensRef = (0, import_firestore16.collection)(
4987
+ const tokensRef = (0, import_firestore18.collection)(
4471
4988
  this.db,
4472
4989
  `${PRACTITIONERS_COLLECTION}/${practitionerId}/${REGISTER_TOKENS_COLLECTION}`
4473
4990
  );
4474
- const q = (0, import_firestore16.query)(
4991
+ const q = (0, import_firestore18.query)(
4475
4992
  tokensRef,
4476
- (0, import_firestore16.where)("status", "==", "active" /* ACTIVE */),
4477
- (0, import_firestore16.where)("expiresAt", ">", import_firestore16.Timestamp.now())
4993
+ (0, import_firestore18.where)("status", "==", "active" /* ACTIVE */),
4994
+ (0, import_firestore18.where)("expiresAt", ">", import_firestore18.Timestamp.now())
4478
4995
  );
4479
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
4996
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4480
4997
  return querySnapshot.docs.map((doc34) => doc34.data());
4481
4998
  }
4482
4999
  /**
@@ -4485,11 +5002,11 @@ var PractitionerService = class extends BaseService {
4485
5002
  * @returns The token if found and valid, null otherwise
4486
5003
  */
4487
5004
  async validateToken(tokenString) {
4488
- const practitionersRef = (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION);
4489
- const practitionersSnapshot = await (0, import_firestore16.getDocs)(practitionersRef);
5005
+ const practitionersRef = (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION);
5006
+ const practitionersSnapshot = await (0, import_firestore18.getDocs)(practitionersRef);
4490
5007
  for (const practitionerDoc of practitionersSnapshot.docs) {
4491
5008
  const practitionerId = practitionerDoc.id;
4492
- const tokensRef = (0, import_firestore16.collection)(
5009
+ const tokensRef = (0, import_firestore18.collection)(
4493
5010
  this.db,
4494
5011
  `${PRACTITIONERS_COLLECTION}/${practitionerId}/${REGISTER_TOKENS_COLLECTION}`
4495
5012
  );
@@ -4497,17 +5014,17 @@ var PractitionerService = class extends BaseService {
4497
5014
  `[PRACTITIONER] Validating token for practitioner ${practitionerId}`,
4498
5015
  {
4499
5016
  tokenString,
4500
- timestamp: import_firestore16.Timestamp.now().toDate()
5017
+ timestamp: import_firestore18.Timestamp.now().toDate()
4501
5018
  }
4502
5019
  );
4503
- const q = (0, import_firestore16.query)(
5020
+ const q = (0, import_firestore18.query)(
4504
5021
  tokensRef,
4505
- (0, import_firestore16.where)("token", "==", tokenString),
4506
- (0, import_firestore16.where)("status", "==", "active" /* ACTIVE */),
4507
- (0, import_firestore16.where)("expiresAt", ">", import_firestore16.Timestamp.now())
5022
+ (0, import_firestore18.where)("token", "==", tokenString),
5023
+ (0, import_firestore18.where)("status", "==", "active" /* ACTIVE */),
5024
+ (0, import_firestore18.where)("expiresAt", ">", import_firestore18.Timestamp.now())
4508
5025
  );
4509
5026
  try {
4510
- const tokenSnapshot = await (0, import_firestore16.getDocs)(q);
5027
+ const tokenSnapshot = await (0, import_firestore18.getDocs)(q);
4511
5028
  console.log(
4512
5029
  `[PRACTITIONER] Token query results for practitioner ${practitionerId}`,
4513
5030
  {
@@ -4540,22 +5057,22 @@ var PractitionerService = class extends BaseService {
4540
5057
  * @param userId ID of the user using the token
4541
5058
  */
4542
5059
  async markTokenAsUsed(tokenId, practitionerId, userId) {
4543
- const tokenRef = (0, import_firestore16.doc)(
5060
+ const tokenRef = (0, import_firestore18.doc)(
4544
5061
  this.db,
4545
5062
  `${PRACTITIONERS_COLLECTION}/${practitionerId}/${REGISTER_TOKENS_COLLECTION}/${tokenId}`
4546
5063
  );
4547
- await (0, import_firestore16.updateDoc)(tokenRef, {
5064
+ await (0, import_firestore18.updateDoc)(tokenRef, {
4548
5065
  status: "used" /* USED */,
4549
5066
  usedBy: userId,
4550
- usedAt: import_firestore16.Timestamp.now()
5067
+ usedAt: import_firestore18.Timestamp.now()
4551
5068
  });
4552
5069
  }
4553
5070
  /**
4554
5071
  * Dohvata zdravstvenog radnika po ID-u
4555
5072
  */
4556
5073
  async getPractitioner(practitionerId) {
4557
- const practitionerDoc = await (0, import_firestore16.getDoc)(
4558
- (0, import_firestore16.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerId)
5074
+ const practitionerDoc = await (0, import_firestore18.getDoc)(
5075
+ (0, import_firestore18.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerId)
4559
5076
  );
4560
5077
  if (!practitionerDoc.exists()) {
4561
5078
  return null;
@@ -4566,11 +5083,11 @@ var PractitionerService = class extends BaseService {
4566
5083
  * Dohvata zdravstvenog radnika po User ID-u
4567
5084
  */
4568
5085
  async getPractitionerByUserRef(userRef) {
4569
- const q = (0, import_firestore16.query)(
4570
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
4571
- (0, import_firestore16.where)("userRef", "==", userRef)
5086
+ const q = (0, import_firestore18.query)(
5087
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
5088
+ (0, import_firestore18.where)("userRef", "==", userRef)
4572
5089
  );
4573
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5090
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4574
5091
  if (querySnapshot.empty) {
4575
5092
  return null;
4576
5093
  }
@@ -4580,37 +5097,37 @@ var PractitionerService = class extends BaseService {
4580
5097
  * Dohvata sve zdravstvene radnike za određenu kliniku sa statusom ACTIVE
4581
5098
  */
4582
5099
  async getPractitionersByClinic(clinicId) {
4583
- const q = (0, import_firestore16.query)(
4584
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
4585
- (0, import_firestore16.where)("clinics", "array-contains", clinicId),
4586
- (0, import_firestore16.where)("isActive", "==", true),
4587
- (0, import_firestore16.where)("status", "==", "active" /* ACTIVE */)
5100
+ const q = (0, import_firestore18.query)(
5101
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
5102
+ (0, import_firestore18.where)("clinics", "array-contains", clinicId),
5103
+ (0, import_firestore18.where)("isActive", "==", true),
5104
+ (0, import_firestore18.where)("status", "==", "active" /* ACTIVE */)
4588
5105
  );
4589
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5106
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4590
5107
  return querySnapshot.docs.map((doc34) => doc34.data());
4591
5108
  }
4592
5109
  /**
4593
5110
  * Dohvata sve zdravstvene radnike za određenu kliniku
4594
5111
  */
4595
5112
  async getAllPractitionersByClinic(clinicId) {
4596
- const q = (0, import_firestore16.query)(
4597
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
4598
- (0, import_firestore16.where)("clinics", "array-contains", clinicId),
4599
- (0, import_firestore16.where)("isActive", "==", true)
5113
+ const q = (0, import_firestore18.query)(
5114
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
5115
+ (0, import_firestore18.where)("clinics", "array-contains", clinicId),
5116
+ (0, import_firestore18.where)("isActive", "==", true)
4600
5117
  );
4601
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5118
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4602
5119
  return querySnapshot.docs.map((doc34) => doc34.data());
4603
5120
  }
4604
5121
  /**
4605
5122
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
4606
5123
  */
4607
5124
  async getDraftPractitionersByClinic(clinicId) {
4608
- const q = (0, import_firestore16.query)(
4609
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
4610
- (0, import_firestore16.where)("clinics", "array-contains", clinicId),
4611
- (0, import_firestore16.where)("status", "==", "draft" /* DRAFT */)
5125
+ const q = (0, import_firestore18.query)(
5126
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
5127
+ (0, import_firestore18.where)("clinics", "array-contains", clinicId),
5128
+ (0, import_firestore18.where)("status", "==", "draft" /* DRAFT */)
4612
5129
  );
4613
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5130
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4614
5131
  return querySnapshot.docs.map((doc34) => doc34.data());
4615
5132
  }
4616
5133
  /**
@@ -4619,21 +5136,28 @@ var PractitionerService = class extends BaseService {
4619
5136
  async updatePractitioner(practitionerId, data) {
4620
5137
  try {
4621
5138
  const validData = data;
4622
- const practitionerRef = (0, import_firestore16.doc)(
5139
+ const practitionerRef = (0, import_firestore18.doc)(
4623
5140
  this.db,
4624
5141
  PRACTITIONERS_COLLECTION,
4625
5142
  practitionerId
4626
5143
  );
4627
- const practitionerDoc = await (0, import_firestore16.getDoc)(practitionerRef);
5144
+ const practitionerDoc = await (0, import_firestore18.getDoc)(practitionerRef);
4628
5145
  if (!practitionerDoc.exists()) {
4629
5146
  throw new Error(`Practitioner ${practitionerId} not found`);
4630
5147
  }
4631
5148
  const currentPractitioner = practitionerDoc.data();
5149
+ let processedData = { ...validData };
5150
+ if (validData.basicInfo) {
5151
+ processedData.basicInfo = await this.processBasicInfo(
5152
+ validData.basicInfo,
5153
+ practitionerId
5154
+ );
5155
+ }
4632
5156
  const updateData = {
4633
- ...validData,
4634
- updatedAt: (0, import_firestore16.serverTimestamp)()
5157
+ ...processedData,
5158
+ updatedAt: (0, import_firestore18.serverTimestamp)()
4635
5159
  };
4636
- await (0, import_firestore16.updateDoc)(practitionerRef, updateData);
5160
+ await (0, import_firestore18.updateDoc)(practitionerRef, updateData);
4637
5161
  const updatedPractitioner = await this.getPractitioner(practitionerId);
4638
5162
  if (!updatedPractitioner) {
4639
5163
  throw new Error(
@@ -4655,12 +5179,12 @@ var PractitionerService = class extends BaseService {
4655
5179
  async addClinic(practitionerId, clinicId) {
4656
5180
  var _a;
4657
5181
  try {
4658
- const practitionerRef = (0, import_firestore16.doc)(
5182
+ const practitionerRef = (0, import_firestore18.doc)(
4659
5183
  this.db,
4660
5184
  PRACTITIONERS_COLLECTION,
4661
5185
  practitionerId
4662
5186
  );
4663
- const practitionerDoc = await (0, import_firestore16.getDoc)(practitionerRef);
5187
+ const practitionerDoc = await (0, import_firestore18.getDoc)(practitionerRef);
4664
5188
  if (!practitionerDoc.exists()) {
4665
5189
  throw new Error(`Practitioner ${practitionerId} not found`);
4666
5190
  }
@@ -4671,9 +5195,9 @@ var PractitionerService = class extends BaseService {
4671
5195
  );
4672
5196
  return;
4673
5197
  }
4674
- await (0, import_firestore16.updateDoc)(practitionerRef, {
4675
- clinics: (0, import_firestore16.arrayUnion)(clinicId),
4676
- updatedAt: (0, import_firestore16.serverTimestamp)()
5198
+ await (0, import_firestore18.updateDoc)(practitionerRef, {
5199
+ clinics: (0, import_firestore18.arrayUnion)(clinicId),
5200
+ updatedAt: (0, import_firestore18.serverTimestamp)()
4677
5201
  });
4678
5202
  } catch (error) {
4679
5203
  console.error(
@@ -4688,18 +5212,18 @@ var PractitionerService = class extends BaseService {
4688
5212
  */
4689
5213
  async removeClinic(practitionerId, clinicId) {
4690
5214
  try {
4691
- const practitionerRef = (0, import_firestore16.doc)(
5215
+ const practitionerRef = (0, import_firestore18.doc)(
4692
5216
  this.db,
4693
5217
  PRACTITIONERS_COLLECTION,
4694
5218
  practitionerId
4695
5219
  );
4696
- const practitionerDoc = await (0, import_firestore16.getDoc)(practitionerRef);
5220
+ const practitionerDoc = await (0, import_firestore18.getDoc)(practitionerRef);
4697
5221
  if (!practitionerDoc.exists()) {
4698
5222
  throw new Error(`Practitioner ${practitionerId} not found`);
4699
5223
  }
4700
- await (0, import_firestore16.updateDoc)(practitionerRef, {
4701
- clinics: (0, import_firestore16.arrayRemove)(clinicId),
4702
- updatedAt: (0, import_firestore16.serverTimestamp)()
5224
+ await (0, import_firestore18.updateDoc)(practitionerRef, {
5225
+ clinics: (0, import_firestore18.arrayRemove)(clinicId),
5226
+ updatedAt: (0, import_firestore18.serverTimestamp)()
4703
5227
  });
4704
5228
  } catch (error) {
4705
5229
  console.error(
@@ -4733,7 +5257,7 @@ var PractitionerService = class extends BaseService {
4733
5257
  if (!practitioner) {
4734
5258
  throw new Error("Practitioner not found");
4735
5259
  }
4736
- await (0, import_firestore16.deleteDoc)((0, import_firestore16.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerId));
5260
+ await (0, import_firestore18.deleteDoc)((0, import_firestore18.doc)(this.db, PRACTITIONERS_COLLECTION, practitionerId));
4737
5261
  }
4738
5262
  /**
4739
5263
  * Validates a registration token and claims the associated draft practitioner profile
@@ -4802,21 +5326,21 @@ var PractitionerService = class extends BaseService {
4802
5326
  try {
4803
5327
  const constraints = [];
4804
5328
  if (!(options == null ? void 0 : options.includeDraftPractitioners)) {
4805
- constraints.push((0, import_firestore16.where)("status", "==", "active" /* ACTIVE */));
5329
+ constraints.push((0, import_firestore18.where)("status", "==", "active" /* ACTIVE */));
4806
5330
  }
4807
- constraints.push((0, import_firestore16.orderBy)("basicInfo.lastName", "asc"));
4808
- constraints.push((0, import_firestore16.orderBy)("basicInfo.firstName", "asc"));
5331
+ constraints.push((0, import_firestore18.orderBy)("basicInfo.lastName", "asc"));
5332
+ constraints.push((0, import_firestore18.orderBy)("basicInfo.firstName", "asc"));
4809
5333
  if ((options == null ? void 0 : options.pagination) && options.pagination > 0) {
4810
5334
  if (options.lastDoc) {
4811
- constraints.push((0, import_firestore16.startAfter)(options.lastDoc));
5335
+ constraints.push((0, import_firestore18.startAfter)(options.lastDoc));
4812
5336
  }
4813
- constraints.push((0, import_firestore16.limit)(options.pagination));
5337
+ constraints.push((0, import_firestore18.limit)(options.pagination));
4814
5338
  }
4815
- const q = (0, import_firestore16.query)(
4816
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
5339
+ const q = (0, import_firestore18.query)(
5340
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
4817
5341
  ...constraints
4818
5342
  );
4819
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5343
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4820
5344
  const practitioners = querySnapshot.docs.map(
4821
5345
  (doc34) => doc34.data()
4822
5346
  );
@@ -4861,31 +5385,31 @@ var PractitionerService = class extends BaseService {
4861
5385
  );
4862
5386
  const constraints = [];
4863
5387
  if (!filters.includeDraftPractitioners) {
4864
- constraints.push((0, import_firestore16.where)("status", "==", "active" /* ACTIVE */));
5388
+ constraints.push((0, import_firestore18.where)("status", "==", "active" /* ACTIVE */));
4865
5389
  }
4866
- constraints.push((0, import_firestore16.where)("isActive", "==", true));
5390
+ constraints.push((0, import_firestore18.where)("isActive", "==", true));
4867
5391
  if (filters.certifications && filters.certifications.length > 0) {
4868
5392
  constraints.push(
4869
- (0, import_firestore16.where)(
5393
+ (0, import_firestore18.where)(
4870
5394
  "certification.certifications",
4871
5395
  "array-contains-any",
4872
5396
  filters.certifications
4873
5397
  )
4874
5398
  );
4875
5399
  }
4876
- constraints.push((0, import_firestore16.orderBy)("basicInfo.lastName", "asc"));
4877
- constraints.push((0, import_firestore16.orderBy)("basicInfo.firstName", "asc"));
5400
+ constraints.push((0, import_firestore18.orderBy)("basicInfo.lastName", "asc"));
5401
+ constraints.push((0, import_firestore18.orderBy)("basicInfo.firstName", "asc"));
4878
5402
  if (filters.pagination && filters.pagination > 0) {
4879
5403
  if (filters.lastDoc) {
4880
- constraints.push((0, import_firestore16.startAfter)(filters.lastDoc));
5404
+ constraints.push((0, import_firestore18.startAfter)(filters.lastDoc));
4881
5405
  }
4882
- constraints.push((0, import_firestore16.limit)(filters.pagination));
5406
+ constraints.push((0, import_firestore18.limit)(filters.pagination));
4883
5407
  }
4884
- const q = (0, import_firestore16.query)(
4885
- (0, import_firestore16.collection)(this.db, PRACTITIONERS_COLLECTION),
5408
+ const q = (0, import_firestore18.query)(
5409
+ (0, import_firestore18.collection)(this.db, PRACTITIONERS_COLLECTION),
4886
5410
  ...constraints
4887
5411
  );
4888
- const querySnapshot = await (0, import_firestore16.getDocs)(q);
5412
+ const querySnapshot = await (0, import_firestore18.getDocs)(q);
4889
5413
  console.log(
4890
5414
  `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
4891
5415
  );
@@ -5007,11 +5531,11 @@ var UserService = class extends BaseService {
5007
5531
  email: firebaseUser.email,
5008
5532
  roles: roles.length > 0 ? roles : ["patient" /* PATIENT */],
5009
5533
  isAnonymous: firebaseUser.isAnonymous,
5010
- createdAt: (0, import_firestore17.serverTimestamp)(),
5011
- updatedAt: (0, import_firestore17.serverTimestamp)(),
5012
- lastLoginAt: (0, import_firestore17.serverTimestamp)()
5534
+ createdAt: (0, import_firestore19.serverTimestamp)(),
5535
+ updatedAt: (0, import_firestore19.serverTimestamp)(),
5536
+ lastLoginAt: (0, import_firestore19.serverTimestamp)()
5013
5537
  };
5014
- await (0, import_firestore17.setDoc)((0, import_firestore17.doc)(this.db, USERS_COLLECTION, userData.uid), userData);
5538
+ await (0, import_firestore19.setDoc)((0, import_firestore19.doc)(this.db, USERS_COLLECTION, userData.uid), userData);
5015
5539
  if (options == null ? void 0 : options.skipProfileCreation) {
5016
5540
  return this.getUserById(userData.uid);
5017
5541
  }
@@ -5020,7 +5544,7 @@ var UserService = class extends BaseService {
5020
5544
  roles,
5021
5545
  options
5022
5546
  );
5023
- await (0, import_firestore17.updateDoc)((0, import_firestore17.doc)(this.db, USERS_COLLECTION, userData.uid), profiles);
5547
+ await (0, import_firestore19.updateDoc)((0, import_firestore19.doc)(this.db, USERS_COLLECTION, userData.uid), profiles);
5024
5548
  return this.getUserById(userData.uid);
5025
5549
  }
5026
5550
  /**
@@ -5098,7 +5622,7 @@ var UserService = class extends BaseService {
5098
5622
  email: "",
5099
5623
  phoneNumber: "",
5100
5624
  title: "",
5101
- dateOfBirth: import_firestore17.Timestamp.now(),
5625
+ dateOfBirth: import_firestore19.Timestamp.now(),
5102
5626
  gender: "other",
5103
5627
  languages: ["Serbian"]
5104
5628
  },
@@ -5107,7 +5631,7 @@ var UserService = class extends BaseService {
5107
5631
  specialties: [],
5108
5632
  licenseNumber: "",
5109
5633
  issuingAuthority: "",
5110
- issueDate: import_firestore17.Timestamp.now(),
5634
+ issueDate: import_firestore19.Timestamp.now(),
5111
5635
  verificationStatus: "pending"
5112
5636
  },
5113
5637
  isActive: true,
@@ -5123,7 +5647,7 @@ var UserService = class extends BaseService {
5123
5647
  * Dohvata korisnika po ID-u
5124
5648
  */
5125
5649
  async getUserById(uid) {
5126
- const userDoc = await (0, import_firestore17.getDoc)((0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid));
5650
+ const userDoc = await (0, import_firestore19.getDoc)((0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid));
5127
5651
  if (!userDoc.exists()) {
5128
5652
  throw USER_ERRORS.NOT_FOUND;
5129
5653
  }
@@ -5134,19 +5658,19 @@ var UserService = class extends BaseService {
5134
5658
  * Dohvata korisnika po email-u
5135
5659
  */
5136
5660
  async getUserByEmail(email) {
5137
- const usersRef = (0, import_firestore17.collection)(this.db, USERS_COLLECTION);
5138
- const q = (0, import_firestore17.query)(usersRef, (0, import_firestore17.where)("email", "==", email));
5139
- const querySnapshot = await (0, import_firestore17.getDocs)(q);
5661
+ const usersRef = (0, import_firestore19.collection)(this.db, USERS_COLLECTION);
5662
+ const q = (0, import_firestore19.query)(usersRef, (0, import_firestore19.where)("email", "==", email));
5663
+ const querySnapshot = await (0, import_firestore19.getDocs)(q);
5140
5664
  if (querySnapshot.empty) return null;
5141
5665
  const userData = querySnapshot.docs[0].data();
5142
5666
  return userSchema.parse(userData);
5143
5667
  }
5144
5668
  async getUsersByRole(role) {
5145
5669
  const constraints = [
5146
- (0, import_firestore17.where)("roles", "array-contains", role)
5670
+ (0, import_firestore19.where)("roles", "array-contains", role)
5147
5671
  ];
5148
- const q = (0, import_firestore17.query)((0, import_firestore17.collection)(this.db, USERS_COLLECTION), ...constraints);
5149
- const querySnapshot = await (0, import_firestore17.getDocs)(q);
5672
+ const q = (0, import_firestore19.query)((0, import_firestore19.collection)(this.db, USERS_COLLECTION), ...constraints);
5673
+ const querySnapshot = await (0, import_firestore19.getDocs)(q);
5150
5674
  const users = querySnapshot.docs.map((doc34) => doc34.data());
5151
5675
  return Promise.all(users.map((userData) => userSchema.parse(userData)));
5152
5676
  }
@@ -5154,33 +5678,33 @@ var UserService = class extends BaseService {
5154
5678
  * Ažurira timestamp poslednjeg logovanja
5155
5679
  */
5156
5680
  async updateUserLoginTimestamp(uid) {
5157
- const userRef = (0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid);
5158
- const userDoc = await (0, import_firestore17.getDoc)(userRef);
5681
+ const userRef = (0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid);
5682
+ const userDoc = await (0, import_firestore19.getDoc)(userRef);
5159
5683
  if (!userDoc.exists()) {
5160
5684
  throw AUTH_ERRORS.USER_NOT_FOUND;
5161
5685
  }
5162
- await (0, import_firestore17.updateDoc)(userRef, {
5163
- lastLoginAt: (0, import_firestore17.serverTimestamp)(),
5164
- updatedAt: (0, import_firestore17.serverTimestamp)()
5686
+ await (0, import_firestore19.updateDoc)(userRef, {
5687
+ lastLoginAt: (0, import_firestore19.serverTimestamp)(),
5688
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5165
5689
  });
5166
5690
  return this.getUserById(uid);
5167
5691
  }
5168
5692
  async upgradeAnonymousUser(uid, email) {
5169
- const userRef = (0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid);
5170
- const userDoc = await (0, import_firestore17.getDoc)(userRef);
5693
+ const userRef = (0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid);
5694
+ const userDoc = await (0, import_firestore19.getDoc)(userRef);
5171
5695
  if (!userDoc.exists()) {
5172
5696
  throw USER_ERRORS.NOT_FOUND;
5173
5697
  }
5174
- await (0, import_firestore17.updateDoc)(userRef, {
5698
+ await (0, import_firestore19.updateDoc)(userRef, {
5175
5699
  email,
5176
5700
  isAnonymous: false,
5177
- updatedAt: (0, import_firestore17.serverTimestamp)()
5701
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5178
5702
  });
5179
5703
  return this.getUserById(uid);
5180
5704
  }
5181
5705
  async updateUser(uid, updates) {
5182
- const userRef = (0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid);
5183
- const userDoc = await (0, import_firestore17.getDoc)(userRef);
5706
+ const userRef = (0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid);
5707
+ const userDoc = await (0, import_firestore19.getDoc)(userRef);
5184
5708
  if (!userDoc.exists()) {
5185
5709
  throw USER_ERRORS.NOT_FOUND;
5186
5710
  }
@@ -5189,12 +5713,12 @@ var UserService = class extends BaseService {
5189
5713
  const updatedUser = {
5190
5714
  ...currentUser,
5191
5715
  ...updates,
5192
- updatedAt: (0, import_firestore17.serverTimestamp)()
5716
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5193
5717
  };
5194
5718
  userSchema.parse(updatedUser);
5195
- await (0, import_firestore17.updateDoc)(userRef, {
5719
+ await (0, import_firestore19.updateDoc)(userRef, {
5196
5720
  ...updates,
5197
- updatedAt: (0, import_firestore17.serverTimestamp)()
5721
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5198
5722
  });
5199
5723
  return this.getUserById(uid);
5200
5724
  } catch (error) {
@@ -5211,10 +5735,10 @@ var UserService = class extends BaseService {
5211
5735
  const user = await this.getUserById(uid);
5212
5736
  if (user.roles.includes(role)) return;
5213
5737
  const profiles = await this.createProfilesForRoles(uid, [role], options);
5214
- await (0, import_firestore17.updateDoc)((0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid), {
5738
+ await (0, import_firestore19.updateDoc)((0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid), {
5215
5739
  roles: [...user.roles, role],
5216
5740
  ...profiles,
5217
- updatedAt: (0, import_firestore17.serverTimestamp)()
5741
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5218
5742
  });
5219
5743
  }
5220
5744
  /**
@@ -5246,15 +5770,15 @@ var UserService = class extends BaseService {
5246
5770
  }
5247
5771
  break;
5248
5772
  }
5249
- await (0, import_firestore17.updateDoc)((0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid), {
5773
+ await (0, import_firestore19.updateDoc)((0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid), {
5250
5774
  roles: user.roles.filter((r) => r !== role),
5251
- updatedAt: (0, import_firestore17.serverTimestamp)()
5775
+ updatedAt: (0, import_firestore19.serverTimestamp)()
5252
5776
  });
5253
5777
  }
5254
5778
  // Delete operations
5255
5779
  async deleteUser(uid) {
5256
- const userRef = (0, import_firestore17.doc)(this.db, USERS_COLLECTION, uid);
5257
- const userDoc = await (0, import_firestore17.getDoc)(userRef);
5780
+ const userRef = (0, import_firestore19.doc)(this.db, USERS_COLLECTION, uid);
5781
+ const userDoc = await (0, import_firestore19.getDoc)(userRef);
5258
5782
  if (!userDoc.exists()) {
5259
5783
  throw USER_ERRORS.NOT_FOUND;
5260
5784
  }
@@ -5275,7 +5799,7 @@ var UserService = class extends BaseService {
5275
5799
  userData.adminProfile
5276
5800
  );
5277
5801
  }
5278
- await (0, import_firestore17.deleteDoc)(userRef);
5802
+ await (0, import_firestore19.deleteDoc)(userRef);
5279
5803
  } catch (error) {
5280
5804
  throw error;
5281
5805
  }
@@ -5283,7 +5807,7 @@ var UserService = class extends BaseService {
5283
5807
  };
5284
5808
 
5285
5809
  // src/services/clinic/utils/clinic-group.utils.ts
5286
- var import_firestore18 = require("firebase/firestore");
5810
+ var import_firestore20 = require("firebase/firestore");
5287
5811
  var import_geofire_common3 = require("geofire-common");
5288
5812
  var import_zod17 = require("zod");
5289
5813
 
@@ -5400,9 +5924,9 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
5400
5924
  throw geohashError;
5401
5925
  }
5402
5926
  }
5403
- const now = import_firestore18.Timestamp.now();
5927
+ const now = import_firestore20.Timestamp.now();
5404
5928
  console.log("[CLINIC_GROUP] Preparing clinic group data object");
5405
- const groupId = (0, import_firestore18.doc)((0, import_firestore18.collection)(db, CLINIC_GROUPS_COLLECTION)).id;
5929
+ const groupId = (0, import_firestore20.doc)((0, import_firestore20.collection)(db, CLINIC_GROUPS_COLLECTION)).id;
5406
5930
  console.log("[CLINIC_GROUP] Logo value:", {
5407
5931
  logoValue: validatedData.logo,
5408
5932
  logoType: validatedData.logo === null ? "null" : typeof validatedData.logo
@@ -5452,7 +5976,7 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
5452
5976
  groupId: groupData.id
5453
5977
  });
5454
5978
  try {
5455
- await (0, import_firestore18.setDoc)((0, import_firestore18.doc)(db, CLINIC_GROUPS_COLLECTION, groupData.id), groupData);
5979
+ await (0, import_firestore20.setDoc)((0, import_firestore20.doc)(db, CLINIC_GROUPS_COLLECTION, groupData.id), groupData);
5456
5980
  console.log("[CLINIC_GROUP] Clinic group saved successfully");
5457
5981
  } catch (firestoreError) {
5458
5982
  console.error(
@@ -5498,19 +6022,19 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
5498
6022
  }
5499
6023
  }
5500
6024
  async function getClinicGroup(db, groupId) {
5501
- const docRef = (0, import_firestore18.doc)(db, CLINIC_GROUPS_COLLECTION, groupId);
5502
- const docSnap = await (0, import_firestore18.getDoc)(docRef);
6025
+ const docRef = (0, import_firestore20.doc)(db, CLINIC_GROUPS_COLLECTION, groupId);
6026
+ const docSnap = await (0, import_firestore20.getDoc)(docRef);
5503
6027
  if (docSnap.exists()) {
5504
6028
  return docSnap.data();
5505
6029
  }
5506
6030
  return null;
5507
6031
  }
5508
6032
  async function getAllActiveGroups(db) {
5509
- const q = (0, import_firestore18.query)(
5510
- (0, import_firestore18.collection)(db, CLINIC_GROUPS_COLLECTION),
5511
- (0, import_firestore18.where)("isActive", "==", true)
6033
+ const q = (0, import_firestore20.query)(
6034
+ (0, import_firestore20.collection)(db, CLINIC_GROUPS_COLLECTION),
6035
+ (0, import_firestore20.where)("isActive", "==", true)
5512
6036
  );
5513
- const querySnapshot = await (0, import_firestore18.getDocs)(q);
6037
+ const querySnapshot = await (0, import_firestore20.getDocs)(q);
5514
6038
  return querySnapshot.docs.map((doc34) => doc34.data());
5515
6039
  }
5516
6040
  async function updateClinicGroup(db, groupId, data, app) {
@@ -5539,10 +6063,10 @@ async function updateClinicGroup(db, groupId, data, app) {
5539
6063
  }
5540
6064
  updatedData = {
5541
6065
  ...updatedData,
5542
- updatedAt: import_firestore18.Timestamp.now()
6066
+ updatedAt: import_firestore20.Timestamp.now()
5543
6067
  };
5544
6068
  console.log("[CLINIC_GROUP] Updating clinic group in Firestore");
5545
- await (0, import_firestore18.updateDoc)((0, import_firestore18.doc)(db, CLINIC_GROUPS_COLLECTION, groupId), updatedData);
6069
+ await (0, import_firestore20.updateDoc)((0, import_firestore20.doc)(db, CLINIC_GROUPS_COLLECTION, groupId), updatedData);
5546
6070
  console.log("[CLINIC_GROUP] Clinic group updated successfully");
5547
6071
  const updatedGroup = await getClinicGroup(db, groupId);
5548
6072
  if (!updatedGroup) {
@@ -5623,10 +6147,10 @@ async function createAdminToken(db, groupId, creatorAdminId, app, data) {
5623
6147
  if (!group.admins.includes(creatorAdminId)) {
5624
6148
  throw new Error("Admin does not belong to this clinic group");
5625
6149
  }
5626
- const now = import_firestore18.Timestamp.now();
6150
+ const now = import_firestore20.Timestamp.now();
5627
6151
  const expiresInDays = (data == null ? void 0 : data.expiresInDays) || 7;
5628
6152
  const email = (data == null ? void 0 : data.email) || null;
5629
- const expiresAt = new import_firestore18.Timestamp(
6153
+ const expiresAt = new import_firestore20.Timestamp(
5630
6154
  now.seconds + expiresInDays * 24 * 60 * 60,
5631
6155
  now.nanoseconds
5632
6156
  );
@@ -5660,7 +6184,7 @@ async function verifyAndUseAdminToken(db, groupId, token, userRef, app) {
5660
6184
  if (adminToken.status !== "active" /* ACTIVE */) {
5661
6185
  throw new Error("Admin token is not active");
5662
6186
  }
5663
- const now = import_firestore18.Timestamp.now();
6187
+ const now = import_firestore20.Timestamp.now();
5664
6188
  if (adminToken.expiresAt.seconds < now.seconds) {
5665
6189
  const updatedTokens2 = group.adminTokens.map(
5666
6190
  (t) => t.id === adminToken.id ? { ...t, status: "expired" /* EXPIRED */ } : t
@@ -5933,24 +6457,24 @@ var import_geofire_common7 = require("geofire-common");
5933
6457
  var import_zod19 = require("zod");
5934
6458
 
5935
6459
  // src/services/clinic/utils/clinic.utils.ts
5936
- var import_firestore19 = require("firebase/firestore");
6460
+ var import_firestore21 = require("firebase/firestore");
5937
6461
  var import_geofire_common4 = require("geofire-common");
5938
6462
  var import_zod18 = require("zod");
5939
6463
  async function getClinic(db, clinicId) {
5940
- const docRef = (0, import_firestore19.doc)(db, CLINICS_COLLECTION, clinicId);
5941
- const docSnap = await (0, import_firestore19.getDoc)(docRef);
6464
+ const docRef = (0, import_firestore21.doc)(db, CLINICS_COLLECTION, clinicId);
6465
+ const docSnap = await (0, import_firestore21.getDoc)(docRef);
5942
6466
  if (docSnap.exists()) {
5943
6467
  return docSnap.data();
5944
6468
  }
5945
6469
  return null;
5946
6470
  }
5947
6471
  async function getClinicsByGroup(db, groupId) {
5948
- const q = (0, import_firestore19.query)(
5949
- (0, import_firestore19.collection)(db, CLINICS_COLLECTION),
5950
- (0, import_firestore19.where)("clinicGroupId", "==", groupId),
5951
- (0, import_firestore19.where)("isActive", "==", true)
6472
+ const q = (0, import_firestore21.query)(
6473
+ (0, import_firestore21.collection)(db, CLINICS_COLLECTION),
6474
+ (0, import_firestore21.where)("clinicGroupId", "==", groupId),
6475
+ (0, import_firestore21.where)("isActive", "==", true)
5952
6476
  );
5953
- const querySnapshot = await (0, import_firestore19.getDocs)(q);
6477
+ const querySnapshot = await (0, import_firestore21.getDocs)(q);
5954
6478
  return querySnapshot.docs.map((doc34) => doc34.data());
5955
6479
  }
5956
6480
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
@@ -6106,11 +6630,11 @@ async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app
6106
6630
  }
6107
6631
  updatedData = {
6108
6632
  ...updatedData,
6109
- updatedAt: import_firestore19.Timestamp.now()
6633
+ updatedAt: import_firestore21.Timestamp.now()
6110
6634
  };
6111
6635
  console.log("[CLINIC] Updating clinic in Firestore");
6112
6636
  try {
6113
- await (0, import_firestore19.updateDoc)((0, import_firestore19.doc)(db, CLINICS_COLLECTION, clinicId), updatedData);
6637
+ await (0, import_firestore21.updateDoc)((0, import_firestore21.doc)(db, CLINICS_COLLECTION, clinicId), updatedData);
6114
6638
  console.log("[CLINIC] Clinic updated successfully");
6115
6639
  } catch (updateError) {
6116
6640
  console.error("[CLINIC] Error updating clinic in Firestore:", updateError);
@@ -6139,12 +6663,12 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
6139
6663
  if (clinicIds.length === 0) {
6140
6664
  return [];
6141
6665
  }
6142
- const constraints = [(0, import_firestore19.where)("id", "in", clinicIds)];
6666
+ const constraints = [(0, import_firestore21.where)("id", "in", clinicIds)];
6143
6667
  if (options.isActive !== void 0) {
6144
- constraints.push((0, import_firestore19.where)("isActive", "==", options.isActive));
6668
+ constraints.push((0, import_firestore21.where)("isActive", "==", options.isActive));
6145
6669
  }
6146
- const q = (0, import_firestore19.query)((0, import_firestore19.collection)(db, CLINICS_COLLECTION), ...constraints);
6147
- const querySnapshot = await (0, import_firestore19.getDocs)(q);
6670
+ const q = (0, import_firestore21.query)((0, import_firestore21.collection)(db, CLINICS_COLLECTION), ...constraints);
6671
+ const querySnapshot = await (0, import_firestore21.getDocs)(q);
6148
6672
  return querySnapshot.docs.map((doc34) => doc34.data());
6149
6673
  }
6150
6674
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
@@ -6158,8 +6682,8 @@ async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGr
6158
6682
  }
6159
6683
  async function getClinicById(db, clinicId) {
6160
6684
  try {
6161
- const clinicRef = (0, import_firestore19.doc)(db, CLINICS_COLLECTION, clinicId);
6162
- const clinicSnapshot = await (0, import_firestore19.getDoc)(clinicRef);
6685
+ const clinicRef = (0, import_firestore21.doc)(db, CLINICS_COLLECTION, clinicId);
6686
+ const clinicSnapshot = await (0, import_firestore21.getDoc)(clinicRef);
6163
6687
  if (!clinicSnapshot.exists()) {
6164
6688
  return null;
6165
6689
  }
@@ -6175,20 +6699,20 @@ async function getClinicById(db, clinicId) {
6175
6699
  }
6176
6700
  async function getAllClinics(db, pagination, lastDoc) {
6177
6701
  try {
6178
- const clinicsCollection = (0, import_firestore19.collection)(db, CLINICS_COLLECTION);
6179
- let clinicsQuery = (0, import_firestore19.query)(clinicsCollection);
6702
+ const clinicsCollection = (0, import_firestore21.collection)(db, CLINICS_COLLECTION);
6703
+ let clinicsQuery = (0, import_firestore21.query)(clinicsCollection);
6180
6704
  if (pagination && pagination > 0) {
6181
6705
  if (lastDoc) {
6182
- clinicsQuery = (0, import_firestore19.query)(
6706
+ clinicsQuery = (0, import_firestore21.query)(
6183
6707
  clinicsCollection,
6184
- (0, import_firestore19.startAfter)(lastDoc),
6185
- (0, import_firestore19.limit)(pagination)
6708
+ (0, import_firestore21.startAfter)(lastDoc),
6709
+ (0, import_firestore21.limit)(pagination)
6186
6710
  );
6187
6711
  } else {
6188
- clinicsQuery = (0, import_firestore19.query)(clinicsCollection, (0, import_firestore19.limit)(pagination));
6712
+ clinicsQuery = (0, import_firestore21.query)(clinicsCollection, (0, import_firestore21.limit)(pagination));
6189
6713
  }
6190
6714
  }
6191
- const clinicsSnapshot = await (0, import_firestore19.getDocs)(clinicsQuery);
6715
+ const clinicsSnapshot = await (0, import_firestore21.getDocs)(clinicsQuery);
6192
6716
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
6193
6717
  const clinics = clinicsSnapshot.docs.map((doc34) => {
6194
6718
  const data = doc34.data();
@@ -6215,12 +6739,12 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
6215
6739
  let lastDocSnapshot = null;
6216
6740
  for (const b of bounds) {
6217
6741
  const constraints = [
6218
- (0, import_firestore19.where)("location.geohash", ">=", b[0]),
6219
- (0, import_firestore19.where)("location.geohash", "<=", b[1]),
6220
- (0, import_firestore19.where)("isActive", "==", true)
6742
+ (0, import_firestore21.where)("location.geohash", ">=", b[0]),
6743
+ (0, import_firestore21.where)("location.geohash", "<=", b[1]),
6744
+ (0, import_firestore21.where)("isActive", "==", true)
6221
6745
  ];
6222
- const q = (0, import_firestore19.query)((0, import_firestore19.collection)(db, CLINICS_COLLECTION), ...constraints);
6223
- const querySnapshot = await (0, import_firestore19.getDocs)(q);
6746
+ const q = (0, import_firestore21.query)((0, import_firestore21.collection)(db, CLINICS_COLLECTION), ...constraints);
6747
+ const querySnapshot = await (0, import_firestore21.getDocs)(q);
6224
6748
  for (const doc34 of querySnapshot.docs) {
6225
6749
  const clinic = doc34.data();
6226
6750
  const distance = (0, import_geofire_common4.distanceBetween)(
@@ -6315,7 +6839,7 @@ async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminServic
6315
6839
  }
6316
6840
 
6317
6841
  // src/services/clinic/utils/search.utils.ts
6318
- var import_firestore20 = require("firebase/firestore");
6842
+ var import_firestore22 = require("firebase/firestore");
6319
6843
  var import_geofire_common5 = require("geofire-common");
6320
6844
  async function findClinicsInRadius(db, center, radiusInKm, filters) {
6321
6845
  const bounds = (0, import_geofire_common5.geohashQueryBounds)(
@@ -6325,20 +6849,20 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
6325
6849
  const matchingDocs = [];
6326
6850
  for (const b of bounds) {
6327
6851
  const constraints = [
6328
- (0, import_firestore20.where)("location.geohash", ">=", b[0]),
6329
- (0, import_firestore20.where)("location.geohash", "<=", b[1]),
6330
- (0, import_firestore20.where)("isActive", "==", true)
6852
+ (0, import_firestore22.where)("location.geohash", ">=", b[0]),
6853
+ (0, import_firestore22.where)("location.geohash", "<=", b[1]),
6854
+ (0, import_firestore22.where)("isActive", "==", true)
6331
6855
  ];
6332
6856
  if (filters == null ? void 0 : filters.services) {
6333
6857
  constraints.push(
6334
- (0, import_firestore20.where)("services", "array-contains-any", filters.services)
6858
+ (0, import_firestore22.where)("services", "array-contains-any", filters.services)
6335
6859
  );
6336
6860
  }
6337
6861
  if ((filters == null ? void 0 : filters.tags) && filters.tags.length > 0) {
6338
- constraints.push((0, import_firestore20.where)("tags", "array-contains-any", filters.tags));
6862
+ constraints.push((0, import_firestore22.where)("tags", "array-contains-any", filters.tags));
6339
6863
  }
6340
- const q = (0, import_firestore20.query)((0, import_firestore20.collection)(db, CLINICS_COLLECTION), ...constraints);
6341
- const querySnapshot = await (0, import_firestore20.getDocs)(q);
6864
+ const q = (0, import_firestore22.query)((0, import_firestore22.collection)(db, CLINICS_COLLECTION), ...constraints);
6865
+ const querySnapshot = await (0, import_firestore22.getDocs)(q);
6342
6866
  for (const doc34 of querySnapshot.docs) {
6343
6867
  const clinic = doc34.data();
6344
6868
  const distance = (0, import_geofire_common5.distanceBetween)(
@@ -6365,7 +6889,7 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
6365
6889
  }
6366
6890
 
6367
6891
  // src/services/clinic/utils/filter.utils.ts
6368
- var import_firestore21 = require("firebase/firestore");
6892
+ var import_firestore23 = require("firebase/firestore");
6369
6893
  var import_geofire_common6 = require("geofire-common");
6370
6894
  async function getClinicsByFilters(db, filters) {
6371
6895
  console.log(
@@ -6375,460 +6899,162 @@ async function getClinicsByFilters(db, filters) {
6375
6899
  const isGeoQuery = filters.center && filters.radiusInKm && filters.radiusInKm > 0;
6376
6900
  const constraints = [];
6377
6901
  if (filters.isActive !== void 0) {
6378
- constraints.push((0, import_firestore21.where)("isActive", "==", filters.isActive));
6902
+ constraints.push((0, import_firestore23.where)("isActive", "==", filters.isActive));
6379
6903
  } else {
6380
- constraints.push((0, import_firestore21.where)("isActive", "==", true));
6904
+ constraints.push((0, import_firestore23.where)("isActive", "==", true));
6381
6905
  }
6382
6906
  if (filters.tags && filters.tags.length > 0) {
6383
- constraints.push((0, import_firestore21.where)("tags", "array-contains", filters.tags[0]));
6907
+ constraints.push((0, import_firestore23.where)("tags", "array-contains", filters.tags[0]));
6384
6908
  }
6385
6909
  if (filters.procedureTechnology) {
6386
6910
  constraints.push(
6387
- (0, import_firestore21.where)("servicesInfo.technology", "==", filters.procedureTechnology)
6911
+ (0, import_firestore23.where)("servicesInfo.technology", "==", filters.procedureTechnology)
6388
6912
  );
6389
6913
  } else if (filters.procedureSubcategory) {
6390
6914
  constraints.push(
6391
- (0, import_firestore21.where)("servicesInfo.subCategory", "==", filters.procedureSubcategory)
6915
+ (0, import_firestore23.where)("servicesInfo.subCategory", "==", filters.procedureSubcategory)
6392
6916
  );
6393
6917
  } else if (filters.procedureCategory) {
6394
6918
  constraints.push(
6395
- (0, import_firestore21.where)("servicesInfo.category", "==", filters.procedureCategory)
6919
+ (0, import_firestore23.where)("servicesInfo.category", "==", filters.procedureCategory)
6396
6920
  );
6397
6921
  } else if (filters.procedureFamily) {
6398
6922
  constraints.push(
6399
- (0, import_firestore21.where)("servicesInfo.procedureFamily", "==", filters.procedureFamily)
6923
+ (0, import_firestore23.where)("servicesInfo.procedureFamily", "==", filters.procedureFamily)
6400
6924
  );
6401
6925
  }
6402
6926
  if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
6403
- constraints.push((0, import_firestore21.startAfter)(filters.lastDoc));
6404
- constraints.push((0, import_firestore21.limit)(filters.pagination));
6927
+ constraints.push((0, import_firestore23.startAfter)(filters.lastDoc));
6928
+ constraints.push((0, import_firestore23.limit)(filters.pagination));
6405
6929
  } else if (filters.pagination && filters.pagination > 0) {
6406
- constraints.push((0, import_firestore21.limit)(filters.pagination));
6930
+ constraints.push((0, import_firestore23.limit)(filters.pagination));
6407
6931
  }
6408
- constraints.push((0, import_firestore21.orderBy)("location.geohash"));
6932
+ constraints.push((0, import_firestore23.orderBy)("location.geohash"));
6409
6933
  let clinicsResult = [];
6410
6934
  let lastVisibleDoc = null;
6411
6935
  if (isGeoQuery) {
6412
6936
  const center = filters.center;
6413
6937
  const radiusInKm = filters.radiusInKm;
6414
6938
  const bounds = (0, import_geofire_common6.geohashQueryBounds)(
6415
- [center.latitude, center.longitude],
6416
- radiusInKm * 1e3
6417
- // Convert to meters
6418
- );
6419
- const matchingClinics = [];
6420
- for (const bound of bounds) {
6421
- const geoConstraints = [
6422
- ...constraints,
6423
- (0, import_firestore21.where)("location.geohash", ">=", bound[0]),
6424
- (0, import_firestore21.where)("location.geohash", "<=", bound[1])
6425
- ];
6426
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(db, CLINICS_COLLECTION), ...geoConstraints);
6427
- const querySnapshot = await (0, import_firestore21.getDocs)(q);
6428
- console.log(
6429
- `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
6430
- );
6431
- for (const doc34 of querySnapshot.docs) {
6432
- const clinic = { ...doc34.data(), id: doc34.id };
6433
- const distance = (0, import_geofire_common6.distanceBetween)(
6434
- [center.latitude, center.longitude],
6435
- [clinic.location.latitude, clinic.location.longitude]
6436
- );
6437
- const distanceInKm = distance / 1e3;
6438
- if (distanceInKm <= radiusInKm) {
6439
- matchingClinics.push({
6440
- ...clinic,
6441
- distance: distanceInKm
6442
- });
6443
- }
6444
- }
6445
- }
6446
- let filteredClinics = matchingClinics;
6447
- if (filters.tags && filters.tags.length > 1) {
6448
- filteredClinics = filteredClinics.filter((clinic) => {
6449
- return filters.tags.every((tag) => clinic.tags.includes(tag));
6450
- });
6451
- }
6452
- if (filters.minRating !== void 0) {
6453
- filteredClinics = filteredClinics.filter(
6454
- (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
6455
- );
6456
- }
6457
- if (filters.maxRating !== void 0) {
6458
- filteredClinics = filteredClinics.filter(
6459
- (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
6460
- );
6461
- }
6462
- filteredClinics.sort((a, b) => a.distance - b.distance);
6463
- if (filters.pagination && filters.pagination > 0) {
6464
- let startIndex = 0;
6465
- if (filters.lastDoc) {
6466
- const lastDocIndex = filteredClinics.findIndex(
6467
- (clinic) => clinic.id === filters.lastDoc.id
6468
- );
6469
- if (lastDocIndex !== -1) {
6470
- startIndex = lastDocIndex + 1;
6471
- }
6472
- }
6473
- const paginatedClinics = filteredClinics.slice(
6474
- startIndex,
6475
- startIndex + filters.pagination
6476
- );
6477
- lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
6478
- clinicsResult = paginatedClinics;
6479
- } else {
6480
- clinicsResult = filteredClinics;
6481
- }
6482
- } else {
6483
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(db, CLINICS_COLLECTION), ...constraints);
6484
- const querySnapshot = await (0, import_firestore21.getDocs)(q);
6485
- console.log(
6486
- `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
6487
- );
6488
- const clinics = querySnapshot.docs.map((doc34) => {
6489
- return { ...doc34.data(), id: doc34.id };
6490
- });
6491
- let filteredClinics = clinics;
6492
- if (filters.center) {
6493
- const center = filters.center;
6494
- const clinicsWithDistance = [];
6495
- filteredClinics.forEach((clinic) => {
6496
- const distance = (0, import_geofire_common6.distanceBetween)(
6497
- [center.latitude, center.longitude],
6498
- [clinic.location.latitude, clinic.location.longitude]
6499
- );
6500
- clinicsWithDistance.push({
6501
- ...clinic,
6502
- distance: distance / 1e3
6503
- // Convert to kilometers
6504
- });
6505
- });
6506
- filteredClinics = clinicsWithDistance;
6507
- filteredClinics.sort(
6508
- (a, b) => a.distance - b.distance
6509
- );
6510
- }
6511
- if (filters.tags && filters.tags.length > 1) {
6512
- filteredClinics = filteredClinics.filter((clinic) => {
6513
- return filters.tags.every((tag) => clinic.tags.includes(tag));
6514
- });
6515
- }
6516
- if (filters.minRating !== void 0) {
6517
- filteredClinics = filteredClinics.filter(
6518
- (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
6519
- );
6520
- }
6521
- if (filters.maxRating !== void 0) {
6522
- filteredClinics = filteredClinics.filter(
6523
- (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
6524
- );
6525
- }
6526
- lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6527
- clinicsResult = filteredClinics;
6528
- }
6529
- return {
6530
- clinics: clinicsResult,
6531
- lastDoc: lastVisibleDoc
6532
- };
6533
- }
6534
-
6535
- // src/services/media/media.service.ts
6536
- var import_firestore22 = require("firebase/firestore");
6537
- var import_storage5 = require("firebase/storage");
6538
- var import_firestore23 = require("firebase/firestore");
6539
- var MediaAccessLevel = /* @__PURE__ */ ((MediaAccessLevel2) => {
6540
- MediaAccessLevel2["PUBLIC"] = "public";
6541
- MediaAccessLevel2["PRIVATE"] = "private";
6542
- MediaAccessLevel2["CONFIDENTIAL"] = "confidential";
6543
- return MediaAccessLevel2;
6544
- })(MediaAccessLevel || {});
6545
- var MEDIA_METADATA_COLLECTION = "media_metadata";
6546
- var MediaService = class extends BaseService {
6547
- constructor(db, auth, app) {
6548
- super(db, auth, app);
6549
- }
6550
- /**
6551
- * Upload a media file, store its metadata, and return the metadata including the URL.
6552
- * @param file - The file to upload.
6553
- * @param ownerId - ID of the owner (user, patient, clinic, etc.).
6554
- * @param accessLevel - Access level (public, private, confidential).
6555
- * @param collectionName - The logical collection name this media belongs to (e.g., 'patient_profile_pictures', 'clinic_logos').
6556
- * @param originalFileName - Optional: the original name of the file, if not using file.name.
6557
- * @returns Promise with the media metadata.
6558
- */
6559
- async uploadMedia(file, ownerId, accessLevel, collectionName, originalFileName) {
6560
- const mediaId = this.generateId();
6561
- const fileNameToUse = originalFileName || (file instanceof File ? file.name : file.toString());
6562
- const uniqueFileName = `${mediaId}-${fileNameToUse}`;
6563
- const filePath = `media/${accessLevel}/${ownerId}/${collectionName}/${uniqueFileName}`;
6564
- console.log(`[MediaService] Uploading file to: ${filePath}`);
6565
- const storageRef = (0, import_storage5.ref)(this.storage, filePath);
6566
- try {
6567
- const uploadResult = await (0, import_storage5.uploadBytes)(storageRef, file, {
6568
- contentType: file.type
6569
- });
6570
- console.log("[MediaService] File uploaded successfully", uploadResult);
6571
- const downloadURL = await (0, import_storage5.getDownloadURL)(uploadResult.ref);
6572
- console.log("[MediaService] Got download URL:", downloadURL);
6573
- const metadata = {
6574
- id: mediaId,
6575
- name: fileNameToUse,
6576
- url: downloadURL,
6577
- contentType: file.type,
6578
- size: file.size,
6579
- createdAt: import_firestore22.Timestamp.now(),
6580
- accessLevel,
6581
- ownerId,
6582
- collectionName,
6583
- path: filePath
6584
- };
6585
- const metadataDocRef = (0, import_firestore23.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
6586
- await (0, import_firestore23.setDoc)(metadataDocRef, metadata);
6587
- console.log("[MediaService] Metadata stored in Firestore:", mediaId);
6588
- return metadata;
6589
- } catch (error) {
6590
- console.error("[MediaService] Error during media upload:", error);
6591
- throw error;
6592
- }
6593
- }
6594
- /**
6595
- * Get media metadata from Firestore by its ID.
6596
- * @param mediaId - ID of the media.
6597
- * @returns Promise with the media metadata or null if not found.
6598
- */
6599
- async getMediaMetadata(mediaId) {
6600
- console.log(`[MediaService] Getting media metadata for ID: ${mediaId}`);
6601
- const docRef = (0, import_firestore23.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
6602
- const docSnap = await (0, import_firestore23.getDoc)(docRef);
6603
- if (docSnap.exists()) {
6604
- console.log("[MediaService] Metadata found:", docSnap.data());
6605
- return docSnap.data();
6606
- }
6607
- console.log("[MediaService] No metadata found for ID:", mediaId);
6608
- return null;
6609
- }
6610
- /**
6611
- * Get media metadata from Firestore by its public URL.
6612
- * @param url - The public URL of the media file.
6613
- * @returns Promise with the media metadata or null if not found.
6614
- */
6615
- async getMediaMetadataByUrl(url) {
6616
- console.log(`[MediaService] Getting media metadata by URL: ${url}`);
6617
- const q = (0, import_firestore23.query)(
6618
- (0, import_firestore23.collection)(this.db, MEDIA_METADATA_COLLECTION),
6619
- (0, import_firestore23.where)("url", "==", url),
6620
- (0, import_firestore23.limit)(1)
6939
+ [center.latitude, center.longitude],
6940
+ radiusInKm * 1e3
6941
+ // Convert to meters
6621
6942
  );
6622
- try {
6943
+ const matchingClinics = [];
6944
+ for (const bound of bounds) {
6945
+ const geoConstraints = [
6946
+ ...constraints,
6947
+ (0, import_firestore23.where)("location.geohash", ">=", bound[0]),
6948
+ (0, import_firestore23.where)("location.geohash", "<=", bound[1])
6949
+ ];
6950
+ const q = (0, import_firestore23.query)((0, import_firestore23.collection)(db, CLINICS_COLLECTION), ...geoConstraints);
6623
6951
  const querySnapshot = await (0, import_firestore23.getDocs)(q);
6624
- if (!querySnapshot.empty) {
6625
- const metadata = querySnapshot.docs[0].data();
6626
- console.log("[MediaService] Metadata found by URL:", metadata);
6627
- return metadata;
6952
+ console.log(
6953
+ `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
6954
+ );
6955
+ for (const doc34 of querySnapshot.docs) {
6956
+ const clinic = { ...doc34.data(), id: doc34.id };
6957
+ const distance = (0, import_geofire_common6.distanceBetween)(
6958
+ [center.latitude, center.longitude],
6959
+ [clinic.location.latitude, clinic.location.longitude]
6960
+ );
6961
+ const distanceInKm = distance / 1e3;
6962
+ if (distanceInKm <= radiusInKm) {
6963
+ matchingClinics.push({
6964
+ ...clinic,
6965
+ distance: distanceInKm
6966
+ });
6967
+ }
6628
6968
  }
6629
- console.log("[MediaService] No metadata found for URL:", url);
6630
- return null;
6631
- } catch (error) {
6632
- console.error("[MediaService] Error fetching metadata by URL:", error);
6633
- throw error;
6634
6969
  }
6635
- }
6636
- /**
6637
- * Delete media from storage and remove metadata from Firestore.
6638
- * @param mediaId - ID of the media to delete.
6639
- */
6640
- async deleteMedia(mediaId) {
6641
- console.log(`[MediaService] Deleting media with ID: ${mediaId}`);
6642
- const metadata = await this.getMediaMetadata(mediaId);
6643
- if (!metadata) {
6644
- console.warn(
6645
- `[MediaService] Metadata not found for media ID ${mediaId}. Cannot delete.`
6646
- );
6647
- return;
6970
+ let filteredClinics = matchingClinics;
6971
+ if (filters.tags && filters.tags.length > 1) {
6972
+ filteredClinics = filteredClinics.filter((clinic) => {
6973
+ return filters.tags.every((tag) => clinic.tags.includes(tag));
6974
+ });
6648
6975
  }
6649
- const storageFileRef = (0, import_storage5.ref)(this.storage, metadata.path);
6650
- try {
6651
- await (0, import_storage5.deleteObject)(storageFileRef);
6652
- console.log(`[MediaService] File deleted from Storage: ${metadata.path}`);
6653
- const metadataDocRef = (0, import_firestore23.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
6654
- await (0, import_firestore23.deleteDoc)(metadataDocRef);
6655
- console.log(
6656
- `[MediaService] Metadata deleted from Firestore for ID: ${mediaId}`
6976
+ if (filters.minRating !== void 0) {
6977
+ filteredClinics = filteredClinics.filter(
6978
+ (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
6657
6979
  );
6658
- } catch (error) {
6659
- console.error(`[MediaService] Error deleting media ${mediaId}:`, error);
6660
- throw error;
6661
6980
  }
6662
- }
6663
- /**
6664
- * Update media access level. This involves moving the file in Firebase Storage
6665
- * to a new path reflecting the new access level, and updating its metadata.
6666
- * @param mediaId - ID of the media to update.
6667
- * @param newAccessLevel - New access level.
6668
- * @returns Promise with the updated media metadata, or null if metadata not found.
6669
- */
6670
- async updateMediaAccessLevel(mediaId, newAccessLevel) {
6671
- var _a;
6672
- console.log(
6673
- `[MediaService] Attempting to update access level for media ID: ${mediaId} to ${newAccessLevel}`
6674
- );
6675
- const metadata = await this.getMediaMetadata(mediaId);
6676
- if (!metadata) {
6677
- console.warn(
6678
- `[MediaService] Metadata not found for media ID ${mediaId}. Cannot update access level.`
6981
+ if (filters.maxRating !== void 0) {
6982
+ filteredClinics = filteredClinics.filter(
6983
+ (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
6679
6984
  );
6680
- return null;
6681
6985
  }
6682
- if (metadata.accessLevel === newAccessLevel) {
6683
- console.log(
6684
- `[MediaService] Media ID ${mediaId} already has access level ${newAccessLevel}. Updating timestamp only.`
6685
- );
6686
- const metadataDocRef = (0, import_firestore23.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
6687
- try {
6688
- await (0, import_firestore23.updateDoc)(metadataDocRef, { updatedAt: import_firestore22.Timestamp.now() });
6689
- return { ...metadata, updatedAt: import_firestore22.Timestamp.now() };
6690
- } catch (error) {
6691
- console.error(
6692
- `[MediaService] Error updating timestamp for media ID ${mediaId}:`,
6693
- error
6986
+ filteredClinics.sort((a, b) => a.distance - b.distance);
6987
+ if (filters.pagination && filters.pagination > 0) {
6988
+ let startIndex = 0;
6989
+ if (filters.lastDoc) {
6990
+ const lastDocIndex = filteredClinics.findIndex(
6991
+ (clinic) => clinic.id === filters.lastDoc.id
6694
6992
  );
6695
- throw error;
6993
+ if (lastDocIndex !== -1) {
6994
+ startIndex = lastDocIndex + 1;
6995
+ }
6696
6996
  }
6997
+ const paginatedClinics = filteredClinics.slice(
6998
+ startIndex,
6999
+ startIndex + filters.pagination
7000
+ );
7001
+ lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
7002
+ clinicsResult = paginatedClinics;
7003
+ } else {
7004
+ clinicsResult = filteredClinics;
6697
7005
  }
6698
- const oldStoragePath = metadata.path;
6699
- const fileNamePart = `${metadata.id}-${metadata.name}`;
6700
- const newStoragePath = `media/${newAccessLevel}/${metadata.ownerId}/${metadata.collectionName}/${fileNamePart}`;
7006
+ } else {
7007
+ const q = (0, import_firestore23.query)((0, import_firestore23.collection)(db, CLINICS_COLLECTION), ...constraints);
7008
+ const querySnapshot = await (0, import_firestore23.getDocs)(q);
6701
7009
  console.log(
6702
- `[MediaService] Moving file for ${mediaId} from ${oldStoragePath} to ${newStoragePath}`
7010
+ `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
6703
7011
  );
6704
- const oldStorageFileRef = (0, import_storage5.ref)(this.storage, oldStoragePath);
6705
- const newStorageFileRef = (0, import_storage5.ref)(this.storage, newStoragePath);
6706
- try {
6707
- console.log(`[MediaService] Downloading bytes from ${oldStoragePath}`);
6708
- const fileBytes = await (0, import_storage5.getBytes)(oldStorageFileRef);
6709
- console.log(
6710
- `[MediaService] Successfully downloaded ${fileBytes.byteLength} bytes from ${oldStoragePath}`
6711
- );
6712
- console.log(`[MediaService] Uploading bytes to ${newStoragePath}`);
6713
- await (0, import_storage5.uploadBytes)(newStorageFileRef, fileBytes, {
6714
- contentType: metadata.contentType
6715
- });
6716
- console.log(
6717
- `[MediaService] Successfully uploaded bytes to ${newStoragePath}`
6718
- );
6719
- const newDownloadURL = await (0, import_storage5.getDownloadURL)(newStorageFileRef);
6720
- console.log(
6721
- `[MediaService] Got new download URL for ${newStoragePath}: ${newDownloadURL}`
6722
- );
6723
- const updateData = {
6724
- accessLevel: newAccessLevel,
6725
- path: newStoragePath,
6726
- url: newDownloadURL,
6727
- updatedAt: import_firestore22.Timestamp.now()
6728
- };
6729
- const metadataDocRef = (0, import_firestore23.doc)(this.db, MEDIA_METADATA_COLLECTION, mediaId);
6730
- console.log(
6731
- `[MediaService] Updating Firestore metadata for ${mediaId} with new data:`,
6732
- updateData
6733
- );
6734
- await (0, import_firestore23.updateDoc)(metadataDocRef, updateData);
6735
- console.log(
6736
- `[MediaService] Successfully updated Firestore metadata for ${mediaId}`
6737
- );
6738
- try {
6739
- console.log(`[MediaService] Deleting old file from ${oldStoragePath}`);
6740
- await (0, import_storage5.deleteObject)(oldStorageFileRef);
6741
- console.log(
6742
- `[MediaService] Successfully deleted old file from ${oldStoragePath}`
6743
- );
6744
- } catch (deleteError) {
6745
- console.error(
6746
- `[MediaService] Failed to delete old file from ${oldStoragePath} for media ID ${mediaId}. This file is now orphaned. Error:`,
6747
- deleteError
7012
+ const clinics = querySnapshot.docs.map((doc34) => {
7013
+ return { ...doc34.data(), id: doc34.id };
7014
+ });
7015
+ let filteredClinics = clinics;
7016
+ if (filters.center) {
7017
+ const center = filters.center;
7018
+ const clinicsWithDistance = [];
7019
+ filteredClinics.forEach((clinic) => {
7020
+ const distance = (0, import_geofire_common6.distanceBetween)(
7021
+ [center.latitude, center.longitude],
7022
+ [clinic.location.latitude, clinic.location.longitude]
6748
7023
  );
6749
- }
6750
- return { ...metadata, ...updateData };
6751
- } catch (error) {
6752
- console.error(
6753
- `[MediaService] Error updating media access level and moving file for ${mediaId}:`,
6754
- error
7024
+ clinicsWithDistance.push({
7025
+ ...clinic,
7026
+ distance: distance / 1e3
7027
+ // Convert to kilometers
7028
+ });
7029
+ });
7030
+ filteredClinics = clinicsWithDistance;
7031
+ filteredClinics.sort(
7032
+ (a, b) => a.distance - b.distance
6755
7033
  );
6756
- if (newStorageFileRef && error.code !== "storage/object-not-found" && ((_a = error.message) == null ? void 0 : _a.includes("uploadBytes"))) {
6757
- console.warn(
6758
- `[MediaService] Attempting to delete partially uploaded file at ${newStoragePath} due to error.`
6759
- );
6760
- try {
6761
- await (0, import_storage5.deleteObject)(newStorageFileRef);
6762
- console.warn(
6763
- `[MediaService] Cleaned up partially uploaded file at ${newStoragePath}.`
6764
- );
6765
- } catch (cleanupError) {
6766
- console.error(
6767
- `[MediaService] Failed to cleanup partially uploaded file at ${newStoragePath}:`,
6768
- cleanupError
6769
- );
6770
- }
6771
- }
6772
- throw error;
6773
- }
6774
- }
6775
- /**
6776
- * List all media for an owner, optionally filtered by collection and access level.
6777
- * @param ownerId - ID of the owner.
6778
- * @param collectionName - Optional: Filter by collection name.
6779
- * @param accessLevel - Optional: Filter by access level.
6780
- * @param count - Optional: Number of items to fetch.
6781
- * @param startAfterId - Optional: ID of the document to start after (for pagination).
6782
- */
6783
- async listMedia(ownerId, collectionName, accessLevel, count, startAfterId) {
6784
- console.log(`[MediaService] Listing media for owner: ${ownerId}`);
6785
- let qConstraints = [(0, import_firestore23.where)("ownerId", "==", ownerId)];
6786
- if (collectionName) {
6787
- qConstraints.push((0, import_firestore23.where)("collectionName", "==", collectionName));
6788
- }
6789
- if (accessLevel) {
6790
- qConstraints.push((0, import_firestore23.where)("accessLevel", "==", accessLevel));
6791
7034
  }
6792
- qConstraints.push((0, import_firestore23.orderBy)("createdAt", "desc"));
6793
- if (count) {
6794
- qConstraints.push((0, import_firestore23.limit)(count));
6795
- }
6796
- if (startAfterId) {
6797
- const startAfterDoc = await this.getMediaMetadata(startAfterId);
6798
- if (startAfterDoc) {
6799
- }
7035
+ if (filters.tags && filters.tags.length > 1) {
7036
+ filteredClinics = filteredClinics.filter((clinic) => {
7037
+ return filters.tags.every((tag) => clinic.tags.includes(tag));
7038
+ });
6800
7039
  }
6801
- const finalQuery = (0, import_firestore23.query)(
6802
- (0, import_firestore23.collection)(this.db, MEDIA_METADATA_COLLECTION),
6803
- ...qConstraints
6804
- );
6805
- try {
6806
- const querySnapshot = await (0, import_firestore23.getDocs)(finalQuery);
6807
- const mediaList = querySnapshot.docs.map(
6808
- (doc34) => doc34.data()
7040
+ if (filters.minRating !== void 0) {
7041
+ filteredClinics = filteredClinics.filter(
7042
+ (clinic) => clinic.reviewInfo.averageRating >= filters.minRating
6809
7043
  );
6810
- console.log(`[MediaService] Found ${mediaList.length} media items.`);
6811
- return mediaList;
6812
- } catch (error) {
6813
- console.error("[MediaService] Error listing media:", error);
6814
- throw error;
6815
7044
  }
6816
- }
6817
- /**
6818
- * Get download URL for media. (Convenience, as URL is in metadata)
6819
- * @param mediaId - ID of the media.
6820
- */
6821
- async getMediaDownloadUrl(mediaId) {
6822
- console.log(`[MediaService] Getting download URL for media ID: ${mediaId}`);
6823
- const metadata = await this.getMediaMetadata(mediaId);
6824
- if (metadata && metadata.url) {
6825
- console.log(`[MediaService] URL found: ${metadata.url}`);
6826
- return metadata.url;
7045
+ if (filters.maxRating !== void 0) {
7046
+ filteredClinics = filteredClinics.filter(
7047
+ (clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
7048
+ );
6827
7049
  }
6828
- console.log(`[MediaService] URL not found for media ID: ${mediaId}`);
6829
- return null;
7050
+ lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7051
+ clinicsResult = filteredClinics;
6830
7052
  }
6831
- };
7053
+ return {
7054
+ clinics: clinicsResult,
7055
+ lastDoc: lastVisibleDoc
7056
+ };
7057
+ }
6832
7058
 
6833
7059
  // src/services/clinic/clinic.service.ts
6834
7060
  var ClinicService = class extends BaseService {
@@ -8533,7 +8759,8 @@ var ProcedureService = class extends BaseService {
8533
8759
  id: practitionerSnapshot.id,
8534
8760
  name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
8535
8761
  description: practitioner.basicInfo.bio || "",
8536
- photo: practitioner.basicInfo.profileImageUrl || "",
8762
+ photo: typeof practitioner.basicInfo.profileImageUrl === "string" ? practitioner.basicInfo.profileImageUrl : "",
8763
+ // Default to empty string if not a processed URL
8537
8764
  rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
8538
8765
  services: practitioner.procedures || []
8539
8766
  };
@@ -8667,7 +8894,8 @@ var ProcedureService = class extends BaseService {
8667
8894
  id: newPractitioner.id,
8668
8895
  name: `${newPractitioner.basicInfo.firstName} ${newPractitioner.basicInfo.lastName}`,
8669
8896
  description: newPractitioner.basicInfo.bio || "",
8670
- photo: newPractitioner.basicInfo.profileImageUrl || "",
8897
+ photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
8898
+ // Default to empty string if not a processed URL
8671
8899
  rating: ((_a = newPractitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
8672
8900
  services: newPractitioner.procedures || []
8673
8901
  };