@blackcode_sa/metaestetics-api 1.7.20 → 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.mjs CHANGED
@@ -987,31 +987,348 @@ import { z as z16 } from "zod";
987
987
 
988
988
  // src/services/patient/patient.service.ts
989
989
  import {
990
- doc as doc6,
991
- getDoc as getDoc9,
992
- writeBatch
990
+ doc as doc7,
991
+ getDoc as getDoc10,
992
+ writeBatch,
993
+ updateDoc as updateDoc7,
994
+ serverTimestamp as serverTimestamp7
993
995
  } from "firebase/firestore";
994
996
 
997
+ // src/services/media/media.service.ts
998
+ import { Timestamp } from "firebase/firestore";
999
+ import {
1000
+ ref,
1001
+ uploadBytes,
1002
+ getDownloadURL,
1003
+ deleteObject,
1004
+ getBytes
1005
+ } from "firebase/storage";
1006
+ import {
1007
+ doc,
1008
+ getDoc,
1009
+ setDoc,
1010
+ updateDoc,
1011
+ collection,
1012
+ query,
1013
+ where,
1014
+ limit,
1015
+ getDocs,
1016
+ deleteDoc,
1017
+ orderBy
1018
+ } from "firebase/firestore";
1019
+ var MediaAccessLevel = /* @__PURE__ */ ((MediaAccessLevel2) => {
1020
+ MediaAccessLevel2["PUBLIC"] = "public";
1021
+ MediaAccessLevel2["PRIVATE"] = "private";
1022
+ MediaAccessLevel2["CONFIDENTIAL"] = "confidential";
1023
+ return MediaAccessLevel2;
1024
+ })(MediaAccessLevel || {});
1025
+ var MEDIA_METADATA_COLLECTION = "media_metadata";
1026
+ var MediaService = class extends BaseService {
1027
+ constructor(db, auth, app) {
1028
+ super(db, auth, app);
1029
+ }
1030
+ /**
1031
+ * Upload a media file, store its metadata, and return the metadata including the URL.
1032
+ * @param file - The file to upload.
1033
+ * @param ownerId - ID of the owner (user, patient, clinic, etc.).
1034
+ * @param accessLevel - Access level (public, private, confidential).
1035
+ * @param collectionName - The logical collection name this media belongs to (e.g., 'patient_profile_pictures', 'clinic_logos').
1036
+ * @param originalFileName - Optional: the original name of the file, if not using file.name.
1037
+ * @returns Promise with the media metadata.
1038
+ */
1039
+ async uploadMedia(file, ownerId, accessLevel, collectionName, originalFileName) {
1040
+ const mediaId = this.generateId();
1041
+ const fileNameToUse = originalFileName || (file instanceof File ? file.name : file.toString());
1042
+ const uniqueFileName = `${mediaId}-${fileNameToUse}`;
1043
+ const filePath = `media/${accessLevel}/${ownerId}/${collectionName}/${uniqueFileName}`;
1044
+ console.log(`[MediaService] Uploading file to: ${filePath}`);
1045
+ const storageRef = ref(this.storage, filePath);
1046
+ try {
1047
+ const uploadResult = await uploadBytes(storageRef, file, {
1048
+ contentType: file.type
1049
+ });
1050
+ console.log("[MediaService] File uploaded successfully", uploadResult);
1051
+ const downloadURL = await getDownloadURL(uploadResult.ref);
1052
+ console.log("[MediaService] Got download URL:", downloadURL);
1053
+ const metadata = {
1054
+ id: mediaId,
1055
+ name: fileNameToUse,
1056
+ url: downloadURL,
1057
+ contentType: file.type,
1058
+ size: file.size,
1059
+ createdAt: Timestamp.now(),
1060
+ accessLevel,
1061
+ ownerId,
1062
+ collectionName,
1063
+ path: filePath
1064
+ };
1065
+ const metadataDocRef = doc(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1066
+ await setDoc(metadataDocRef, metadata);
1067
+ console.log("[MediaService] Metadata stored in Firestore:", mediaId);
1068
+ return metadata;
1069
+ } catch (error) {
1070
+ console.error("[MediaService] Error during media upload:", error);
1071
+ throw error;
1072
+ }
1073
+ }
1074
+ /**
1075
+ * Get media metadata from Firestore by its ID.
1076
+ * @param mediaId - ID of the media.
1077
+ * @returns Promise with the media metadata or null if not found.
1078
+ */
1079
+ async getMediaMetadata(mediaId) {
1080
+ console.log(`[MediaService] Getting media metadata for ID: ${mediaId}`);
1081
+ const docRef = doc(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1082
+ const docSnap = await getDoc(docRef);
1083
+ if (docSnap.exists()) {
1084
+ console.log("[MediaService] Metadata found:", docSnap.data());
1085
+ return docSnap.data();
1086
+ }
1087
+ console.log("[MediaService] No metadata found for ID:", mediaId);
1088
+ return null;
1089
+ }
1090
+ /**
1091
+ * Get media metadata from Firestore by its public URL.
1092
+ * @param url - The public URL of the media file.
1093
+ * @returns Promise with the media metadata or null if not found.
1094
+ */
1095
+ async getMediaMetadataByUrl(url) {
1096
+ console.log(`[MediaService] Getting media metadata by URL: ${url}`);
1097
+ const q = query(
1098
+ collection(this.db, MEDIA_METADATA_COLLECTION),
1099
+ where("url", "==", url),
1100
+ limit(1)
1101
+ );
1102
+ try {
1103
+ const querySnapshot = await getDocs(q);
1104
+ if (!querySnapshot.empty) {
1105
+ const metadata = querySnapshot.docs[0].data();
1106
+ console.log("[MediaService] Metadata found by URL:", metadata);
1107
+ return metadata;
1108
+ }
1109
+ console.log("[MediaService] No metadata found for URL:", url);
1110
+ return null;
1111
+ } catch (error) {
1112
+ console.error("[MediaService] Error fetching metadata by URL:", error);
1113
+ throw error;
1114
+ }
1115
+ }
1116
+ /**
1117
+ * Delete media from storage and remove metadata from Firestore.
1118
+ * @param mediaId - ID of the media to delete.
1119
+ */
1120
+ async deleteMedia(mediaId) {
1121
+ console.log(`[MediaService] Deleting media with ID: ${mediaId}`);
1122
+ const metadata = await this.getMediaMetadata(mediaId);
1123
+ if (!metadata) {
1124
+ console.warn(
1125
+ `[MediaService] Metadata not found for media ID ${mediaId}. Cannot delete.`
1126
+ );
1127
+ return;
1128
+ }
1129
+ const storageFileRef = ref(this.storage, metadata.path);
1130
+ try {
1131
+ await deleteObject(storageFileRef);
1132
+ console.log(`[MediaService] File deleted from Storage: ${metadata.path}`);
1133
+ const metadataDocRef = doc(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1134
+ await deleteDoc(metadataDocRef);
1135
+ console.log(
1136
+ `[MediaService] Metadata deleted from Firestore for ID: ${mediaId}`
1137
+ );
1138
+ } catch (error) {
1139
+ console.error(`[MediaService] Error deleting media ${mediaId}:`, error);
1140
+ throw error;
1141
+ }
1142
+ }
1143
+ /**
1144
+ * Update media access level. This involves moving the file in Firebase Storage
1145
+ * to a new path reflecting the new access level, and updating its metadata.
1146
+ * @param mediaId - ID of the media to update.
1147
+ * @param newAccessLevel - New access level.
1148
+ * @returns Promise with the updated media metadata, or null if metadata not found.
1149
+ */
1150
+ async updateMediaAccessLevel(mediaId, newAccessLevel) {
1151
+ var _a;
1152
+ console.log(
1153
+ `[MediaService] Attempting to update access level for media ID: ${mediaId} to ${newAccessLevel}`
1154
+ );
1155
+ const metadata = await this.getMediaMetadata(mediaId);
1156
+ if (!metadata) {
1157
+ console.warn(
1158
+ `[MediaService] Metadata not found for media ID ${mediaId}. Cannot update access level.`
1159
+ );
1160
+ return null;
1161
+ }
1162
+ if (metadata.accessLevel === newAccessLevel) {
1163
+ console.log(
1164
+ `[MediaService] Media ID ${mediaId} already has access level ${newAccessLevel}. Updating timestamp only.`
1165
+ );
1166
+ const metadataDocRef = doc(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1167
+ try {
1168
+ await updateDoc(metadataDocRef, { updatedAt: Timestamp.now() });
1169
+ return { ...metadata, updatedAt: Timestamp.now() };
1170
+ } catch (error) {
1171
+ console.error(
1172
+ `[MediaService] Error updating timestamp for media ID ${mediaId}:`,
1173
+ error
1174
+ );
1175
+ throw error;
1176
+ }
1177
+ }
1178
+ const oldStoragePath = metadata.path;
1179
+ const fileNamePart = `${metadata.id}-${metadata.name}`;
1180
+ const newStoragePath = `media/${newAccessLevel}/${metadata.ownerId}/${metadata.collectionName}/${fileNamePart}`;
1181
+ console.log(
1182
+ `[MediaService] Moving file for ${mediaId} from ${oldStoragePath} to ${newStoragePath}`
1183
+ );
1184
+ const oldStorageFileRef = ref(this.storage, oldStoragePath);
1185
+ const newStorageFileRef = ref(this.storage, newStoragePath);
1186
+ try {
1187
+ console.log(`[MediaService] Downloading bytes from ${oldStoragePath}`);
1188
+ const fileBytes = await getBytes(oldStorageFileRef);
1189
+ console.log(
1190
+ `[MediaService] Successfully downloaded ${fileBytes.byteLength} bytes from ${oldStoragePath}`
1191
+ );
1192
+ console.log(`[MediaService] Uploading bytes to ${newStoragePath}`);
1193
+ await uploadBytes(newStorageFileRef, fileBytes, {
1194
+ contentType: metadata.contentType
1195
+ });
1196
+ console.log(
1197
+ `[MediaService] Successfully uploaded bytes to ${newStoragePath}`
1198
+ );
1199
+ const newDownloadURL = await getDownloadURL(newStorageFileRef);
1200
+ console.log(
1201
+ `[MediaService] Got new download URL for ${newStoragePath}: ${newDownloadURL}`
1202
+ );
1203
+ const updateData = {
1204
+ accessLevel: newAccessLevel,
1205
+ path: newStoragePath,
1206
+ url: newDownloadURL,
1207
+ updatedAt: Timestamp.now()
1208
+ };
1209
+ const metadataDocRef = doc(this.db, MEDIA_METADATA_COLLECTION, mediaId);
1210
+ console.log(
1211
+ `[MediaService] Updating Firestore metadata for ${mediaId} with new data:`,
1212
+ updateData
1213
+ );
1214
+ await updateDoc(metadataDocRef, updateData);
1215
+ console.log(
1216
+ `[MediaService] Successfully updated Firestore metadata for ${mediaId}`
1217
+ );
1218
+ try {
1219
+ console.log(`[MediaService] Deleting old file from ${oldStoragePath}`);
1220
+ await deleteObject(oldStorageFileRef);
1221
+ console.log(
1222
+ `[MediaService] Successfully deleted old file from ${oldStoragePath}`
1223
+ );
1224
+ } catch (deleteError) {
1225
+ console.error(
1226
+ `[MediaService] Failed to delete old file from ${oldStoragePath} for media ID ${mediaId}. This file is now orphaned. Error:`,
1227
+ deleteError
1228
+ );
1229
+ }
1230
+ return { ...metadata, ...updateData };
1231
+ } catch (error) {
1232
+ console.error(
1233
+ `[MediaService] Error updating media access level and moving file for ${mediaId}:`,
1234
+ error
1235
+ );
1236
+ if (newStorageFileRef && error.code !== "storage/object-not-found" && ((_a = error.message) == null ? void 0 : _a.includes("uploadBytes"))) {
1237
+ console.warn(
1238
+ `[MediaService] Attempting to delete partially uploaded file at ${newStoragePath} due to error.`
1239
+ );
1240
+ try {
1241
+ await deleteObject(newStorageFileRef);
1242
+ console.warn(
1243
+ `[MediaService] Cleaned up partially uploaded file at ${newStoragePath}.`
1244
+ );
1245
+ } catch (cleanupError) {
1246
+ console.error(
1247
+ `[MediaService] Failed to cleanup partially uploaded file at ${newStoragePath}:`,
1248
+ cleanupError
1249
+ );
1250
+ }
1251
+ }
1252
+ throw error;
1253
+ }
1254
+ }
1255
+ /**
1256
+ * List all media for an owner, optionally filtered by collection and access level.
1257
+ * @param ownerId - ID of the owner.
1258
+ * @param collectionName - Optional: Filter by collection name.
1259
+ * @param accessLevel - Optional: Filter by access level.
1260
+ * @param count - Optional: Number of items to fetch.
1261
+ * @param startAfterId - Optional: ID of the document to start after (for pagination).
1262
+ */
1263
+ async listMedia(ownerId, collectionName, accessLevel, count, startAfterId) {
1264
+ console.log(`[MediaService] Listing media for owner: ${ownerId}`);
1265
+ let qConstraints = [where("ownerId", "==", ownerId)];
1266
+ if (collectionName) {
1267
+ qConstraints.push(where("collectionName", "==", collectionName));
1268
+ }
1269
+ if (accessLevel) {
1270
+ qConstraints.push(where("accessLevel", "==", accessLevel));
1271
+ }
1272
+ qConstraints.push(orderBy("createdAt", "desc"));
1273
+ if (count) {
1274
+ qConstraints.push(limit(count));
1275
+ }
1276
+ if (startAfterId) {
1277
+ const startAfterDoc = await this.getMediaMetadata(startAfterId);
1278
+ if (startAfterDoc) {
1279
+ }
1280
+ }
1281
+ const finalQuery = query(
1282
+ collection(this.db, MEDIA_METADATA_COLLECTION),
1283
+ ...qConstraints
1284
+ );
1285
+ try {
1286
+ const querySnapshot = await getDocs(finalQuery);
1287
+ const mediaList = querySnapshot.docs.map(
1288
+ (doc34) => doc34.data()
1289
+ );
1290
+ console.log(`[MediaService] Found ${mediaList.length} media items.`);
1291
+ return mediaList;
1292
+ } catch (error) {
1293
+ console.error("[MediaService] Error listing media:", error);
1294
+ throw error;
1295
+ }
1296
+ }
1297
+ /**
1298
+ * Get download URL for media. (Convenience, as URL is in metadata)
1299
+ * @param mediaId - ID of the media.
1300
+ */
1301
+ async getMediaDownloadUrl(mediaId) {
1302
+ console.log(`[MediaService] Getting download URL for media ID: ${mediaId}`);
1303
+ const metadata = await this.getMediaMetadata(mediaId);
1304
+ if (metadata && metadata.url) {
1305
+ console.log(`[MediaService] URL found: ${metadata.url}`);
1306
+ return metadata.url;
1307
+ }
1308
+ console.log(`[MediaService] URL not found for media ID: ${mediaId}`);
1309
+ return null;
1310
+ }
1311
+ };
1312
+
995
1313
  // src/services/patient/utils/profile.utils.ts
996
1314
  import {
997
- getDoc as getDoc5,
998
- setDoc as setDoc4,
999
- updateDoc as updateDoc3,
1315
+ getDoc as getDoc6,
1316
+ setDoc as setDoc5,
1317
+ updateDoc as updateDoc4,
1000
1318
  arrayUnion as arrayUnion2,
1001
1319
  arrayRemove as arrayRemove2,
1002
1320
  serverTimestamp as serverTimestamp4,
1003
1321
  increment,
1004
- Timestamp as Timestamp4,
1005
- collection as collection3,
1006
- query as query3,
1007
- where as where3,
1008
- getDocs as getDocs3,
1009
- limit as limit2,
1322
+ Timestamp as Timestamp5,
1323
+ collection as collection4,
1324
+ query as query4,
1325
+ where as where4,
1326
+ getDocs as getDocs4,
1327
+ limit as limit3,
1010
1328
  startAfter as startAfter2,
1011
- doc as doc4
1329
+ doc as doc5
1012
1330
  } from "firebase/firestore";
1013
- import { ref, uploadBytes, getDownloadURL, deleteObject } from "firebase/storage";
1014
- import { z as z8 } from "zod";
1331
+ import { z as z9 } from "zod";
1015
1332
 
1016
1333
  // src/types/patient/medical-info.types.ts
1017
1334
  var PATIENT_MEDICAL_INFO_COLLECTION = "medical_info";
@@ -1040,11 +1357,19 @@ var Gender = /* @__PURE__ */ ((Gender2) => {
1040
1357
  })(Gender || {});
1041
1358
 
1042
1359
  // src/validations/patient.schema.ts
1043
- import { z as z6 } from "zod";
1044
- import { Timestamp as Timestamp2 } from "firebase/firestore";
1360
+ import { z as z7 } from "zod";
1361
+ import { Timestamp as Timestamp3 } from "firebase/firestore";
1362
+
1363
+ // src/validations/media.schema.ts
1364
+ import { z as z4 } from "zod";
1365
+ var mediaResourceSchema = z4.union([
1366
+ z4.string().url(),
1367
+ z4.instanceof(File),
1368
+ z4.instanceof(Blob)
1369
+ ]);
1045
1370
 
1046
1371
  // src/validations/patient/medical-info.schema.ts
1047
- import { z as z5 } from "zod";
1372
+ import { z as z6 } from "zod";
1048
1373
 
1049
1374
  // src/types/patient/allergies.ts
1050
1375
  var AllergyType = /* @__PURE__ */ ((AllergyType2) => {
@@ -1133,80 +1458,80 @@ var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
1133
1458
  })(Contraindication || {});
1134
1459
 
1135
1460
  // src/validations/common.schema.ts
1136
- import { z as z4 } from "zod";
1137
- import { Timestamp } from "firebase/firestore";
1138
- var timestampSchema2 = z4.union([
1139
- z4.object({
1140
- seconds: z4.number(),
1141
- nanoseconds: z4.number()
1461
+ import { z as z5 } from "zod";
1462
+ import { Timestamp as Timestamp2 } from "firebase/firestore";
1463
+ var timestampSchema2 = z5.union([
1464
+ z5.object({
1465
+ seconds: z5.number(),
1466
+ nanoseconds: z5.number()
1142
1467
  }),
1143
- z4.instanceof(Timestamp)
1468
+ z5.instanceof(Timestamp2)
1144
1469
  ]).transform((data) => {
1145
- if (data instanceof Timestamp) {
1470
+ if (data instanceof Timestamp2) {
1146
1471
  return data;
1147
1472
  }
1148
- return new Timestamp(data.seconds, data.nanoseconds);
1473
+ return new Timestamp2(data.seconds, data.nanoseconds);
1149
1474
  });
1150
1475
 
1151
1476
  // src/validations/patient/medical-info.schema.ts
1152
- var allergySubtypeSchema = z5.union([
1153
- z5.nativeEnum(MedicationAllergySubtype),
1154
- z5.nativeEnum(FoodAllergySubtype),
1155
- z5.nativeEnum(EnvironmentalAllergySubtype),
1156
- z5.nativeEnum(CosmeticAllergySubtype),
1157
- z5.literal("other")
1477
+ var allergySubtypeSchema = z6.union([
1478
+ z6.nativeEnum(MedicationAllergySubtype),
1479
+ z6.nativeEnum(FoodAllergySubtype),
1480
+ z6.nativeEnum(EnvironmentalAllergySubtype),
1481
+ z6.nativeEnum(CosmeticAllergySubtype),
1482
+ z6.literal("other")
1158
1483
  ]);
1159
- var allergySchema = z5.object({
1160
- type: z5.nativeEnum(AllergyType),
1484
+ var allergySchema = z6.object({
1485
+ type: z6.nativeEnum(AllergyType),
1161
1486
  subtype: allergySubtypeSchema,
1162
- name: z5.string().optional().nullable(),
1163
- severity: z5.enum(["mild", "moderate", "severe"]).optional(),
1164
- reaction: z5.string().optional().nullable(),
1487
+ name: z6.string().optional().nullable(),
1488
+ severity: z6.enum(["mild", "moderate", "severe"]).optional(),
1489
+ reaction: z6.string().optional().nullable(),
1165
1490
  diagnosed: timestampSchema2.optional().nullable(),
1166
- notes: z5.string().optional().nullable()
1491
+ notes: z6.string().optional().nullable()
1167
1492
  });
1168
- var vitalStatsSchema = z5.object({
1169
- height: z5.number().positive().optional(),
1170
- weight: z5.number().positive().optional(),
1171
- bloodType: z5.enum(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]).optional(),
1172
- bloodPressure: z5.object({
1173
- systolic: z5.number().min(70).max(200),
1174
- diastolic: z5.number().min(40).max(130),
1493
+ var vitalStatsSchema = z6.object({
1494
+ height: z6.number().positive().optional(),
1495
+ weight: z6.number().positive().optional(),
1496
+ bloodType: z6.enum(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]).optional(),
1497
+ bloodPressure: z6.object({
1498
+ systolic: z6.number().min(70).max(200),
1499
+ diastolic: z6.number().min(40).max(130),
1175
1500
  lastMeasured: timestampSchema2
1176
1501
  }).optional()
1177
1502
  });
1178
- var blockingConditionSchema = z5.object({
1179
- condition: z5.nativeEnum(BlockingCondition),
1503
+ var blockingConditionSchema = z6.object({
1504
+ condition: z6.nativeEnum(BlockingCondition),
1180
1505
  diagnosedAt: timestampSchema2,
1181
- notes: z5.string().optional().nullable(),
1182
- isActive: z5.boolean()
1506
+ notes: z6.string().optional().nullable(),
1507
+ isActive: z6.boolean()
1183
1508
  });
1184
- var contraindicationSchema = z5.object({
1185
- condition: z5.nativeEnum(Contraindication),
1509
+ var contraindicationSchema = z6.object({
1510
+ condition: z6.nativeEnum(Contraindication),
1186
1511
  lastOccurrence: timestampSchema2,
1187
- frequency: z5.enum(["rare", "occasional", "frequent"]),
1188
- notes: z5.string().optional().nullable(),
1189
- isActive: z5.boolean()
1512
+ frequency: z6.enum(["rare", "occasional", "frequent"]),
1513
+ notes: z6.string().optional().nullable(),
1514
+ isActive: z6.boolean()
1190
1515
  });
1191
- var medicationSchema = z5.object({
1192
- name: z5.string().min(1),
1193
- dosage: z5.string().min(1),
1194
- frequency: z5.string().min(1),
1516
+ var medicationSchema = z6.object({
1517
+ name: z6.string().min(1),
1518
+ dosage: z6.string().min(1),
1519
+ frequency: z6.string().min(1),
1195
1520
  startDate: timestampSchema2.optional().nullable(),
1196
1521
  endDate: timestampSchema2.optional().nullable(),
1197
- prescribedBy: z5.string().optional().nullable()
1522
+ prescribedBy: z6.string().optional().nullable()
1198
1523
  });
1199
- var patientMedicalInfoSchema = z5.object({
1200
- patientId: z5.string(),
1524
+ var patientMedicalInfoSchema = z6.object({
1525
+ patientId: z6.string(),
1201
1526
  vitalStats: vitalStatsSchema,
1202
- blockingConditions: z5.array(blockingConditionSchema),
1203
- contraindications: z5.array(contraindicationSchema),
1204
- allergies: z5.array(allergySchema),
1205
- currentMedications: z5.array(medicationSchema),
1206
- emergencyNotes: z5.string().optional(),
1527
+ blockingConditions: z6.array(blockingConditionSchema),
1528
+ contraindications: z6.array(contraindicationSchema),
1529
+ allergies: z6.array(allergySchema),
1530
+ currentMedications: z6.array(medicationSchema),
1531
+ emergencyNotes: z6.string().optional(),
1207
1532
  lastUpdated: timestampSchema2,
1208
- updatedBy: z5.string(),
1209
- verifiedBy: z5.string().optional(),
1533
+ updatedBy: z6.string(),
1534
+ verifiedBy: z6.string().optional(),
1210
1535
  verifiedAt: timestampSchema2.optional()
1211
1536
  });
1212
1537
  var createPatientMedicalInfoSchema = patientMedicalInfoSchema.omit({
@@ -1220,141 +1545,140 @@ var updatePatientMedicalInfoSchema = createPatientMedicalInfoSchema.partial();
1220
1545
  var updateVitalStatsSchema = vitalStatsSchema;
1221
1546
  var addAllergySchema = allergySchema;
1222
1547
  var updateAllergySchema = allergySchema.partial().extend({
1223
- allergyIndex: z5.number().min(0)
1548
+ allergyIndex: z6.number().min(0)
1224
1549
  });
1225
1550
  var addBlockingConditionSchema = blockingConditionSchema;
1226
1551
  var updateBlockingConditionSchema = blockingConditionSchema.partial().extend({
1227
- conditionIndex: z5.number().min(0)
1552
+ conditionIndex: z6.number().min(0)
1228
1553
  });
1229
1554
  var addContraindicationSchema = contraindicationSchema;
1230
1555
  var updateContraindicationSchema = contraindicationSchema.partial().extend({
1231
- contraindicationIndex: z5.number().min(0)
1556
+ contraindicationIndex: z6.number().min(0)
1232
1557
  });
1233
1558
  var addMedicationSchema = medicationSchema;
1234
1559
  var updateMedicationSchema = medicationSchema.partial().extend({
1235
- medicationIndex: z5.number().min(0)
1560
+ medicationIndex: z6.number().min(0)
1236
1561
  });
1237
1562
 
1238
1563
  // src/validations/patient.schema.ts
1239
- var locationDataSchema = z6.object({
1240
- latitude: z6.number().min(-90).max(90),
1241
- longitude: z6.number().min(-180).max(180),
1242
- geohash: z6.string().optional()
1564
+ var locationDataSchema = z7.object({
1565
+ latitude: z7.number().min(-90).max(90),
1566
+ longitude: z7.number().min(-180).max(180),
1567
+ geohash: z7.string().optional()
1243
1568
  });
1244
- var addressDataSchema = z6.object({
1245
- address: z6.string(),
1246
- city: z6.string(),
1247
- country: z6.string(),
1248
- postalCode: z6.string()
1569
+ var addressDataSchema = z7.object({
1570
+ address: z7.string(),
1571
+ city: z7.string(),
1572
+ country: z7.string(),
1573
+ postalCode: z7.string()
1249
1574
  });
1250
- var emergencyContactSchema = z6.object({
1251
- name: z6.string(),
1252
- relationship: z6.string(),
1253
- phoneNumber: z6.string(),
1254
- isNotifiable: z6.boolean()
1575
+ var emergencyContactSchema = z7.object({
1576
+ name: z7.string(),
1577
+ relationship: z7.string(),
1578
+ phoneNumber: z7.string(),
1579
+ isNotifiable: z7.boolean()
1255
1580
  });
1256
- var gamificationSchema = z6.object({
1257
- level: z6.number(),
1258
- points: z6.number()
1581
+ var gamificationSchema = z7.object({
1582
+ level: z7.number(),
1583
+ points: z7.number()
1259
1584
  });
1260
- var patientLocationInfoSchema = z6.object({
1261
- patientId: z6.string(),
1262
- userRef: z6.string(),
1585
+ var patientLocationInfoSchema = z7.object({
1586
+ patientId: z7.string(),
1587
+ userRef: z7.string(),
1263
1588
  locationData: locationDataSchema,
1264
- createdAt: z6.instanceof(Timestamp2),
1265
- updatedAt: z6.instanceof(Timestamp2)
1589
+ createdAt: z7.instanceof(Timestamp3),
1590
+ updatedAt: z7.instanceof(Timestamp3)
1266
1591
  });
1267
- var createPatientLocationInfoSchema = z6.object({
1268
- patientId: z6.string(),
1269
- userRef: z6.string(),
1592
+ var createPatientLocationInfoSchema = z7.object({
1593
+ patientId: z7.string(),
1594
+ userRef: z7.string(),
1270
1595
  locationData: locationDataSchema
1271
1596
  });
1272
- var patientSensitiveInfoSchema = z6.object({
1273
- patientId: z6.string(),
1274
- userRef: z6.string(),
1275
- photoUrl: z6.string().optional(),
1276
- firstName: z6.string().min(2),
1277
- lastName: z6.string().min(2),
1278
- dateOfBirth: z6.instanceof(Timestamp2).nullable(),
1279
- gender: z6.nativeEnum(Gender),
1280
- email: z6.string().email().optional(),
1281
- phoneNumber: z6.string().optional(),
1282
- alternativePhoneNumber: z6.string().optional(),
1597
+ var patientSensitiveInfoSchema = z7.object({
1598
+ patientId: z7.string(),
1599
+ userRef: z7.string(),
1600
+ firstName: z7.string().min(2),
1601
+ lastName: z7.string().min(2),
1602
+ dateOfBirth: z7.instanceof(Timestamp3).nullable(),
1603
+ gender: z7.nativeEnum(Gender),
1604
+ email: z7.string().email().optional(),
1605
+ phoneNumber: z7.string().optional(),
1606
+ alternativePhoneNumber: z7.string().optional(),
1283
1607
  addressData: addressDataSchema.optional(),
1284
- emergencyContacts: z6.array(emergencyContactSchema).optional(),
1285
- createdAt: z6.instanceof(Timestamp2),
1286
- updatedAt: z6.instanceof(Timestamp2)
1608
+ emergencyContacts: z7.array(emergencyContactSchema).optional(),
1609
+ createdAt: z7.instanceof(Timestamp3),
1610
+ updatedAt: z7.instanceof(Timestamp3)
1287
1611
  });
1288
- var patientDoctorSchema = z6.object({
1289
- userRef: z6.string(),
1290
- assignedAt: z6.instanceof(Timestamp2),
1291
- assignedBy: z6.string().optional(),
1292
- isActive: z6.boolean(),
1293
- notes: z6.string().optional()
1612
+ var patientDoctorSchema = z7.object({
1613
+ userRef: z7.string(),
1614
+ assignedAt: z7.instanceof(Timestamp3),
1615
+ assignedBy: z7.string().optional(),
1616
+ isActive: z7.boolean(),
1617
+ notes: z7.string().optional()
1294
1618
  });
1295
- var patientClinicSchema = z6.object({
1296
- clinicId: z6.string(),
1297
- assignedAt: z6.instanceof(Timestamp2),
1298
- assignedBy: z6.string().optional(),
1299
- isActive: z6.boolean(),
1300
- notes: z6.string().optional()
1619
+ var patientClinicSchema = z7.object({
1620
+ clinicId: z7.string(),
1621
+ assignedAt: z7.instanceof(Timestamp3),
1622
+ assignedBy: z7.string().optional(),
1623
+ isActive: z7.boolean(),
1624
+ notes: z7.string().optional()
1301
1625
  });
1302
- var patientProfileSchema = z6.object({
1303
- id: z6.string(),
1304
- userRef: z6.string(),
1305
- displayName: z6.string(),
1306
- profilePhoto: z6.string().url().nullable(),
1626
+ var patientProfileSchema = z7.object({
1627
+ id: z7.string(),
1628
+ userRef: z7.string(),
1629
+ displayName: z7.string(),
1307
1630
  gamification: gamificationSchema,
1308
- expoTokens: z6.array(z6.string()),
1309
- isActive: z6.boolean(),
1310
- isVerified: z6.boolean(),
1311
- doctors: z6.array(patientDoctorSchema),
1312
- clinics: z6.array(patientClinicSchema),
1313
- doctorIds: z6.array(z6.string()),
1314
- clinicIds: z6.array(z6.string()),
1315
- createdAt: z6.instanceof(Timestamp2),
1316
- updatedAt: z6.instanceof(Timestamp2)
1631
+ expoTokens: z7.array(z7.string()),
1632
+ isActive: z7.boolean(),
1633
+ isVerified: z7.boolean(),
1634
+ phoneNumber: z7.string().nullable().optional(),
1635
+ dateOfBirth: z7.instanceof(Timestamp3).nullable().optional(),
1636
+ doctors: z7.array(patientDoctorSchema),
1637
+ clinics: z7.array(patientClinicSchema),
1638
+ doctorIds: z7.array(z7.string()),
1639
+ clinicIds: z7.array(z7.string()),
1640
+ createdAt: z7.instanceof(Timestamp3),
1641
+ updatedAt: z7.instanceof(Timestamp3)
1317
1642
  });
1318
- var createPatientProfileSchema = z6.object({
1319
- userRef: z6.string(),
1320
- displayName: z6.string(),
1321
- profilePhoto: z6.string().url().nullable().optional(),
1322
- expoTokens: z6.array(z6.string()),
1643
+ var createPatientProfileSchema = z7.object({
1644
+ userRef: z7.string(),
1645
+ displayName: z7.string(),
1646
+ expoTokens: z7.array(z7.string()),
1323
1647
  gamification: gamificationSchema.optional(),
1324
- isActive: z6.boolean(),
1325
- isVerified: z6.boolean(),
1326
- doctors: z6.array(patientDoctorSchema).optional(),
1327
- clinics: z6.array(patientClinicSchema).optional(),
1328
- doctorIds: z6.array(z6.string()).optional(),
1329
- clinicIds: z6.array(z6.string()).optional()
1648
+ isActive: z7.boolean(),
1649
+ isVerified: z7.boolean(),
1650
+ doctors: z7.array(patientDoctorSchema).optional(),
1651
+ clinics: z7.array(patientClinicSchema).optional(),
1652
+ doctorIds: z7.array(z7.string()).optional(),
1653
+ clinicIds: z7.array(z7.string()).optional()
1330
1654
  });
1331
- var createPatientSensitiveInfoSchema = z6.object({
1332
- patientId: z6.string(),
1333
- userRef: z6.string(),
1334
- photoUrl: z6.string().optional(),
1335
- firstName: z6.string().min(2),
1336
- lastName: z6.string().min(2),
1337
- dateOfBirth: z6.instanceof(Timestamp2).nullable(),
1338
- gender: z6.nativeEnum(Gender),
1339
- email: z6.string().email().optional(),
1340
- phoneNumber: z6.string().optional(),
1341
- alternativePhoneNumber: z6.string().optional(),
1655
+ var createPatientSensitiveInfoSchema = z7.object({
1656
+ patientId: z7.string(),
1657
+ userRef: z7.string(),
1658
+ photoUrl: mediaResourceSchema.nullable().optional(),
1659
+ firstName: z7.string().min(2),
1660
+ lastName: z7.string().min(2),
1661
+ dateOfBirth: z7.instanceof(Timestamp3).nullable(),
1662
+ gender: z7.nativeEnum(Gender),
1663
+ email: z7.string().email().optional(),
1664
+ phoneNumber: z7.string().optional(),
1665
+ alternativePhoneNumber: z7.string().optional(),
1342
1666
  addressData: addressDataSchema.optional(),
1343
- emergencyContacts: z6.array(emergencyContactSchema).optional()
1667
+ emergencyContacts: z7.array(emergencyContactSchema).optional()
1344
1668
  });
1345
- var searchPatientsSchema = z6.object({
1346
- clinicId: z6.string().optional(),
1347
- practitionerId: z6.string().optional()
1669
+ var searchPatientsSchema = z7.object({
1670
+ clinicId: z7.string().optional(),
1671
+ practitionerId: z7.string().optional()
1348
1672
  }).refine((data) => data.clinicId || data.practitionerId, {
1349
1673
  message: "At least one of clinicId or practitionerId must be provided",
1350
1674
  path: []
1351
1675
  // Optional: specify a path like ['clinicId'] or ['practitionerId']
1352
1676
  });
1353
- var requesterInfoSchema = z6.object({
1354
- id: z6.string(),
1355
- role: z6.enum(["clinic_admin", "practitioner"]),
1356
- associatedClinicId: z6.string().optional(),
1357
- associatedPractitionerId: z6.string().optional()
1677
+ var requesterInfoSchema = z7.object({
1678
+ id: z7.string(),
1679
+ role: z7.enum(["clinic_admin", "practitioner"]),
1680
+ associatedClinicId: z7.string().optional(),
1681
+ associatedPractitionerId: z7.string().optional()
1358
1682
  }).refine(
1359
1683
  (data) => {
1360
1684
  if (data.role === "clinic_admin") {
@@ -1372,47 +1696,79 @@ var requesterInfoSchema = z6.object({
1372
1696
 
1373
1697
  // src/services/patient/utils/docs.utils.ts
1374
1698
  import {
1375
- doc,
1376
- collection,
1377
- query,
1378
- where,
1379
- getDocs,
1380
- getDoc as getDoc2
1699
+ doc as doc2,
1700
+ collection as collection2,
1701
+ query as query2,
1702
+ where as where2,
1703
+ getDocs as getDocs2,
1704
+ getDoc as getDoc3
1381
1705
  } from "firebase/firestore";
1382
1706
 
1383
1707
  // src/services/patient/utils/sensitive.utils.ts
1384
1708
  import {
1385
- getDoc,
1386
- updateDoc,
1387
- setDoc,
1709
+ getDoc as getDoc2,
1710
+ updateDoc as updateDoc2,
1711
+ setDoc as setDoc2,
1388
1712
  serverTimestamp
1389
1713
  } from "firebase/firestore";
1390
- import { z as z7 } from "zod";
1391
- var createSensitiveInfoUtil = async (db, data, requesterUserId) => {
1714
+ import { z as z8 } from "zod";
1715
+ var handlePhotoUrlUpload = async (photoUrl, patientId, mediaService) => {
1716
+ if (!photoUrl) {
1717
+ return null;
1718
+ }
1719
+ if (typeof photoUrl === "string") {
1720
+ return photoUrl;
1721
+ }
1722
+ if (photoUrl instanceof File || photoUrl instanceof Blob) {
1723
+ const mediaMetadata = await mediaService.uploadMedia(
1724
+ photoUrl,
1725
+ patientId,
1726
+ // Using patientId as ownerId
1727
+ "private" /* PRIVATE */,
1728
+ // Sensitive info should be private
1729
+ "patient_sensitive_photos",
1730
+ photoUrl instanceof File ? photoUrl.name : `sensitive_photo_${patientId}`
1731
+ );
1732
+ return mediaMetadata.url;
1733
+ }
1734
+ return null;
1735
+ };
1736
+ var createSensitiveInfoUtil = async (db, data, requesterUserId, mediaService) => {
1392
1737
  try {
1393
1738
  if (data.userRef !== requesterUserId) {
1394
1739
  throw new Error("Only patient can create their sensitive information");
1395
1740
  }
1396
1741
  const validatedData = createPatientSensitiveInfoSchema.parse(data);
1397
- const sensitiveDoc = await getDoc(
1742
+ const sensitiveDoc = await getDoc2(
1398
1743
  getSensitiveInfoDocRef(db, data.patientId)
1399
1744
  );
1400
1745
  if (sensitiveDoc.exists()) {
1401
1746
  throw new Error("Sensitive information already exists for this patient");
1402
1747
  }
1748
+ let processedPhotoUrl = null;
1749
+ if (validatedData.photoUrl && mediaService) {
1750
+ processedPhotoUrl = await handlePhotoUrlUpload(
1751
+ validatedData.photoUrl,
1752
+ data.patientId,
1753
+ mediaService
1754
+ );
1755
+ } else if (typeof validatedData.photoUrl === "string") {
1756
+ processedPhotoUrl = validatedData.photoUrl;
1757
+ }
1403
1758
  const sensitiveInfoData = {
1404
1759
  ...validatedData,
1760
+ photoUrl: processedPhotoUrl,
1405
1761
  createdAt: serverTimestamp(),
1406
1762
  updatedAt: serverTimestamp()
1407
1763
  };
1408
- await setDoc(getSensitiveInfoDocRef(db, data.patientId), sensitiveInfoData);
1409
- const createdDoc = await getDoc(getSensitiveInfoDocRef(db, data.patientId));
1764
+ await setDoc2(getSensitiveInfoDocRef(db, data.patientId), sensitiveInfoData);
1765
+ const createdDoc = await getDoc2(getSensitiveInfoDocRef(db, data.patientId));
1410
1766
  if (!createdDoc.exists()) {
1411
1767
  throw new Error("Failed to create sensitive information");
1412
1768
  }
1413
1769
  return createdDoc.data();
1414
1770
  } catch (error) {
1415
- if (error instanceof z7.ZodError) {
1771
+ if (error instanceof z8.ZodError) {
1416
1772
  throw new Error("Invalid sensitive info data: " + error.message);
1417
1773
  }
1418
1774
  throw error;
@@ -1420,17 +1776,32 @@ var createSensitiveInfoUtil = async (db, data, requesterUserId) => {
1420
1776
  };
1421
1777
  var getSensitiveInfoUtil = async (db, patientId, requesterUserId) => {
1422
1778
  await initSensitiveInfoDocIfNotExists(db, patientId, requesterUserId);
1423
- const sensitiveDoc = await getDoc(getSensitiveInfoDocRef(db, patientId));
1779
+ const sensitiveDoc = await getDoc2(getSensitiveInfoDocRef(db, patientId));
1424
1780
  return sensitiveDoc.exists() ? sensitiveDoc.data() : null;
1425
1781
  };
1426
- var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId) => {
1782
+ var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId, mediaService) => {
1427
1783
  await initSensitiveInfoDocIfNotExists(db, patientId, requesterUserId);
1784
+ let processedPhotoUrl = void 0;
1785
+ if (data.photoUrl !== void 0) {
1786
+ if (mediaService) {
1787
+ processedPhotoUrl = await handlePhotoUrlUpload(
1788
+ data.photoUrl,
1789
+ patientId,
1790
+ mediaService
1791
+ );
1792
+ } else if (typeof data.photoUrl === "string" || data.photoUrl === null) {
1793
+ processedPhotoUrl = data.photoUrl;
1794
+ } else {
1795
+ throw new Error("MediaService required to process photo upload");
1796
+ }
1797
+ }
1428
1798
  const updateData = {
1429
1799
  ...data,
1800
+ photoUrl: processedPhotoUrl,
1430
1801
  updatedAt: serverTimestamp()
1431
1802
  };
1432
- await updateDoc(getSensitiveInfoDocRef(db, patientId), updateData);
1433
- const updatedDoc = await getDoc(getSensitiveInfoDocRef(db, patientId));
1803
+ await updateDoc2(getSensitiveInfoDocRef(db, patientId), updateData);
1804
+ const updatedDoc = await getDoc2(getSensitiveInfoDocRef(db, patientId));
1434
1805
  if (!updatedDoc.exists()) {
1435
1806
  throw new Error("Failed to retrieve updated sensitive information");
1436
1807
  }
@@ -1439,21 +1810,21 @@ var updateSensitiveInfoUtil = async (db, patientId, data, requesterUserId) => {
1439
1810
 
1440
1811
  // src/services/patient/utils/docs.utils.ts
1441
1812
  var getPatientDocRef = (db, patientId) => {
1442
- return doc(db, PATIENTS_COLLECTION, patientId);
1813
+ return doc2(db, PATIENTS_COLLECTION, patientId);
1443
1814
  };
1444
1815
  var getPatientDocRefByUserRef = async (db, userRef) => {
1445
- const patientsRef = collection(db, PATIENTS_COLLECTION);
1446
- const q = query(patientsRef, where("userRef", "==", userRef));
1447
- const querySnapshot = await getDocs(q);
1816
+ const patientsRef = collection2(db, PATIENTS_COLLECTION);
1817
+ const q = query2(patientsRef, where2("userRef", "==", userRef));
1818
+ const querySnapshot = await getDocs2(q);
1448
1819
  if (querySnapshot.empty) {
1449
1820
  throw new Error("Patient profile not found");
1450
1821
  }
1451
- return doc(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
1822
+ return doc2(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
1452
1823
  };
1453
1824
  var getSensitiveInfoDocRef = (db, patientId) => {
1454
1825
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_SENSITIVE_INFO_COLLECTION}/${patientId}`;
1455
1826
  console.log(`[getSensitiveInfoDocRef] Creating reference with path: ${path}`);
1456
- return doc(
1827
+ return doc2(
1457
1828
  db,
1458
1829
  PATIENTS_COLLECTION,
1459
1830
  patientId,
@@ -1464,7 +1835,7 @@ var getSensitiveInfoDocRef = (db, patientId) => {
1464
1835
  var getLocationInfoDocRef = (db, patientId) => {
1465
1836
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_LOCATION_INFO_COLLECTION}/${patientId}`;
1466
1837
  console.log(`[getLocationInfoDocRef] Creating reference with path: ${path}`);
1467
- return doc(
1838
+ return doc2(
1468
1839
  db,
1469
1840
  PATIENTS_COLLECTION,
1470
1841
  patientId,
@@ -1475,7 +1846,7 @@ var getLocationInfoDocRef = (db, patientId) => {
1475
1846
  var getMedicalInfoDocRef = (db, patientId) => {
1476
1847
  const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_MEDICAL_INFO_COLLECTION}/${patientId}`;
1477
1848
  console.log(`[getMedicalInfoDocRef] Creating reference with path: ${path}`);
1478
- return doc(
1849
+ return doc2(
1479
1850
  db,
1480
1851
  PATIENTS_COLLECTION,
1481
1852
  patientId,
@@ -1492,7 +1863,7 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1492
1863
  console.log(
1493
1864
  `[initSensitiveInfoDocIfNotExists] Got document reference: ${sensitiveInfoRef.path}`
1494
1865
  );
1495
- const sensitiveDoc = await getDoc2(sensitiveInfoRef);
1866
+ const sensitiveDoc = await getDoc3(sensitiveInfoRef);
1496
1867
  console.log(
1497
1868
  `[initSensitiveInfoDocIfNotExists] Document exists: ${sensitiveDoc.exists()}`
1498
1869
  );
@@ -1516,7 +1887,7 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1516
1887
  )
1517
1888
  );
1518
1889
  await createSensitiveInfoUtil(db, defaultSensitiveInfo, userRef);
1519
- const verifyDoc = await getDoc2(sensitiveInfoRef);
1890
+ const verifyDoc = await getDoc3(sensitiveInfoRef);
1520
1891
  console.log(
1521
1892
  `[initSensitiveInfoDocIfNotExists] Verification - document exists: ${verifyDoc.exists()}`
1522
1893
  );
@@ -1534,24 +1905,24 @@ var initSensitiveInfoDocIfNotExists = async (db, patientId, userRef) => {
1534
1905
 
1535
1906
  // src/services/patient/utils/medical.utils.ts
1536
1907
  import {
1537
- getDoc as getDoc4,
1538
- updateDoc as updateDoc2,
1539
- setDoc as setDoc3,
1908
+ getDoc as getDoc5,
1909
+ updateDoc as updateDoc3,
1910
+ setDoc as setDoc4,
1540
1911
  serverTimestamp as serverTimestamp3,
1541
1912
  arrayUnion,
1542
- Timestamp as Timestamp3
1913
+ Timestamp as Timestamp4
1543
1914
  } from "firebase/firestore";
1544
1915
 
1545
1916
  // src/services/patient/utils/practitioner.utils.ts
1546
1917
  import {
1547
- collection as collection2,
1548
- query as query2,
1549
- where as where2,
1550
- getDocs as getDocs2,
1551
- limit,
1918
+ collection as collection3,
1919
+ query as query3,
1920
+ where as where3,
1921
+ getDocs as getDocs3,
1922
+ limit as limit2,
1552
1923
  startAfter,
1553
- doc as doc2,
1554
- getDoc as getDoc3
1924
+ doc as doc3,
1925
+ getDoc as getDoc4
1555
1926
  } from "firebase/firestore";
1556
1927
 
1557
1928
  // src/types/practitioner/index.ts
@@ -1577,23 +1948,23 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
1577
1948
  `[getPatientsByPractitionerUtil] Fetching patients for practitioner ID: ${practitionerId} with options:`,
1578
1949
  options
1579
1950
  );
1580
- const patientsCollection = collection2(db, PATIENTS_COLLECTION);
1951
+ const patientsCollection = collection3(db, PATIENTS_COLLECTION);
1581
1952
  const constraints = [
1582
- where2("doctorIds", "array-contains", practitionerId)
1953
+ where3("doctorIds", "array-contains", practitionerId)
1583
1954
  ];
1584
- let q = query2(patientsCollection, ...constraints);
1955
+ let q = query3(patientsCollection, ...constraints);
1585
1956
  if (options == null ? void 0 : options.limit) {
1586
- q = query2(q, limit(options.limit));
1957
+ q = query3(q, limit2(options.limit));
1587
1958
  }
1588
1959
  if (options == null ? void 0 : options.startAfter) {
1589
- const startAfterDoc = await getDoc3(
1590
- doc2(db, PATIENTS_COLLECTION, options.startAfter)
1960
+ const startAfterDoc = await getDoc4(
1961
+ doc3(db, PATIENTS_COLLECTION, options.startAfter)
1591
1962
  );
1592
1963
  if (startAfterDoc.exists()) {
1593
- q = query2(q, startAfter(startAfterDoc));
1964
+ q = query3(q, startAfter(startAfterDoc));
1594
1965
  }
1595
1966
  }
1596
- const patientsSnapshot = await getDocs2(q);
1967
+ const patientsSnapshot = await getDocs3(q);
1597
1968
  const patients = [];
1598
1969
  patientsSnapshot.forEach((doc34) => {
1599
1970
  patients.push(doc34.data());
@@ -1626,7 +1997,7 @@ var getPatientsByPractitionerWithDetailsUtil = async (db, practitionerId, option
1626
1997
  const patientProfilesWithDetails = await Promise.all(
1627
1998
  patientProfiles.map(async (profile) => {
1628
1999
  try {
1629
- const sensitiveInfoDoc = await getDoc3(
2000
+ const sensitiveInfoDoc = await getDoc4(
1630
2001
  getSensitiveInfoDocRef(db, profile.id)
1631
2002
  );
1632
2003
  const sensitiveInfo = sensitiveInfoDoc.exists() ? sensitiveInfoDoc.data() : void 0;
@@ -1662,13 +2033,13 @@ var getPractitionerProfileByUserRef = async (db, userRef) => {
1662
2033
  console.log(
1663
2034
  `[getPractitionerProfileByUserRef] Fetching practitioner with userRef: ${userRef}`
1664
2035
  );
1665
- const practitionersCollection = collection2(db, PRACTITIONERS_COLLECTION);
1666
- const q = query2(
2036
+ const practitionersCollection = collection3(db, PRACTITIONERS_COLLECTION);
2037
+ const q = query3(
1667
2038
  practitionersCollection,
1668
- where2("userRef", "==", userRef),
1669
- limit(1)
2039
+ where3("userRef", "==", userRef),
2040
+ limit2(1)
1670
2041
  );
1671
- const querySnapshot = await getDocs2(q);
2042
+ const querySnapshot = await getDocs3(q);
1672
2043
  if (querySnapshot.empty) {
1673
2044
  console.log(
1674
2045
  `[getPractitionerProfileByUserRef] No practitioner found with userRef: ${userRef}`
@@ -1702,7 +2073,7 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1702
2073
  console.log(
1703
2074
  `[ensureMedicalInfoExists] Got document reference: ${medicalInfoRef.path}`
1704
2075
  );
1705
- const medicalInfoDoc = await getDoc4(medicalInfoRef);
2076
+ const medicalInfoDoc = await getDoc5(medicalInfoRef);
1706
2077
  console.log(
1707
2078
  `[ensureMedicalInfoExists] Document exists: ${medicalInfoDoc.exists()}`
1708
2079
  );
@@ -1720,9 +2091,9 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1720
2091
  (key, value) => value && typeof value === "object" && value.constructor && value.constructor.name === "Object" ? "[serverTimestamp]" : value
1721
2092
  )
1722
2093
  );
1723
- await setDoc3(medicalInfoRef, defaultData);
2094
+ await setDoc4(medicalInfoRef, defaultData);
1724
2095
  console.log(`[ensureMedicalInfoExists] Document created successfully`);
1725
- const verifyDoc = await getDoc4(medicalInfoRef);
2096
+ const verifyDoc = await getDoc5(medicalInfoRef);
1726
2097
  console.log(
1727
2098
  `[ensureMedicalInfoExists] Verification - document exists: ${verifyDoc.exists()}`
1728
2099
  );
@@ -1738,7 +2109,7 @@ var ensureMedicalInfoExists = async (db, patientId, userRef) => {
1738
2109
  };
1739
2110
  var checkMedicalAccessUtil = async (db, patientId, userRef, userRoles) => {
1740
2111
  var _a;
1741
- const patientDoc = await getDoc4(getPatientDocRef(db, patientId));
2112
+ const patientDoc = await getDoc5(getPatientDocRef(db, patientId));
1742
2113
  if (!patientDoc.exists()) {
1743
2114
  throw new Error("Patient profile not found");
1744
2115
  }
@@ -1771,17 +2142,17 @@ var checkMedicalAccessUtil = async (db, patientId, userRef, userRoles) => {
1771
2142
  var createMedicalInfoUtil = async (db, patientId, data, userRef, userRoles) => {
1772
2143
  await checkMedicalAccessUtil(db, patientId, userRef, userRoles);
1773
2144
  const validatedData = createPatientMedicalInfoSchema.parse(data);
1774
- await setDoc3(getMedicalInfoDocRef(db, patientId), {
2145
+ await setDoc4(getMedicalInfoDocRef(db, patientId), {
1775
2146
  ...validatedData,
1776
2147
  patientId,
1777
- lastUpdated: Timestamp3.now(),
2148
+ lastUpdated: Timestamp4.now(),
1778
2149
  updatedBy: userRef
1779
2150
  });
1780
2151
  };
1781
2152
  var getMedicalInfoUtil = async (db, patientId, userRef, userRoles) => {
1782
2153
  await checkMedicalAccessUtil(db, patientId, userRef, userRoles);
1783
2154
  const docRef = getMedicalInfoDocRef(db, patientId);
1784
- const snapshot = await getDoc4(docRef);
2155
+ const snapshot = await getDoc5(docRef);
1785
2156
  if (!snapshot.exists()) {
1786
2157
  throw new Error("Medicinske informacije nisu prona\u0111ene");
1787
2158
  }
@@ -1790,7 +2161,7 @@ var getMedicalInfoUtil = async (db, patientId, userRef, userRoles) => {
1790
2161
  var updateVitalStatsUtil = async (db, patientId, data, userRef) => {
1791
2162
  await ensureMedicalInfoExists(db, patientId, userRef);
1792
2163
  const validatedData = updateVitalStatsSchema.parse(data);
1793
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2164
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1794
2165
  vitalStats: validatedData,
1795
2166
  lastUpdated: serverTimestamp3(),
1796
2167
  updatedBy: userRef
@@ -1799,7 +2170,7 @@ var updateVitalStatsUtil = async (db, patientId, data, userRef) => {
1799
2170
  var addAllergyUtil = async (db, patientId, data, userRef) => {
1800
2171
  await ensureMedicalInfoExists(db, patientId, userRef);
1801
2172
  const validatedData = addAllergySchema.parse(data);
1802
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2173
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1803
2174
  allergies: arrayUnion(validatedData),
1804
2175
  lastUpdated: serverTimestamp3(),
1805
2176
  updatedBy: userRef
@@ -1808,7 +2179,7 @@ var addAllergyUtil = async (db, patientId, data, userRef) => {
1808
2179
  var updateAllergyUtil = async (db, patientId, data, userRef) => {
1809
2180
  const validatedData = updateAllergySchema.parse(data);
1810
2181
  const { allergyIndex, ...updateData } = validatedData;
1811
- const docSnapshot = await getDoc4(getMedicalInfoDocRef(db, patientId));
2182
+ const docSnapshot = await getDoc5(getMedicalInfoDocRef(db, patientId));
1812
2183
  if (!docSnapshot.exists()) throw new Error("Medical info not found");
1813
2184
  const medicalInfo = patientMedicalInfoSchema.parse(docSnapshot.data());
1814
2185
  if (allergyIndex >= medicalInfo.allergies.length) {
@@ -1819,14 +2190,14 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
1819
2190
  ...updatedAllergies[allergyIndex],
1820
2191
  ...updateData
1821
2192
  };
1822
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2193
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1823
2194
  allergies: updatedAllergies,
1824
2195
  lastUpdated: serverTimestamp3(),
1825
2196
  updatedBy: userRef
1826
2197
  });
1827
2198
  };
1828
2199
  var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1829
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2200
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1830
2201
  if (!doc34.exists()) throw new Error("Medical info not found");
1831
2202
  const medicalInfo = doc34.data();
1832
2203
  if (allergyIndex >= medicalInfo.allergies.length) {
@@ -1835,7 +2206,7 @@ var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1835
2206
  const updatedAllergies = medicalInfo.allergies.filter(
1836
2207
  (_, index) => index !== allergyIndex
1837
2208
  );
1838
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2209
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1839
2210
  allergies: updatedAllergies,
1840
2211
  lastUpdated: serverTimestamp3(),
1841
2212
  updatedBy: userRef
@@ -1844,7 +2215,7 @@ var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
1844
2215
  var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
1845
2216
  await ensureMedicalInfoExists(db, patientId, userRef);
1846
2217
  const validatedData = addBlockingConditionSchema.parse(data);
1847
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2218
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1848
2219
  blockingConditions: arrayUnion(validatedData),
1849
2220
  lastUpdated: serverTimestamp3(),
1850
2221
  updatedBy: userRef
@@ -1853,7 +2224,7 @@ var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
1853
2224
  var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1854
2225
  const validatedData = updateBlockingConditionSchema.parse(data);
1855
2226
  const { conditionIndex, ...updateData } = validatedData;
1856
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2227
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1857
2228
  if (!doc34.exists()) throw new Error("Medical info not found");
1858
2229
  const medicalInfo = doc34.data();
1859
2230
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
@@ -1864,14 +2235,14 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
1864
2235
  ...updatedConditions[conditionIndex],
1865
2236
  ...updateData
1866
2237
  };
1867
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2238
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1868
2239
  blockingConditions: updatedConditions,
1869
2240
  lastUpdated: serverTimestamp3(),
1870
2241
  updatedBy: userRef
1871
2242
  });
1872
2243
  };
1873
2244
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
1874
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2245
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1875
2246
  if (!doc34.exists()) throw new Error("Medical info not found");
1876
2247
  const medicalInfo = doc34.data();
1877
2248
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
@@ -1880,7 +2251,7 @@ var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef)
1880
2251
  const updatedConditions = medicalInfo.blockingConditions.filter(
1881
2252
  (_, index) => index !== conditionIndex
1882
2253
  );
1883
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2254
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1884
2255
  blockingConditions: updatedConditions,
1885
2256
  lastUpdated: serverTimestamp3(),
1886
2257
  updatedBy: userRef
@@ -1889,7 +2260,7 @@ var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef)
1889
2260
  var addContraindicationUtil = async (db, patientId, data, userRef) => {
1890
2261
  await ensureMedicalInfoExists(db, patientId, userRef);
1891
2262
  const validatedData = addContraindicationSchema.parse(data);
1892
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2263
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1893
2264
  contraindications: arrayUnion(validatedData),
1894
2265
  lastUpdated: serverTimestamp3(),
1895
2266
  updatedBy: userRef
@@ -1898,7 +2269,7 @@ var addContraindicationUtil = async (db, patientId, data, userRef) => {
1898
2269
  var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1899
2270
  const validatedData = updateContraindicationSchema.parse(data);
1900
2271
  const { contraindicationIndex, ...updateData } = validatedData;
1901
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2272
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1902
2273
  if (!doc34.exists()) throw new Error("Medical info not found");
1903
2274
  const medicalInfo = doc34.data();
1904
2275
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
@@ -1909,14 +2280,14 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
1909
2280
  ...updatedContraindications[contraindicationIndex],
1910
2281
  ...updateData
1911
2282
  };
1912
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2283
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1913
2284
  contraindications: updatedContraindications,
1914
2285
  lastUpdated: serverTimestamp3(),
1915
2286
  updatedBy: userRef
1916
2287
  });
1917
2288
  };
1918
2289
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
1919
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2290
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1920
2291
  if (!doc34.exists()) throw new Error("Medical info not found");
1921
2292
  const medicalInfo = doc34.data();
1922
2293
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
@@ -1925,7 +2296,7 @@ var removeContraindicationUtil = async (db, patientId, contraindicationIndex, us
1925
2296
  const updatedContraindications = medicalInfo.contraindications.filter(
1926
2297
  (_, index) => index !== contraindicationIndex
1927
2298
  );
1928
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2299
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1929
2300
  contraindications: updatedContraindications,
1930
2301
  lastUpdated: serverTimestamp3(),
1931
2302
  updatedBy: userRef
@@ -1934,7 +2305,7 @@ var removeContraindicationUtil = async (db, patientId, contraindicationIndex, us
1934
2305
  var addMedicationUtil = async (db, patientId, data, userRef) => {
1935
2306
  await ensureMedicalInfoExists(db, patientId, userRef);
1936
2307
  const validatedData = addMedicationSchema.parse(data);
1937
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2308
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1938
2309
  currentMedications: arrayUnion(validatedData),
1939
2310
  lastUpdated: serverTimestamp3(),
1940
2311
  updatedBy: userRef
@@ -1943,7 +2314,7 @@ var addMedicationUtil = async (db, patientId, data, userRef) => {
1943
2314
  var updateMedicationUtil = async (db, patientId, data, userRef) => {
1944
2315
  const validatedData = updateMedicationSchema.parse(data);
1945
2316
  const { medicationIndex, ...updateData } = validatedData;
1946
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2317
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1947
2318
  if (!doc34.exists()) throw new Error("Medical info not found");
1948
2319
  const medicalInfo = doc34.data();
1949
2320
  if (medicationIndex >= medicalInfo.currentMedications.length) {
@@ -1954,14 +2325,14 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
1954
2325
  ...updatedMedications[medicationIndex],
1955
2326
  ...updateData
1956
2327
  };
1957
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2328
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1958
2329
  currentMedications: updatedMedications,
1959
2330
  lastUpdated: serverTimestamp3(),
1960
2331
  updatedBy: userRef
1961
2332
  });
1962
2333
  };
1963
2334
  var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
1964
- const doc34 = await getDoc4(getMedicalInfoDocRef(db, patientId));
2335
+ const doc34 = await getDoc5(getMedicalInfoDocRef(db, patientId));
1965
2336
  if (!doc34.exists()) throw new Error("Medical info not found");
1966
2337
  const medicalInfo = doc34.data();
1967
2338
  if (medicationIndex >= medicalInfo.currentMedications.length) {
@@ -1970,7 +2341,7 @@ var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
1970
2341
  const updatedMedications = medicalInfo.currentMedications.filter(
1971
2342
  (_, index) => index !== medicationIndex
1972
2343
  );
1973
- await updateDoc2(getMedicalInfoDocRef(db, patientId), {
2344
+ await updateDoc3(getMedicalInfoDocRef(db, patientId), {
1974
2345
  currentMedications: updatedMedications,
1975
2346
  lastUpdated: serverTimestamp3(),
1976
2347
  updatedBy: userRef
@@ -1989,7 +2360,6 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
1989
2360
  id: patientId,
1990
2361
  userRef: validatedData.userRef,
1991
2362
  displayName: validatedData.displayName,
1992
- profilePhoto: validatedData.profilePhoto || null,
1993
2363
  expoTokens: validatedData.expoTokens,
1994
2364
  gamification: validatedData.gamification || {
1995
2365
  level: 1,
@@ -2006,10 +2376,10 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
2006
2376
  };
2007
2377
  patientProfileSchema.parse({
2008
2378
  ...patientData,
2009
- createdAt: Timestamp4.now(),
2010
- updatedAt: Timestamp4.now()
2379
+ createdAt: Timestamp5.now(),
2380
+ updatedAt: Timestamp5.now()
2011
2381
  });
2012
- await setDoc4(getPatientDocRef(db, patientId), patientData);
2382
+ await setDoc5(getPatientDocRef(db, patientId), patientData);
2013
2383
  console.log(`[createPatientProfileUtil] Creating sensitive info document`);
2014
2384
  let sensitiveInfoSuccess = false;
2015
2385
  try {
@@ -2023,69 +2393,91 @@ var createPatientProfileUtil = async (db, data, generateId2) => {
2023
2393
  );
2024
2394
  sensitiveInfoSuccess = true;
2025
2395
  } catch (sensitiveError) {
2026
- console.error(`[createPatientProfileUtil] Error creating sensitive info:`, sensitiveError);
2396
+ console.error(
2397
+ `[createPatientProfileUtil] Error creating sensitive info:`,
2398
+ sensitiveError
2399
+ );
2027
2400
  }
2028
2401
  console.log(`[createPatientProfileUtil] Creating medical info document`);
2029
2402
  let medicalInfoSuccess = false;
2030
2403
  try {
2031
2404
  await ensureMedicalInfoExists(db, patientId, validatedData.userRef);
2032
- console.log(`[createPatientProfileUtil] Medical info document created successfully`);
2405
+ console.log(
2406
+ `[createPatientProfileUtil] Medical info document created successfully`
2407
+ );
2033
2408
  medicalInfoSuccess = true;
2034
2409
  } catch (medicalError) {
2035
- console.error(`[createPatientProfileUtil] Error creating medical info:`, medicalError);
2410
+ console.error(
2411
+ `[createPatientProfileUtil] Error creating medical info:`,
2412
+ medicalError
2413
+ );
2036
2414
  }
2037
2415
  if (!sensitiveInfoSuccess || !medicalInfoSuccess) {
2038
- console.log(`[createPatientProfileUtil] Using fallback method to create documents`);
2416
+ console.log(
2417
+ `[createPatientProfileUtil] Using fallback method to create documents`
2418
+ );
2039
2419
  try {
2040
2420
  await testCreateSubDocuments(db, patientId, validatedData.userRef);
2041
- console.log(`[createPatientProfileUtil] Fallback method completed successfully`);
2421
+ console.log(
2422
+ `[createPatientProfileUtil] Fallback method completed successfully`
2423
+ );
2042
2424
  } catch (fallbackError) {
2043
- console.error(`[createPatientProfileUtil] Fallback method failed:`, fallbackError);
2425
+ console.error(
2426
+ `[createPatientProfileUtil] Fallback method failed:`,
2427
+ fallbackError
2428
+ );
2044
2429
  }
2045
2430
  }
2046
2431
  console.log(`[createPatientProfileUtil] Verifying patient document exists`);
2047
- const patientDoc = await getDoc5(getPatientDocRef(db, patientId));
2432
+ const patientDoc = await getDoc6(getPatientDocRef(db, patientId));
2048
2433
  if (!patientDoc.exists()) {
2049
- console.error(`[createPatientProfileUtil] Patient document not found after creation`);
2434
+ console.error(
2435
+ `[createPatientProfileUtil] Patient document not found after creation`
2436
+ );
2050
2437
  throw new Error("Failed to create patient profile");
2051
2438
  }
2052
- console.log(`[createPatientProfileUtil] Patient profile creation completed successfully`);
2439
+ console.log(
2440
+ `[createPatientProfileUtil] Patient profile creation completed successfully`
2441
+ );
2053
2442
  return patientDoc.data();
2054
2443
  } catch (error) {
2055
- console.error(`[createPatientProfileUtil] Error in patient profile creation:`, error);
2056
- if (error instanceof z8.ZodError) {
2444
+ console.error(
2445
+ `[createPatientProfileUtil] Error in patient profile creation:`,
2446
+ error
2447
+ );
2448
+ if (error instanceof z9.ZodError) {
2057
2449
  throw new Error("Invalid patient data: " + error.message);
2058
2450
  }
2059
2451
  throw error;
2060
2452
  }
2061
2453
  };
2062
2454
  var getPatientProfileUtil = async (db, patientId) => {
2063
- const patientDoc = await getDoc5(getPatientDocRef(db, patientId));
2455
+ const patientDoc = await getDoc6(getPatientDocRef(db, patientId));
2064
2456
  return patientDoc.exists() ? patientDoc.data() : null;
2065
2457
  };
2066
2458
  var getPatientProfileByUserRefUtil = async (db, userRef) => {
2067
2459
  try {
2068
2460
  const docRef = await getPatientDocRefByUserRef(db, userRef);
2069
- const patientDoc = await getDoc5(docRef);
2461
+ const patientDoc = await getDoc6(docRef);
2070
2462
  return patientDoc.exists() ? patientDoc.data() : null;
2071
2463
  } catch (error) {
2072
2464
  return null;
2073
2465
  }
2074
2466
  };
2075
2467
  var addExpoTokenUtil = async (db, patientId, token) => {
2076
- await updateDoc3(getPatientDocRef(db, patientId), {
2468
+ await updateDoc4(getPatientDocRef(db, patientId), {
2077
2469
  expoTokens: arrayUnion2(token),
2078
2470
  updatedAt: serverTimestamp4()
2079
2471
  });
2080
2472
  };
2081
2473
  var removeExpoTokenUtil = async (db, patientId, token) => {
2082
- await updateDoc3(getPatientDocRef(db, patientId), {
2474
+ await updateDoc4(getPatientDocRef(db, patientId), {
2083
2475
  expoTokens: arrayRemove2(token),
2084
2476
  updatedAt: serverTimestamp4()
2085
2477
  });
2086
2478
  };
2087
2479
  var addPointsUtil = async (db, patientId, points) => {
2088
- await updateDoc3(getPatientDocRef(db, patientId), {
2480
+ await updateDoc4(getPatientDocRef(db, patientId), {
2089
2481
  "gamification.points": increment(points),
2090
2482
  updatedAt: serverTimestamp4()
2091
2483
  });
@@ -2096,8 +2488,8 @@ var updatePatientProfileUtil = async (db, patientId, data) => {
2096
2488
  ...data,
2097
2489
  updatedAt: serverTimestamp4()
2098
2490
  };
2099
- await updateDoc3(getPatientDocRef(db, patientId), updateData);
2100
- const updatedDoc = await getDoc5(getPatientDocRef(db, patientId));
2491
+ await updateDoc4(getPatientDocRef(db, patientId), updateData);
2492
+ const updatedDoc = await getDoc6(getPatientDocRef(db, patientId));
2101
2493
  if (!updatedDoc.exists()) {
2102
2494
  throw new Error("Patient profile not found after update");
2103
2495
  }
@@ -2110,7 +2502,7 @@ var updatePatientProfileUtil = async (db, patientId, data) => {
2110
2502
  var updatePatientProfileByUserRefUtil = async (db, userRef, data) => {
2111
2503
  try {
2112
2504
  const docRef = await getPatientDocRefByUserRef(db, userRef);
2113
- const patientDoc = await getDoc5(docRef);
2505
+ const patientDoc = await getDoc6(docRef);
2114
2506
  if (!patientDoc.exists()) {
2115
2507
  throw new Error("Patient profile not found");
2116
2508
  }
@@ -2118,49 +2510,10 @@ var updatePatientProfileByUserRefUtil = async (db, userRef, data) => {
2118
2510
  return updatePatientProfileUtil(db, patientData.id, data);
2119
2511
  } catch (error) {
2120
2512
  const errorMessage = error instanceof Error ? error.message : String(error);
2121
- throw new Error(`Failed to update patient profile by user ref: ${errorMessage}`);
2122
- }
2123
- };
2124
- var uploadProfilePhotoUtil = async (storage, patientId, file) => {
2125
- const photoRef = ref(storage, `patient-photos/${patientId}/profile-photo`);
2126
- await uploadBytes(photoRef, file);
2127
- return getDownloadURL(photoRef);
2128
- };
2129
- var updateProfilePhotoUtil = async (storage, db, patientId, file) => {
2130
- const patientDoc = await getDoc5(getPatientDocRef(db, patientId));
2131
- if (!patientDoc.exists()) throw new Error("Patient profile not found");
2132
- const patientData = patientDoc.data();
2133
- if (patientData.profilePhoto) {
2134
- try {
2135
- const oldPhotoRef = ref(storage, patientData.profilePhoto);
2136
- await deleteObject(oldPhotoRef);
2137
- } catch (error) {
2138
- console.warn("Failed to delete old profile photo:", error);
2139
- }
2140
- }
2141
- const newPhotoUrl = await uploadProfilePhotoUtil(storage, patientId, file);
2142
- await updateDoc3(getPatientDocRef(db, patientId), {
2143
- profilePhoto: newPhotoUrl,
2144
- updatedAt: serverTimestamp4()
2145
- });
2146
- return newPhotoUrl;
2147
- };
2148
- var deleteProfilePhotoUtil = async (storage, db, patientId) => {
2149
- const patientDoc = await getDoc5(getPatientDocRef(db, patientId));
2150
- if (!patientDoc.exists()) throw new Error("Patient profile not found");
2151
- const patientData = patientDoc.data();
2152
- if (patientData.profilePhoto) {
2153
- try {
2154
- const photoRef = ref(storage, patientData.profilePhoto);
2155
- await deleteObject(photoRef);
2156
- } catch (error) {
2157
- console.warn("Failed to delete profile photo:", error);
2158
- }
2513
+ throw new Error(
2514
+ `Failed to update patient profile by user ref: ${errorMessage}`
2515
+ );
2159
2516
  }
2160
- await updateDoc3(getPatientDocRef(db, patientId), {
2161
- profilePhoto: null,
2162
- updatedAt: serverTimestamp4()
2163
- });
2164
2517
  };
2165
2518
  var testCreateSubDocuments = async (db, patientId, userRef) => {
2166
2519
  console.log(
@@ -2169,33 +2522,41 @@ var testCreateSubDocuments = async (db, patientId, userRef) => {
2169
2522
  try {
2170
2523
  console.log(`[testCreateSubDocuments] Testing sensitive info creation`);
2171
2524
  const sensitiveInfoRef = getSensitiveInfoDocRef(db, patientId);
2172
- console.log(`[testCreateSubDocuments] Sensitive info path: ${sensitiveInfoRef.path}`);
2525
+ console.log(
2526
+ `[testCreateSubDocuments] Sensitive info path: ${sensitiveInfoRef.path}`
2527
+ );
2173
2528
  const defaultSensitiveInfo = {
2174
2529
  patientId,
2175
2530
  userRef,
2176
2531
  photoUrl: "",
2177
2532
  firstName: "Name",
2178
2533
  lastName: "Surname",
2179
- dateOfBirth: Timestamp4.now(),
2534
+ dateOfBirth: Timestamp5.now(),
2180
2535
  gender: "prefer_not_to_say" /* PREFER_NOT_TO_SAY */,
2181
2536
  email: "test@example.com",
2182
2537
  phoneNumber: "",
2183
- createdAt: Timestamp4.now(),
2184
- updatedAt: Timestamp4.now()
2538
+ createdAt: Timestamp5.now(),
2539
+ updatedAt: Timestamp5.now()
2185
2540
  };
2186
- await setDoc4(sensitiveInfoRef, defaultSensitiveInfo);
2187
- console.log(`[testCreateSubDocuments] Sensitive info document created directly`);
2541
+ await setDoc5(sensitiveInfoRef, defaultSensitiveInfo);
2542
+ console.log(
2543
+ `[testCreateSubDocuments] Sensitive info document created directly`
2544
+ );
2188
2545
  console.log(`[testCreateSubDocuments] Testing medical info creation`);
2189
2546
  const medicalInfoRef = getMedicalInfoDocRef(db, patientId);
2190
- console.log(`[testCreateSubDocuments] Medical info path: ${medicalInfoRef.path}`);
2547
+ console.log(
2548
+ `[testCreateSubDocuments] Medical info path: ${medicalInfoRef.path}`
2549
+ );
2191
2550
  const defaultMedicalInfo = {
2192
2551
  ...DEFAULT_MEDICAL_INFO,
2193
2552
  patientId,
2194
- lastUpdated: Timestamp4.now(),
2553
+ lastUpdated: Timestamp5.now(),
2195
2554
  updatedBy: userRef
2196
2555
  };
2197
- await setDoc4(medicalInfoRef, defaultMedicalInfo);
2198
- console.log(`[testCreateSubDocuments] Medical info document created directly`);
2556
+ await setDoc5(medicalInfoRef, defaultMedicalInfo);
2557
+ console.log(
2558
+ `[testCreateSubDocuments] Medical info document created directly`
2559
+ );
2199
2560
  console.log(`[testCreateSubDocuments] Test completed successfully`);
2200
2561
  } catch (error) {
2201
2562
  console.error(`[testCreateSubDocuments] Error:`, error);
@@ -2206,10 +2567,12 @@ var searchPatientsUtil = async (db, params, requester) => {
2206
2567
  searchPatientsSchema.parse(params);
2207
2568
  requesterInfoSchema.parse(requester);
2208
2569
  const constraints = [];
2209
- const patientsCollectionRef = collection3(db, PATIENTS_COLLECTION);
2570
+ const patientsCollectionRef = collection4(db, PATIENTS_COLLECTION);
2210
2571
  if (requester.role === "clinic_admin") {
2211
2572
  if (!requester.associatedClinicId) {
2212
- throw new Error("Associated clinic ID is required for clinic admin search.");
2573
+ throw new Error(
2574
+ "Associated clinic ID is required for clinic admin search."
2575
+ );
2213
2576
  }
2214
2577
  if (params.clinicId && params.clinicId !== requester.associatedClinicId) {
2215
2578
  console.warn(
@@ -2217,13 +2580,19 @@ var searchPatientsUtil = async (db, params, requester) => {
2217
2580
  );
2218
2581
  return [];
2219
2582
  }
2220
- constraints.push(where3("clinicIds", "array-contains", requester.associatedClinicId));
2583
+ constraints.push(
2584
+ where4("clinicIds", "array-contains", requester.associatedClinicId)
2585
+ );
2221
2586
  if (params.practitionerId) {
2222
- constraints.push(where3("doctorIds", "array-contains", params.practitionerId));
2587
+ constraints.push(
2588
+ where4("doctorIds", "array-contains", params.practitionerId)
2589
+ );
2223
2590
  }
2224
2591
  } else if (requester.role === "practitioner") {
2225
2592
  if (!requester.associatedPractitionerId) {
2226
- throw new Error("Associated practitioner ID is required for practitioner search.");
2593
+ throw new Error(
2594
+ "Associated practitioner ID is required for practitioner search."
2595
+ );
2227
2596
  }
2228
2597
  if (params.practitionerId && params.practitionerId !== requester.associatedPractitionerId) {
2229
2598
  console.warn(
@@ -2231,18 +2600,24 @@ var searchPatientsUtil = async (db, params, requester) => {
2231
2600
  );
2232
2601
  return [];
2233
2602
  }
2234
- constraints.push(where3("doctorIds", "array-contains", requester.associatedPractitionerId));
2603
+ constraints.push(
2604
+ where4("doctorIds", "array-contains", requester.associatedPractitionerId)
2605
+ );
2235
2606
  if (params.clinicId) {
2236
- constraints.push(where3("clinicIds", "array-contains", params.clinicId));
2607
+ constraints.push(where4("clinicIds", "array-contains", params.clinicId));
2237
2608
  }
2238
2609
  } else {
2239
2610
  throw new Error("Invalid requester role.");
2240
2611
  }
2241
2612
  try {
2242
- const finalQuery = query3(patientsCollectionRef, ...constraints);
2243
- const querySnapshot = await getDocs3(finalQuery);
2244
- const patients = querySnapshot.docs.map((doc34) => doc34.data());
2245
- console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
2613
+ const finalQuery = query4(patientsCollectionRef, ...constraints);
2614
+ const querySnapshot = await getDocs4(finalQuery);
2615
+ const patients = querySnapshot.docs.map(
2616
+ (doc34) => doc34.data()
2617
+ );
2618
+ console.log(
2619
+ `[searchPatientsUtil] Found ${patients.length} patients matching criteria.`
2620
+ );
2246
2621
  return patients;
2247
2622
  } catch (error) {
2248
2623
  console.error("[searchPatientsUtil] Error searching patients:", error);
@@ -2251,19 +2626,24 @@ var searchPatientsUtil = async (db, params, requester) => {
2251
2626
  };
2252
2627
  var getAllPatientsUtil = async (db, options) => {
2253
2628
  try {
2254
- console.log(`[getAllPatientsUtil] Fetching patients with options:`, options);
2255
- const patientsCollection = collection3(db, PATIENTS_COLLECTION);
2256
- let q = query3(patientsCollection);
2629
+ console.log(
2630
+ `[getAllPatientsUtil] Fetching patients with options:`,
2631
+ options
2632
+ );
2633
+ const patientsCollection = collection4(db, PATIENTS_COLLECTION);
2634
+ let q = query4(patientsCollection);
2257
2635
  if (options == null ? void 0 : options.limit) {
2258
- q = query3(q, limit2(options.limit));
2636
+ q = query4(q, limit3(options.limit));
2259
2637
  }
2260
2638
  if (options == null ? void 0 : options.startAfter) {
2261
- const startAfterDoc = await getDoc5(doc4(db, PATIENTS_COLLECTION, options.startAfter));
2639
+ const startAfterDoc = await getDoc6(
2640
+ doc5(db, PATIENTS_COLLECTION, options.startAfter)
2641
+ );
2262
2642
  if (startAfterDoc.exists()) {
2263
- q = query3(q, startAfter2(startAfterDoc));
2643
+ q = query4(q, startAfter2(startAfterDoc));
2264
2644
  }
2265
2645
  }
2266
- const patientsSnapshot = await getDocs3(q);
2646
+ const patientsSnapshot = await getDocs4(q);
2267
2647
  const patients = [];
2268
2648
  patientsSnapshot.forEach((doc34) => {
2269
2649
  patients.push(doc34.data());
@@ -2280,12 +2660,12 @@ var getAllPatientsUtil = async (db, options) => {
2280
2660
 
2281
2661
  // src/services/patient/utils/location.utils.ts
2282
2662
  import {
2283
- getDoc as getDoc6,
2284
- updateDoc as updateDoc4,
2285
- setDoc as setDoc5,
2663
+ getDoc as getDoc7,
2664
+ updateDoc as updateDoc5,
2665
+ setDoc as setDoc6,
2286
2666
  serverTimestamp as serverTimestamp5
2287
2667
  } from "firebase/firestore";
2288
- import { z as z9 } from "zod";
2668
+ import { z as z10 } from "zod";
2289
2669
  import { geohashForLocation } from "geofire-common";
2290
2670
  var updatePatientLocationUtil = async (db, patientId, latitude, longitude) => {
2291
2671
  const locationData = {
@@ -2297,7 +2677,7 @@ var updatePatientLocationUtil = async (db, patientId, latitude, longitude) => {
2297
2677
  locationData,
2298
2678
  updatedAt: serverTimestamp5()
2299
2679
  };
2300
- await updateDoc4(getLocationInfoDocRef(db, patientId), updateData);
2680
+ await updateDoc5(getLocationInfoDocRef(db, patientId), updateData);
2301
2681
  };
2302
2682
  var createLocationInfoUtil = async (db, data, requesterId) => {
2303
2683
  try {
@@ -2317,14 +2697,14 @@ var createLocationInfoUtil = async (db, data, requesterId) => {
2317
2697
  createdAt: serverTimestamp5(),
2318
2698
  updatedAt: serverTimestamp5()
2319
2699
  };
2320
- await setDoc5(getLocationInfoDocRef(db, data.patientId), locationData);
2321
- const locationDoc = await getDoc6(getLocationInfoDocRef(db, data.patientId));
2700
+ await setDoc6(getLocationInfoDocRef(db, data.patientId), locationData);
2701
+ const locationDoc = await getDoc7(getLocationInfoDocRef(db, data.patientId));
2322
2702
  if (!locationDoc.exists()) {
2323
2703
  throw new Error("Failed to create location information");
2324
2704
  }
2325
2705
  return locationDoc.data();
2326
2706
  } catch (error) {
2327
- if (error instanceof z9.ZodError) {
2707
+ if (error instanceof z10.ZodError) {
2328
2708
  throw new Error("Invalid location data: " + error.message);
2329
2709
  }
2330
2710
  throw error;
@@ -2334,7 +2714,7 @@ var getLocationInfoUtil = async (db, patientId, requesterId) => {
2334
2714
  if (patientId !== requesterId) {
2335
2715
  throw new Error("Unauthorized access to location information");
2336
2716
  }
2337
- const locationDoc = await getDoc6(getLocationInfoDocRef(db, patientId));
2717
+ const locationDoc = await getDoc7(getLocationInfoDocRef(db, patientId));
2338
2718
  return locationDoc.exists() ? locationDoc.data() : null;
2339
2719
  };
2340
2720
  var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
@@ -2352,7 +2732,7 @@ var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
2352
2732
  };
2353
2733
  }
2354
2734
  updateData.updatedAt = serverTimestamp5();
2355
- await updateDoc4(getLocationInfoDocRef(db, patientId), updateData);
2735
+ await updateDoc5(getLocationInfoDocRef(db, patientId), updateData);
2356
2736
  const updatedInfo = await getLocationInfoUtil(db, patientId, requesterId);
2357
2737
  if (!updatedInfo) {
2358
2738
  throw new Error("Failed to retrieve updated location information");
@@ -2362,22 +2742,22 @@ var updateLocationInfoUtil = async (db, patientId, data, requesterId) => {
2362
2742
 
2363
2743
  // src/services/patient/utils/medical-stuff.utils.ts
2364
2744
  import {
2365
- getDoc as getDoc7,
2366
- updateDoc as updateDoc5,
2745
+ getDoc as getDoc8,
2746
+ updateDoc as updateDoc6,
2367
2747
  arrayUnion as arrayUnion3,
2368
2748
  arrayRemove as arrayRemove3,
2369
2749
  serverTimestamp as serverTimestamp6,
2370
- Timestamp as Timestamp5
2750
+ Timestamp as Timestamp6
2371
2751
  } from "firebase/firestore";
2372
2752
  var addDoctorUtil = async (db, patientId, doctorRef, assignedBy) => {
2373
2753
  var _a;
2374
2754
  const newDoctor = {
2375
2755
  userRef: doctorRef,
2376
- assignedAt: Timestamp5.now(),
2756
+ assignedAt: Timestamp6.now(),
2377
2757
  assignedBy,
2378
2758
  isActive: true
2379
2759
  };
2380
- const patientDoc = await getDoc7(getPatientDocRef(db, patientId));
2760
+ const patientDoc = await getDoc8(getPatientDocRef(db, patientId));
2381
2761
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2382
2762
  const patientData = patientDoc.data();
2383
2763
  const existingDoctorIndex = (_a = patientData.doctors) == null ? void 0 : _a.findIndex(
@@ -2392,23 +2772,23 @@ var addDoctorUtil = async (db, patientId, doctorRef, assignedBy) => {
2392
2772
  updatedDoctors[existingDoctorIndex] = {
2393
2773
  ...updatedDoctors[existingDoctorIndex],
2394
2774
  isActive: true,
2395
- assignedAt: Timestamp5.now(),
2775
+ assignedAt: Timestamp6.now(),
2396
2776
  assignedBy
2397
2777
  };
2398
2778
  updates.doctors = updatedDoctors;
2399
2779
  } else {
2400
2780
  updates.doctors = arrayUnion3(newDoctor);
2401
2781
  }
2402
- await updateDoc5(getPatientDocRef(db, patientId), updates);
2782
+ await updateDoc6(getPatientDocRef(db, patientId), updates);
2403
2783
  };
2404
2784
  var removeDoctorUtil = async (db, patientId, doctorRef) => {
2405
2785
  var _a;
2406
2786
  const patientDocRef = getPatientDocRef(db, patientId);
2407
- const patientDoc = await getDoc7(patientDocRef);
2787
+ const patientDoc = await getDoc8(patientDocRef);
2408
2788
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2409
2789
  const patientData = patientDoc.data();
2410
2790
  const updatedDoctors = ((_a = patientData.doctors) == null ? void 0 : _a.filter((doctor) => doctor.userRef !== doctorRef)) || [];
2411
- await updateDoc5(patientDocRef, {
2791
+ await updateDoc6(patientDocRef, {
2412
2792
  doctors: updatedDoctors,
2413
2793
  // Set the filtered array
2414
2794
  doctorIds: arrayRemove3(doctorRef),
@@ -2420,11 +2800,11 @@ var addClinicUtil = async (db, patientId, clinicId, assignedBy) => {
2420
2800
  var _a;
2421
2801
  const newClinic = {
2422
2802
  clinicId,
2423
- assignedAt: Timestamp5.now(),
2803
+ assignedAt: Timestamp6.now(),
2424
2804
  assignedBy,
2425
2805
  isActive: true
2426
2806
  };
2427
- const patientDoc = await getDoc7(getPatientDocRef(db, patientId));
2807
+ const patientDoc = await getDoc8(getPatientDocRef(db, patientId));
2428
2808
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2429
2809
  const patientData = patientDoc.data();
2430
2810
  const existingClinicIndex = (_a = patientData.clinics) == null ? void 0 : _a.findIndex(
@@ -2439,23 +2819,23 @@ var addClinicUtil = async (db, patientId, clinicId, assignedBy) => {
2439
2819
  updatedClinics[existingClinicIndex] = {
2440
2820
  ...updatedClinics[existingClinicIndex],
2441
2821
  isActive: true,
2442
- assignedAt: Timestamp5.now(),
2822
+ assignedAt: Timestamp6.now(),
2443
2823
  assignedBy
2444
2824
  };
2445
2825
  updates.clinics = updatedClinics;
2446
2826
  } else {
2447
2827
  updates.clinics = arrayUnion3(newClinic);
2448
2828
  }
2449
- await updateDoc5(getPatientDocRef(db, patientId), updates);
2829
+ await updateDoc6(getPatientDocRef(db, patientId), updates);
2450
2830
  };
2451
2831
  var removeClinicUtil = async (db, patientId, clinicId) => {
2452
2832
  var _a;
2453
2833
  const patientDocRef = getPatientDocRef(db, patientId);
2454
- const patientDoc = await getDoc7(patientDocRef);
2834
+ const patientDoc = await getDoc8(patientDocRef);
2455
2835
  if (!patientDoc.exists()) throw new Error("Patient profile not found");
2456
2836
  const patientData = patientDoc.data();
2457
2837
  const updatedClinics = ((_a = patientData.clinics) == null ? void 0 : _a.filter((clinic) => clinic.clinicId !== clinicId)) || [];
2458
- await updateDoc5(patientDocRef, {
2838
+ await updateDoc6(patientDocRef, {
2459
2839
  clinics: updatedClinics,
2460
2840
  // Set the filtered array
2461
2841
  clinicIds: arrayRemove3(clinicId),
@@ -2466,14 +2846,14 @@ var removeClinicUtil = async (db, patientId, clinicId) => {
2466
2846
 
2467
2847
  // src/services/patient/utils/clinic.utils.ts
2468
2848
  import {
2469
- collection as collection4,
2470
- query as query4,
2471
- where as where4,
2472
- getDocs as getDocs4,
2473
- limit as limit3,
2849
+ collection as collection5,
2850
+ query as query5,
2851
+ where as where5,
2852
+ getDocs as getDocs5,
2853
+ limit as limit4,
2474
2854
  startAfter as startAfter3,
2475
- doc as doc5,
2476
- getDoc as getDoc8
2855
+ doc as doc6,
2856
+ getDoc as getDoc9
2477
2857
  } from "firebase/firestore";
2478
2858
  var getPatientsByClinicUtil = async (db, clinicId, options) => {
2479
2859
  try {
@@ -2481,23 +2861,23 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2481
2861
  `[getPatientsByClinicUtil] Fetching patients for clinic ID: ${clinicId} with options:`,
2482
2862
  options
2483
2863
  );
2484
- const patientsCollection = collection4(db, PATIENTS_COLLECTION);
2864
+ const patientsCollection = collection5(db, PATIENTS_COLLECTION);
2485
2865
  const constraints = [
2486
- where4("clinicIds", "array-contains", clinicId)
2866
+ where5("clinicIds", "array-contains", clinicId)
2487
2867
  ];
2488
- let q = query4(patientsCollection, ...constraints);
2868
+ let q = query5(patientsCollection, ...constraints);
2489
2869
  if (options == null ? void 0 : options.limit) {
2490
- q = query4(q, limit3(options.limit));
2870
+ q = query5(q, limit4(options.limit));
2491
2871
  }
2492
2872
  if (options == null ? void 0 : options.startAfter) {
2493
- const startAfterDoc = await getDoc8(
2494
- doc5(db, PATIENTS_COLLECTION, options.startAfter)
2873
+ const startAfterDoc = await getDoc9(
2874
+ doc6(db, PATIENTS_COLLECTION, options.startAfter)
2495
2875
  );
2496
2876
  if (startAfterDoc.exists()) {
2497
- q = query4(q, startAfter3(startAfterDoc));
2877
+ q = query5(q, startAfter3(startAfterDoc));
2498
2878
  }
2499
2879
  }
2500
- const patientsSnapshot = await getDocs4(q);
2880
+ const patientsSnapshot = await getDocs5(q);
2501
2881
  const patients = [];
2502
2882
  patientsSnapshot.forEach((doc34) => {
2503
2883
  patients.push(doc34.data());
@@ -2521,6 +2901,7 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
2521
2901
  var PatientService = class extends BaseService {
2522
2902
  constructor(db, auth, app) {
2523
2903
  super(db, auth, app);
2904
+ this.mediaService = new MediaService(db, auth, app);
2524
2905
  }
2525
2906
  // Metode za rad sa profilom pacijenta
2526
2907
  async createPatientProfile(data) {
@@ -2557,7 +2938,12 @@ var PatientService = class extends BaseService {
2557
2938
  }
2558
2939
  // Metode za rad sa osetljivim informacijama
2559
2940
  async createSensitiveInfo(data, requesterUserId) {
2560
- return createSensitiveInfoUtil(this.db, data, requesterUserId);
2941
+ return createSensitiveInfoUtil(
2942
+ this.db,
2943
+ data,
2944
+ requesterUserId,
2945
+ this.mediaService
2946
+ );
2561
2947
  }
2562
2948
  async getSensitiveInfo(patientId, requesterUserId) {
2563
2949
  return getSensitiveInfoUtil(this.db, patientId, requesterUserId);
@@ -2568,7 +2954,13 @@ var PatientService = class extends BaseService {
2568
2954
  return this.getSensitiveInfo(profile.id, requesterUserId);
2569
2955
  }
2570
2956
  async updateSensitiveInfo(patientId, data, requesterUserId) {
2571
- return updateSensitiveInfoUtil(this.db, patientId, data, requesterUserId);
2957
+ return updateSensitiveInfoUtil(
2958
+ this.db,
2959
+ patientId,
2960
+ data,
2961
+ requesterUserId,
2962
+ this.mediaService
2963
+ );
2572
2964
  }
2573
2965
  // Metode za rad sa medicinskim informacijama
2574
2966
  async createMedicalInfo(patientId, data) {
@@ -2701,8 +3093,8 @@ var PatientService = class extends BaseService {
2701
3093
  if (!this.auth.currentUser) {
2702
3094
  throw new Error("No authenticated user");
2703
3095
  }
2704
- const userDoc = await getDoc9(
2705
- doc6(this.db, "users", this.auth.currentUser.uid)
3096
+ const userDoc = await getDoc10(
3097
+ doc7(this.db, "users", this.auth.currentUser.uid)
2706
3098
  );
2707
3099
  if (!userDoc.exists()) {
2708
3100
  throw new Error("User not found");
@@ -2737,14 +3129,113 @@ var PatientService = class extends BaseService {
2737
3129
  await removeClinicUtil(this.db, patientId, clinicId);
2738
3130
  }
2739
3131
  // Metode za rad sa profilnom slikom
3132
+ /**
3133
+ * Uploads a profile photo for a patient
3134
+ * @param patientId - ID of the patient
3135
+ * @param file - File or Blob to upload
3136
+ * @returns URL of the uploaded photo
3137
+ */
2740
3138
  async uploadProfilePhoto(patientId, file) {
2741
- return uploadProfilePhotoUtil(this.storage, patientId, file);
3139
+ console.log(
3140
+ `[PatientService] Uploading profile photo for patient ${patientId}`
3141
+ );
3142
+ const mediaMetadata = await this.mediaService.uploadMedia(
3143
+ file,
3144
+ patientId,
3145
+ // Using patientId as ownerId
3146
+ "private" /* PRIVATE */,
3147
+ // Profile photos should be private
3148
+ "patient_profile_photos",
3149
+ file instanceof File ? file.name : `profile_photo_${patientId}`
3150
+ );
3151
+ await updateDoc7(getSensitiveInfoDocRef(this.db, patientId), {
3152
+ photoUrl: mediaMetadata.url,
3153
+ updatedAt: serverTimestamp7()
3154
+ });
3155
+ return mediaMetadata.url;
2742
3156
  }
3157
+ /**
3158
+ * Updates a patient's profile photo (replaces existing one)
3159
+ * @param patientId - ID of the patient
3160
+ * @param file - New file or Blob to upload
3161
+ * @returns URL of the new uploaded photo
3162
+ */
2743
3163
  async updateProfilePhoto(patientId, file) {
2744
- return updateProfilePhotoUtil(this.storage, this.db, patientId, file);
3164
+ console.log(
3165
+ `[PatientService] Updating profile photo for patient ${patientId}`
3166
+ );
3167
+ const currentUser = await this.getCurrentUser();
3168
+ const currentSensitiveInfo = await this.getSensitiveInfo(
3169
+ patientId,
3170
+ currentUser.uid
3171
+ );
3172
+ if ((currentSensitiveInfo == null ? void 0 : currentSensitiveInfo.photoUrl) && typeof currentSensitiveInfo.photoUrl === "string") {
3173
+ try {
3174
+ const existingMediaMetadata = await this.mediaService.getMediaMetadataByUrl(
3175
+ currentSensitiveInfo.photoUrl
3176
+ );
3177
+ if (existingMediaMetadata) {
3178
+ await this.mediaService.deleteMedia(existingMediaMetadata.id);
3179
+ }
3180
+ } catch (error) {
3181
+ console.warn(
3182
+ `[PatientService] Could not delete old profile photo for patient ${patientId}:`,
3183
+ error
3184
+ );
3185
+ }
3186
+ }
3187
+ return this.uploadProfilePhoto(patientId, file);
2745
3188
  }
3189
+ /**
3190
+ * Deletes a patient's profile photo
3191
+ * @param patientId - ID of the patient
3192
+ */
2746
3193
  async deleteProfilePhoto(patientId) {
2747
- await deleteProfilePhotoUtil(this.storage, this.db, patientId);
3194
+ console.log(
3195
+ `[PatientService] Deleting profile photo for patient ${patientId}`
3196
+ );
3197
+ const currentUser = await this.getCurrentUser();
3198
+ const currentSensitiveInfo = await this.getSensitiveInfo(
3199
+ patientId,
3200
+ currentUser.uid
3201
+ );
3202
+ if ((currentSensitiveInfo == null ? void 0 : currentSensitiveInfo.photoUrl) && typeof currentSensitiveInfo.photoUrl === "string") {
3203
+ try {
3204
+ const existingMediaMetadata = await this.mediaService.getMediaMetadataByUrl(
3205
+ currentSensitiveInfo.photoUrl
3206
+ );
3207
+ if (existingMediaMetadata) {
3208
+ await this.mediaService.deleteMedia(existingMediaMetadata.id);
3209
+ }
3210
+ } catch (error) {
3211
+ console.warn(
3212
+ `[PatientService] Could not delete profile photo for patient ${patientId}:`,
3213
+ error
3214
+ );
3215
+ }
3216
+ await updateDoc7(getSensitiveInfoDocRef(this.db, patientId), {
3217
+ photoUrl: null,
3218
+ updatedAt: serverTimestamp7()
3219
+ });
3220
+ }
3221
+ }
3222
+ /**
3223
+ * Handles profile photo upload for patients (supports MediaResource)
3224
+ * @param photoUrl - MediaResource (File, Blob, or URL string) from CreatePatientSensitiveInfoData
3225
+ * @param patientId - ID of the patient
3226
+ * @returns URL string of the uploaded or existing photo
3227
+ */
3228
+ async handleProfilePhotoUpload(photoUrl, patientId) {
3229
+ if (!photoUrl) {
3230
+ return void 0;
3231
+ }
3232
+ if (typeof photoUrl === "string") {
3233
+ return photoUrl;
3234
+ }
3235
+ if (photoUrl instanceof File || photoUrl instanceof Blob) {
3236
+ return this.uploadProfilePhoto(patientId, photoUrl);
3237
+ }
3238
+ return void 0;
2748
3239
  }
2749
3240
  // Metode za ažuriranje profila
2750
3241
  async updatePatientProfile(patientId, data) {
@@ -2838,16 +3329,16 @@ var PatientService = class extends BaseService {
2838
3329
 
2839
3330
  // src/services/clinic/utils/admin.utils.ts
2840
3331
  import {
2841
- collection as collection5,
2842
- doc as doc7,
2843
- getDoc as getDoc10,
2844
- getDocs as getDocs5,
2845
- query as query5,
2846
- where as where5,
2847
- updateDoc as updateDoc7,
2848
- setDoc as setDoc6,
2849
- deleteDoc,
2850
- Timestamp as Timestamp7,
3332
+ collection as collection6,
3333
+ doc as doc8,
3334
+ getDoc as getDoc11,
3335
+ getDocs as getDocs6,
3336
+ query as query6,
3337
+ where as where6,
3338
+ updateDoc as updateDoc8,
3339
+ setDoc as setDoc7,
3340
+ deleteDoc as deleteDoc2,
3341
+ Timestamp as Timestamp8,
2851
3342
  serverTimestamp as serverTimestamp8
2852
3343
  } from "firebase/firestore";
2853
3344
 
@@ -2976,131 +3467,131 @@ var SubscriptionModel = /* @__PURE__ */ ((SubscriptionModel2) => {
2976
3467
 
2977
3468
  // src/validations/clinic.schema.ts
2978
3469
  import { z as z13 } from "zod";
2979
- import { Timestamp as Timestamp6 } from "firebase/firestore";
3470
+ import { Timestamp as Timestamp7 } from "firebase/firestore";
2980
3471
 
2981
3472
  // src/validations/reviews.schema.ts
2982
- import { z as z10 } from "zod";
2983
- var baseReviewSchema = z10.object({
2984
- id: z10.string().min(1),
2985
- patientId: z10.string().min(1),
2986
- fullReviewId: z10.string().min(1),
2987
- createdAt: z10.date(),
2988
- updatedAt: z10.date(),
2989
- comment: z10.string().min(1).max(2e3),
2990
- isVerified: z10.boolean(),
2991
- isPublished: z10.boolean()
3473
+ import { z as z11 } from "zod";
3474
+ var baseReviewSchema = z11.object({
3475
+ id: z11.string().min(1),
3476
+ patientId: z11.string().min(1),
3477
+ fullReviewId: z11.string().min(1),
3478
+ createdAt: z11.date(),
3479
+ updatedAt: z11.date(),
3480
+ comment: z11.string().min(1).max(2e3),
3481
+ isVerified: z11.boolean(),
3482
+ isPublished: z11.boolean()
2992
3483
  });
2993
- var baseReviewCreateSchema = z10.object({
2994
- patientId: z10.string().min(1),
2995
- comment: z10.string().min(1).max(2e3),
2996
- isVerified: z10.boolean().default(false),
2997
- isPublished: z10.boolean().default(true)
3484
+ var baseReviewCreateSchema = z11.object({
3485
+ patientId: z11.string().min(1),
3486
+ comment: z11.string().min(1).max(2e3),
3487
+ isVerified: z11.boolean().default(false),
3488
+ isPublished: z11.boolean().default(true)
2998
3489
  });
2999
3490
  var clinicReviewSchema = baseReviewSchema.extend({
3000
- clinicId: z10.string().min(1),
3001
- cleanliness: z10.number().min(1).max(5),
3002
- facilities: z10.number().min(1).max(5),
3003
- staffFriendliness: z10.number().min(1).max(5),
3004
- waitingTime: z10.number().min(1).max(5),
3005
- accessibility: z10.number().min(1).max(5),
3006
- overallRating: z10.number().min(1).max(5),
3007
- wouldRecommend: z10.boolean()
3491
+ clinicId: z11.string().min(1),
3492
+ cleanliness: z11.number().min(1).max(5),
3493
+ facilities: z11.number().min(1).max(5),
3494
+ staffFriendliness: z11.number().min(1).max(5),
3495
+ waitingTime: z11.number().min(1).max(5),
3496
+ accessibility: z11.number().min(1).max(5),
3497
+ overallRating: z11.number().min(1).max(5),
3498
+ wouldRecommend: z11.boolean()
3008
3499
  });
3009
3500
  var createClinicReviewSchema = baseReviewCreateSchema.extend({
3010
- clinicId: z10.string().min(1),
3011
- cleanliness: z10.number().min(1).max(5),
3012
- facilities: z10.number().min(1).max(5),
3013
- staffFriendliness: z10.number().min(1).max(5),
3014
- waitingTime: z10.number().min(1).max(5),
3015
- accessibility: z10.number().min(1).max(5),
3016
- wouldRecommend: z10.boolean()
3501
+ clinicId: z11.string().min(1),
3502
+ cleanliness: z11.number().min(1).max(5),
3503
+ facilities: z11.number().min(1).max(5),
3504
+ staffFriendliness: z11.number().min(1).max(5),
3505
+ waitingTime: z11.number().min(1).max(5),
3506
+ accessibility: z11.number().min(1).max(5),
3507
+ wouldRecommend: z11.boolean()
3017
3508
  });
3018
3509
  var practitionerReviewSchema = baseReviewSchema.extend({
3019
- practitionerId: z10.string().min(1),
3020
- knowledgeAndExpertise: z10.number().min(1).max(5),
3021
- communicationSkills: z10.number().min(1).max(5),
3022
- bedSideManner: z10.number().min(1).max(5),
3023
- thoroughness: z10.number().min(1).max(5),
3024
- trustworthiness: z10.number().min(1).max(5),
3025
- overallRating: z10.number().min(1).max(5),
3026
- wouldRecommend: z10.boolean()
3510
+ practitionerId: z11.string().min(1),
3511
+ knowledgeAndExpertise: z11.number().min(1).max(5),
3512
+ communicationSkills: z11.number().min(1).max(5),
3513
+ bedSideManner: z11.number().min(1).max(5),
3514
+ thoroughness: z11.number().min(1).max(5),
3515
+ trustworthiness: z11.number().min(1).max(5),
3516
+ overallRating: z11.number().min(1).max(5),
3517
+ wouldRecommend: z11.boolean()
3027
3518
  });
3028
3519
  var createPractitionerReviewSchema = baseReviewCreateSchema.extend({
3029
- practitionerId: z10.string().min(1),
3030
- knowledgeAndExpertise: z10.number().min(1).max(5),
3031
- communicationSkills: z10.number().min(1).max(5),
3032
- bedSideManner: z10.number().min(1).max(5),
3033
- thoroughness: z10.number().min(1).max(5),
3034
- trustworthiness: z10.number().min(1).max(5),
3035
- wouldRecommend: z10.boolean()
3520
+ practitionerId: z11.string().min(1),
3521
+ knowledgeAndExpertise: z11.number().min(1).max(5),
3522
+ communicationSkills: z11.number().min(1).max(5),
3523
+ bedSideManner: z11.number().min(1).max(5),
3524
+ thoroughness: z11.number().min(1).max(5),
3525
+ trustworthiness: z11.number().min(1).max(5),
3526
+ wouldRecommend: z11.boolean()
3036
3527
  });
3037
3528
  var procedureReviewSchema = baseReviewSchema.extend({
3038
- procedureId: z10.string().min(1),
3039
- effectivenessOfTreatment: z10.number().min(1).max(5),
3040
- outcomeExplanation: z10.number().min(1).max(5),
3041
- painManagement: z10.number().min(1).max(5),
3042
- followUpCare: z10.number().min(1).max(5),
3043
- valueForMoney: z10.number().min(1).max(5),
3044
- overallRating: z10.number().min(1).max(5),
3045
- wouldRecommend: z10.boolean()
3529
+ procedureId: z11.string().min(1),
3530
+ effectivenessOfTreatment: z11.number().min(1).max(5),
3531
+ outcomeExplanation: z11.number().min(1).max(5),
3532
+ painManagement: z11.number().min(1).max(5),
3533
+ followUpCare: z11.number().min(1).max(5),
3534
+ valueForMoney: z11.number().min(1).max(5),
3535
+ overallRating: z11.number().min(1).max(5),
3536
+ wouldRecommend: z11.boolean()
3046
3537
  });
3047
3538
  var createProcedureReviewSchema = baseReviewCreateSchema.extend({
3048
- procedureId: z10.string().min(1),
3049
- effectivenessOfTreatment: z10.number().min(1).max(5),
3050
- outcomeExplanation: z10.number().min(1).max(5),
3051
- painManagement: z10.number().min(1).max(5),
3052
- followUpCare: z10.number().min(1).max(5),
3053
- valueForMoney: z10.number().min(1).max(5),
3054
- wouldRecommend: z10.boolean()
3539
+ procedureId: z11.string().min(1),
3540
+ effectivenessOfTreatment: z11.number().min(1).max(5),
3541
+ outcomeExplanation: z11.number().min(1).max(5),
3542
+ painManagement: z11.number().min(1).max(5),
3543
+ followUpCare: z11.number().min(1).max(5),
3544
+ valueForMoney: z11.number().min(1).max(5),
3545
+ wouldRecommend: z11.boolean()
3055
3546
  });
3056
- var clinicReviewInfoSchema = z10.object({
3057
- totalReviews: z10.number().min(0),
3058
- averageRating: z10.number().min(0).max(5),
3059
- cleanliness: z10.number().min(0).max(5),
3060
- facilities: z10.number().min(0).max(5),
3061
- staffFriendliness: z10.number().min(0).max(5),
3062
- waitingTime: z10.number().min(0).max(5),
3063
- accessibility: z10.number().min(0).max(5),
3064
- recommendationPercentage: z10.number().min(0).max(100)
3547
+ var clinicReviewInfoSchema = z11.object({
3548
+ totalReviews: z11.number().min(0),
3549
+ averageRating: z11.number().min(0).max(5),
3550
+ cleanliness: z11.number().min(0).max(5),
3551
+ facilities: z11.number().min(0).max(5),
3552
+ staffFriendliness: z11.number().min(0).max(5),
3553
+ waitingTime: z11.number().min(0).max(5),
3554
+ accessibility: z11.number().min(0).max(5),
3555
+ recommendationPercentage: z11.number().min(0).max(100)
3065
3556
  });
3066
- var practitionerReviewInfoSchema = z10.object({
3067
- totalReviews: z10.number().min(0),
3068
- averageRating: z10.number().min(0).max(5),
3069
- knowledgeAndExpertise: z10.number().min(0).max(5),
3070
- communicationSkills: z10.number().min(0).max(5),
3071
- bedSideManner: z10.number().min(0).max(5),
3072
- thoroughness: z10.number().min(0).max(5),
3073
- trustworthiness: z10.number().min(0).max(5),
3074
- recommendationPercentage: z10.number().min(0).max(100)
3557
+ var practitionerReviewInfoSchema = z11.object({
3558
+ totalReviews: z11.number().min(0),
3559
+ averageRating: z11.number().min(0).max(5),
3560
+ knowledgeAndExpertise: z11.number().min(0).max(5),
3561
+ communicationSkills: z11.number().min(0).max(5),
3562
+ bedSideManner: z11.number().min(0).max(5),
3563
+ thoroughness: z11.number().min(0).max(5),
3564
+ trustworthiness: z11.number().min(0).max(5),
3565
+ recommendationPercentage: z11.number().min(0).max(100)
3075
3566
  });
3076
- var procedureReviewInfoSchema = z10.object({
3077
- totalReviews: z10.number().min(0),
3078
- averageRating: z10.number().min(0).max(5),
3079
- effectivenessOfTreatment: z10.number().min(0).max(5),
3080
- outcomeExplanation: z10.number().min(0).max(5),
3081
- painManagement: z10.number().min(0).max(5),
3082
- followUpCare: z10.number().min(0).max(5),
3083
- valueForMoney: z10.number().min(0).max(5),
3084
- recommendationPercentage: z10.number().min(0).max(100)
3567
+ var procedureReviewInfoSchema = z11.object({
3568
+ totalReviews: z11.number().min(0),
3569
+ averageRating: z11.number().min(0).max(5),
3570
+ effectivenessOfTreatment: z11.number().min(0).max(5),
3571
+ outcomeExplanation: z11.number().min(0).max(5),
3572
+ painManagement: z11.number().min(0).max(5),
3573
+ followUpCare: z11.number().min(0).max(5),
3574
+ valueForMoney: z11.number().min(0).max(5),
3575
+ recommendationPercentage: z11.number().min(0).max(100)
3085
3576
  });
3086
- var reviewSchema = z10.object({
3087
- id: z10.string().min(1),
3088
- appointmentId: z10.string().min(1),
3089
- patientId: z10.string().min(1),
3090
- createdAt: z10.date(),
3091
- updatedAt: z10.date(),
3577
+ var reviewSchema = z11.object({
3578
+ id: z11.string().min(1),
3579
+ appointmentId: z11.string().min(1),
3580
+ patientId: z11.string().min(1),
3581
+ createdAt: z11.date(),
3582
+ updatedAt: z11.date(),
3092
3583
  clinicReview: clinicReviewSchema.optional(),
3093
3584
  practitionerReview: practitionerReviewSchema.optional(),
3094
3585
  procedureReview: procedureReviewSchema.optional(),
3095
- overallComment: z10.string().min(1).max(2e3),
3096
- overallRating: z10.number().min(1).max(5)
3586
+ overallComment: z11.string().min(1).max(2e3),
3587
+ overallRating: z11.number().min(1).max(5)
3097
3588
  });
3098
- var createReviewSchema = z10.object({
3099
- patientId: z10.string().min(1),
3589
+ var createReviewSchema = z11.object({
3590
+ patientId: z11.string().min(1),
3100
3591
  clinicReview: createClinicReviewSchema.optional(),
3101
3592
  practitionerReview: createPractitionerReviewSchema.optional(),
3102
3593
  procedureReview: createProcedureReviewSchema.optional(),
3103
- overallComment: z10.string().min(1).max(2e3)
3594
+ overallComment: z11.string().min(1).max(2e3)
3104
3595
  }).refine(
3105
3596
  (data) => {
3106
3597
  return data.clinicReview || data.practitionerReview || data.procedureReview;
@@ -3112,7 +3603,7 @@ var createReviewSchema = z10.object({
3112
3603
  );
3113
3604
 
3114
3605
  // src/validations/shared.schema.ts
3115
- import { z as z11 } from "zod";
3606
+ import { z as z12 } from "zod";
3116
3607
 
3117
3608
  // src/backoffice/types/static/procedure-family.types.ts
3118
3609
  var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
@@ -3141,65 +3632,57 @@ var Currency = /* @__PURE__ */ ((Currency2) => {
3141
3632
  })(Currency || {});
3142
3633
 
3143
3634
  // src/validations/shared.schema.ts
3144
- var sharedClinicContactInfoSchema = z11.object({
3145
- email: z11.string().email(),
3146
- phoneNumber: z11.string(),
3147
- alternativePhoneNumber: z11.string().nullable().optional(),
3148
- website: z11.string().nullable().optional()
3635
+ var sharedClinicContactInfoSchema = z12.object({
3636
+ email: z12.string().email(),
3637
+ phoneNumber: z12.string(),
3638
+ alternativePhoneNumber: z12.string().nullable().optional(),
3639
+ website: z12.string().nullable().optional()
3149
3640
  });
3150
- var sharedClinicLocationSchema = z11.object({
3151
- address: z11.string(),
3152
- city: z11.string(),
3153
- country: z11.string(),
3154
- postalCode: z11.string(),
3155
- latitude: z11.number().min(-90).max(90),
3156
- longitude: z11.number().min(-180).max(180),
3157
- geohash: z11.string().nullable().optional()
3641
+ var sharedClinicLocationSchema = z12.object({
3642
+ address: z12.string(),
3643
+ city: z12.string(),
3644
+ country: z12.string(),
3645
+ postalCode: z12.string(),
3646
+ latitude: z12.number().min(-90).max(90),
3647
+ longitude: z12.number().min(-180).max(180),
3648
+ geohash: z12.string().nullable().optional()
3158
3649
  });
3159
- var procedureSummaryInfoSchema = z11.object({
3160
- id: z11.string().min(1),
3161
- name: z11.string().min(1),
3162
- description: z11.string().optional(),
3163
- photo: z11.string().optional(),
3164
- family: z11.nativeEnum(ProcedureFamily),
3165
- categoryName: z11.string(),
3166
- subcategoryName: z11.string(),
3167
- technologyName: z11.string(),
3168
- price: z11.number().nonnegative(),
3169
- pricingMeasure: z11.nativeEnum(PricingMeasure),
3170
- currency: z11.nativeEnum(Currency),
3171
- duration: z11.number().int().positive(),
3172
- clinicId: z11.string().min(1),
3173
- clinicName: z11.string().min(1),
3174
- practitionerId: z11.string().min(1),
3175
- practitionerName: z11.string().min(1)
3650
+ var procedureSummaryInfoSchema = z12.object({
3651
+ id: z12.string().min(1),
3652
+ name: z12.string().min(1),
3653
+ description: z12.string().optional(),
3654
+ photo: z12.string().optional(),
3655
+ family: z12.nativeEnum(ProcedureFamily),
3656
+ categoryName: z12.string(),
3657
+ subcategoryName: z12.string(),
3658
+ technologyName: z12.string(),
3659
+ price: z12.number().nonnegative(),
3660
+ pricingMeasure: z12.nativeEnum(PricingMeasure),
3661
+ currency: z12.nativeEnum(Currency),
3662
+ duration: z12.number().int().positive(),
3663
+ clinicId: z12.string().min(1),
3664
+ clinicName: z12.string().min(1),
3665
+ practitionerId: z12.string().min(1),
3666
+ practitionerName: z12.string().min(1)
3176
3667
  });
3177
- var clinicInfoSchema = z11.object({
3178
- id: z11.string(),
3179
- featuredPhoto: z11.string(),
3180
- name: z11.string(),
3181
- description: z11.string().nullable().optional(),
3668
+ var clinicInfoSchema = z12.object({
3669
+ id: z12.string(),
3670
+ featuredPhoto: z12.string(),
3671
+ name: z12.string(),
3672
+ description: z12.string().nullable().optional(),
3182
3673
  location: sharedClinicLocationSchema,
3183
3674
  contactInfo: sharedClinicContactInfoSchema
3184
3675
  });
3185
- var doctorInfoSchema = z11.object({
3186
- id: z11.string(),
3187
- name: z11.string(),
3188
- description: z11.string().nullable().optional(),
3189
- photo: z11.string(),
3190
- rating: z11.number().min(0).max(5),
3191
- services: z11.array(z11.string())
3676
+ var doctorInfoSchema = z12.object({
3677
+ id: z12.string(),
3678
+ name: z12.string(),
3679
+ description: z12.string().nullable().optional(),
3680
+ photo: z12.string(),
3681
+ rating: z12.number().min(0).max(5),
3682
+ services: z12.array(z12.string())
3192
3683
  // List of procedure IDs practitioner offers
3193
3684
  });
3194
3685
 
3195
- // src/validations/media.schema.ts
3196
- import { z as z12 } from "zod";
3197
- var mediaResourceSchema = z12.union([
3198
- z12.string().url(),
3199
- z12.instanceof(File),
3200
- z12.instanceof(Blob)
3201
- ]);
3202
-
3203
3686
  // src/validations/clinic.schema.ts
3204
3687
  var clinicContactInfoSchema = z13.object({
3205
3688
  email: z13.string().email(),
@@ -3259,8 +3742,8 @@ var clinicAdminSchema = z13.object({
3259
3742
  clinicsManagedInfo: z13.array(clinicInfoSchema),
3260
3743
  contactInfo: contactPersonSchema,
3261
3744
  roleTitle: z13.string(),
3262
- createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3263
- updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3745
+ createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3746
+ updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3264
3747
  isActive: z13.boolean()
3265
3748
  });
3266
3749
  var adminTokenSchema = z13.object({
@@ -3269,9 +3752,9 @@ var adminTokenSchema = z13.object({
3269
3752
  email: z13.string().email().optional().nullable(),
3270
3753
  status: z13.nativeEnum(AdminTokenStatus),
3271
3754
  usedByUserRef: z13.string().optional(),
3272
- createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3755
+ createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3273
3756
  // Timestamp
3274
- expiresAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6))
3757
+ expiresAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7))
3275
3758
  // Timestamp
3276
3759
  });
3277
3760
  var createAdminTokenSchema = z13.object({
@@ -3291,9 +3774,9 @@ var clinicGroupSchema = z13.object({
3291
3774
  adminsInfo: z13.array(adminInfoSchema),
3292
3775
  adminTokens: z13.array(adminTokenSchema),
3293
3776
  ownerId: z13.string().nullable(),
3294
- createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3777
+ createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3295
3778
  // Timestamp
3296
- updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3779
+ updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3297
3780
  // Timestamp
3298
3781
  isActive: z13.boolean(),
3299
3782
  logo: mediaResourceSchema.optional().nullable(),
@@ -3335,9 +3818,9 @@ var clinicSchema = z13.object({
3335
3818
  // Use the correct schema for aggregated procedure info
3336
3819
  reviewInfo: clinicReviewInfoSchema,
3337
3820
  admins: z13.array(z13.string()),
3338
- createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3821
+ createdAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3339
3822
  // Timestamp
3340
- updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp6)),
3823
+ updatedAt: z13.instanceof(Date).or(z13.instanceof(Timestamp7)),
3341
3824
  // Timestamp
3342
3825
  isActive: z13.boolean(),
3343
3826
  isVerified: z13.boolean(),
@@ -3559,7 +4042,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3559
4042
  }
3560
4043
  console.log("[CLINIC_ADMIN] Preparing admin data object");
3561
4044
  const adminData = {
3562
- id: doc7(collection5(db, CLINIC_ADMINS_COLLECTION)).id,
4045
+ id: doc8(collection6(db, CLINIC_ADMINS_COLLECTION)).id,
3563
4046
  // Generate a new ID for the admin document
3564
4047
  userRef: validatedData.userRef,
3565
4048
  clinicGroupId: clinicGroupId || "",
@@ -3579,8 +4062,8 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3579
4062
  try {
3580
4063
  clinicAdminSchema.parse({
3581
4064
  ...adminData,
3582
- createdAt: Timestamp7.now(),
3583
- updatedAt: Timestamp7.now()
4065
+ createdAt: Timestamp8.now(),
4066
+ updatedAt: Timestamp8.now()
3584
4067
  });
3585
4068
  console.log("[CLINIC_ADMIN] Admin object validation passed");
3586
4069
  } catch (schemaError) {
@@ -3594,7 +4077,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
3594
4077
  adminId: adminData.id
3595
4078
  });
3596
4079
  try {
3597
- await setDoc6(doc7(db, CLINIC_ADMINS_COLLECTION, adminData.id), adminData);
4080
+ await setDoc7(doc8(db, CLINIC_ADMINS_COLLECTION, adminData.id), adminData);
3598
4081
  console.log("[CLINIC_ADMIN] Admin saved successfully");
3599
4082
  } catch (firestoreError) {
3600
4083
  console.error(
@@ -3643,30 +4126,30 @@ async function checkClinicGroupExists(db, groupId, clinicGroupService) {
3643
4126
  return !!group;
3644
4127
  }
3645
4128
  async function getClinicAdmin(db, adminId) {
3646
- const docRef = doc7(db, CLINIC_ADMINS_COLLECTION, adminId);
3647
- const docSnap = await getDoc10(docRef);
4129
+ const docRef = doc8(db, CLINIC_ADMINS_COLLECTION, adminId);
4130
+ const docSnap = await getDoc11(docRef);
3648
4131
  if (docSnap.exists()) {
3649
4132
  return docSnap.data();
3650
4133
  }
3651
4134
  return null;
3652
4135
  }
3653
4136
  async function getClinicAdminByUserRef(db, userRef) {
3654
- const q = query5(
3655
- collection5(db, CLINIC_ADMINS_COLLECTION),
3656
- where5("userRef", "==", userRef)
4137
+ const q = query6(
4138
+ collection6(db, CLINIC_ADMINS_COLLECTION),
4139
+ where6("userRef", "==", userRef)
3657
4140
  );
3658
- const querySnapshot = await getDocs5(q);
4141
+ const querySnapshot = await getDocs6(q);
3659
4142
  if (querySnapshot.empty) {
3660
4143
  return null;
3661
4144
  }
3662
4145
  return querySnapshot.docs[0].data();
3663
4146
  }
3664
4147
  async function getClinicAdminsByGroup(db, clinicGroupId) {
3665
- const q = query5(
3666
- collection5(db, CLINIC_ADMINS_COLLECTION),
3667
- where5("clinicGroupId", "==", clinicGroupId)
4148
+ const q = query6(
4149
+ collection6(db, CLINIC_ADMINS_COLLECTION),
4150
+ where6("clinicGroupId", "==", clinicGroupId)
3668
4151
  );
3669
- const querySnapshot = await getDocs5(q);
4152
+ const querySnapshot = await getDocs6(q);
3670
4153
  return querySnapshot.docs.map((doc34) => doc34.data());
3671
4154
  }
3672
4155
  async function updateClinicAdmin(db, adminId, data) {
@@ -3678,7 +4161,7 @@ async function updateClinicAdmin(db, adminId, data) {
3678
4161
  ...data,
3679
4162
  updatedAt: serverTimestamp8()
3680
4163
  };
3681
- await updateDoc7(doc7(db, CLINIC_ADMINS_COLLECTION, adminId), updatedData);
4164
+ await updateDoc8(doc8(db, CLINIC_ADMINS_COLLECTION, adminId), updatedData);
3682
4165
  const updatedAdmin = await getClinicAdmin(db, adminId);
3683
4166
  if (!updatedAdmin) {
3684
4167
  throw new Error("Failed to retrieve updated admin");
@@ -3690,7 +4173,7 @@ async function deleteClinicAdmin(db, adminId) {
3690
4173
  if (!admin) {
3691
4174
  throw new Error("Clinic admin not found");
3692
4175
  }
3693
- await deleteDoc(doc7(db, CLINIC_ADMINS_COLLECTION, adminId));
4176
+ await deleteDoc2(doc8(db, CLINIC_ADMINS_COLLECTION, adminId));
3694
4177
  }
3695
4178
  async function addClinicToManaged(db, adminId, clinicId, requesterId, clinicService) {
3696
4179
  const admin = await getClinicAdmin(db, adminId);
@@ -3861,413 +4344,97 @@ var ClinicAdminService = class extends BaseService {
3861
4344
  async getClinicAdmin(adminId) {
3862
4345
  return getClinicAdmin(this.db, adminId);
3863
4346
  }
3864
- /**
3865
- * Dohvata admin profil po korisničkom ID-u
3866
- */
3867
- async getClinicAdminByUserRef(userRef) {
3868
- return getClinicAdminByUserRef(this.db, userRef);
3869
- }
3870
- /**
3871
- * Dohvata sve admine u grupi
3872
- */
3873
- async getClinicAdminsByGroup(clinicGroupId) {
3874
- return getClinicAdminsByGroup(this.db, clinicGroupId);
3875
- }
3876
- /**
3877
- * Ažurira admin profil
3878
- */
3879
- async updateClinicAdmin(adminId, data) {
3880
- return updateClinicAdmin(this.db, adminId, data);
3881
- }
3882
- /**
3883
- * Briše admin profil
3884
- */
3885
- async deleteClinicAdmin(adminId) {
3886
- return deleteClinicAdmin(this.db, adminId);
3887
- }
3888
- /**
3889
- * Dodaje kliniku u listu klinika kojima admin upravlja
3890
- */
3891
- async addClinicToManaged(adminId, clinicId, requesterId) {
3892
- return addClinicToManaged(
3893
- this.db,
3894
- adminId,
3895
- clinicId,
3896
- requesterId,
3897
- this.getClinicService()
3898
- );
3899
- }
3900
- /**
3901
- * Uklanja kliniku iz liste klinika kojima admin upravlja
3902
- */
3903
- async removeClinicFromManaged(adminId, clinicId, requesterId) {
3904
- return removeClinicFromManaged(
3905
- this.db,
3906
- adminId,
3907
- clinicId,
3908
- requesterId
3909
- );
3910
- }
3911
- /**
3912
- * Dohvata sve klinike kojima admin upravlja
3913
- */
3914
- async getManagedClinics(adminId) {
3915
- return getManagedClinics(
3916
- this.db,
3917
- adminId,
3918
- this.getClinicService()
3919
- );
3920
- }
3921
- /**
3922
- * Dohvata sve aktivne klinike kojima admin upravlja
3923
- */
3924
- async getActiveManagedClinics(adminId) {
3925
- return getActiveManagedClinics(
3926
- this.db,
3927
- adminId,
3928
- this.getClinicService()
3929
- );
3930
- }
3931
- // TODO: Add more methods for clinic admins for managing permissions, editing profiles by the admin, or by the clinic group owner and so on
3932
- // Generally refactor admin permissions and clinic group permissions and systems for admin management
3933
- };
3934
-
3935
- // src/services/practitioner/practitioner.service.ts
3936
- import {
3937
- collection as collection7,
3938
- doc as doc9,
3939
- getDoc as getDoc12,
3940
- getDocs as getDocs7,
3941
- query as query7,
3942
- where as where7,
3943
- updateDoc as updateDoc9,
3944
- setDoc as setDoc8,
3945
- deleteDoc as deleteDoc3,
3946
- Timestamp as Timestamp10,
3947
- serverTimestamp as serverTimestamp9,
3948
- limit as limit5,
3949
- startAfter as startAfter4,
3950
- orderBy as orderBy2,
3951
- arrayUnion as arrayUnion5,
3952
- arrayRemove as arrayRemove4
3953
- } from "firebase/firestore";
3954
-
3955
- // src/services/media/media.service.ts
3956
- import { Timestamp as Timestamp8 } from "firebase/firestore";
3957
- import {
3958
- ref as ref2,
3959
- uploadBytes as uploadBytes2,
3960
- getDownloadURL as getDownloadURL2,
3961
- deleteObject as deleteObject2,
3962
- getBytes
3963
- } from "firebase/storage";
3964
- import {
3965
- doc as doc8,
3966
- getDoc as getDoc11,
3967
- setDoc as setDoc7,
3968
- updateDoc as updateDoc8,
3969
- collection as collection6,
3970
- query as query6,
3971
- where as where6,
3972
- limit as limit4,
3973
- getDocs as getDocs6,
3974
- deleteDoc as deleteDoc2,
3975
- orderBy
3976
- } from "firebase/firestore";
3977
- var MediaAccessLevel = /* @__PURE__ */ ((MediaAccessLevel2) => {
3978
- MediaAccessLevel2["PUBLIC"] = "public";
3979
- MediaAccessLevel2["PRIVATE"] = "private";
3980
- MediaAccessLevel2["CONFIDENTIAL"] = "confidential";
3981
- return MediaAccessLevel2;
3982
- })(MediaAccessLevel || {});
3983
- var MEDIA_METADATA_COLLECTION = "media_metadata";
3984
- var MediaService = class extends BaseService {
3985
- constructor(db, auth, app) {
3986
- super(db, auth, app);
3987
- }
3988
- /**
3989
- * Upload a media file, store its metadata, and return the metadata including the URL.
3990
- * @param file - The file to upload.
3991
- * @param ownerId - ID of the owner (user, patient, clinic, etc.).
3992
- * @param accessLevel - Access level (public, private, confidential).
3993
- * @param collectionName - The logical collection name this media belongs to (e.g., 'patient_profile_pictures', 'clinic_logos').
3994
- * @param originalFileName - Optional: the original name of the file, if not using file.name.
3995
- * @returns Promise with the media metadata.
3996
- */
3997
- async uploadMedia(file, ownerId, accessLevel, collectionName, originalFileName) {
3998
- const mediaId = this.generateId();
3999
- const fileNameToUse = originalFileName || (file instanceof File ? file.name : file.toString());
4000
- const uniqueFileName = `${mediaId}-${fileNameToUse}`;
4001
- const filePath = `media/${accessLevel}/${ownerId}/${collectionName}/${uniqueFileName}`;
4002
- console.log(`[MediaService] Uploading file to: ${filePath}`);
4003
- const storageRef = ref2(this.storage, filePath);
4004
- try {
4005
- const uploadResult = await uploadBytes2(storageRef, file, {
4006
- contentType: file.type
4007
- });
4008
- console.log("[MediaService] File uploaded successfully", uploadResult);
4009
- const downloadURL = await getDownloadURL2(uploadResult.ref);
4010
- console.log("[MediaService] Got download URL:", downloadURL);
4011
- const metadata = {
4012
- id: mediaId,
4013
- name: fileNameToUse,
4014
- url: downloadURL,
4015
- contentType: file.type,
4016
- size: file.size,
4017
- createdAt: Timestamp8.now(),
4018
- accessLevel,
4019
- ownerId,
4020
- collectionName,
4021
- path: filePath
4022
- };
4023
- const metadataDocRef = doc8(this.db, MEDIA_METADATA_COLLECTION, mediaId);
4024
- await setDoc7(metadataDocRef, metadata);
4025
- console.log("[MediaService] Metadata stored in Firestore:", mediaId);
4026
- return metadata;
4027
- } catch (error) {
4028
- console.error("[MediaService] Error during media upload:", error);
4029
- throw error;
4030
- }
4347
+ /**
4348
+ * Dohvata admin profil po korisničkom ID-u
4349
+ */
4350
+ async getClinicAdminByUserRef(userRef) {
4351
+ return getClinicAdminByUserRef(this.db, userRef);
4031
4352
  }
4032
4353
  /**
4033
- * Get media metadata from Firestore by its ID.
4034
- * @param mediaId - ID of the media.
4035
- * @returns Promise with the media metadata or null if not found.
4354
+ * Dohvata sve admine u grupi
4036
4355
  */
4037
- async getMediaMetadata(mediaId) {
4038
- console.log(`[MediaService] Getting media metadata for ID: ${mediaId}`);
4039
- const docRef = doc8(this.db, MEDIA_METADATA_COLLECTION, mediaId);
4040
- const docSnap = await getDoc11(docRef);
4041
- if (docSnap.exists()) {
4042
- console.log("[MediaService] Metadata found:", docSnap.data());
4043
- return docSnap.data();
4044
- }
4045
- console.log("[MediaService] No metadata found for ID:", mediaId);
4046
- return null;
4356
+ async getClinicAdminsByGroup(clinicGroupId) {
4357
+ return getClinicAdminsByGroup(this.db, clinicGroupId);
4047
4358
  }
4048
4359
  /**
4049
- * Get media metadata from Firestore by its public URL.
4050
- * @param url - The public URL of the media file.
4051
- * @returns Promise with the media metadata or null if not found.
4360
+ * Ažurira admin profil
4052
4361
  */
4053
- async getMediaMetadataByUrl(url) {
4054
- console.log(`[MediaService] Getting media metadata by URL: ${url}`);
4055
- const q = query6(
4056
- collection6(this.db, MEDIA_METADATA_COLLECTION),
4057
- where6("url", "==", url),
4058
- limit4(1)
4059
- );
4060
- try {
4061
- const querySnapshot = await getDocs6(q);
4062
- if (!querySnapshot.empty) {
4063
- const metadata = querySnapshot.docs[0].data();
4064
- console.log("[MediaService] Metadata found by URL:", metadata);
4065
- return metadata;
4066
- }
4067
- console.log("[MediaService] No metadata found for URL:", url);
4068
- return null;
4069
- } catch (error) {
4070
- console.error("[MediaService] Error fetching metadata by URL:", error);
4071
- throw error;
4072
- }
4362
+ async updateClinicAdmin(adminId, data) {
4363
+ return updateClinicAdmin(this.db, adminId, data);
4073
4364
  }
4074
4365
  /**
4075
- * Delete media from storage and remove metadata from Firestore.
4076
- * @param mediaId - ID of the media to delete.
4366
+ * Briše admin profil
4077
4367
  */
4078
- async deleteMedia(mediaId) {
4079
- console.log(`[MediaService] Deleting media with ID: ${mediaId}`);
4080
- const metadata = await this.getMediaMetadata(mediaId);
4081
- if (!metadata) {
4082
- console.warn(
4083
- `[MediaService] Metadata not found for media ID ${mediaId}. Cannot delete.`
4084
- );
4085
- return;
4086
- }
4087
- const storageFileRef = ref2(this.storage, metadata.path);
4088
- try {
4089
- await deleteObject2(storageFileRef);
4090
- console.log(`[MediaService] File deleted from Storage: ${metadata.path}`);
4091
- const metadataDocRef = doc8(this.db, MEDIA_METADATA_COLLECTION, mediaId);
4092
- await deleteDoc2(metadataDocRef);
4093
- console.log(
4094
- `[MediaService] Metadata deleted from Firestore for ID: ${mediaId}`
4095
- );
4096
- } catch (error) {
4097
- console.error(`[MediaService] Error deleting media ${mediaId}:`, error);
4098
- throw error;
4099
- }
4368
+ async deleteClinicAdmin(adminId) {
4369
+ return deleteClinicAdmin(this.db, adminId);
4100
4370
  }
4101
4371
  /**
4102
- * Update media access level. This involves moving the file in Firebase Storage
4103
- * to a new path reflecting the new access level, and updating its metadata.
4104
- * @param mediaId - ID of the media to update.
4105
- * @param newAccessLevel - New access level.
4106
- * @returns Promise with the updated media metadata, or null if metadata not found.
4372
+ * Dodaje kliniku u listu klinika kojima admin upravlja
4107
4373
  */
4108
- async updateMediaAccessLevel(mediaId, newAccessLevel) {
4109
- var _a;
4110
- console.log(
4111
- `[MediaService] Attempting to update access level for media ID: ${mediaId} to ${newAccessLevel}`
4374
+ async addClinicToManaged(adminId, clinicId, requesterId) {
4375
+ return addClinicToManaged(
4376
+ this.db,
4377
+ adminId,
4378
+ clinicId,
4379
+ requesterId,
4380
+ this.getClinicService()
4112
4381
  );
4113
- const metadata = await this.getMediaMetadata(mediaId);
4114
- if (!metadata) {
4115
- console.warn(
4116
- `[MediaService] Metadata not found for media ID ${mediaId}. Cannot update access level.`
4117
- );
4118
- return null;
4119
- }
4120
- if (metadata.accessLevel === newAccessLevel) {
4121
- console.log(
4122
- `[MediaService] Media ID ${mediaId} already has access level ${newAccessLevel}. Updating timestamp only.`
4123
- );
4124
- const metadataDocRef = doc8(this.db, MEDIA_METADATA_COLLECTION, mediaId);
4125
- try {
4126
- await updateDoc8(metadataDocRef, { updatedAt: Timestamp8.now() });
4127
- return { ...metadata, updatedAt: Timestamp8.now() };
4128
- } catch (error) {
4129
- console.error(
4130
- `[MediaService] Error updating timestamp for media ID ${mediaId}:`,
4131
- error
4132
- );
4133
- throw error;
4134
- }
4135
- }
4136
- const oldStoragePath = metadata.path;
4137
- const fileNamePart = `${metadata.id}-${metadata.name}`;
4138
- const newStoragePath = `media/${newAccessLevel}/${metadata.ownerId}/${metadata.collectionName}/${fileNamePart}`;
4139
- console.log(
4140
- `[MediaService] Moving file for ${mediaId} from ${oldStoragePath} to ${newStoragePath}`
4382
+ }
4383
+ /**
4384
+ * Uklanja kliniku iz liste klinika kojima admin upravlja
4385
+ */
4386
+ async removeClinicFromManaged(adminId, clinicId, requesterId) {
4387
+ return removeClinicFromManaged(
4388
+ this.db,
4389
+ adminId,
4390
+ clinicId,
4391
+ requesterId
4141
4392
  );
4142
- const oldStorageFileRef = ref2(this.storage, oldStoragePath);
4143
- const newStorageFileRef = ref2(this.storage, newStoragePath);
4144
- try {
4145
- console.log(`[MediaService] Downloading bytes from ${oldStoragePath}`);
4146
- const fileBytes = await getBytes(oldStorageFileRef);
4147
- console.log(
4148
- `[MediaService] Successfully downloaded ${fileBytes.byteLength} bytes from ${oldStoragePath}`
4149
- );
4150
- console.log(`[MediaService] Uploading bytes to ${newStoragePath}`);
4151
- await uploadBytes2(newStorageFileRef, fileBytes, {
4152
- contentType: metadata.contentType
4153
- });
4154
- console.log(
4155
- `[MediaService] Successfully uploaded bytes to ${newStoragePath}`
4156
- );
4157
- const newDownloadURL = await getDownloadURL2(newStorageFileRef);
4158
- console.log(
4159
- `[MediaService] Got new download URL for ${newStoragePath}: ${newDownloadURL}`
4160
- );
4161
- const updateData = {
4162
- accessLevel: newAccessLevel,
4163
- path: newStoragePath,
4164
- url: newDownloadURL,
4165
- updatedAt: Timestamp8.now()
4166
- };
4167
- const metadataDocRef = doc8(this.db, MEDIA_METADATA_COLLECTION, mediaId);
4168
- console.log(
4169
- `[MediaService] Updating Firestore metadata for ${mediaId} with new data:`,
4170
- updateData
4171
- );
4172
- await updateDoc8(metadataDocRef, updateData);
4173
- console.log(
4174
- `[MediaService] Successfully updated Firestore metadata for ${mediaId}`
4175
- );
4176
- try {
4177
- console.log(`[MediaService] Deleting old file from ${oldStoragePath}`);
4178
- await deleteObject2(oldStorageFileRef);
4179
- console.log(
4180
- `[MediaService] Successfully deleted old file from ${oldStoragePath}`
4181
- );
4182
- } catch (deleteError) {
4183
- console.error(
4184
- `[MediaService] Failed to delete old file from ${oldStoragePath} for media ID ${mediaId}. This file is now orphaned. Error:`,
4185
- deleteError
4186
- );
4187
- }
4188
- return { ...metadata, ...updateData };
4189
- } catch (error) {
4190
- console.error(
4191
- `[MediaService] Error updating media access level and moving file for ${mediaId}:`,
4192
- error
4193
- );
4194
- if (newStorageFileRef && error.code !== "storage/object-not-found" && ((_a = error.message) == null ? void 0 : _a.includes("uploadBytes"))) {
4195
- console.warn(
4196
- `[MediaService] Attempting to delete partially uploaded file at ${newStoragePath} due to error.`
4197
- );
4198
- try {
4199
- await deleteObject2(newStorageFileRef);
4200
- console.warn(
4201
- `[MediaService] Cleaned up partially uploaded file at ${newStoragePath}.`
4202
- );
4203
- } catch (cleanupError) {
4204
- console.error(
4205
- `[MediaService] Failed to cleanup partially uploaded file at ${newStoragePath}:`,
4206
- cleanupError
4207
- );
4208
- }
4209
- }
4210
- throw error;
4211
- }
4212
4393
  }
4213
4394
  /**
4214
- * List all media for an owner, optionally filtered by collection and access level.
4215
- * @param ownerId - ID of the owner.
4216
- * @param collectionName - Optional: Filter by collection name.
4217
- * @param accessLevel - Optional: Filter by access level.
4218
- * @param count - Optional: Number of items to fetch.
4219
- * @param startAfterId - Optional: ID of the document to start after (for pagination).
4395
+ * Dohvata sve klinike kojima admin upravlja
4220
4396
  */
4221
- async listMedia(ownerId, collectionName, accessLevel, count, startAfterId) {
4222
- console.log(`[MediaService] Listing media for owner: ${ownerId}`);
4223
- let qConstraints = [where6("ownerId", "==", ownerId)];
4224
- if (collectionName) {
4225
- qConstraints.push(where6("collectionName", "==", collectionName));
4226
- }
4227
- if (accessLevel) {
4228
- qConstraints.push(where6("accessLevel", "==", accessLevel));
4229
- }
4230
- qConstraints.push(orderBy("createdAt", "desc"));
4231
- if (count) {
4232
- qConstraints.push(limit4(count));
4233
- }
4234
- if (startAfterId) {
4235
- const startAfterDoc = await this.getMediaMetadata(startAfterId);
4236
- if (startAfterDoc) {
4237
- }
4238
- }
4239
- const finalQuery = query6(
4240
- collection6(this.db, MEDIA_METADATA_COLLECTION),
4241
- ...qConstraints
4397
+ async getManagedClinics(adminId) {
4398
+ return getManagedClinics(
4399
+ this.db,
4400
+ adminId,
4401
+ this.getClinicService()
4242
4402
  );
4243
- try {
4244
- const querySnapshot = await getDocs6(finalQuery);
4245
- const mediaList = querySnapshot.docs.map(
4246
- (doc34) => doc34.data()
4247
- );
4248
- console.log(`[MediaService] Found ${mediaList.length} media items.`);
4249
- return mediaList;
4250
- } catch (error) {
4251
- console.error("[MediaService] Error listing media:", error);
4252
- throw error;
4253
- }
4254
4403
  }
4255
4404
  /**
4256
- * Get download URL for media. (Convenience, as URL is in metadata)
4257
- * @param mediaId - ID of the media.
4405
+ * Dohvata sve aktivne klinike kojima admin upravlja
4258
4406
  */
4259
- async getMediaDownloadUrl(mediaId) {
4260
- console.log(`[MediaService] Getting download URL for media ID: ${mediaId}`);
4261
- const metadata = await this.getMediaMetadata(mediaId);
4262
- if (metadata && metadata.url) {
4263
- console.log(`[MediaService] URL found: ${metadata.url}`);
4264
- return metadata.url;
4265
- }
4266
- console.log(`[MediaService] URL not found for media ID: ${mediaId}`);
4267
- return null;
4407
+ async getActiveManagedClinics(adminId) {
4408
+ return getActiveManagedClinics(
4409
+ this.db,
4410
+ adminId,
4411
+ this.getClinicService()
4412
+ );
4268
4413
  }
4414
+ // TODO: Add more methods for clinic admins for managing permissions, editing profiles by the admin, or by the clinic group owner and so on
4415
+ // Generally refactor admin permissions and clinic group permissions and systems for admin management
4269
4416
  };
4270
4417
 
4418
+ // src/services/practitioner/practitioner.service.ts
4419
+ import {
4420
+ collection as collection7,
4421
+ doc as doc9,
4422
+ getDoc as getDoc12,
4423
+ getDocs as getDocs7,
4424
+ query as query7,
4425
+ where as where7,
4426
+ updateDoc as updateDoc9,
4427
+ setDoc as setDoc8,
4428
+ deleteDoc as deleteDoc3,
4429
+ Timestamp as Timestamp10,
4430
+ serverTimestamp as serverTimestamp9,
4431
+ limit as limit5,
4432
+ startAfter as startAfter4,
4433
+ orderBy as orderBy2,
4434
+ arrayUnion as arrayUnion5,
4435
+ arrayRemove as arrayRemove4
4436
+ } from "firebase/firestore";
4437
+
4271
4438
  // src/validations/practitioner.schema.ts
4272
4439
  import { z as z14 } from "zod";
4273
4440
  import { Timestamp as Timestamp9 } from "firebase/firestore";
@@ -5567,10 +5734,10 @@ import { z as z17 } from "zod";
5567
5734
  // src/services/clinic/utils/photos.utils.ts
5568
5735
  import {
5569
5736
  getStorage as getStorage3,
5570
- ref as ref3,
5571
- uploadBytes as uploadBytes3,
5572
- getDownloadURL as getDownloadURL3,
5573
- deleteObject as deleteObject3
5737
+ ref as ref2,
5738
+ uploadBytes as uploadBytes2,
5739
+ getDownloadURL as getDownloadURL2,
5740
+ deleteObject as deleteObject2
5574
5741
  } from "firebase/storage";
5575
5742
  async function uploadPhoto(photo, entityType, entityId, photoType, app, fileName) {
5576
5743
  if (!photo || typeof photo !== "string" || !photo.startsWith("data:")) {
@@ -5582,7 +5749,7 @@ async function uploadPhoto(photo, entityType, entityId, photoType, app, fileName
5582
5749
  );
5583
5750
  const storage = getStorage3(app);
5584
5751
  const storageFileName = fileName || `${photoType}-${Date.now()}`;
5585
- const storageRef = ref3(
5752
+ const storageRef = ref2(
5586
5753
  storage,
5587
5754
  `${entityType}/${entityId}/${storageFileName}`
5588
5755
  );
@@ -5594,8 +5761,8 @@ async function uploadPhoto(photo, entityType, entityId, photoType, app, fileName
5594
5761
  byteArrays.push(byteCharacters.charCodeAt(i));
5595
5762
  }
5596
5763
  const blob = new Blob([new Uint8Array(byteArrays)], { type: contentType });
5597
- await uploadBytes3(storageRef, blob, { contentType });
5598
- const downloadUrl = await getDownloadURL3(storageRef);
5764
+ await uploadBytes2(storageRef, blob, { contentType });
5765
+ const downloadUrl = await getDownloadURL2(storageRef);
5599
5766
  console.log(`[PHOTO_UTILS] ${photoType} uploaded successfully`, {
5600
5767
  downloadUrl
5601
5768
  });