@blackcode_sa/metaestetics-api 1.7.40 → 1.7.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +4 -4
- package/dist/admin/index.d.ts +4 -4
- package/dist/backoffice/index.d.mts +4 -4
- package/dist/backoffice/index.d.ts +4 -4
- package/dist/index.d.mts +106 -98
- package/dist/index.d.ts +106 -98
- package/dist/index.js +455 -374
- package/dist/index.mjs +582 -500
- package/package.json +1 -1
- package/src/services/auth/index.ts +21 -0
- package/src/services/auth/utils/error.utils.ts +90 -0
- package/src/services/auth/utils/firebase.utils.ts +49 -0
- package/src/services/auth/utils/index.ts +21 -0
- package/src/services/auth/utils/practitioner.utils.ts +125 -0
- package/src/services/auth.service.ts +143 -155
- package/src/services/practitioner/practitioner.service.ts +5 -3
- package/src/types/practitioner/index.ts +4 -4
- package/src/validations/patient.schema.ts +2 -1
- package/src/validations/practitioner.schema.ts +7 -4
package/dist/index.mjs
CHANGED
|
@@ -599,7 +599,8 @@ import {
|
|
|
599
599
|
import {
|
|
600
600
|
collection as collection14,
|
|
601
601
|
query as query14,
|
|
602
|
-
getDocs as getDocs14
|
|
602
|
+
getDocs as getDocs14,
|
|
603
|
+
runTransaction
|
|
603
604
|
} from "firebase/firestore";
|
|
604
605
|
|
|
605
606
|
// src/types/calendar/index.ts
|
|
@@ -645,7 +646,7 @@ var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
|
645
646
|
var USERS_COLLECTION = "users";
|
|
646
647
|
|
|
647
648
|
// src/services/auth.service.ts
|
|
648
|
-
import { z as
|
|
649
|
+
import { z as z22 } from "zod";
|
|
649
650
|
|
|
650
651
|
// src/validations/schemas.ts
|
|
651
652
|
import { z as z4 } from "zod";
|
|
@@ -1658,6 +1659,7 @@ var createPatientLocationInfoSchema = z7.object({
|
|
|
1658
1659
|
var patientSensitiveInfoSchema = z7.object({
|
|
1659
1660
|
patientId: z7.string(),
|
|
1660
1661
|
userRef: z7.string(),
|
|
1662
|
+
photoUrl: z7.string().nullable().optional(),
|
|
1661
1663
|
firstName: z7.string().min(2),
|
|
1662
1664
|
lastName: z7.string().min(2),
|
|
1663
1665
|
dateOfBirth: z7.instanceof(Timestamp3).nullable(),
|
|
@@ -4521,10 +4523,10 @@ var practitionerBasicInfoSchema = z14.object({
|
|
|
4521
4523
|
lastName: z14.string().min(2).max(50),
|
|
4522
4524
|
title: z14.string().min(2).max(100),
|
|
4523
4525
|
email: z14.string().email(),
|
|
4524
|
-
phoneNumber: z14.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number"),
|
|
4525
|
-
dateOfBirth: z14.instanceof(Timestamp9).or(z14.date()),
|
|
4526
|
+
phoneNumber: z14.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number").nullable(),
|
|
4527
|
+
dateOfBirth: z14.instanceof(Timestamp9).or(z14.date()).nullable(),
|
|
4526
4528
|
gender: z14.enum(["male", "female", "other"]),
|
|
4527
|
-
profileImageUrl: mediaResourceSchema.optional(),
|
|
4529
|
+
profileImageUrl: mediaResourceSchema.optional().nullable(),
|
|
4528
4530
|
bio: z14.string().max(1e3).optional(),
|
|
4529
4531
|
languages: z14.array(z14.string()).min(1)
|
|
4530
4532
|
});
|
|
@@ -4534,7 +4536,7 @@ var practitionerCertificationSchema = z14.object({
|
|
|
4534
4536
|
licenseNumber: z14.string().min(3).max(50),
|
|
4535
4537
|
issuingAuthority: z14.string().min(2).max(100),
|
|
4536
4538
|
issueDate: z14.instanceof(Timestamp9).or(z14.date()),
|
|
4537
|
-
expiryDate: z14.instanceof(Timestamp9).or(z14.date()).optional(),
|
|
4539
|
+
expiryDate: z14.instanceof(Timestamp9).or(z14.date()).optional().nullable(),
|
|
4538
4540
|
verificationStatus: z14.enum(["pending", "verified", "rejected"])
|
|
4539
4541
|
});
|
|
4540
4542
|
var timeSlotSchema = z14.object({
|
|
@@ -7692,6 +7694,125 @@ var ClinicService = class extends BaseService {
|
|
|
7692
7694
|
}
|
|
7693
7695
|
};
|
|
7694
7696
|
|
|
7697
|
+
// src/services/auth/utils/firebase.utils.ts
|
|
7698
|
+
import { fetchSignInMethodsForEmail } from "firebase/auth";
|
|
7699
|
+
var checkEmailExists = async (auth, email) => {
|
|
7700
|
+
try {
|
|
7701
|
+
const methods = await fetchSignInMethodsForEmail(auth, email);
|
|
7702
|
+
return methods.length > 0;
|
|
7703
|
+
} catch (error) {
|
|
7704
|
+
console.warn(
|
|
7705
|
+
"[FIREBASE] Could not check email existence, allowing signup to proceed:",
|
|
7706
|
+
error
|
|
7707
|
+
);
|
|
7708
|
+
return false;
|
|
7709
|
+
}
|
|
7710
|
+
};
|
|
7711
|
+
var cleanupFirebaseUser = async (firebaseUser) => {
|
|
7712
|
+
try {
|
|
7713
|
+
console.log("[FIREBASE] Cleaning up Firebase user", {
|
|
7714
|
+
uid: firebaseUser.uid
|
|
7715
|
+
});
|
|
7716
|
+
await firebaseUser.delete();
|
|
7717
|
+
console.log("[FIREBASE] Firebase user cleanup successful");
|
|
7718
|
+
} catch (cleanupError) {
|
|
7719
|
+
console.error("[FIREBASE] Failed to cleanup Firebase user:", cleanupError);
|
|
7720
|
+
}
|
|
7721
|
+
};
|
|
7722
|
+
|
|
7723
|
+
// src/services/auth/utils/error.utils.ts
|
|
7724
|
+
import { z as z20 } from "zod";
|
|
7725
|
+
var handleFirebaseError = (error) => {
|
|
7726
|
+
const firebaseError = error;
|
|
7727
|
+
switch (firebaseError.code) {
|
|
7728
|
+
case "auth/email-already-in-use" /* EMAIL_ALREADY_IN_USE */:
|
|
7729
|
+
return AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
|
|
7730
|
+
case "auth/weak-password":
|
|
7731
|
+
return new Error(
|
|
7732
|
+
"Password is too weak. Please choose a stronger password."
|
|
7733
|
+
);
|
|
7734
|
+
case "auth/invalid-email":
|
|
7735
|
+
return new Error("Please enter a valid email address.");
|
|
7736
|
+
case "auth/network-request-failed":
|
|
7737
|
+
return new Error(
|
|
7738
|
+
"Network error. Please check your internet connection and try again."
|
|
7739
|
+
);
|
|
7740
|
+
default:
|
|
7741
|
+
return new Error(
|
|
7742
|
+
`Account creation failed: ${firebaseError.message || "Unknown error"}`
|
|
7743
|
+
);
|
|
7744
|
+
}
|
|
7745
|
+
};
|
|
7746
|
+
var handleSignupError = (error) => {
|
|
7747
|
+
if (error instanceof z20.ZodError) {
|
|
7748
|
+
const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
7749
|
+
return new Error(`Validation failed: ${errorMessages}`);
|
|
7750
|
+
}
|
|
7751
|
+
if (error.code && error.code.startsWith("auth/")) {
|
|
7752
|
+
return handleFirebaseError(error);
|
|
7753
|
+
}
|
|
7754
|
+
if (error.message && error.message.includes("token")) {
|
|
7755
|
+
return new Error("Invalid or expired invitation token");
|
|
7756
|
+
}
|
|
7757
|
+
if (error.message && error.message.includes("validation")) {
|
|
7758
|
+
return new Error(`Invalid practitioner data: ${error.message}`);
|
|
7759
|
+
}
|
|
7760
|
+
return new Error(
|
|
7761
|
+
`Registration failed: ${error.message || "Unknown error occurred"}`
|
|
7762
|
+
);
|
|
7763
|
+
};
|
|
7764
|
+
|
|
7765
|
+
// src/services/auth/utils/practitioner.utils.ts
|
|
7766
|
+
import { z as z21 } from "zod";
|
|
7767
|
+
var profileDataSchema = z21.object({
|
|
7768
|
+
basicInfo: practitionerBasicInfoSchema.partial().optional(),
|
|
7769
|
+
certification: practitionerCertificationSchema.partial().optional()
|
|
7770
|
+
}).partial();
|
|
7771
|
+
var buildPractitionerData = (data, userRef) => {
|
|
7772
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
7773
|
+
const basicInfo = {
|
|
7774
|
+
firstName: data.firstName || "Name",
|
|
7775
|
+
lastName: data.lastName || "Surname",
|
|
7776
|
+
email: data.email,
|
|
7777
|
+
phoneNumber: ((_b = (_a = data.profileData) == null ? void 0 : _a.basicInfo) == null ? void 0 : _b.phoneNumber) || null,
|
|
7778
|
+
profileImageUrl: ((_d = (_c = data.profileData) == null ? void 0 : _c.basicInfo) == null ? void 0 : _d.profileImageUrl) || "",
|
|
7779
|
+
gender: ((_f = (_e = data.profileData) == null ? void 0 : _e.basicInfo) == null ? void 0 : _f.gender) || "other",
|
|
7780
|
+
bio: ((_h = (_g = data.profileData) == null ? void 0 : _g.basicInfo) == null ? void 0 : _h.bio) || "",
|
|
7781
|
+
title: "Practitioner",
|
|
7782
|
+
dateOfBirth: ((_j = (_i = data.profileData) == null ? void 0 : _i.basicInfo) == null ? void 0 : _j.dateOfBirth) || /* @__PURE__ */ new Date(),
|
|
7783
|
+
languages: ((_l = (_k = data.profileData) == null ? void 0 : _k.basicInfo) == null ? void 0 : _l.languages) || ["English"]
|
|
7784
|
+
};
|
|
7785
|
+
const certification = ((_m = data.profileData) == null ? void 0 : _m.certification) || {
|
|
7786
|
+
level: "aesthetician" /* AESTHETICIAN */,
|
|
7787
|
+
specialties: [],
|
|
7788
|
+
licenseNumber: "Pending",
|
|
7789
|
+
issuingAuthority: "Pending",
|
|
7790
|
+
issueDate: /* @__PURE__ */ new Date(),
|
|
7791
|
+
verificationStatus: "pending"
|
|
7792
|
+
};
|
|
7793
|
+
return {
|
|
7794
|
+
userRef,
|
|
7795
|
+
basicInfo,
|
|
7796
|
+
certification,
|
|
7797
|
+
status: "active" /* ACTIVE */,
|
|
7798
|
+
isActive: true,
|
|
7799
|
+
isVerified: false
|
|
7800
|
+
};
|
|
7801
|
+
};
|
|
7802
|
+
var validatePractitionerProfileData = async (profileData) => {
|
|
7803
|
+
try {
|
|
7804
|
+
await profileDataSchema.parseAsync(profileData);
|
|
7805
|
+
} catch (error) {
|
|
7806
|
+
if (error instanceof z21.ZodError) {
|
|
7807
|
+
const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
7808
|
+
throw new Error(
|
|
7809
|
+
`Practitioner profile validation failed: ${errorMessages}`
|
|
7810
|
+
);
|
|
7811
|
+
}
|
|
7812
|
+
throw error;
|
|
7813
|
+
}
|
|
7814
|
+
};
|
|
7815
|
+
|
|
7695
7816
|
// src/services/auth.service.ts
|
|
7696
7817
|
var AuthService = class extends BaseService {
|
|
7697
7818
|
constructor(db, auth, app, userService) {
|
|
@@ -7699,10 +7820,7 @@ var AuthService = class extends BaseService {
|
|
|
7699
7820
|
this.googleProvider = new GoogleAuthProvider();
|
|
7700
7821
|
this.facebookProvider = new FacebookAuthProvider();
|
|
7701
7822
|
this.appleProvider = new OAuthProvider("apple.com");
|
|
7702
|
-
|
|
7703
|
-
userService = new UserService(db, auth, app);
|
|
7704
|
-
}
|
|
7705
|
-
this.userService = userService;
|
|
7823
|
+
this.userService = userService || new UserService(db, auth, app);
|
|
7706
7824
|
}
|
|
7707
7825
|
/**
|
|
7708
7826
|
* Registruje novog korisnika sa email-om i lozinkom
|
|
@@ -7751,7 +7869,7 @@ var AuthService = class extends BaseService {
|
|
|
7751
7869
|
});
|
|
7752
7870
|
} catch (firebaseError) {
|
|
7753
7871
|
console.error("[AUTH] Firebase user creation failed:", firebaseError);
|
|
7754
|
-
throw firebaseError;
|
|
7872
|
+
throw handleFirebaseError(firebaseError);
|
|
7755
7873
|
}
|
|
7756
7874
|
console.log("[AUTH] Creating user with CLINIC_ADMIN role");
|
|
7757
7875
|
let user;
|
|
@@ -8005,7 +8123,7 @@ var AuthService = class extends BaseService {
|
|
|
8005
8123
|
clinicAdmin: adminProfile
|
|
8006
8124
|
};
|
|
8007
8125
|
} catch (error) {
|
|
8008
|
-
if (error instanceof
|
|
8126
|
+
if (error instanceof z22.ZodError) {
|
|
8009
8127
|
console.error(
|
|
8010
8128
|
"[AUTH] Zod validation error in signUpClinicAdmin:",
|
|
8011
8129
|
JSON.stringify(error.errors, null, 2)
|
|
@@ -8180,7 +8298,7 @@ var AuthService = class extends BaseService {
|
|
|
8180
8298
|
email
|
|
8181
8299
|
);
|
|
8182
8300
|
} catch (error) {
|
|
8183
|
-
if (error instanceof
|
|
8301
|
+
if (error instanceof z22.ZodError) {
|
|
8184
8302
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
8185
8303
|
}
|
|
8186
8304
|
const firebaseError = error;
|
|
@@ -8303,7 +8421,7 @@ var AuthService = class extends BaseService {
|
|
|
8303
8421
|
await emailSchema.parseAsync(email);
|
|
8304
8422
|
await sendPasswordResetEmail(this.auth, email);
|
|
8305
8423
|
} catch (error) {
|
|
8306
|
-
if (error instanceof
|
|
8424
|
+
if (error instanceof z22.ZodError) {
|
|
8307
8425
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
8308
8426
|
}
|
|
8309
8427
|
const firebaseError = error;
|
|
@@ -8342,7 +8460,7 @@ var AuthService = class extends BaseService {
|
|
|
8342
8460
|
await passwordSchema.parseAsync(newPassword);
|
|
8343
8461
|
await confirmPasswordReset(this.auth, oobCode, newPassword);
|
|
8344
8462
|
} catch (error) {
|
|
8345
|
-
if (error instanceof
|
|
8463
|
+
if (error instanceof z22.ZodError) {
|
|
8346
8464
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
8347
8465
|
}
|
|
8348
8466
|
const firebaseError = error;
|
|
@@ -8357,31 +8475,21 @@ var AuthService = class extends BaseService {
|
|
|
8357
8475
|
}
|
|
8358
8476
|
}
|
|
8359
8477
|
/**
|
|
8360
|
-
* Registers a new practitioner user with email and password
|
|
8361
|
-
*
|
|
8478
|
+
* Registers a new practitioner user with email and password (ATOMIC VERSION)
|
|
8479
|
+
* Uses Firestore transactions to ensure atomicity and proper rollback on failures
|
|
8362
8480
|
*
|
|
8363
8481
|
* @param data - Practitioner signup data containing either new profile details or token for claiming draft profile
|
|
8364
8482
|
* @returns Object containing the created user and practitioner profile
|
|
8365
8483
|
*/
|
|
8366
8484
|
async signUpPractitioner(data) {
|
|
8367
|
-
|
|
8485
|
+
let firebaseUser = null;
|
|
8368
8486
|
try {
|
|
8369
|
-
console.log("[AUTH] Starting practitioner signup process", {
|
|
8487
|
+
console.log("[AUTH] Starting atomic practitioner signup process", {
|
|
8370
8488
|
email: data.email,
|
|
8371
8489
|
hasToken: !!data.token
|
|
8372
8490
|
});
|
|
8373
|
-
|
|
8374
|
-
await practitionerSignupSchema.parseAsync(data);
|
|
8375
|
-
console.log("[AUTH] Practitioner signup data validation passed");
|
|
8376
|
-
} catch (validationError) {
|
|
8377
|
-
console.error(
|
|
8378
|
-
"[AUTH] Validation error in signUpPractitioner:",
|
|
8379
|
-
validationError
|
|
8380
|
-
);
|
|
8381
|
-
throw validationError;
|
|
8382
|
-
}
|
|
8491
|
+
await this.validateSignupData(data);
|
|
8383
8492
|
console.log("[AUTH] Creating Firebase user");
|
|
8384
|
-
let firebaseUser;
|
|
8385
8493
|
try {
|
|
8386
8494
|
const result = await createUserWithEmailAndPassword(
|
|
8387
8495
|
this.auth,
|
|
@@ -8394,136 +8502,110 @@ var AuthService = class extends BaseService {
|
|
|
8394
8502
|
});
|
|
8395
8503
|
} catch (firebaseError) {
|
|
8396
8504
|
console.error("[AUTH] Firebase user creation failed:", firebaseError);
|
|
8397
|
-
throw firebaseError;
|
|
8505
|
+
throw handleFirebaseError(firebaseError);
|
|
8398
8506
|
}
|
|
8399
|
-
console.log("[AUTH]
|
|
8400
|
-
|
|
8401
|
-
try {
|
|
8402
|
-
user = await this.userService.createUser(
|
|
8403
|
-
firebaseUser,
|
|
8404
|
-
["practitioner" /* PRACTITIONER */],
|
|
8405
|
-
{
|
|
8406
|
-
skipProfileCreation: true
|
|
8407
|
-
// We'll create the profile separately
|
|
8408
|
-
}
|
|
8409
|
-
);
|
|
8410
|
-
console.log("[AUTH] User with PRACTITIONER role created successfully", {
|
|
8411
|
-
userId: user.uid
|
|
8412
|
-
});
|
|
8413
|
-
} catch (userCreationError) {
|
|
8414
|
-
console.error("[AUTH] User creation failed:", userCreationError);
|
|
8415
|
-
throw userCreationError;
|
|
8416
|
-
}
|
|
8417
|
-
console.log("[AUTH] Initializing practitioner service");
|
|
8418
|
-
const practitionerService = new PractitionerService(
|
|
8507
|
+
console.log("[AUTH] Starting Firestore transaction");
|
|
8508
|
+
const transactionResult = await runTransaction(
|
|
8419
8509
|
this.db,
|
|
8420
|
-
|
|
8421
|
-
this.app
|
|
8422
|
-
);
|
|
8423
|
-
let practitioner = null;
|
|
8424
|
-
if (data.token) {
|
|
8425
|
-
console.log("[AUTH] Token provided, attempting to claim draft profile");
|
|
8426
|
-
try {
|
|
8427
|
-
practitioner = await practitionerService.validateTokenAndClaimProfile(
|
|
8428
|
-
data.token,
|
|
8429
|
-
firebaseUser.uid
|
|
8430
|
-
);
|
|
8431
|
-
if (!practitioner) {
|
|
8432
|
-
throw new Error("Invalid or expired invitation token");
|
|
8433
|
-
}
|
|
8434
|
-
console.log("[AUTH] Successfully claimed draft profile", {
|
|
8435
|
-
practitionerId: practitioner.id
|
|
8436
|
-
});
|
|
8437
|
-
await this.userService.updateUser(firebaseUser.uid, {
|
|
8438
|
-
practitionerProfile: practitioner.id
|
|
8439
|
-
});
|
|
8510
|
+
async (transaction) => {
|
|
8440
8511
|
console.log(
|
|
8441
|
-
"[AUTH]
|
|
8512
|
+
"[AUTH] Transaction started - creating user and practitioner"
|
|
8442
8513
|
);
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
} else {
|
|
8448
|
-
console.log("[AUTH] Creating new practitioner profile");
|
|
8449
|
-
if (!data.profileData) {
|
|
8450
|
-
data.profileData = {};
|
|
8451
|
-
}
|
|
8452
|
-
const basicInfo = {
|
|
8453
|
-
firstName: data.firstName || "",
|
|
8454
|
-
lastName: data.lastName || "",
|
|
8455
|
-
email: data.email,
|
|
8456
|
-
phoneNumber: ((_a = data.profileData.basicInfo) == null ? void 0 : _a.phoneNumber) || "",
|
|
8457
|
-
profileImageUrl: ((_b = data.profileData.basicInfo) == null ? void 0 : _b.profileImageUrl) || "",
|
|
8458
|
-
gender: ((_c = data.profileData.basicInfo) == null ? void 0 : _c.gender) || "other",
|
|
8459
|
-
// Default to "other" if not provided
|
|
8460
|
-
bio: ((_d = data.profileData.basicInfo) == null ? void 0 : _d.bio) || "",
|
|
8461
|
-
title: "Practitioner",
|
|
8462
|
-
// Default title
|
|
8463
|
-
dateOfBirth: /* @__PURE__ */ new Date(),
|
|
8464
|
-
// Default to today
|
|
8465
|
-
languages: ["English"]
|
|
8466
|
-
// Default language
|
|
8467
|
-
};
|
|
8468
|
-
const certification = data.profileData.certification || {
|
|
8469
|
-
level: "aesthetician" /* AESTHETICIAN */,
|
|
8470
|
-
specialties: [],
|
|
8471
|
-
licenseNumber: "Pending",
|
|
8472
|
-
issuingAuthority: "Pending",
|
|
8473
|
-
issueDate: /* @__PURE__ */ new Date(),
|
|
8474
|
-
verificationStatus: "pending"
|
|
8475
|
-
};
|
|
8476
|
-
const createPractitionerData = {
|
|
8477
|
-
userRef: firebaseUser.uid,
|
|
8478
|
-
basicInfo,
|
|
8479
|
-
certification,
|
|
8480
|
-
status: "active" /* ACTIVE */,
|
|
8481
|
-
isActive: true,
|
|
8482
|
-
isVerified: false
|
|
8483
|
-
};
|
|
8484
|
-
try {
|
|
8485
|
-
practitioner = await practitionerService.createPractitioner(
|
|
8486
|
-
createPractitionerData
|
|
8514
|
+
const practitionerService = new PractitionerService(
|
|
8515
|
+
this.db,
|
|
8516
|
+
this.auth,
|
|
8517
|
+
this.app
|
|
8487
8518
|
);
|
|
8488
|
-
console.log("[AUTH]
|
|
8489
|
-
|
|
8490
|
-
|
|
8519
|
+
console.log("[AUTH] Creating user document");
|
|
8520
|
+
const user = await this.userService.createUser(
|
|
8521
|
+
firebaseUser,
|
|
8522
|
+
["practitioner" /* PRACTITIONER */],
|
|
8523
|
+
{ skipProfileCreation: true }
|
|
8524
|
+
);
|
|
8525
|
+
let practitioner;
|
|
8526
|
+
if (data.token) {
|
|
8527
|
+
console.log(
|
|
8528
|
+
"[AUTH] Claiming existing practitioner profile with token"
|
|
8529
|
+
);
|
|
8530
|
+
const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
|
|
8531
|
+
data.token,
|
|
8532
|
+
firebaseUser.uid
|
|
8533
|
+
);
|
|
8534
|
+
if (!claimedPractitioner) {
|
|
8535
|
+
throw new Error("Invalid or expired invitation token");
|
|
8536
|
+
}
|
|
8537
|
+
practitioner = claimedPractitioner;
|
|
8538
|
+
} else {
|
|
8539
|
+
console.log("[AUTH] Creating new practitioner profile");
|
|
8540
|
+
const practitionerData = buildPractitionerData(
|
|
8541
|
+
data,
|
|
8542
|
+
firebaseUser.uid
|
|
8543
|
+
);
|
|
8544
|
+
practitioner = await practitionerService.createPractitioner(
|
|
8545
|
+
practitionerData
|
|
8546
|
+
);
|
|
8547
|
+
}
|
|
8548
|
+
console.log("[AUTH] Linking practitioner to user");
|
|
8491
8549
|
await this.userService.updateUser(firebaseUser.uid, {
|
|
8492
8550
|
practitionerProfile: practitioner.id
|
|
8493
8551
|
});
|
|
8494
|
-
console.log(
|
|
8495
|
-
|
|
8496
|
-
);
|
|
8497
|
-
} catch (createError) {
|
|
8498
|
-
console.error(
|
|
8499
|
-
"[AUTH] Failed to create practitioner profile:",
|
|
8500
|
-
createError
|
|
8501
|
-
);
|
|
8502
|
-
throw createError;
|
|
8552
|
+
console.log("[AUTH] Transaction operations completed successfully");
|
|
8553
|
+
return { user, practitioner };
|
|
8503
8554
|
}
|
|
8504
|
-
|
|
8505
|
-
console.log("[AUTH]
|
|
8506
|
-
userId: user.uid,
|
|
8507
|
-
practitionerId:
|
|
8555
|
+
);
|
|
8556
|
+
console.log("[AUTH] Atomic practitioner signup completed successfully", {
|
|
8557
|
+
userId: transactionResult.user.uid,
|
|
8558
|
+
practitionerId: transactionResult.practitioner.id
|
|
8508
8559
|
});
|
|
8509
|
-
return
|
|
8510
|
-
user,
|
|
8511
|
-
practitioner
|
|
8512
|
-
};
|
|
8560
|
+
return transactionResult;
|
|
8513
8561
|
} catch (error) {
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8562
|
+
console.error(
|
|
8563
|
+
"[AUTH] Atomic signup failed, initiating cleanup...",
|
|
8564
|
+
error
|
|
8565
|
+
);
|
|
8566
|
+
if (firebaseUser) {
|
|
8567
|
+
await cleanupFirebaseUser(firebaseUser);
|
|
8520
8568
|
}
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
|
|
8569
|
+
throw handleSignupError(error);
|
|
8570
|
+
}
|
|
8571
|
+
}
|
|
8572
|
+
/**
|
|
8573
|
+
* Pre-validate all signup data before any mutations
|
|
8574
|
+
* Prevents partial creation by catching issues early
|
|
8575
|
+
*/
|
|
8576
|
+
async validateSignupData(data) {
|
|
8577
|
+
console.log("[AUTH] Pre-validating signup data");
|
|
8578
|
+
try {
|
|
8579
|
+
await practitionerSignupSchema.parseAsync(data);
|
|
8580
|
+
console.log("[AUTH] Schema validation passed");
|
|
8581
|
+
const emailExists = await checkEmailExists(this.auth, data.email);
|
|
8582
|
+
if (emailExists) {
|
|
8583
|
+
console.log("[AUTH] Email already exists:", data.email);
|
|
8524
8584
|
throw AUTH_ERRORS.EMAIL_ALREADY_EXISTS;
|
|
8525
8585
|
}
|
|
8526
|
-
console.
|
|
8586
|
+
console.log("[AUTH] Email availability confirmed");
|
|
8587
|
+
if (data.token) {
|
|
8588
|
+
const practitionerService = new PractitionerService(
|
|
8589
|
+
this.db,
|
|
8590
|
+
this.auth,
|
|
8591
|
+
this.app
|
|
8592
|
+
);
|
|
8593
|
+
const isValidToken = await practitionerService.validateToken(
|
|
8594
|
+
data.token
|
|
8595
|
+
);
|
|
8596
|
+
if (!isValidToken) {
|
|
8597
|
+
console.log("[AUTH] Invalid token provided:", data.token);
|
|
8598
|
+
throw new Error("Invalid or expired invitation token");
|
|
8599
|
+
}
|
|
8600
|
+
console.log("[AUTH] Token validation passed");
|
|
8601
|
+
}
|
|
8602
|
+
if (data.profileData) {
|
|
8603
|
+
await validatePractitionerProfileData(data.profileData);
|
|
8604
|
+
console.log("[AUTH] Profile data validation passed");
|
|
8605
|
+
}
|
|
8606
|
+
console.log("[AUTH] All pre-validation checks passed");
|
|
8607
|
+
} catch (error) {
|
|
8608
|
+
console.error("[AUTH] Pre-validation failed:", error);
|
|
8527
8609
|
throw error;
|
|
8528
8610
|
}
|
|
8529
8611
|
}
|
|
@@ -8595,8 +8677,8 @@ import {
|
|
|
8595
8677
|
query as query15,
|
|
8596
8678
|
where as where15,
|
|
8597
8679
|
updateDoc as updateDoc15,
|
|
8598
|
-
deleteDoc as
|
|
8599
|
-
orderBy as
|
|
8680
|
+
deleteDoc as deleteDoc9,
|
|
8681
|
+
orderBy as orderBy5,
|
|
8600
8682
|
Timestamp as Timestamp16,
|
|
8601
8683
|
addDoc as addDoc2,
|
|
8602
8684
|
writeBatch as writeBatch5
|
|
@@ -8680,7 +8762,7 @@ var NotificationService = class extends BaseService {
|
|
|
8680
8762
|
const q = query15(
|
|
8681
8763
|
collection15(this.db, NOTIFICATIONS_COLLECTION),
|
|
8682
8764
|
where15("userId", "==", userId),
|
|
8683
|
-
|
|
8765
|
+
orderBy5("notificationTime", "desc")
|
|
8684
8766
|
);
|
|
8685
8767
|
const querySnapshot = await getDocs15(q);
|
|
8686
8768
|
return querySnapshot.docs.map((doc36) => ({
|
|
@@ -8696,7 +8778,7 @@ var NotificationService = class extends BaseService {
|
|
|
8696
8778
|
collection15(this.db, NOTIFICATIONS_COLLECTION),
|
|
8697
8779
|
where15("userId", "==", userId),
|
|
8698
8780
|
where15("isRead", "==", false),
|
|
8699
|
-
|
|
8781
|
+
orderBy5("notificationTime", "desc")
|
|
8700
8782
|
);
|
|
8701
8783
|
const querySnapshot = await getDocs15(q);
|
|
8702
8784
|
return querySnapshot.docs.map((doc36) => ({
|
|
@@ -8760,7 +8842,7 @@ var NotificationService = class extends BaseService {
|
|
|
8760
8842
|
NOTIFICATIONS_COLLECTION,
|
|
8761
8843
|
notificationId
|
|
8762
8844
|
);
|
|
8763
|
-
await
|
|
8845
|
+
await deleteDoc9(notificationRef);
|
|
8764
8846
|
}
|
|
8765
8847
|
/**
|
|
8766
8848
|
* Dohvata notifikacije po tipu
|
|
@@ -8770,7 +8852,7 @@ var NotificationService = class extends BaseService {
|
|
|
8770
8852
|
collection15(this.db, NOTIFICATIONS_COLLECTION),
|
|
8771
8853
|
where15("userId", "==", userId),
|
|
8772
8854
|
where15("notificationType", "==", type),
|
|
8773
|
-
|
|
8855
|
+
orderBy5("notificationTime", "desc")
|
|
8774
8856
|
);
|
|
8775
8857
|
const querySnapshot = await getDocs15(q);
|
|
8776
8858
|
return querySnapshot.docs.map((doc36) => ({
|
|
@@ -8785,7 +8867,7 @@ var NotificationService = class extends BaseService {
|
|
|
8785
8867
|
const q = query15(
|
|
8786
8868
|
collection15(this.db, NOTIFICATIONS_COLLECTION),
|
|
8787
8869
|
where15("appointmentId", "==", appointmentId),
|
|
8788
|
-
|
|
8870
|
+
orderBy5("notificationTime", "desc")
|
|
8789
8871
|
);
|
|
8790
8872
|
const querySnapshot = await getDocs15(q);
|
|
8791
8873
|
return querySnapshot.docs.map((doc36) => ({
|
|
@@ -8805,74 +8887,74 @@ import {
|
|
|
8805
8887
|
where as where16,
|
|
8806
8888
|
updateDoc as updateDoc16,
|
|
8807
8889
|
setDoc as setDoc14,
|
|
8808
|
-
deleteDoc as
|
|
8809
|
-
serverTimestamp as
|
|
8810
|
-
orderBy as
|
|
8811
|
-
limit as
|
|
8812
|
-
startAfter as
|
|
8890
|
+
deleteDoc as deleteDoc10,
|
|
8891
|
+
serverTimestamp as serverTimestamp13,
|
|
8892
|
+
orderBy as orderBy6,
|
|
8893
|
+
limit as limit9,
|
|
8894
|
+
startAfter as startAfter8
|
|
8813
8895
|
} from "firebase/firestore";
|
|
8814
8896
|
|
|
8815
8897
|
// src/types/procedure/index.ts
|
|
8816
8898
|
var PROCEDURES_COLLECTION = "procedures";
|
|
8817
8899
|
|
|
8818
8900
|
// src/validations/procedure.schema.ts
|
|
8819
|
-
import { z as
|
|
8820
|
-
var createProcedureSchema =
|
|
8821
|
-
name:
|
|
8822
|
-
description:
|
|
8823
|
-
family:
|
|
8824
|
-
categoryId:
|
|
8825
|
-
subcategoryId:
|
|
8826
|
-
technologyId:
|
|
8827
|
-
productId:
|
|
8828
|
-
price:
|
|
8829
|
-
currency:
|
|
8830
|
-
pricingMeasure:
|
|
8831
|
-
duration:
|
|
8901
|
+
import { z as z23 } from "zod";
|
|
8902
|
+
var createProcedureSchema = z23.object({
|
|
8903
|
+
name: z23.string().min(1).max(200),
|
|
8904
|
+
description: z23.string().min(1).max(2e3),
|
|
8905
|
+
family: z23.nativeEnum(ProcedureFamily),
|
|
8906
|
+
categoryId: z23.string().min(1),
|
|
8907
|
+
subcategoryId: z23.string().min(1),
|
|
8908
|
+
technologyId: z23.string().min(1),
|
|
8909
|
+
productId: z23.string().min(1),
|
|
8910
|
+
price: z23.number().min(0),
|
|
8911
|
+
currency: z23.nativeEnum(Currency),
|
|
8912
|
+
pricingMeasure: z23.nativeEnum(PricingMeasure),
|
|
8913
|
+
duration: z23.number().min(1).max(480),
|
|
8832
8914
|
// Max 8 hours
|
|
8833
|
-
practitionerId:
|
|
8834
|
-
clinicBranchId:
|
|
8835
|
-
photos:
|
|
8915
|
+
practitionerId: z23.string().min(1),
|
|
8916
|
+
clinicBranchId: z23.string().min(1),
|
|
8917
|
+
photos: z23.array(mediaResourceSchema).optional()
|
|
8836
8918
|
});
|
|
8837
|
-
var updateProcedureSchema =
|
|
8838
|
-
name:
|
|
8839
|
-
description:
|
|
8840
|
-
price:
|
|
8841
|
-
currency:
|
|
8842
|
-
pricingMeasure:
|
|
8843
|
-
duration:
|
|
8844
|
-
isActive:
|
|
8845
|
-
practitionerId:
|
|
8846
|
-
categoryId:
|
|
8847
|
-
subcategoryId:
|
|
8848
|
-
technologyId:
|
|
8849
|
-
productId:
|
|
8850
|
-
clinicBranchId:
|
|
8851
|
-
photos:
|
|
8919
|
+
var updateProcedureSchema = z23.object({
|
|
8920
|
+
name: z23.string().min(3).max(100).optional(),
|
|
8921
|
+
description: z23.string().min(3).max(1e3).optional(),
|
|
8922
|
+
price: z23.number().min(0).optional(),
|
|
8923
|
+
currency: z23.nativeEnum(Currency).optional(),
|
|
8924
|
+
pricingMeasure: z23.nativeEnum(PricingMeasure).optional(),
|
|
8925
|
+
duration: z23.number().min(0).optional(),
|
|
8926
|
+
isActive: z23.boolean().optional(),
|
|
8927
|
+
practitionerId: z23.string().optional(),
|
|
8928
|
+
categoryId: z23.string().optional(),
|
|
8929
|
+
subcategoryId: z23.string().optional(),
|
|
8930
|
+
technologyId: z23.string().optional(),
|
|
8931
|
+
productId: z23.string().optional(),
|
|
8932
|
+
clinicBranchId: z23.string().optional(),
|
|
8933
|
+
photos: z23.array(mediaResourceSchema).optional()
|
|
8852
8934
|
});
|
|
8853
8935
|
var procedureSchema = createProcedureSchema.extend({
|
|
8854
|
-
id:
|
|
8855
|
-
category:
|
|
8936
|
+
id: z23.string().min(1),
|
|
8937
|
+
category: z23.any(),
|
|
8856
8938
|
// We'll validate the full category object separately
|
|
8857
|
-
subcategory:
|
|
8939
|
+
subcategory: z23.any(),
|
|
8858
8940
|
// We'll validate the full subcategory object separately
|
|
8859
|
-
technology:
|
|
8941
|
+
technology: z23.any(),
|
|
8860
8942
|
// We'll validate the full technology object separately
|
|
8861
|
-
product:
|
|
8943
|
+
product: z23.any(),
|
|
8862
8944
|
// We'll validate the full product object separately
|
|
8863
|
-
blockingConditions:
|
|
8945
|
+
blockingConditions: z23.array(z23.any()),
|
|
8864
8946
|
// We'll validate blocking conditions separately
|
|
8865
|
-
contraindications:
|
|
8947
|
+
contraindications: z23.array(z23.any()),
|
|
8866
8948
|
// We'll validate contraindications separately
|
|
8867
|
-
treatmentBenefits:
|
|
8949
|
+
treatmentBenefits: z23.array(z23.any()),
|
|
8868
8950
|
// We'll validate treatment benefits separately
|
|
8869
|
-
preRequirements:
|
|
8951
|
+
preRequirements: z23.array(z23.any()),
|
|
8870
8952
|
// We'll validate requirements separately
|
|
8871
|
-
postRequirements:
|
|
8953
|
+
postRequirements: z23.array(z23.any()),
|
|
8872
8954
|
// We'll validate requirements separately
|
|
8873
|
-
certificationRequirement:
|
|
8955
|
+
certificationRequirement: z23.any(),
|
|
8874
8956
|
// We'll validate certification requirement separately
|
|
8875
|
-
documentationTemplates:
|
|
8957
|
+
documentationTemplates: z23.array(z23.any()),
|
|
8876
8958
|
// We'll validate documentation templates separately
|
|
8877
8959
|
clinicInfo: clinicInfoSchema,
|
|
8878
8960
|
// Clinic info validation
|
|
@@ -8880,9 +8962,9 @@ var procedureSchema = createProcedureSchema.extend({
|
|
|
8880
8962
|
// Doctor info validation
|
|
8881
8963
|
reviewInfo: procedureReviewInfoSchema,
|
|
8882
8964
|
// Procedure review info validation
|
|
8883
|
-
isActive:
|
|
8884
|
-
createdAt:
|
|
8885
|
-
updatedAt:
|
|
8965
|
+
isActive: z23.boolean(),
|
|
8966
|
+
createdAt: z23.date(),
|
|
8967
|
+
updatedAt: z23.date()
|
|
8886
8968
|
});
|
|
8887
8969
|
|
|
8888
8970
|
// src/services/procedure/procedure.service.ts
|
|
@@ -9054,8 +9136,8 @@ var ProcedureService = class extends BaseService {
|
|
|
9054
9136
|
const procedureRef = doc16(this.db, PROCEDURES_COLLECTION, procedureId);
|
|
9055
9137
|
await setDoc14(procedureRef, {
|
|
9056
9138
|
...newProcedure,
|
|
9057
|
-
createdAt:
|
|
9058
|
-
updatedAt:
|
|
9139
|
+
createdAt: serverTimestamp13(),
|
|
9140
|
+
updatedAt: serverTimestamp13()
|
|
9059
9141
|
});
|
|
9060
9142
|
const savedDoc = await getDoc19(procedureRef);
|
|
9061
9143
|
return savedDoc.data();
|
|
@@ -9243,7 +9325,7 @@ var ProcedureService = class extends BaseService {
|
|
|
9243
9325
|
}
|
|
9244
9326
|
await updateDoc16(procedureRef, {
|
|
9245
9327
|
...updatedProcedureData,
|
|
9246
|
-
updatedAt:
|
|
9328
|
+
updatedAt: serverTimestamp13()
|
|
9247
9329
|
});
|
|
9248
9330
|
const updatedSnapshot = await getDoc19(procedureRef);
|
|
9249
9331
|
return updatedSnapshot.data();
|
|
@@ -9261,7 +9343,7 @@ var ProcedureService = class extends BaseService {
|
|
|
9261
9343
|
}
|
|
9262
9344
|
await updateDoc16(procedureRef, {
|
|
9263
9345
|
isActive: false,
|
|
9264
|
-
updatedAt:
|
|
9346
|
+
updatedAt: serverTimestamp13()
|
|
9265
9347
|
});
|
|
9266
9348
|
}
|
|
9267
9349
|
/**
|
|
@@ -9275,7 +9357,7 @@ var ProcedureService = class extends BaseService {
|
|
|
9275
9357
|
if (!procedureSnapshot.exists()) {
|
|
9276
9358
|
return false;
|
|
9277
9359
|
}
|
|
9278
|
-
await
|
|
9360
|
+
await deleteDoc10(procedureRef);
|
|
9279
9361
|
return true;
|
|
9280
9362
|
}
|
|
9281
9363
|
/**
|
|
@@ -9304,24 +9386,24 @@ var ProcedureService = class extends BaseService {
|
|
|
9304
9386
|
const proceduresCollection = collection16(this.db, PROCEDURES_COLLECTION);
|
|
9305
9387
|
let proceduresQuery = query16(proceduresCollection);
|
|
9306
9388
|
if (pagination && pagination > 0) {
|
|
9307
|
-
const { limit:
|
|
9389
|
+
const { limit: limit16, startAfter: startAfter14 } = await import("firebase/firestore");
|
|
9308
9390
|
if (lastDoc) {
|
|
9309
9391
|
proceduresQuery = query16(
|
|
9310
9392
|
proceduresCollection,
|
|
9311
|
-
|
|
9393
|
+
orderBy6("name"),
|
|
9312
9394
|
// Use imported orderBy
|
|
9313
|
-
|
|
9314
|
-
|
|
9395
|
+
startAfter14(lastDoc),
|
|
9396
|
+
limit16(pagination)
|
|
9315
9397
|
);
|
|
9316
9398
|
} else {
|
|
9317
9399
|
proceduresQuery = query16(
|
|
9318
9400
|
proceduresCollection,
|
|
9319
|
-
|
|
9320
|
-
|
|
9401
|
+
orderBy6("name"),
|
|
9402
|
+
limit16(pagination)
|
|
9321
9403
|
);
|
|
9322
9404
|
}
|
|
9323
9405
|
} else {
|
|
9324
|
-
proceduresQuery = query16(proceduresCollection,
|
|
9406
|
+
proceduresQuery = query16(proceduresCollection, orderBy6("name"));
|
|
9325
9407
|
}
|
|
9326
9408
|
const proceduresSnapshot = await getDocs16(proceduresQuery);
|
|
9327
9409
|
const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
|
|
@@ -9379,12 +9461,12 @@ var ProcedureService = class extends BaseService {
|
|
|
9379
9461
|
if (filters.procedureFamily) {
|
|
9380
9462
|
constraints.push(where16("family", "==", filters.procedureFamily));
|
|
9381
9463
|
}
|
|
9382
|
-
constraints.push(
|
|
9464
|
+
constraints.push(orderBy6("clinicInfo.location.geohash"));
|
|
9383
9465
|
if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
|
|
9384
|
-
constraints.push(
|
|
9385
|
-
constraints.push(
|
|
9466
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
9467
|
+
constraints.push(limit9(filters.pagination));
|
|
9386
9468
|
} else if (filters.pagination && filters.pagination > 0) {
|
|
9387
|
-
constraints.push(
|
|
9469
|
+
constraints.push(limit9(filters.pagination));
|
|
9388
9470
|
}
|
|
9389
9471
|
let proceduresResult = [];
|
|
9390
9472
|
let lastVisibleDoc = null;
|
|
@@ -9670,8 +9752,8 @@ var ProcedureService = class extends BaseService {
|
|
|
9670
9752
|
const procedureRef = doc16(this.db, PROCEDURES_COLLECTION, procedureId);
|
|
9671
9753
|
await setDoc14(procedureRef, {
|
|
9672
9754
|
...newProcedure,
|
|
9673
|
-
createdAt:
|
|
9674
|
-
updatedAt:
|
|
9755
|
+
createdAt: serverTimestamp13(),
|
|
9756
|
+
updatedAt: serverTimestamp13()
|
|
9675
9757
|
});
|
|
9676
9758
|
const savedDoc = await getDoc19(procedureRef);
|
|
9677
9759
|
return savedDoc.data();
|
|
@@ -9688,11 +9770,11 @@ import {
|
|
|
9688
9770
|
where as where17,
|
|
9689
9771
|
updateDoc as updateDoc17,
|
|
9690
9772
|
setDoc as setDoc15,
|
|
9691
|
-
deleteDoc as
|
|
9773
|
+
deleteDoc as deleteDoc11,
|
|
9692
9774
|
Timestamp as Timestamp18,
|
|
9693
|
-
serverTimestamp as
|
|
9694
|
-
orderBy as
|
|
9695
|
-
limit as
|
|
9775
|
+
serverTimestamp as serverTimestamp14,
|
|
9776
|
+
orderBy as orderBy7,
|
|
9777
|
+
limit as limit10
|
|
9696
9778
|
} from "firebase/firestore";
|
|
9697
9779
|
var PractitionerInviteService = class extends BaseService {
|
|
9698
9780
|
constructor(db, auth, app) {
|
|
@@ -9787,7 +9869,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9787
9869
|
try {
|
|
9788
9870
|
const constraints = [
|
|
9789
9871
|
where17("practitionerId", "==", practitionerId),
|
|
9790
|
-
|
|
9872
|
+
orderBy7("createdAt", "desc")
|
|
9791
9873
|
];
|
|
9792
9874
|
if (statusFilter && statusFilter.length > 0) {
|
|
9793
9875
|
constraints.push(where17("status", "in", statusFilter));
|
|
@@ -9816,7 +9898,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9816
9898
|
try {
|
|
9817
9899
|
const constraints = [
|
|
9818
9900
|
where17("clinicId", "==", clinicId),
|
|
9819
|
-
|
|
9901
|
+
orderBy7("createdAt", "desc")
|
|
9820
9902
|
];
|
|
9821
9903
|
if (statusFilter && statusFilter.length > 0) {
|
|
9822
9904
|
constraints.push(where17("status", "in", statusFilter));
|
|
@@ -9852,7 +9934,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9852
9934
|
const updateData = {
|
|
9853
9935
|
status: "accepted" /* ACCEPTED */,
|
|
9854
9936
|
acceptedAt: Timestamp18.now(),
|
|
9855
|
-
updatedAt:
|
|
9937
|
+
updatedAt: serverTimestamp14()
|
|
9856
9938
|
};
|
|
9857
9939
|
const docRef = doc17(this.db, PRACTITIONER_INVITES_COLLECTION, inviteId);
|
|
9858
9940
|
await updateDoc17(docRef, updateData);
|
|
@@ -9884,7 +9966,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9884
9966
|
status: "rejected" /* REJECTED */,
|
|
9885
9967
|
rejectionReason: rejectionReason || null,
|
|
9886
9968
|
rejectedAt: Timestamp18.now(),
|
|
9887
|
-
updatedAt:
|
|
9969
|
+
updatedAt: serverTimestamp14()
|
|
9888
9970
|
};
|
|
9889
9971
|
const docRef = doc17(this.db, PRACTITIONER_INVITES_COLLECTION, inviteId);
|
|
9890
9972
|
await updateDoc17(docRef, updateData);
|
|
@@ -9916,7 +9998,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9916
9998
|
status: "cancelled" /* CANCELLED */,
|
|
9917
9999
|
cancelReason: cancelReason || null,
|
|
9918
10000
|
cancelledAt: Timestamp18.now(),
|
|
9919
|
-
updatedAt:
|
|
10001
|
+
updatedAt: serverTimestamp14()
|
|
9920
10002
|
};
|
|
9921
10003
|
const docRef = doc17(this.db, PRACTITIONER_INVITES_COLLECTION, inviteId);
|
|
9922
10004
|
await updateDoc17(docRef, updateData);
|
|
@@ -9972,9 +10054,9 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
9972
10054
|
}
|
|
9973
10055
|
const orderField = filters.orderBy || "createdAt";
|
|
9974
10056
|
const orderDirection = filters.orderDirection || "desc";
|
|
9975
|
-
constraints.push(
|
|
10057
|
+
constraints.push(orderBy7(orderField, orderDirection));
|
|
9976
10058
|
if (filters.limit) {
|
|
9977
|
-
constraints.push(
|
|
10059
|
+
constraints.push(limit10(filters.limit));
|
|
9978
10060
|
}
|
|
9979
10061
|
const q = query17(
|
|
9980
10062
|
collection17(this.db, PRACTITIONER_INVITES_COLLECTION),
|
|
@@ -10010,7 +10092,7 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
10010
10092
|
async deleteInvite(inviteId) {
|
|
10011
10093
|
try {
|
|
10012
10094
|
const docRef = doc17(this.db, PRACTITIONER_INVITES_COLLECTION, inviteId);
|
|
10013
|
-
await
|
|
10095
|
+
await deleteDoc11(docRef);
|
|
10014
10096
|
} catch (error) {
|
|
10015
10097
|
console.error(
|
|
10016
10098
|
"[PractitionerInviteService] Error deleting invite:",
|
|
@@ -10065,8 +10147,8 @@ var PractitionerInviteService = class extends BaseService {
|
|
|
10065
10147
|
collection17(this.db, PRACTITIONER_INVITES_COLLECTION),
|
|
10066
10148
|
where17("practitionerId", "==", practitionerId),
|
|
10067
10149
|
where17("clinicId", "==", clinicId),
|
|
10068
|
-
|
|
10069
|
-
|
|
10150
|
+
orderBy7("createdAt", "desc"),
|
|
10151
|
+
limit10(1)
|
|
10070
10152
|
);
|
|
10071
10153
|
const querySnapshot = await getDocs17(q);
|
|
10072
10154
|
if (querySnapshot.empty) {
|
|
@@ -10091,12 +10173,12 @@ import {
|
|
|
10091
10173
|
getDocs as getDocs18,
|
|
10092
10174
|
setDoc as setDoc16,
|
|
10093
10175
|
updateDoc as updateDoc18,
|
|
10094
|
-
deleteDoc as
|
|
10176
|
+
deleteDoc as deleteDoc12,
|
|
10095
10177
|
query as query18,
|
|
10096
10178
|
where as where18,
|
|
10097
|
-
orderBy as
|
|
10098
|
-
limit as
|
|
10099
|
-
startAfter as
|
|
10179
|
+
orderBy as orderBy8,
|
|
10180
|
+
limit as limit11,
|
|
10181
|
+
startAfter as startAfter9
|
|
10100
10182
|
} from "firebase/firestore";
|
|
10101
10183
|
var DocumentationTemplateService = class extends BaseService {
|
|
10102
10184
|
constructor() {
|
|
@@ -10249,7 +10331,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10249
10331
|
this.db,
|
|
10250
10332
|
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions`
|
|
10251
10333
|
);
|
|
10252
|
-
const q = query18(versionsCollectionRef,
|
|
10334
|
+
const q = query18(versionsCollectionRef, orderBy8("version", "desc"));
|
|
10253
10335
|
const querySnapshot = await getDocs18(q);
|
|
10254
10336
|
const versions = [];
|
|
10255
10337
|
querySnapshot.forEach((doc36) => {
|
|
@@ -10263,7 +10345,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10263
10345
|
*/
|
|
10264
10346
|
async deleteTemplate(templateId) {
|
|
10265
10347
|
const docRef = doc18(this.collectionRef, templateId);
|
|
10266
|
-
await
|
|
10348
|
+
await deleteDoc12(docRef);
|
|
10267
10349
|
}
|
|
10268
10350
|
/**
|
|
10269
10351
|
* Get all active templates
|
|
@@ -10275,11 +10357,11 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10275
10357
|
let q = query18(
|
|
10276
10358
|
this.collectionRef,
|
|
10277
10359
|
where18("isActive", "==", true),
|
|
10278
|
-
|
|
10279
|
-
|
|
10360
|
+
orderBy8("updatedAt", "desc"),
|
|
10361
|
+
limit11(pageSize)
|
|
10280
10362
|
);
|
|
10281
10363
|
if (lastDoc) {
|
|
10282
|
-
q = query18(q,
|
|
10364
|
+
q = query18(q, startAfter9(lastDoc));
|
|
10283
10365
|
}
|
|
10284
10366
|
const querySnapshot = await getDocs18(q);
|
|
10285
10367
|
const templates = [];
|
|
@@ -10305,11 +10387,11 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10305
10387
|
this.collectionRef,
|
|
10306
10388
|
where18("isActive", "==", true),
|
|
10307
10389
|
where18("tags", "array-contains-any", tags),
|
|
10308
|
-
|
|
10309
|
-
|
|
10390
|
+
orderBy8("updatedAt", "desc"),
|
|
10391
|
+
limit11(pageSize)
|
|
10310
10392
|
);
|
|
10311
10393
|
if (lastDoc) {
|
|
10312
|
-
q = query18(q,
|
|
10394
|
+
q = query18(q, startAfter9(lastDoc));
|
|
10313
10395
|
}
|
|
10314
10396
|
const querySnapshot = await getDocs18(q);
|
|
10315
10397
|
const templates = [];
|
|
@@ -10334,11 +10416,11 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10334
10416
|
let q = query18(
|
|
10335
10417
|
this.collectionRef,
|
|
10336
10418
|
where18("createdBy", "==", userId),
|
|
10337
|
-
|
|
10338
|
-
|
|
10419
|
+
orderBy8("updatedAt", "desc"),
|
|
10420
|
+
limit11(pageSize)
|
|
10339
10421
|
);
|
|
10340
10422
|
if (lastDoc) {
|
|
10341
|
-
q = query18(q,
|
|
10423
|
+
q = query18(q, startAfter9(lastDoc));
|
|
10342
10424
|
}
|
|
10343
10425
|
const querySnapshot = await getDocs18(q);
|
|
10344
10426
|
const templates = [];
|
|
@@ -10361,7 +10443,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
10361
10443
|
let q = query18(
|
|
10362
10444
|
this.collectionRef,
|
|
10363
10445
|
where18("isActive", "==", true),
|
|
10364
|
-
|
|
10446
|
+
orderBy8("updatedAt", "desc")
|
|
10365
10447
|
);
|
|
10366
10448
|
if ((options == null ? void 0 : options.isUserForm) !== void 0) {
|
|
10367
10449
|
q = query18(q, where18("isUserForm", "==", options.isUserForm));
|
|
@@ -10387,9 +10469,9 @@ import {
|
|
|
10387
10469
|
setDoc as setDoc17,
|
|
10388
10470
|
updateDoc as updateDoc19,
|
|
10389
10471
|
query as query19,
|
|
10390
|
-
orderBy as
|
|
10391
|
-
limit as
|
|
10392
|
-
startAfter as
|
|
10472
|
+
orderBy as orderBy9,
|
|
10473
|
+
limit as limit12,
|
|
10474
|
+
startAfter as startAfter10
|
|
10393
10475
|
} from "firebase/firestore";
|
|
10394
10476
|
var FilledDocumentService = class extends BaseService {
|
|
10395
10477
|
constructor(...args) {
|
|
@@ -10541,11 +10623,11 @@ var FilledDocumentService = class extends BaseService {
|
|
|
10541
10623
|
);
|
|
10542
10624
|
let q = query19(
|
|
10543
10625
|
subcollectionRef,
|
|
10544
|
-
|
|
10545
|
-
|
|
10626
|
+
orderBy9("updatedAt", "desc"),
|
|
10627
|
+
limit12(pageSize)
|
|
10546
10628
|
);
|
|
10547
10629
|
if (lastDoc) {
|
|
10548
|
-
q = query19(q,
|
|
10630
|
+
q = query19(q, startAfter10(lastDoc));
|
|
10549
10631
|
}
|
|
10550
10632
|
return this.executeQuery(q);
|
|
10551
10633
|
}
|
|
@@ -10565,11 +10647,11 @@ var FilledDocumentService = class extends BaseService {
|
|
|
10565
10647
|
);
|
|
10566
10648
|
let q = query19(
|
|
10567
10649
|
subcollectionRef,
|
|
10568
|
-
|
|
10569
|
-
|
|
10650
|
+
orderBy9("updatedAt", "desc"),
|
|
10651
|
+
limit12(pageSize)
|
|
10570
10652
|
);
|
|
10571
10653
|
if (lastDoc) {
|
|
10572
|
-
q = query19(q,
|
|
10654
|
+
q = query19(q, startAfter10(lastDoc));
|
|
10573
10655
|
}
|
|
10574
10656
|
return this.executeQuery(q);
|
|
10575
10657
|
}
|
|
@@ -10739,7 +10821,7 @@ var FilledDocumentService = class extends BaseService {
|
|
|
10739
10821
|
};
|
|
10740
10822
|
|
|
10741
10823
|
// src/services/calendar/calendar-refactored.service.ts
|
|
10742
|
-
import { Timestamp as Timestamp28, serverTimestamp as
|
|
10824
|
+
import { Timestamp as Timestamp28, serverTimestamp as serverTimestamp21 } from "firebase/firestore";
|
|
10743
10825
|
|
|
10744
10826
|
// src/types/calendar/synced-calendar.types.ts
|
|
10745
10827
|
var SyncedCalendarProvider = /* @__PURE__ */ ((SyncedCalendarProvider3) => {
|
|
@@ -10763,42 +10845,42 @@ import {
|
|
|
10763
10845
|
} from "firebase/firestore";
|
|
10764
10846
|
|
|
10765
10847
|
// src/validations/calendar.schema.ts
|
|
10766
|
-
import { z as
|
|
10848
|
+
import { z as z25 } from "zod";
|
|
10767
10849
|
import { Timestamp as Timestamp21 } from "firebase/firestore";
|
|
10768
10850
|
|
|
10769
10851
|
// src/validations/profile-info.schema.ts
|
|
10770
|
-
import { z as
|
|
10852
|
+
import { z as z24 } from "zod";
|
|
10771
10853
|
import { Timestamp as Timestamp20 } from "firebase/firestore";
|
|
10772
|
-
var clinicInfoSchema2 =
|
|
10773
|
-
id:
|
|
10774
|
-
featuredPhoto:
|
|
10775
|
-
name:
|
|
10776
|
-
description:
|
|
10854
|
+
var clinicInfoSchema2 = z24.object({
|
|
10855
|
+
id: z24.string(),
|
|
10856
|
+
featuredPhoto: z24.string(),
|
|
10857
|
+
name: z24.string(),
|
|
10858
|
+
description: z24.string(),
|
|
10777
10859
|
location: clinicLocationSchema,
|
|
10778
10860
|
contactInfo: clinicContactInfoSchema
|
|
10779
10861
|
});
|
|
10780
|
-
var practitionerProfileInfoSchema =
|
|
10781
|
-
id:
|
|
10782
|
-
practitionerPhoto:
|
|
10783
|
-
name:
|
|
10784
|
-
email:
|
|
10785
|
-
phone:
|
|
10862
|
+
var practitionerProfileInfoSchema = z24.object({
|
|
10863
|
+
id: z24.string(),
|
|
10864
|
+
practitionerPhoto: z24.string().nullable(),
|
|
10865
|
+
name: z24.string(),
|
|
10866
|
+
email: z24.string().email(),
|
|
10867
|
+
phone: z24.string().nullable(),
|
|
10786
10868
|
certification: practitionerCertificationSchema
|
|
10787
10869
|
});
|
|
10788
|
-
var patientProfileInfoSchema =
|
|
10789
|
-
id:
|
|
10790
|
-
fullName:
|
|
10791
|
-
email:
|
|
10792
|
-
phone:
|
|
10793
|
-
dateOfBirth:
|
|
10794
|
-
gender:
|
|
10870
|
+
var patientProfileInfoSchema = z24.object({
|
|
10871
|
+
id: z24.string(),
|
|
10872
|
+
fullName: z24.string(),
|
|
10873
|
+
email: z24.string().email(),
|
|
10874
|
+
phone: z24.string().nullable(),
|
|
10875
|
+
dateOfBirth: z24.instanceof(Timestamp20),
|
|
10876
|
+
gender: z24.nativeEnum(Gender)
|
|
10795
10877
|
});
|
|
10796
10878
|
|
|
10797
10879
|
// src/validations/calendar.schema.ts
|
|
10798
10880
|
var MIN_APPOINTMENT_DURATION = 15;
|
|
10799
|
-
var calendarEventTimeSchema =
|
|
10800
|
-
start:
|
|
10801
|
-
end:
|
|
10881
|
+
var calendarEventTimeSchema = z25.object({
|
|
10882
|
+
start: z25.instanceof(Date).or(z25.instanceof(Timestamp21)),
|
|
10883
|
+
end: z25.instanceof(Date).or(z25.instanceof(Timestamp21))
|
|
10802
10884
|
}).refine(
|
|
10803
10885
|
(data) => {
|
|
10804
10886
|
const startDate = data.start instanceof Timestamp21 ? data.start.toDate() : data.start;
|
|
@@ -10819,46 +10901,46 @@ var calendarEventTimeSchema = z23.object({
|
|
|
10819
10901
|
path: ["start"]
|
|
10820
10902
|
}
|
|
10821
10903
|
);
|
|
10822
|
-
var timeSlotSchema2 =
|
|
10823
|
-
start:
|
|
10824
|
-
end:
|
|
10825
|
-
isAvailable:
|
|
10904
|
+
var timeSlotSchema2 = z25.object({
|
|
10905
|
+
start: z25.date(),
|
|
10906
|
+
end: z25.date(),
|
|
10907
|
+
isAvailable: z25.boolean()
|
|
10826
10908
|
}).refine((data) => data.start < data.end, {
|
|
10827
10909
|
message: "End time must be after start time",
|
|
10828
10910
|
path: ["end"]
|
|
10829
10911
|
});
|
|
10830
|
-
var syncedCalendarEventSchema =
|
|
10831
|
-
eventId:
|
|
10832
|
-
syncedCalendarProvider:
|
|
10833
|
-
syncedAt:
|
|
10912
|
+
var syncedCalendarEventSchema = z25.object({
|
|
10913
|
+
eventId: z25.string(),
|
|
10914
|
+
syncedCalendarProvider: z25.nativeEnum(SyncedCalendarProvider),
|
|
10915
|
+
syncedAt: z25.instanceof(Date).or(z25.instanceof(Timestamp21))
|
|
10834
10916
|
});
|
|
10835
|
-
var procedureInfoSchema =
|
|
10836
|
-
name:
|
|
10837
|
-
description:
|
|
10838
|
-
duration:
|
|
10839
|
-
price:
|
|
10840
|
-
currency:
|
|
10917
|
+
var procedureInfoSchema = z25.object({
|
|
10918
|
+
name: z25.string(),
|
|
10919
|
+
description: z25.string(),
|
|
10920
|
+
duration: z25.number().min(MIN_APPOINTMENT_DURATION),
|
|
10921
|
+
price: z25.number().min(0),
|
|
10922
|
+
currency: z25.nativeEnum(Currency)
|
|
10841
10923
|
});
|
|
10842
|
-
var procedureCategorizationSchema =
|
|
10843
|
-
procedureFamily:
|
|
10924
|
+
var procedureCategorizationSchema = z25.object({
|
|
10925
|
+
procedureFamily: z25.string(),
|
|
10844
10926
|
// Replace with proper enum when available
|
|
10845
|
-
procedureCategory:
|
|
10927
|
+
procedureCategory: z25.string(),
|
|
10846
10928
|
// Replace with proper enum when available
|
|
10847
|
-
procedureSubcategory:
|
|
10929
|
+
procedureSubcategory: z25.string(),
|
|
10848
10930
|
// Replace with proper enum when available
|
|
10849
|
-
procedureTechnology:
|
|
10931
|
+
procedureTechnology: z25.string(),
|
|
10850
10932
|
// Replace with proper enum when available
|
|
10851
|
-
procedureProduct:
|
|
10933
|
+
procedureProduct: z25.string()
|
|
10852
10934
|
// Replace with proper enum when available
|
|
10853
10935
|
});
|
|
10854
|
-
var createAppointmentSchema2 =
|
|
10855
|
-
clinicId:
|
|
10856
|
-
doctorId:
|
|
10857
|
-
patientId:
|
|
10858
|
-
procedureId:
|
|
10936
|
+
var createAppointmentSchema2 = z25.object({
|
|
10937
|
+
clinicId: z25.string().min(1, "Clinic ID is required"),
|
|
10938
|
+
doctorId: z25.string().min(1, "Doctor ID is required"),
|
|
10939
|
+
patientId: z25.string().min(1, "Patient ID is required"),
|
|
10940
|
+
procedureId: z25.string().min(1, "Procedure ID is required"),
|
|
10859
10941
|
eventLocation: clinicLocationSchema,
|
|
10860
10942
|
eventTime: calendarEventTimeSchema,
|
|
10861
|
-
description:
|
|
10943
|
+
description: z25.string().optional()
|
|
10862
10944
|
}).refine(
|
|
10863
10945
|
(data) => {
|
|
10864
10946
|
return true;
|
|
@@ -10867,95 +10949,95 @@ var createAppointmentSchema2 = z23.object({
|
|
|
10867
10949
|
message: "Invalid appointment parameters"
|
|
10868
10950
|
}
|
|
10869
10951
|
);
|
|
10870
|
-
var updateAppointmentSchema2 =
|
|
10871
|
-
appointmentId:
|
|
10872
|
-
clinicId:
|
|
10873
|
-
doctorId:
|
|
10874
|
-
patientId:
|
|
10952
|
+
var updateAppointmentSchema2 = z25.object({
|
|
10953
|
+
appointmentId: z25.string().min(1, "Appointment ID is required"),
|
|
10954
|
+
clinicId: z25.string().min(1, "Clinic ID is required"),
|
|
10955
|
+
doctorId: z25.string().min(1, "Doctor ID is required"),
|
|
10956
|
+
patientId: z25.string().min(1, "Patient ID is required"),
|
|
10875
10957
|
eventTime: calendarEventTimeSchema.optional(),
|
|
10876
|
-
description:
|
|
10877
|
-
status:
|
|
10958
|
+
description: z25.string().optional(),
|
|
10959
|
+
status: z25.nativeEnum(CalendarEventStatus).optional()
|
|
10878
10960
|
});
|
|
10879
|
-
var createCalendarEventSchema =
|
|
10880
|
-
id:
|
|
10881
|
-
clinicBranchId:
|
|
10882
|
-
clinicBranchInfo:
|
|
10883
|
-
practitionerProfileId:
|
|
10961
|
+
var createCalendarEventSchema = z25.object({
|
|
10962
|
+
id: z25.string(),
|
|
10963
|
+
clinicBranchId: z25.string().nullable().optional(),
|
|
10964
|
+
clinicBranchInfo: z25.any().nullable().optional(),
|
|
10965
|
+
practitionerProfileId: z25.string().nullable().optional(),
|
|
10884
10966
|
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
10885
|
-
patientProfileId:
|
|
10967
|
+
patientProfileId: z25.string().nullable().optional(),
|
|
10886
10968
|
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
10887
|
-
procedureId:
|
|
10888
|
-
appointmentId:
|
|
10889
|
-
syncedCalendarEventId:
|
|
10890
|
-
eventName:
|
|
10969
|
+
procedureId: z25.string().nullable().optional(),
|
|
10970
|
+
appointmentId: z25.string().nullable().optional(),
|
|
10971
|
+
syncedCalendarEventId: z25.array(syncedCalendarEventSchema).nullable().optional(),
|
|
10972
|
+
eventName: z25.string().min(1, "Event name is required"),
|
|
10891
10973
|
eventLocation: clinicLocationSchema.optional(),
|
|
10892
10974
|
eventTime: calendarEventTimeSchema,
|
|
10893
|
-
description:
|
|
10894
|
-
status:
|
|
10895
|
-
syncStatus:
|
|
10896
|
-
eventType:
|
|
10897
|
-
createdAt:
|
|
10975
|
+
description: z25.string().optional(),
|
|
10976
|
+
status: z25.nativeEnum(CalendarEventStatus),
|
|
10977
|
+
syncStatus: z25.nativeEnum(CalendarSyncStatus),
|
|
10978
|
+
eventType: z25.nativeEnum(CalendarEventType),
|
|
10979
|
+
createdAt: z25.any(),
|
|
10898
10980
|
// FieldValue for server timestamp
|
|
10899
|
-
updatedAt:
|
|
10981
|
+
updatedAt: z25.any()
|
|
10900
10982
|
// FieldValue for server timestamp
|
|
10901
10983
|
});
|
|
10902
|
-
var updateCalendarEventSchema =
|
|
10903
|
-
syncedCalendarEventId:
|
|
10904
|
-
appointmentId:
|
|
10905
|
-
eventName:
|
|
10984
|
+
var updateCalendarEventSchema = z25.object({
|
|
10985
|
+
syncedCalendarEventId: z25.array(syncedCalendarEventSchema).nullable().optional(),
|
|
10986
|
+
appointmentId: z25.string().nullable().optional(),
|
|
10987
|
+
eventName: z25.string().optional(),
|
|
10906
10988
|
eventTime: calendarEventTimeSchema.optional(),
|
|
10907
|
-
description:
|
|
10908
|
-
status:
|
|
10909
|
-
syncStatus:
|
|
10910
|
-
eventType:
|
|
10911
|
-
updatedAt:
|
|
10989
|
+
description: z25.string().optional(),
|
|
10990
|
+
status: z25.nativeEnum(CalendarEventStatus).optional(),
|
|
10991
|
+
syncStatus: z25.nativeEnum(CalendarSyncStatus).optional(),
|
|
10992
|
+
eventType: z25.nativeEnum(CalendarEventType).optional(),
|
|
10993
|
+
updatedAt: z25.any()
|
|
10912
10994
|
// FieldValue for server timestamp
|
|
10913
10995
|
});
|
|
10914
|
-
var calendarEventSchema =
|
|
10915
|
-
id:
|
|
10916
|
-
clinicBranchId:
|
|
10917
|
-
clinicBranchInfo:
|
|
10996
|
+
var calendarEventSchema = z25.object({
|
|
10997
|
+
id: z25.string(),
|
|
10998
|
+
clinicBranchId: z25.string().nullable().optional(),
|
|
10999
|
+
clinicBranchInfo: z25.any().nullable().optional(),
|
|
10918
11000
|
// Will be replaced with proper clinic info schema
|
|
10919
|
-
practitionerProfileId:
|
|
11001
|
+
practitionerProfileId: z25.string().nullable().optional(),
|
|
10920
11002
|
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
10921
|
-
patientProfileId:
|
|
11003
|
+
patientProfileId: z25.string().nullable().optional(),
|
|
10922
11004
|
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
10923
|
-
procedureId:
|
|
11005
|
+
procedureId: z25.string().nullable().optional(),
|
|
10924
11006
|
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
10925
11007
|
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
10926
|
-
appointmentId:
|
|
10927
|
-
syncedCalendarEventId:
|
|
10928
|
-
eventName:
|
|
11008
|
+
appointmentId: z25.string().nullable().optional(),
|
|
11009
|
+
syncedCalendarEventId: z25.array(syncedCalendarEventSchema).nullable().optional(),
|
|
11010
|
+
eventName: z25.string(),
|
|
10929
11011
|
eventLocation: clinicLocationSchema.optional(),
|
|
10930
11012
|
eventTime: calendarEventTimeSchema,
|
|
10931
|
-
description:
|
|
10932
|
-
status:
|
|
10933
|
-
syncStatus:
|
|
10934
|
-
eventType:
|
|
10935
|
-
createdAt:
|
|
10936
|
-
updatedAt:
|
|
11013
|
+
description: z25.string().optional(),
|
|
11014
|
+
status: z25.nativeEnum(CalendarEventStatus),
|
|
11015
|
+
syncStatus: z25.nativeEnum(CalendarSyncStatus),
|
|
11016
|
+
eventType: z25.nativeEnum(CalendarEventType),
|
|
11017
|
+
createdAt: z25.instanceof(Date).or(z25.instanceof(Timestamp21)),
|
|
11018
|
+
updatedAt: z25.instanceof(Date).or(z25.instanceof(Timestamp21))
|
|
10937
11019
|
});
|
|
10938
|
-
var createBlockingEventSchema =
|
|
10939
|
-
entityType:
|
|
10940
|
-
entityId:
|
|
10941
|
-
eventName:
|
|
11020
|
+
var createBlockingEventSchema = z25.object({
|
|
11021
|
+
entityType: z25.enum(["practitioner", "clinic"]),
|
|
11022
|
+
entityId: z25.string().min(1, "Entity ID is required"),
|
|
11023
|
+
eventName: z25.string().min(1, "Event name is required").max(200, "Event name too long"),
|
|
10942
11024
|
eventTime: calendarEventTimeSchema,
|
|
10943
|
-
eventType:
|
|
11025
|
+
eventType: z25.enum([
|
|
10944
11026
|
"blocking" /* BLOCKING */,
|
|
10945
11027
|
"break" /* BREAK */,
|
|
10946
11028
|
"free_day" /* FREE_DAY */,
|
|
10947
11029
|
"other" /* OTHER */
|
|
10948
11030
|
]),
|
|
10949
|
-
description:
|
|
11031
|
+
description: z25.string().max(1e3, "Description too long").optional()
|
|
10950
11032
|
});
|
|
10951
|
-
var updateBlockingEventSchema =
|
|
10952
|
-
entityType:
|
|
10953
|
-
entityId:
|
|
10954
|
-
eventId:
|
|
10955
|
-
eventName:
|
|
11033
|
+
var updateBlockingEventSchema = z25.object({
|
|
11034
|
+
entityType: z25.enum(["practitioner", "clinic"]),
|
|
11035
|
+
entityId: z25.string().min(1, "Entity ID is required"),
|
|
11036
|
+
eventId: z25.string().min(1, "Event ID is required"),
|
|
11037
|
+
eventName: z25.string().min(1, "Event name is required").max(200, "Event name too long").optional(),
|
|
10956
11038
|
eventTime: calendarEventTimeSchema.optional(),
|
|
10957
|
-
description:
|
|
10958
|
-
status:
|
|
11039
|
+
description: z25.string().max(1e3, "Description too long").optional(),
|
|
11040
|
+
status: z25.nativeEnum(CalendarEventStatus).optional()
|
|
10959
11041
|
});
|
|
10960
11042
|
|
|
10961
11043
|
// src/services/calendar/utils/clinic.utils.ts
|
|
@@ -10966,12 +11048,12 @@ import {
|
|
|
10966
11048
|
getDocs as getDocs20,
|
|
10967
11049
|
setDoc as setDoc18,
|
|
10968
11050
|
updateDoc as updateDoc20,
|
|
10969
|
-
deleteDoc as
|
|
11051
|
+
deleteDoc as deleteDoc13,
|
|
10970
11052
|
query as query20,
|
|
10971
11053
|
where as where20,
|
|
10972
|
-
orderBy as
|
|
11054
|
+
orderBy as orderBy10,
|
|
10973
11055
|
Timestamp as Timestamp22,
|
|
10974
|
-
serverTimestamp as
|
|
11056
|
+
serverTimestamp as serverTimestamp16
|
|
10975
11057
|
} from "firebase/firestore";
|
|
10976
11058
|
|
|
10977
11059
|
// src/services/calendar/utils/docs.utils.ts
|
|
@@ -11020,8 +11102,8 @@ async function createClinicCalendarEventUtil(db, clinicId, eventData, generateId
|
|
|
11020
11102
|
const newEvent = {
|
|
11021
11103
|
id: eventId,
|
|
11022
11104
|
...eventData,
|
|
11023
|
-
createdAt:
|
|
11024
|
-
updatedAt:
|
|
11105
|
+
createdAt: serverTimestamp16(),
|
|
11106
|
+
updatedAt: serverTimestamp16()
|
|
11025
11107
|
};
|
|
11026
11108
|
await setDoc18(eventRef, newEvent);
|
|
11027
11109
|
return {
|
|
@@ -11034,7 +11116,7 @@ async function updateClinicCalendarEventUtil(db, clinicId, eventId, updateData)
|
|
|
11034
11116
|
const eventRef = getClinicCalendarEventDocRef(db, clinicId, eventId);
|
|
11035
11117
|
const updates = {
|
|
11036
11118
|
...updateData,
|
|
11037
|
-
updatedAt:
|
|
11119
|
+
updatedAt: serverTimestamp16()
|
|
11038
11120
|
};
|
|
11039
11121
|
await updateDoc20(eventRef, updates);
|
|
11040
11122
|
const updatedDoc = await getDoc23(eventRef);
|
|
@@ -11070,12 +11152,12 @@ import {
|
|
|
11070
11152
|
getDocs as getDocs21,
|
|
11071
11153
|
setDoc as setDoc19,
|
|
11072
11154
|
updateDoc as updateDoc21,
|
|
11073
|
-
deleteDoc as
|
|
11155
|
+
deleteDoc as deleteDoc14,
|
|
11074
11156
|
query as query21,
|
|
11075
11157
|
where as where21,
|
|
11076
|
-
orderBy as
|
|
11158
|
+
orderBy as orderBy11,
|
|
11077
11159
|
Timestamp as Timestamp23,
|
|
11078
|
-
serverTimestamp as
|
|
11160
|
+
serverTimestamp as serverTimestamp17
|
|
11079
11161
|
} from "firebase/firestore";
|
|
11080
11162
|
async function createPatientCalendarEventUtil(db, patientId, eventData, generateId2) {
|
|
11081
11163
|
const eventId = generateId2();
|
|
@@ -11083,8 +11165,8 @@ async function createPatientCalendarEventUtil(db, patientId, eventData, generate
|
|
|
11083
11165
|
const newEvent = {
|
|
11084
11166
|
id: eventId,
|
|
11085
11167
|
...eventData,
|
|
11086
|
-
createdAt:
|
|
11087
|
-
updatedAt:
|
|
11168
|
+
createdAt: serverTimestamp17(),
|
|
11169
|
+
updatedAt: serverTimestamp17()
|
|
11088
11170
|
};
|
|
11089
11171
|
await setDoc19(eventRef, newEvent);
|
|
11090
11172
|
return {
|
|
@@ -11097,7 +11179,7 @@ async function updatePatientCalendarEventUtil(db, patientId, eventId, updateData
|
|
|
11097
11179
|
const eventRef = getPatientCalendarEventDocRef(db, patientId, eventId);
|
|
11098
11180
|
const updates = {
|
|
11099
11181
|
...updateData,
|
|
11100
|
-
updatedAt:
|
|
11182
|
+
updatedAt: serverTimestamp17()
|
|
11101
11183
|
};
|
|
11102
11184
|
await updateDoc21(eventRef, updates);
|
|
11103
11185
|
const updatedDoc = await getDoc24(eventRef);
|
|
@@ -11114,12 +11196,12 @@ import {
|
|
|
11114
11196
|
getDocs as getDocs22,
|
|
11115
11197
|
setDoc as setDoc20,
|
|
11116
11198
|
updateDoc as updateDoc22,
|
|
11117
|
-
deleteDoc as
|
|
11199
|
+
deleteDoc as deleteDoc15,
|
|
11118
11200
|
query as query22,
|
|
11119
11201
|
where as where22,
|
|
11120
|
-
orderBy as
|
|
11202
|
+
orderBy as orderBy12,
|
|
11121
11203
|
Timestamp as Timestamp24,
|
|
11122
|
-
serverTimestamp as
|
|
11204
|
+
serverTimestamp as serverTimestamp18
|
|
11123
11205
|
} from "firebase/firestore";
|
|
11124
11206
|
async function createPractitionerCalendarEventUtil(db, practitionerId, eventData, generateId2) {
|
|
11125
11207
|
const eventId = generateId2();
|
|
@@ -11131,8 +11213,8 @@ async function createPractitionerCalendarEventUtil(db, practitionerId, eventData
|
|
|
11131
11213
|
const newEvent = {
|
|
11132
11214
|
id: eventId,
|
|
11133
11215
|
...eventData,
|
|
11134
|
-
createdAt:
|
|
11135
|
-
updatedAt:
|
|
11216
|
+
createdAt: serverTimestamp18(),
|
|
11217
|
+
updatedAt: serverTimestamp18()
|
|
11136
11218
|
};
|
|
11137
11219
|
await setDoc20(eventRef, newEvent);
|
|
11138
11220
|
return {
|
|
@@ -11149,7 +11231,7 @@ async function updatePractitionerCalendarEventUtil(db, practitionerId, eventId,
|
|
|
11149
11231
|
);
|
|
11150
11232
|
const updates = {
|
|
11151
11233
|
...updateData,
|
|
11152
|
-
updatedAt:
|
|
11234
|
+
updatedAt: serverTimestamp18()
|
|
11153
11235
|
};
|
|
11154
11236
|
await updateDoc22(eventRef, updates);
|
|
11155
11237
|
const updatedDoc = await getDoc25(eventRef);
|
|
@@ -11217,12 +11299,12 @@ import {
|
|
|
11217
11299
|
getDocs as getDocs23,
|
|
11218
11300
|
setDoc as setDoc21,
|
|
11219
11301
|
updateDoc as updateDoc23,
|
|
11220
|
-
deleteDoc as
|
|
11302
|
+
deleteDoc as deleteDoc16,
|
|
11221
11303
|
query as query23,
|
|
11222
11304
|
where as where23,
|
|
11223
|
-
orderBy as
|
|
11305
|
+
orderBy as orderBy13,
|
|
11224
11306
|
Timestamp as Timestamp25,
|
|
11225
|
-
serverTimestamp as
|
|
11307
|
+
serverTimestamp as serverTimestamp19
|
|
11226
11308
|
} from "firebase/firestore";
|
|
11227
11309
|
async function searchCalendarEventsUtil(db, params) {
|
|
11228
11310
|
const { searchLocation, entityId, ...filters } = params;
|
|
@@ -11323,11 +11405,11 @@ import {
|
|
|
11323
11405
|
getDocs as getDocs24,
|
|
11324
11406
|
setDoc as setDoc22,
|
|
11325
11407
|
updateDoc as updateDoc24,
|
|
11326
|
-
deleteDoc as
|
|
11408
|
+
deleteDoc as deleteDoc17,
|
|
11327
11409
|
query as query24,
|
|
11328
|
-
orderBy as
|
|
11410
|
+
orderBy as orderBy14,
|
|
11329
11411
|
Timestamp as Timestamp26,
|
|
11330
|
-
serverTimestamp as
|
|
11412
|
+
serverTimestamp as serverTimestamp20
|
|
11331
11413
|
} from "firebase/firestore";
|
|
11332
11414
|
async function createPractitionerSyncedCalendarUtil(db, practitionerId, calendarData, generateId2) {
|
|
11333
11415
|
const calendarId = generateId2();
|
|
@@ -11339,8 +11421,8 @@ async function createPractitionerSyncedCalendarUtil(db, practitionerId, calendar
|
|
|
11339
11421
|
const newCalendar = {
|
|
11340
11422
|
id: calendarId,
|
|
11341
11423
|
...calendarData,
|
|
11342
|
-
createdAt:
|
|
11343
|
-
updatedAt:
|
|
11424
|
+
createdAt: serverTimestamp20(),
|
|
11425
|
+
updatedAt: serverTimestamp20()
|
|
11344
11426
|
};
|
|
11345
11427
|
await setDoc22(calendarRef, newCalendar);
|
|
11346
11428
|
return {
|
|
@@ -11355,8 +11437,8 @@ async function createPatientSyncedCalendarUtil(db, patientId, calendarData, gene
|
|
|
11355
11437
|
const newCalendar = {
|
|
11356
11438
|
id: calendarId,
|
|
11357
11439
|
...calendarData,
|
|
11358
|
-
createdAt:
|
|
11359
|
-
updatedAt:
|
|
11440
|
+
createdAt: serverTimestamp20(),
|
|
11441
|
+
updatedAt: serverTimestamp20()
|
|
11360
11442
|
};
|
|
11361
11443
|
await setDoc22(calendarRef, newCalendar);
|
|
11362
11444
|
return {
|
|
@@ -11371,8 +11453,8 @@ async function createClinicSyncedCalendarUtil(db, clinicId, calendarData, genera
|
|
|
11371
11453
|
const newCalendar = {
|
|
11372
11454
|
id: calendarId,
|
|
11373
11455
|
...calendarData,
|
|
11374
|
-
createdAt:
|
|
11375
|
-
updatedAt:
|
|
11456
|
+
createdAt: serverTimestamp20(),
|
|
11457
|
+
updatedAt: serverTimestamp20()
|
|
11376
11458
|
};
|
|
11377
11459
|
await setDoc22(calendarRef, newCalendar);
|
|
11378
11460
|
return {
|
|
@@ -11398,7 +11480,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
|
|
|
11398
11480
|
db,
|
|
11399
11481
|
`practitioners/${practitionerId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
11400
11482
|
);
|
|
11401
|
-
const q = query24(calendarsRef,
|
|
11483
|
+
const q = query24(calendarsRef, orderBy14("createdAt", "desc"));
|
|
11402
11484
|
const querySnapshot = await getDocs24(q);
|
|
11403
11485
|
return querySnapshot.docs.map((doc36) => doc36.data());
|
|
11404
11486
|
}
|
|
@@ -11415,7 +11497,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
|
|
|
11415
11497
|
db,
|
|
11416
11498
|
`patients/${patientId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
11417
11499
|
);
|
|
11418
|
-
const q = query24(calendarsRef,
|
|
11500
|
+
const q = query24(calendarsRef, orderBy14("createdAt", "desc"));
|
|
11419
11501
|
const querySnapshot = await getDocs24(q);
|
|
11420
11502
|
return querySnapshot.docs.map((doc36) => doc36.data());
|
|
11421
11503
|
}
|
|
@@ -11432,7 +11514,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
|
|
|
11432
11514
|
db,
|
|
11433
11515
|
`clinics/${clinicId}/${SYNCED_CALENDARS_COLLECTION}`
|
|
11434
11516
|
);
|
|
11435
|
-
const q = query24(calendarsRef,
|
|
11517
|
+
const q = query24(calendarsRef, orderBy14("createdAt", "desc"));
|
|
11436
11518
|
const querySnapshot = await getDocs24(q);
|
|
11437
11519
|
return querySnapshot.docs.map((doc36) => doc36.data());
|
|
11438
11520
|
}
|
|
@@ -11444,7 +11526,7 @@ async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendar
|
|
|
11444
11526
|
);
|
|
11445
11527
|
const updates = {
|
|
11446
11528
|
...updateData,
|
|
11447
|
-
updatedAt:
|
|
11529
|
+
updatedAt: serverTimestamp20()
|
|
11448
11530
|
};
|
|
11449
11531
|
await updateDoc24(calendarRef, updates);
|
|
11450
11532
|
const updatedDoc = await getDoc27(calendarRef);
|
|
@@ -11457,7 +11539,7 @@ async function updatePatientSyncedCalendarUtil(db, patientId, calendarId, update
|
|
|
11457
11539
|
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
11458
11540
|
const updates = {
|
|
11459
11541
|
...updateData,
|
|
11460
|
-
updatedAt:
|
|
11542
|
+
updatedAt: serverTimestamp20()
|
|
11461
11543
|
};
|
|
11462
11544
|
await updateDoc24(calendarRef, updates);
|
|
11463
11545
|
const updatedDoc = await getDoc27(calendarRef);
|
|
@@ -11470,7 +11552,7 @@ async function updateClinicSyncedCalendarUtil(db, clinicId, calendarId, updateDa
|
|
|
11470
11552
|
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
11471
11553
|
const updates = {
|
|
11472
11554
|
...updateData,
|
|
11473
|
-
updatedAt:
|
|
11555
|
+
updatedAt: serverTimestamp20()
|
|
11474
11556
|
};
|
|
11475
11557
|
await updateDoc24(calendarRef, updates);
|
|
11476
11558
|
const updatedDoc = await getDoc27(calendarRef);
|
|
@@ -11485,15 +11567,15 @@ async function deletePractitionerSyncedCalendarUtil(db, practitionerId, calendar
|
|
|
11485
11567
|
practitionerId,
|
|
11486
11568
|
calendarId
|
|
11487
11569
|
);
|
|
11488
|
-
await
|
|
11570
|
+
await deleteDoc17(calendarRef);
|
|
11489
11571
|
}
|
|
11490
11572
|
async function deletePatientSyncedCalendarUtil(db, patientId, calendarId) {
|
|
11491
11573
|
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
11492
|
-
await
|
|
11574
|
+
await deleteDoc17(calendarRef);
|
|
11493
11575
|
}
|
|
11494
11576
|
async function deleteClinicSyncedCalendarUtil(db, clinicId, calendarId) {
|
|
11495
11577
|
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
11496
|
-
await
|
|
11578
|
+
await deleteDoc17(calendarRef);
|
|
11497
11579
|
}
|
|
11498
11580
|
async function updateLastSyncedTimestampUtil(db, entityType, entityId, calendarId) {
|
|
11499
11581
|
const updateData = {
|
|
@@ -12692,8 +12774,8 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
12692
12774
|
const newEvent = {
|
|
12693
12775
|
id: eventId,
|
|
12694
12776
|
...eventData,
|
|
12695
|
-
createdAt:
|
|
12696
|
-
updatedAt:
|
|
12777
|
+
createdAt: serverTimestamp21(),
|
|
12778
|
+
updatedAt: serverTimestamp21()
|
|
12697
12779
|
};
|
|
12698
12780
|
await setDoc23(eventRef, newEvent);
|
|
12699
12781
|
return {
|
|
@@ -12909,7 +12991,7 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
12909
12991
|
end: Timestamp28.fromDate(endTime)
|
|
12910
12992
|
},
|
|
12911
12993
|
description: externalEvent.description || "",
|
|
12912
|
-
updatedAt:
|
|
12994
|
+
updatedAt: serverTimestamp21()
|
|
12913
12995
|
});
|
|
12914
12996
|
console.log(`Updated local event ${eventId} from external event`);
|
|
12915
12997
|
} catch (error) {
|
|
@@ -12936,7 +13018,7 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
12936
13018
|
);
|
|
12937
13019
|
await updateDoc25(eventRef, {
|
|
12938
13020
|
status,
|
|
12939
|
-
updatedAt:
|
|
13021
|
+
updatedAt: serverTimestamp21()
|
|
12940
13022
|
});
|
|
12941
13023
|
console.log(`Updated event ${eventId} status to ${status}`);
|
|
12942
13024
|
} catch (error) {
|
|
@@ -13327,7 +13409,7 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
13327
13409
|
}
|
|
13328
13410
|
await updateDoc25(eventRef, {
|
|
13329
13411
|
syncedCalendarEventId: syncIds,
|
|
13330
|
-
updatedAt:
|
|
13412
|
+
updatedAt: serverTimestamp21()
|
|
13331
13413
|
});
|
|
13332
13414
|
console.log(
|
|
13333
13415
|
`Updated event ${eventId} with sync ID ${syncEvent.eventId}`
|
|
@@ -13550,8 +13632,8 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
13550
13632
|
};
|
|
13551
13633
|
|
|
13552
13634
|
// src/services/calendar/calendar.v3.service.ts
|
|
13553
|
-
import { Timestamp as Timestamp29, serverTimestamp as
|
|
13554
|
-
import { doc as doc27, getDoc as getDoc29, setDoc as setDoc24, updateDoc as updateDoc26, deleteDoc as
|
|
13635
|
+
import { Timestamp as Timestamp29, serverTimestamp as serverTimestamp22 } from "firebase/firestore";
|
|
13636
|
+
import { doc as doc27, getDoc as getDoc29, setDoc as setDoc24, updateDoc as updateDoc26, deleteDoc as deleteDoc18 } from "firebase/firestore";
|
|
13555
13637
|
var CalendarServiceV3 = class extends BaseService {
|
|
13556
13638
|
/**
|
|
13557
13639
|
* Creates a new CalendarServiceV3 instance
|
|
@@ -13585,8 +13667,8 @@ var CalendarServiceV3 = class extends BaseService {
|
|
|
13585
13667
|
status: "confirmed" /* CONFIRMED */,
|
|
13586
13668
|
// Blocking events are always confirmed
|
|
13587
13669
|
syncStatus: "internal" /* INTERNAL */,
|
|
13588
|
-
createdAt:
|
|
13589
|
-
updatedAt:
|
|
13670
|
+
createdAt: serverTimestamp22(),
|
|
13671
|
+
updatedAt: serverTimestamp22()
|
|
13590
13672
|
};
|
|
13591
13673
|
if (params.entityType === "practitioner") {
|
|
13592
13674
|
eventData.practitionerProfileId = params.entityId;
|
|
@@ -13616,7 +13698,7 @@ var CalendarServiceV3 = class extends BaseService {
|
|
|
13616
13698
|
throw new Error(`Blocking event with ID ${params.eventId} not found`);
|
|
13617
13699
|
}
|
|
13618
13700
|
const updateData = {
|
|
13619
|
-
updatedAt:
|
|
13701
|
+
updatedAt: serverTimestamp22()
|
|
13620
13702
|
};
|
|
13621
13703
|
if (params.eventName !== void 0) {
|
|
13622
13704
|
updateData.eventName = params.eventName;
|
|
@@ -13647,7 +13729,7 @@ var CalendarServiceV3 = class extends BaseService {
|
|
|
13647
13729
|
if (!eventDoc.exists()) {
|
|
13648
13730
|
throw new Error(`Blocking event with ID ${eventId} not found`);
|
|
13649
13731
|
}
|
|
13650
|
-
await
|
|
13732
|
+
await deleteDoc18(eventRef);
|
|
13651
13733
|
}
|
|
13652
13734
|
/**
|
|
13653
13735
|
* Gets a specific blocking event
|
|
@@ -13755,15 +13837,15 @@ import {
|
|
|
13755
13837
|
query as query26,
|
|
13756
13838
|
where as where26,
|
|
13757
13839
|
setDoc as setDoc25,
|
|
13758
|
-
deleteDoc as
|
|
13759
|
-
serverTimestamp as
|
|
13840
|
+
deleteDoc as deleteDoc19,
|
|
13841
|
+
serverTimestamp as serverTimestamp23
|
|
13760
13842
|
} from "firebase/firestore";
|
|
13761
13843
|
|
|
13762
13844
|
// src/types/reviews/index.ts
|
|
13763
13845
|
var REVIEWS_COLLECTION = "reviews";
|
|
13764
13846
|
|
|
13765
13847
|
// src/services/reviews/reviews.service.ts
|
|
13766
|
-
import { z as
|
|
13848
|
+
import { z as z26 } from "zod";
|
|
13767
13849
|
var ReviewService = class extends BaseService {
|
|
13768
13850
|
constructor(db, auth, app) {
|
|
13769
13851
|
super(db, auth, app);
|
|
@@ -13845,12 +13927,12 @@ var ReviewService = class extends BaseService {
|
|
|
13845
13927
|
const docRef = doc28(this.db, REVIEWS_COLLECTION, reviewId);
|
|
13846
13928
|
await setDoc25(docRef, {
|
|
13847
13929
|
...review,
|
|
13848
|
-
createdAt:
|
|
13849
|
-
updatedAt:
|
|
13930
|
+
createdAt: serverTimestamp23(),
|
|
13931
|
+
updatedAt: serverTimestamp23()
|
|
13850
13932
|
});
|
|
13851
13933
|
return review;
|
|
13852
13934
|
} catch (error) {
|
|
13853
|
-
if (error instanceof
|
|
13935
|
+
if (error instanceof z26.ZodError) {
|
|
13854
13936
|
throw new Error(`Invalid review data: ${error.message}`);
|
|
13855
13937
|
}
|
|
13856
13938
|
throw error;
|
|
@@ -13946,7 +14028,7 @@ var ReviewService = class extends BaseService {
|
|
|
13946
14028
|
if (!review) {
|
|
13947
14029
|
throw new Error(`Review with ID ${reviewId} not found`);
|
|
13948
14030
|
}
|
|
13949
|
-
await
|
|
14031
|
+
await deleteDoc19(doc28(this.db, REVIEWS_COLLECTION, reviewId));
|
|
13950
14032
|
}
|
|
13951
14033
|
/**
|
|
13952
14034
|
* Calculates the average of an array of numbers
|
|
@@ -13966,15 +14048,15 @@ var ReviewService = class extends BaseService {
|
|
|
13966
14048
|
// src/services/appointment/appointment.service.ts
|
|
13967
14049
|
import {
|
|
13968
14050
|
Timestamp as Timestamp31,
|
|
13969
|
-
serverTimestamp as
|
|
14051
|
+
serverTimestamp as serverTimestamp25,
|
|
13970
14052
|
arrayUnion as arrayUnion8,
|
|
13971
14053
|
arrayRemove as arrayRemove7,
|
|
13972
14054
|
where as where28,
|
|
13973
|
-
orderBy as
|
|
14055
|
+
orderBy as orderBy16,
|
|
13974
14056
|
collection as collection28,
|
|
13975
14057
|
query as query28,
|
|
13976
|
-
limit as
|
|
13977
|
-
startAfter as
|
|
14058
|
+
limit as limit14,
|
|
14059
|
+
startAfter as startAfter12,
|
|
13978
14060
|
getDocs as getDocs28
|
|
13979
14061
|
} from "firebase/firestore";
|
|
13980
14062
|
import { getFunctions as getFunctions2 } from "firebase/functions";
|
|
@@ -13989,11 +14071,11 @@ import {
|
|
|
13989
14071
|
where as where27,
|
|
13990
14072
|
setDoc as setDoc26,
|
|
13991
14073
|
updateDoc as updateDoc27,
|
|
13992
|
-
serverTimestamp as
|
|
14074
|
+
serverTimestamp as serverTimestamp24,
|
|
13993
14075
|
Timestamp as Timestamp30,
|
|
13994
|
-
orderBy as
|
|
13995
|
-
limit as
|
|
13996
|
-
startAfter as
|
|
14076
|
+
orderBy as orderBy15,
|
|
14077
|
+
limit as limit13,
|
|
14078
|
+
startAfter as startAfter11
|
|
13997
14079
|
} from "firebase/firestore";
|
|
13998
14080
|
|
|
13999
14081
|
// src/backoffice/types/technology.types.ts
|
|
@@ -14052,7 +14134,7 @@ async function updateAppointmentUtil2(db, appointmentId, data) {
|
|
|
14052
14134
|
...data,
|
|
14053
14135
|
completedPreRequirements,
|
|
14054
14136
|
completedPostRequirements,
|
|
14055
|
-
updatedAt:
|
|
14137
|
+
updatedAt: serverTimestamp24()
|
|
14056
14138
|
};
|
|
14057
14139
|
Object.keys(updateData).forEach((key) => {
|
|
14058
14140
|
if (updateData[key] === void 0) {
|
|
@@ -14112,7 +14194,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
|
|
|
14112
14194
|
}
|
|
14113
14195
|
await updateDoc27(calendarEventRef, {
|
|
14114
14196
|
status: calendarStatus,
|
|
14115
|
-
updatedAt:
|
|
14197
|
+
updatedAt: serverTimestamp24()
|
|
14116
14198
|
});
|
|
14117
14199
|
} catch (error) {
|
|
14118
14200
|
console.error(`Error updating calendar event ${calendarEventId}:`, error);
|
|
@@ -14165,12 +14247,12 @@ async function searchAppointmentsUtil(db, params) {
|
|
|
14165
14247
|
constraints.push(where27("status", "==", params.status));
|
|
14166
14248
|
}
|
|
14167
14249
|
}
|
|
14168
|
-
constraints.push(
|
|
14250
|
+
constraints.push(orderBy15("appointmentStartTime", "asc"));
|
|
14169
14251
|
if (params.limit) {
|
|
14170
|
-
constraints.push(
|
|
14252
|
+
constraints.push(limit13(params.limit));
|
|
14171
14253
|
}
|
|
14172
14254
|
if (params.startAfter) {
|
|
14173
|
-
constraints.push(
|
|
14255
|
+
constraints.push(startAfter11(params.startAfter));
|
|
14174
14256
|
}
|
|
14175
14257
|
const q = query27(collection27(db, APPOINTMENTS_COLLECTION), ...constraints);
|
|
14176
14258
|
const querySnapshot = await getDocs27(q);
|
|
@@ -14544,7 +14626,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14544
14626
|
);
|
|
14545
14627
|
const updateData = {
|
|
14546
14628
|
status: newStatus,
|
|
14547
|
-
updatedAt:
|
|
14629
|
+
updatedAt: serverTimestamp25()
|
|
14548
14630
|
};
|
|
14549
14631
|
if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */ || newStatus === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
|
|
14550
14632
|
if (!(details == null ? void 0 : details.cancellationReason)) {
|
|
@@ -14641,7 +14723,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14641
14723
|
appointmentEndTime: endTimestamp,
|
|
14642
14724
|
rescheduleTime: Timestamp31.now(),
|
|
14643
14725
|
confirmationTime: null,
|
|
14644
|
-
updatedAt:
|
|
14726
|
+
updatedAt: serverTimestamp25()
|
|
14645
14727
|
};
|
|
14646
14728
|
return this.updateAppointment(validatedParams.appointmentId, updateData);
|
|
14647
14729
|
}
|
|
@@ -14772,7 +14854,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14772
14854
|
status: "in_progress" /* IN_PROGRESS */,
|
|
14773
14855
|
procedureActualStartTime: Timestamp31.now(),
|
|
14774
14856
|
// Set actual start time
|
|
14775
|
-
updatedAt:
|
|
14857
|
+
updatedAt: serverTimestamp25()
|
|
14776
14858
|
};
|
|
14777
14859
|
return this.updateAppointment(appointmentId, updateData);
|
|
14778
14860
|
}
|
|
@@ -14813,7 +14895,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14813
14895
|
},
|
|
14814
14896
|
// Optionally update appointmentEndTime to the actual completion time
|
|
14815
14897
|
// appointmentEndTime: procedureCompletionTime,
|
|
14816
|
-
updatedAt:
|
|
14898
|
+
updatedAt: serverTimestamp25()
|
|
14817
14899
|
};
|
|
14818
14900
|
return this.updateAppointment(appointmentId, updateData);
|
|
14819
14901
|
}
|
|
@@ -14856,7 +14938,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14856
14938
|
};
|
|
14857
14939
|
const updateData = {
|
|
14858
14940
|
media: arrayUnion8(newMediaItem),
|
|
14859
|
-
updatedAt:
|
|
14941
|
+
updatedAt: serverTimestamp25()
|
|
14860
14942
|
};
|
|
14861
14943
|
return this.updateAppointment(appointmentId, updateData);
|
|
14862
14944
|
}
|
|
@@ -14877,7 +14959,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14877
14959
|
}
|
|
14878
14960
|
const updateData = {
|
|
14879
14961
|
media: arrayRemove7(mediaToRemove),
|
|
14880
|
-
updatedAt:
|
|
14962
|
+
updatedAt: serverTimestamp25()
|
|
14881
14963
|
};
|
|
14882
14964
|
return this.updateAppointment(appointmentId, updateData);
|
|
14883
14965
|
}
|
|
@@ -14895,7 +14977,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14895
14977
|
};
|
|
14896
14978
|
const updateData = {
|
|
14897
14979
|
reviewInfo: newReviewInfo,
|
|
14898
|
-
updatedAt:
|
|
14980
|
+
updatedAt: serverTimestamp25()
|
|
14899
14981
|
};
|
|
14900
14982
|
return this.updateAppointment(appointmentId, updateData);
|
|
14901
14983
|
}
|
|
@@ -14909,7 +14991,7 @@ var AppointmentService = class extends BaseService {
|
|
|
14909
14991
|
const updateData = {
|
|
14910
14992
|
paymentStatus,
|
|
14911
14993
|
paymentTransactionId: paymentTransactionId || null,
|
|
14912
|
-
updatedAt:
|
|
14994
|
+
updatedAt: serverTimestamp25()
|
|
14913
14995
|
};
|
|
14914
14996
|
return this.updateAppointment(appointmentId, updateData);
|
|
14915
14997
|
}
|
|
@@ -14969,12 +15051,12 @@ var AppointmentService = class extends BaseService {
|
|
|
14969
15051
|
)
|
|
14970
15052
|
);
|
|
14971
15053
|
}
|
|
14972
|
-
constraints.push(
|
|
15054
|
+
constraints.push(orderBy16("appointmentStartTime", "asc"));
|
|
14973
15055
|
if (options == null ? void 0 : options.limit) {
|
|
14974
|
-
constraints.push(
|
|
15056
|
+
constraints.push(limit14(options.limit));
|
|
14975
15057
|
}
|
|
14976
15058
|
if (options == null ? void 0 : options.startAfter) {
|
|
14977
|
-
constraints.push(
|
|
15059
|
+
constraints.push(startAfter12(options.startAfter));
|
|
14978
15060
|
}
|
|
14979
15061
|
const q = query28(
|
|
14980
15062
|
collection28(this.db, APPOINTMENTS_COLLECTION),
|
|
@@ -15042,12 +15124,12 @@ var AppointmentService = class extends BaseService {
|
|
|
15042
15124
|
Timestamp31.fromDate(effectiveEndDate)
|
|
15043
15125
|
)
|
|
15044
15126
|
);
|
|
15045
|
-
constraints.push(
|
|
15127
|
+
constraints.push(orderBy16("appointmentStartTime", "desc"));
|
|
15046
15128
|
if (options == null ? void 0 : options.limit) {
|
|
15047
|
-
constraints.push(
|
|
15129
|
+
constraints.push(limit14(options.limit));
|
|
15048
15130
|
}
|
|
15049
15131
|
if (options == null ? void 0 : options.startAfter) {
|
|
15050
|
-
constraints.push(
|
|
15132
|
+
constraints.push(startAfter12(options.startAfter));
|
|
15051
15133
|
}
|
|
15052
15134
|
const q = query28(
|
|
15053
15135
|
collection28(this.db, APPOINTMENTS_COLLECTION),
|
|
@@ -15081,9 +15163,9 @@ import {
|
|
|
15081
15163
|
doc as doc30,
|
|
15082
15164
|
updateDoc as updateDoc28,
|
|
15083
15165
|
Timestamp as Timestamp32,
|
|
15084
|
-
orderBy as
|
|
15085
|
-
limit as
|
|
15086
|
-
startAfter as
|
|
15166
|
+
orderBy as orderBy17,
|
|
15167
|
+
limit as limit15,
|
|
15168
|
+
startAfter as startAfter13,
|
|
15087
15169
|
getDoc as getDoc32
|
|
15088
15170
|
} from "firebase/firestore";
|
|
15089
15171
|
|
|
@@ -15153,7 +15235,7 @@ var PatientRequirementsService = class extends BaseService {
|
|
|
15153
15235
|
*/
|
|
15154
15236
|
async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
|
|
15155
15237
|
const collRef = this.getPatientRequirementsCollectionRef(patientId);
|
|
15156
|
-
let q = query29(collRef,
|
|
15238
|
+
let q = query29(collRef, orderBy17("createdAt", "desc"));
|
|
15157
15239
|
const queryConstraints = [];
|
|
15158
15240
|
if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
|
|
15159
15241
|
queryConstraints.push(
|
|
@@ -15164,9 +15246,9 @@ var PatientRequirementsService = class extends BaseService {
|
|
|
15164
15246
|
queryConstraints.push(where29("overallStatus", "in", filters.statuses));
|
|
15165
15247
|
}
|
|
15166
15248
|
if (lastVisible) {
|
|
15167
|
-
queryConstraints.push(
|
|
15249
|
+
queryConstraints.push(startAfter13(lastVisible));
|
|
15168
15250
|
}
|
|
15169
|
-
queryConstraints.push(
|
|
15251
|
+
queryConstraints.push(limit15(pageLimit));
|
|
15170
15252
|
q = query29(collRef, ...queryConstraints);
|
|
15171
15253
|
const snapshot = await getDocs29(q);
|
|
15172
15254
|
let requirements = snapshot.docs.map((docSnap) => {
|
|
@@ -16136,63 +16218,63 @@ var ProductService = class extends BaseService {
|
|
|
16136
16218
|
};
|
|
16137
16219
|
|
|
16138
16220
|
// src/validations/notification.schema.ts
|
|
16139
|
-
import { z as
|
|
16140
|
-
var baseNotificationSchema =
|
|
16141
|
-
id:
|
|
16142
|
-
userId:
|
|
16143
|
-
notificationTime:
|
|
16221
|
+
import { z as z27 } from "zod";
|
|
16222
|
+
var baseNotificationSchema = z27.object({
|
|
16223
|
+
id: z27.string().optional(),
|
|
16224
|
+
userId: z27.string(),
|
|
16225
|
+
notificationTime: z27.any(),
|
|
16144
16226
|
// Timestamp
|
|
16145
|
-
notificationType:
|
|
16146
|
-
notificationTokens:
|
|
16147
|
-
status:
|
|
16148
|
-
createdAt:
|
|
16227
|
+
notificationType: z27.nativeEnum(NotificationType),
|
|
16228
|
+
notificationTokens: z27.array(z27.string()),
|
|
16229
|
+
status: z27.nativeEnum(NotificationStatus),
|
|
16230
|
+
createdAt: z27.any().optional(),
|
|
16149
16231
|
// Timestamp
|
|
16150
|
-
updatedAt:
|
|
16232
|
+
updatedAt: z27.any().optional(),
|
|
16151
16233
|
// Timestamp
|
|
16152
|
-
title:
|
|
16153
|
-
body:
|
|
16154
|
-
isRead:
|
|
16155
|
-
userRole:
|
|
16234
|
+
title: z27.string(),
|
|
16235
|
+
body: z27.string(),
|
|
16236
|
+
isRead: z27.boolean(),
|
|
16237
|
+
userRole: z27.nativeEnum(UserRole)
|
|
16156
16238
|
});
|
|
16157
16239
|
var preRequirementNotificationSchema = baseNotificationSchema.extend({
|
|
16158
|
-
notificationType:
|
|
16159
|
-
treatmentId:
|
|
16160
|
-
requirements:
|
|
16161
|
-
deadline:
|
|
16240
|
+
notificationType: z27.literal("preRequirementInstructionDue" /* PRE_REQUIREMENT_INSTRUCTION_DUE */),
|
|
16241
|
+
treatmentId: z27.string(),
|
|
16242
|
+
requirements: z27.array(z27.string()),
|
|
16243
|
+
deadline: z27.any()
|
|
16162
16244
|
// Timestamp
|
|
16163
16245
|
});
|
|
16164
16246
|
var postRequirementNotificationSchema = baseNotificationSchema.extend({
|
|
16165
|
-
notificationType:
|
|
16247
|
+
notificationType: z27.literal(
|
|
16166
16248
|
"postRequirementInstructionDue" /* POST_REQUIREMENT_INSTRUCTION_DUE */
|
|
16167
16249
|
),
|
|
16168
|
-
treatmentId:
|
|
16169
|
-
requirements:
|
|
16170
|
-
deadline:
|
|
16250
|
+
treatmentId: z27.string(),
|
|
16251
|
+
requirements: z27.array(z27.string()),
|
|
16252
|
+
deadline: z27.any()
|
|
16171
16253
|
// Timestamp
|
|
16172
16254
|
});
|
|
16173
16255
|
var requirementInstructionDueNotificationSchema = baseNotificationSchema.extend({
|
|
16174
|
-
notificationType:
|
|
16175
|
-
appointmentId:
|
|
16176
|
-
patientRequirementInstanceId:
|
|
16177
|
-
instructionId:
|
|
16178
|
-
originalRequirementId:
|
|
16256
|
+
notificationType: z27.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
|
|
16257
|
+
appointmentId: z27.string(),
|
|
16258
|
+
patientRequirementInstanceId: z27.string(),
|
|
16259
|
+
instructionId: z27.string(),
|
|
16260
|
+
originalRequirementId: z27.string().optional()
|
|
16179
16261
|
});
|
|
16180
16262
|
var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
|
|
16181
|
-
notificationType:
|
|
16182
|
-
appointmentId:
|
|
16183
|
-
appointmentTime:
|
|
16263
|
+
notificationType: z27.literal("appointmentReminder" /* APPOINTMENT_REMINDER */),
|
|
16264
|
+
appointmentId: z27.string(),
|
|
16265
|
+
appointmentTime: z27.any(),
|
|
16184
16266
|
// Timestamp
|
|
16185
|
-
treatmentType:
|
|
16186
|
-
doctorName:
|
|
16267
|
+
treatmentType: z27.string(),
|
|
16268
|
+
doctorName: z27.string()
|
|
16187
16269
|
});
|
|
16188
16270
|
var appointmentNotificationSchema = baseNotificationSchema.extend({
|
|
16189
|
-
notificationType:
|
|
16190
|
-
appointmentId:
|
|
16191
|
-
appointmentStatus:
|
|
16192
|
-
previousStatus:
|
|
16193
|
-
reason:
|
|
16271
|
+
notificationType: z27.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
|
|
16272
|
+
appointmentId: z27.string(),
|
|
16273
|
+
appointmentStatus: z27.string(),
|
|
16274
|
+
previousStatus: z27.string(),
|
|
16275
|
+
reason: z27.string().optional()
|
|
16194
16276
|
});
|
|
16195
|
-
var notificationSchema =
|
|
16277
|
+
var notificationSchema = z27.discriminatedUnion("notificationType", [
|
|
16196
16278
|
preRequirementNotificationSchema,
|
|
16197
16279
|
postRequirementNotificationSchema,
|
|
16198
16280
|
requirementInstructionDueNotificationSchema,
|