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