@blackcode_sa/metaestetics-api 1.4.8 → 1.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +16 -16
- package/dist/index.d.ts +16 -16
- package/dist/index.js +736 -184
- package/dist/index.mjs +755 -196
- package/package.json +1 -1
- package/src/services/auth.service.ts +33 -11
- package/src/services/clinic/clinic-group.service.ts +63 -9
- package/src/services/clinic/clinic.service.ts +32 -9
- package/src/services/clinic/utils/admin.utils.ts +6 -51
- package/src/services/clinic/utils/clinic-group.utils.ts +178 -45
- package/src/services/clinic/utils/clinic.utils.ts +482 -39
- package/src/services/clinic/utils/photos.utils.ts +188 -0
- package/src/services/clinic/utils/review.utils.ts +24 -17
- package/src/services/clinic/utils/tag.utils.ts +33 -8
- package/src/types/clinic/index.ts +5 -5
- package/src/validations/clinic.schema.ts +3 -3
package/dist/index.mjs
CHANGED
|
@@ -2375,7 +2375,7 @@ var clinicGroupSchema = z9.object({
|
|
|
2375
2375
|
admins: z9.array(z9.string()),
|
|
2376
2376
|
adminsInfo: z9.array(adminInfoSchema),
|
|
2377
2377
|
adminTokens: z9.array(adminTokenSchema),
|
|
2378
|
-
ownerId: z9.string(),
|
|
2378
|
+
ownerId: z9.string().nullable(),
|
|
2379
2379
|
createdAt: z9.instanceof(Date).or(z9.instanceof(Timestamp5)),
|
|
2380
2380
|
// Timestamp
|
|
2381
2381
|
updatedAt: z9.instanceof(Date).or(z9.instanceof(Timestamp5)),
|
|
@@ -2451,7 +2451,7 @@ var createClinicGroupSchema = z9.object({
|
|
|
2451
2451
|
hqLocation: clinicLocationSchema,
|
|
2452
2452
|
contactInfo: clinicContactInfoSchema,
|
|
2453
2453
|
contactPerson: contactPersonSchema,
|
|
2454
|
-
ownerId: z9.string(),
|
|
2454
|
+
ownerId: z9.string().nullable(),
|
|
2455
2455
|
isActive: z9.boolean(),
|
|
2456
2456
|
logo: z9.string().optional().nullable(),
|
|
2457
2457
|
practiceType: z9.nativeEnum(PracticeType).optional(),
|
|
@@ -2485,7 +2485,7 @@ var createClinicSchema = z9.object({
|
|
|
2485
2485
|
});
|
|
2486
2486
|
var createDefaultClinicGroupSchema = z9.object({
|
|
2487
2487
|
name: z9.string(),
|
|
2488
|
-
ownerId: z9.string(),
|
|
2488
|
+
ownerId: z9.string().nullable(),
|
|
2489
2489
|
contactPerson: contactPersonSchema,
|
|
2490
2490
|
contactInfo: clinicContactInfoSchema,
|
|
2491
2491
|
hqLocation: clinicLocationSchema,
|
|
@@ -2583,45 +2583,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
|
|
|
2583
2583
|
hasGroupId: !!clinicGroupId
|
|
2584
2584
|
});
|
|
2585
2585
|
if (validatedData.isGroupOwner && !clinicGroupId) {
|
|
2586
|
-
console.log("[CLINIC_ADMIN]
|
|
2587
|
-
const defaultGroup = {
|
|
2588
|
-
name: `${validatedData.contactInfo.firstName}'s Group`,
|
|
2589
|
-
ownerId: validatedData.userRef,
|
|
2590
|
-
contactPerson: validatedData.contactInfo,
|
|
2591
|
-
contactInfo: {
|
|
2592
|
-
email: validatedData.contactInfo.email,
|
|
2593
|
-
phoneNumber: validatedData.contactInfo.phoneNumber || ""
|
|
2594
|
-
},
|
|
2595
|
-
hqLocation: {
|
|
2596
|
-
address: "",
|
|
2597
|
-
city: "",
|
|
2598
|
-
country: "",
|
|
2599
|
-
postalCode: "",
|
|
2600
|
-
latitude: 0,
|
|
2601
|
-
longitude: 0
|
|
2602
|
-
},
|
|
2603
|
-
isActive: true
|
|
2604
|
-
};
|
|
2605
|
-
console.log("[CLINIC_ADMIN] Default group data prepared", {
|
|
2606
|
-
groupName: defaultGroup.name
|
|
2607
|
-
});
|
|
2608
|
-
try {
|
|
2609
|
-
const clinicGroup = await clinicGroupService.createClinicGroup(
|
|
2610
|
-
defaultGroup,
|
|
2611
|
-
validatedData.userRef,
|
|
2612
|
-
true
|
|
2613
|
-
);
|
|
2614
|
-
clinicGroupId = clinicGroup.id;
|
|
2615
|
-
console.log("[CLINIC_ADMIN] Default group created successfully", {
|
|
2616
|
-
groupId: clinicGroupId
|
|
2617
|
-
});
|
|
2618
|
-
} catch (groupCreationError) {
|
|
2619
|
-
console.error(
|
|
2620
|
-
"[CLINIC_ADMIN] Error creating default group:",
|
|
2621
|
-
groupCreationError
|
|
2622
|
-
);
|
|
2623
|
-
throw groupCreationError;
|
|
2624
|
-
}
|
|
2586
|
+
console.log("[CLINIC_ADMIN] Owner will be assigned to group later");
|
|
2625
2587
|
} else if (!validatedData.isGroupOwner && !clinicGroupId) {
|
|
2626
2588
|
console.error("[CLINIC_ADMIN] Missing clinic group ID for non-owner admin");
|
|
2627
2589
|
throw new Error("Clinic group ID is required for non-owner admins");
|
|
@@ -2651,16 +2613,12 @@ async function createClinicAdmin(db, data, clinicGroupService) {
|
|
|
2651
2613
|
}
|
|
2652
2614
|
}
|
|
2653
2615
|
console.log("[CLINIC_ADMIN] Preparing admin data object");
|
|
2654
|
-
if (!clinicGroupId) {
|
|
2655
|
-
console.error(
|
|
2656
|
-
"[CLINIC_ADMIN] clinicGroupId is undefined, which should not happen at this point"
|
|
2657
|
-
);
|
|
2658
|
-
throw new Error("clinicGroupId is required but was undefined");
|
|
2659
|
-
}
|
|
2660
2616
|
const adminData = {
|
|
2661
|
-
id:
|
|
2617
|
+
id: doc4(collection2(db, CLINIC_ADMINS_COLLECTION)).id,
|
|
2618
|
+
// Generate a new ID for the admin document
|
|
2662
2619
|
userRef: validatedData.userRef,
|
|
2663
|
-
clinicGroupId,
|
|
2620
|
+
clinicGroupId: clinicGroupId || "",
|
|
2621
|
+
// Empty string for now if no group ID
|
|
2664
2622
|
isGroupOwner: validatedData.isGroupOwner,
|
|
2665
2623
|
clinicsManaged: [],
|
|
2666
2624
|
// Uvek krećemo od prazne liste
|
|
@@ -3706,6 +3664,65 @@ import {
|
|
|
3706
3664
|
} from "firebase/firestore";
|
|
3707
3665
|
import { geohashForLocation as geohashForLocation2 } from "geofire-common";
|
|
3708
3666
|
import { z as z13 } from "zod";
|
|
3667
|
+
|
|
3668
|
+
// src/services/clinic/utils/photos.utils.ts
|
|
3669
|
+
import {
|
|
3670
|
+
getStorage as getStorage2,
|
|
3671
|
+
ref as ref2,
|
|
3672
|
+
uploadBytes as uploadBytes2,
|
|
3673
|
+
getDownloadURL as getDownloadURL2,
|
|
3674
|
+
deleteObject as deleteObject2
|
|
3675
|
+
} from "firebase/storage";
|
|
3676
|
+
async function uploadPhoto(photo, entityType, entityId, photoType, app, fileName) {
|
|
3677
|
+
if (!photo || typeof photo !== "string" || !photo.startsWith("data:")) {
|
|
3678
|
+
return photo;
|
|
3679
|
+
}
|
|
3680
|
+
try {
|
|
3681
|
+
console.log(
|
|
3682
|
+
`[PHOTO_UTILS] Uploading ${photoType} for ${entityType}/${entityId}`
|
|
3683
|
+
);
|
|
3684
|
+
const storage = getStorage2(app);
|
|
3685
|
+
const storageFileName = fileName || `${photoType}-${Date.now()}`;
|
|
3686
|
+
const storageRef = ref2(
|
|
3687
|
+
storage,
|
|
3688
|
+
`${entityType}/${entityId}/${storageFileName}`
|
|
3689
|
+
);
|
|
3690
|
+
const base64Data = photo.split(",")[1];
|
|
3691
|
+
const contentType = photo.split(";")[0].split(":")[1];
|
|
3692
|
+
const byteCharacters = atob(base64Data);
|
|
3693
|
+
const byteArrays = [];
|
|
3694
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
3695
|
+
byteArrays.push(byteCharacters.charCodeAt(i));
|
|
3696
|
+
}
|
|
3697
|
+
const blob = new Blob([new Uint8Array(byteArrays)], { type: contentType });
|
|
3698
|
+
await uploadBytes2(storageRef, blob, { contentType });
|
|
3699
|
+
const downloadUrl = await getDownloadURL2(storageRef);
|
|
3700
|
+
console.log(`[PHOTO_UTILS] ${photoType} uploaded successfully`, {
|
|
3701
|
+
downloadUrl
|
|
3702
|
+
});
|
|
3703
|
+
return downloadUrl;
|
|
3704
|
+
} catch (error) {
|
|
3705
|
+
console.error(`[PHOTO_UTILS] Error uploading ${photoType}:`, error);
|
|
3706
|
+
return null;
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
async function uploadMultiplePhotos(photos, entityType, entityId, photoType, app) {
|
|
3710
|
+
if (!photos || !Array.isArray(photos) || photos.length === 0) {
|
|
3711
|
+
return [];
|
|
3712
|
+
}
|
|
3713
|
+
const uploadPromises = photos.map(
|
|
3714
|
+
(photo, index) => uploadPhoto(photo, entityType, entityId, `${photoType}-${index}`, app)
|
|
3715
|
+
);
|
|
3716
|
+
try {
|
|
3717
|
+
const results = await Promise.all(uploadPromises);
|
|
3718
|
+
return results.filter((url) => url !== null);
|
|
3719
|
+
} catch (error) {
|
|
3720
|
+
console.error(`[PHOTO_UTILS] Error uploading multiple photos:`, error);
|
|
3721
|
+
return photos.filter((photo) => !photo.startsWith("data:"));
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
|
|
3725
|
+
// src/services/clinic/utils/clinic-group.utils.ts
|
|
3709
3726
|
function generateId() {
|
|
3710
3727
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
3711
3728
|
const timestamp = Date.now().toString(36);
|
|
@@ -3715,7 +3732,8 @@ function generateId() {
|
|
|
3715
3732
|
).join("");
|
|
3716
3733
|
return `${randomPart}-${timestamp}`;
|
|
3717
3734
|
}
|
|
3718
|
-
async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdminService) {
|
|
3735
|
+
async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdminService, app) {
|
|
3736
|
+
var _a, _b, _c, _d, _e;
|
|
3719
3737
|
console.log("[CLINIC_GROUP] Starting clinic group creation", {
|
|
3720
3738
|
ownerId,
|
|
3721
3739
|
isDefault
|
|
@@ -3769,23 +3787,49 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
|
|
|
3769
3787
|
}
|
|
3770
3788
|
const now = Timestamp10.now();
|
|
3771
3789
|
console.log("[CLINIC_GROUP] Preparing clinic group data object");
|
|
3790
|
+
const groupId = doc7(collection5(db, CLINIC_GROUPS_COLLECTION)).id;
|
|
3772
3791
|
console.log("[CLINIC_GROUP] Logo value:", {
|
|
3773
3792
|
logoValue: validatedData.logo,
|
|
3774
3793
|
logoType: validatedData.logo === null ? "null" : typeof validatedData.logo
|
|
3775
3794
|
});
|
|
3795
|
+
let logoUrl = await uploadPhoto(
|
|
3796
|
+
validatedData.logo || null,
|
|
3797
|
+
"clinic-groups",
|
|
3798
|
+
groupId,
|
|
3799
|
+
"logo",
|
|
3800
|
+
app
|
|
3801
|
+
);
|
|
3802
|
+
console.log("[CLINIC_GROUP] Logo processed", { logoUrl });
|
|
3776
3803
|
const groupData = {
|
|
3777
3804
|
...validatedData,
|
|
3778
|
-
id:
|
|
3805
|
+
id: groupId,
|
|
3806
|
+
name: validatedData.name,
|
|
3807
|
+
logo: logoUrl,
|
|
3808
|
+
// Use the uploaded logo URL or the original value
|
|
3779
3809
|
description: isDefault ? void 0 : validatedData.description || void 0,
|
|
3780
3810
|
hqLocation: {
|
|
3781
|
-
|
|
3811
|
+
address: validatedData.hqLocation.address || "",
|
|
3812
|
+
city: validatedData.hqLocation.city || "",
|
|
3813
|
+
country: validatedData.hqLocation.country || "",
|
|
3814
|
+
postalCode: validatedData.hqLocation.postalCode || "",
|
|
3815
|
+
latitude: validatedData.hqLocation.latitude || 0,
|
|
3816
|
+
longitude: validatedData.hqLocation.longitude || 0,
|
|
3782
3817
|
geohash: validatedData.hqLocation.geohash || void 0
|
|
3783
3818
|
},
|
|
3784
3819
|
contactInfo: {
|
|
3785
|
-
|
|
3820
|
+
email: validatedData.contactInfo.email || "",
|
|
3821
|
+
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
3786
3822
|
alternativePhoneNumber: isDefault ? void 0 : validatedData.contactInfo.alternativePhoneNumber || void 0,
|
|
3787
3823
|
website: isDefault ? void 0 : validatedData.contactInfo.website || void 0
|
|
3788
3824
|
},
|
|
3825
|
+
contactPerson: {
|
|
3826
|
+
firstName: ((_a = validatedData.contactPerson) == null ? void 0 : _a.firstName) || "",
|
|
3827
|
+
lastName: ((_b = validatedData.contactPerson) == null ? void 0 : _b.lastName) || "",
|
|
3828
|
+
email: ((_c = validatedData.contactPerson) == null ? void 0 : _c.email) || "",
|
|
3829
|
+
title: ((_d = validatedData.contactPerson) == null ? void 0 : _d.title) || null,
|
|
3830
|
+
phoneNumber: ((_e = validatedData.contactPerson) == null ? void 0 : _e.phoneNumber) || null
|
|
3831
|
+
},
|
|
3832
|
+
subscriptionModel: validatedData.subscriptionModel || "no_subscription" /* NO_SUBSCRIPTION */,
|
|
3789
3833
|
clinics: [],
|
|
3790
3834
|
clinicsInfo: [],
|
|
3791
3835
|
admins: [ownerId],
|
|
@@ -3873,35 +3917,75 @@ async function getAllActiveGroups(db) {
|
|
|
3873
3917
|
const querySnapshot = await getDocs5(q);
|
|
3874
3918
|
return querySnapshot.docs.map((doc14) => doc14.data());
|
|
3875
3919
|
}
|
|
3876
|
-
async function updateClinicGroup(db, groupId, data) {
|
|
3920
|
+
async function updateClinicGroup(db, groupId, data, app) {
|
|
3921
|
+
console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
|
|
3877
3922
|
const group = await getClinicGroup(db, groupId);
|
|
3878
3923
|
if (!group) {
|
|
3924
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
3879
3925
|
throw new Error("Clinic group not found");
|
|
3880
3926
|
}
|
|
3881
|
-
|
|
3882
|
-
|
|
3927
|
+
let updatedData = { ...data };
|
|
3928
|
+
if (data.logo && typeof data.logo === "string" && data.logo.startsWith("data:")) {
|
|
3929
|
+
console.log("[CLINIC_GROUP] Processing logo for update");
|
|
3930
|
+
try {
|
|
3931
|
+
const logoUrl = await uploadPhoto(
|
|
3932
|
+
data.logo,
|
|
3933
|
+
"clinic-groups",
|
|
3934
|
+
groupId,
|
|
3935
|
+
"logo",
|
|
3936
|
+
app
|
|
3937
|
+
);
|
|
3938
|
+
console.log("[CLINIC_GROUP] Logo processed for update", { logoUrl });
|
|
3939
|
+
updatedData.logo = logoUrl;
|
|
3940
|
+
} catch (error) {
|
|
3941
|
+
console.error("[CLINIC_GROUP] Error processing logo for update:", error);
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
updatedData = {
|
|
3945
|
+
...updatedData,
|
|
3883
3946
|
updatedAt: Timestamp10.now()
|
|
3884
3947
|
};
|
|
3948
|
+
console.log("[CLINIC_GROUP] Updating clinic group in Firestore");
|
|
3885
3949
|
await updateDoc10(doc7(db, CLINIC_GROUPS_COLLECTION, groupId), updatedData);
|
|
3950
|
+
console.log("[CLINIC_GROUP] Clinic group updated successfully");
|
|
3886
3951
|
const updatedGroup = await getClinicGroup(db, groupId);
|
|
3887
3952
|
if (!updatedGroup) {
|
|
3953
|
+
console.error("[CLINIC_GROUP] Failed to retrieve updated clinic group");
|
|
3888
3954
|
throw new Error("Failed to retrieve updated clinic group");
|
|
3889
3955
|
}
|
|
3890
3956
|
return updatedGroup;
|
|
3891
3957
|
}
|
|
3892
|
-
async function addAdminToGroup(db, groupId, adminId) {
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3958
|
+
async function addAdminToGroup(db, groupId, adminId, app) {
|
|
3959
|
+
console.log("[CLINIC_GROUP] Adding admin to group", { groupId, adminId });
|
|
3960
|
+
try {
|
|
3961
|
+
const group = await getClinicGroup(db, groupId);
|
|
3962
|
+
if (!group) {
|
|
3963
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
3964
|
+
throw new Error("Clinic group not found");
|
|
3965
|
+
}
|
|
3966
|
+
if (group.admins.includes(adminId)) {
|
|
3967
|
+
console.log("[CLINIC_GROUP] Admin is already in the group", {
|
|
3968
|
+
adminId,
|
|
3969
|
+
groupId
|
|
3970
|
+
});
|
|
3971
|
+
return;
|
|
3972
|
+
}
|
|
3973
|
+
console.log("[CLINIC_GROUP] Updating group with new admin");
|
|
3974
|
+
await updateClinicGroup(
|
|
3975
|
+
db,
|
|
3976
|
+
groupId,
|
|
3977
|
+
{
|
|
3978
|
+
admins: [...group.admins, adminId]
|
|
3979
|
+
},
|
|
3980
|
+
app
|
|
3981
|
+
);
|
|
3982
|
+
console.log("[CLINIC_GROUP] Admin added to group successfully");
|
|
3983
|
+
} catch (error) {
|
|
3984
|
+
console.error("[CLINIC_GROUP] Error adding admin to group:", error);
|
|
3985
|
+
throw error;
|
|
3899
3986
|
}
|
|
3900
|
-
await updateClinicGroup(db, groupId, {
|
|
3901
|
-
admins: [...group.admins, adminId]
|
|
3902
|
-
});
|
|
3903
3987
|
}
|
|
3904
|
-
async function removeAdminFromGroup(db, groupId, adminId) {
|
|
3988
|
+
async function removeAdminFromGroup(db, groupId, adminId, app) {
|
|
3905
3989
|
const group = await getClinicGroup(db, groupId);
|
|
3906
3990
|
if (!group) {
|
|
3907
3991
|
throw new Error("Clinic group not found");
|
|
@@ -3912,21 +3996,30 @@ async function removeAdminFromGroup(db, groupId, adminId) {
|
|
|
3912
3996
|
if (!group.admins.includes(adminId)) {
|
|
3913
3997
|
return;
|
|
3914
3998
|
}
|
|
3915
|
-
await updateClinicGroup(
|
|
3916
|
-
|
|
3917
|
-
|
|
3999
|
+
await updateClinicGroup(
|
|
4000
|
+
db,
|
|
4001
|
+
groupId,
|
|
4002
|
+
{
|
|
4003
|
+
admins: group.admins.filter((id) => id !== adminId)
|
|
4004
|
+
},
|
|
4005
|
+
app
|
|
4006
|
+
);
|
|
3918
4007
|
}
|
|
3919
|
-
async function deactivateClinicGroup(db, groupId) {
|
|
4008
|
+
async function deactivateClinicGroup(db, groupId, app) {
|
|
3920
4009
|
const group = await getClinicGroup(db, groupId);
|
|
3921
4010
|
if (!group) {
|
|
3922
4011
|
throw new Error("Clinic group not found");
|
|
3923
4012
|
}
|
|
3924
|
-
await
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
4013
|
+
await updateClinicGroup(
|
|
4014
|
+
db,
|
|
4015
|
+
groupId,
|
|
4016
|
+
{
|
|
4017
|
+
isActive: false
|
|
4018
|
+
},
|
|
4019
|
+
app
|
|
4020
|
+
);
|
|
3928
4021
|
}
|
|
3929
|
-
async function createAdminToken(db, groupId, creatorAdminId, data) {
|
|
4022
|
+
async function createAdminToken(db, groupId, creatorAdminId, app, data) {
|
|
3930
4023
|
const group = await getClinicGroup(db, groupId);
|
|
3931
4024
|
if (!group) {
|
|
3932
4025
|
throw new Error("Clinic group not found");
|
|
@@ -3947,12 +4040,17 @@ async function createAdminToken(db, groupId, creatorAdminId, data) {
|
|
|
3947
4040
|
createdAt: now,
|
|
3948
4041
|
expiresAt
|
|
3949
4042
|
};
|
|
3950
|
-
await updateClinicGroup(
|
|
3951
|
-
|
|
3952
|
-
|
|
4043
|
+
await updateClinicGroup(
|
|
4044
|
+
db,
|
|
4045
|
+
groupId,
|
|
4046
|
+
{
|
|
4047
|
+
adminTokens: [...group.adminTokens, token]
|
|
4048
|
+
},
|
|
4049
|
+
app
|
|
4050
|
+
);
|
|
3953
4051
|
return token;
|
|
3954
4052
|
}
|
|
3955
|
-
async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
4053
|
+
async function verifyAndUseAdminToken(db, groupId, token, userRef, app) {
|
|
3956
4054
|
const group = await getClinicGroup(db, groupId);
|
|
3957
4055
|
if (!group) {
|
|
3958
4056
|
throw new Error("Clinic group not found");
|
|
@@ -3969,9 +4067,14 @@ async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
|
3969
4067
|
const updatedTokens2 = group.adminTokens.map(
|
|
3970
4068
|
(t) => t.id === adminToken.id ? { ...t, status: "expired" /* EXPIRED */ } : t
|
|
3971
4069
|
);
|
|
3972
|
-
await updateClinicGroup(
|
|
3973
|
-
|
|
3974
|
-
|
|
4070
|
+
await updateClinicGroup(
|
|
4071
|
+
db,
|
|
4072
|
+
groupId,
|
|
4073
|
+
{
|
|
4074
|
+
adminTokens: updatedTokens2
|
|
4075
|
+
},
|
|
4076
|
+
app
|
|
4077
|
+
);
|
|
3975
4078
|
throw new Error("Admin token has expired");
|
|
3976
4079
|
}
|
|
3977
4080
|
const updatedTokens = group.adminTokens.map(
|
|
@@ -3981,12 +4084,17 @@ async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
|
3981
4084
|
usedByUserRef: userRef
|
|
3982
4085
|
} : t
|
|
3983
4086
|
);
|
|
3984
|
-
await updateClinicGroup(
|
|
3985
|
-
|
|
3986
|
-
|
|
4087
|
+
await updateClinicGroup(
|
|
4088
|
+
db,
|
|
4089
|
+
groupId,
|
|
4090
|
+
{
|
|
4091
|
+
adminTokens: updatedTokens
|
|
4092
|
+
},
|
|
4093
|
+
app
|
|
4094
|
+
);
|
|
3987
4095
|
return true;
|
|
3988
4096
|
}
|
|
3989
|
-
async function deleteAdminToken(db, groupId, tokenId, adminId) {
|
|
4097
|
+
async function deleteAdminToken(db, groupId, tokenId, adminId, app) {
|
|
3990
4098
|
const group = await getClinicGroup(db, groupId);
|
|
3991
4099
|
if (!group) {
|
|
3992
4100
|
throw new Error("Clinic group not found");
|
|
@@ -3995,11 +4103,16 @@ async function deleteAdminToken(db, groupId, tokenId, adminId) {
|
|
|
3995
4103
|
throw new Error("Admin does not belong to this clinic group");
|
|
3996
4104
|
}
|
|
3997
4105
|
const updatedTokens = group.adminTokens.filter((t) => t.id !== tokenId);
|
|
3998
|
-
await updateClinicGroup(
|
|
3999
|
-
|
|
4000
|
-
|
|
4106
|
+
await updateClinicGroup(
|
|
4107
|
+
db,
|
|
4108
|
+
groupId,
|
|
4109
|
+
{
|
|
4110
|
+
adminTokens: updatedTokens
|
|
4111
|
+
},
|
|
4112
|
+
app
|
|
4113
|
+
);
|
|
4001
4114
|
}
|
|
4002
|
-
async function getActiveAdminTokens(db, groupId, adminId) {
|
|
4115
|
+
async function getActiveAdminTokens(db, groupId, adminId, app) {
|
|
4003
4116
|
const group = await getClinicGroup(db, groupId);
|
|
4004
4117
|
if (!group) {
|
|
4005
4118
|
throw new Error("Clinic group not found");
|
|
@@ -4025,7 +4138,8 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4025
4138
|
data,
|
|
4026
4139
|
ownerId,
|
|
4027
4140
|
isDefault,
|
|
4028
|
-
this.clinicAdminService
|
|
4141
|
+
this.clinicAdminService,
|
|
4142
|
+
this.app
|
|
4029
4143
|
);
|
|
4030
4144
|
}
|
|
4031
4145
|
/**
|
|
@@ -4044,25 +4158,35 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4044
4158
|
* Ažurira grupaciju klinika
|
|
4045
4159
|
*/
|
|
4046
4160
|
async updateClinicGroup(groupId, data) {
|
|
4047
|
-
return updateClinicGroup(this.db, groupId, data);
|
|
4161
|
+
return updateClinicGroup(this.db, groupId, data, this.app);
|
|
4048
4162
|
}
|
|
4049
4163
|
/**
|
|
4050
4164
|
* Dodaje admina u grupaciju
|
|
4051
4165
|
*/
|
|
4052
4166
|
async addAdminToGroup(groupId, adminId) {
|
|
4053
|
-
return addAdminToGroup(
|
|
4167
|
+
return addAdminToGroup(
|
|
4168
|
+
this.db,
|
|
4169
|
+
groupId,
|
|
4170
|
+
adminId,
|
|
4171
|
+
this.app
|
|
4172
|
+
);
|
|
4054
4173
|
}
|
|
4055
4174
|
/**
|
|
4056
4175
|
* Uklanja admina iz grupacije
|
|
4057
4176
|
*/
|
|
4058
4177
|
async removeAdminFromGroup(groupId, adminId) {
|
|
4059
|
-
return removeAdminFromGroup(
|
|
4178
|
+
return removeAdminFromGroup(
|
|
4179
|
+
this.db,
|
|
4180
|
+
groupId,
|
|
4181
|
+
adminId,
|
|
4182
|
+
this.app
|
|
4183
|
+
);
|
|
4060
4184
|
}
|
|
4061
4185
|
/**
|
|
4062
4186
|
* Deaktivira grupaciju klinika
|
|
4063
4187
|
*/
|
|
4064
4188
|
async deactivateClinicGroup(groupId) {
|
|
4065
|
-
return deactivateClinicGroup(this.db, groupId);
|
|
4189
|
+
return deactivateClinicGroup(this.db, groupId, this.app);
|
|
4066
4190
|
}
|
|
4067
4191
|
/**
|
|
4068
4192
|
* Sets up additional clinic group information after initial creation
|
|
@@ -4072,18 +4196,45 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4072
4196
|
* @returns The updated clinic group
|
|
4073
4197
|
*/
|
|
4074
4198
|
async setupClinicGroup(groupId, setupData) {
|
|
4199
|
+
console.log("[CLINIC_GROUP] Setting up clinic group", { groupId });
|
|
4075
4200
|
const clinicGroup = await this.getClinicGroup(groupId);
|
|
4076
4201
|
if (!clinicGroup) {
|
|
4202
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
4077
4203
|
throw new Error(`Clinic group with ID ${groupId} not found`);
|
|
4078
4204
|
}
|
|
4205
|
+
let logoUrl = setupData.logo;
|
|
4206
|
+
if (logoUrl && typeof logoUrl === "string" && logoUrl.startsWith("data:")) {
|
|
4207
|
+
console.log("[CLINIC_GROUP] Processing logo in setupClinicGroup");
|
|
4208
|
+
try {
|
|
4209
|
+
const uploadedLogoUrl = await uploadPhoto(
|
|
4210
|
+
logoUrl,
|
|
4211
|
+
"clinic-groups",
|
|
4212
|
+
groupId,
|
|
4213
|
+
"logo",
|
|
4214
|
+
this.app
|
|
4215
|
+
);
|
|
4216
|
+
console.log("[CLINIC_GROUP] Logo processed in setupClinicGroup", {
|
|
4217
|
+
uploadedLogoUrl
|
|
4218
|
+
});
|
|
4219
|
+
if (uploadedLogoUrl !== null) {
|
|
4220
|
+
logoUrl = uploadedLogoUrl;
|
|
4221
|
+
}
|
|
4222
|
+
} catch (error) {
|
|
4223
|
+
console.error(
|
|
4224
|
+
"[CLINIC_GROUP] Error processing logo in setupClinicGroup:",
|
|
4225
|
+
error
|
|
4226
|
+
);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4079
4229
|
const updateData = {
|
|
4080
4230
|
languages: setupData.languages,
|
|
4081
4231
|
practiceType: setupData.practiceType,
|
|
4082
4232
|
description: setupData.description,
|
|
4083
|
-
logo:
|
|
4233
|
+
logo: logoUrl,
|
|
4084
4234
|
calendarSyncEnabled: setupData.calendarSyncEnabled,
|
|
4085
4235
|
autoConfirmAppointments: setupData.autoConfirmAppointments
|
|
4086
4236
|
};
|
|
4237
|
+
console.log("[CLINIC_GROUP] Updating clinic group with setup data");
|
|
4087
4238
|
return this.updateClinicGroup(groupId, updateData);
|
|
4088
4239
|
}
|
|
4089
4240
|
/**
|
|
@@ -4094,6 +4245,7 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4094
4245
|
this.db,
|
|
4095
4246
|
groupId,
|
|
4096
4247
|
creatorAdminId,
|
|
4248
|
+
this.app,
|
|
4097
4249
|
data
|
|
4098
4250
|
);
|
|
4099
4251
|
}
|
|
@@ -4105,7 +4257,8 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4105
4257
|
this.db,
|
|
4106
4258
|
groupId,
|
|
4107
4259
|
token,
|
|
4108
|
-
userRef
|
|
4260
|
+
userRef,
|
|
4261
|
+
this.app
|
|
4109
4262
|
);
|
|
4110
4263
|
}
|
|
4111
4264
|
/**
|
|
@@ -4116,14 +4269,20 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4116
4269
|
this.db,
|
|
4117
4270
|
groupId,
|
|
4118
4271
|
tokenId,
|
|
4119
|
-
adminId
|
|
4272
|
+
adminId,
|
|
4273
|
+
this.app
|
|
4120
4274
|
);
|
|
4121
4275
|
}
|
|
4122
4276
|
/**
|
|
4123
4277
|
* Dohvata aktivne admin tokene
|
|
4124
4278
|
*/
|
|
4125
4279
|
async getActiveAdminTokens(groupId, adminId) {
|
|
4126
|
-
return getActiveAdminTokens(
|
|
4280
|
+
return getActiveAdminTokens(
|
|
4281
|
+
this.db,
|
|
4282
|
+
groupId,
|
|
4283
|
+
adminId,
|
|
4284
|
+
this.app
|
|
4285
|
+
);
|
|
4127
4286
|
}
|
|
4128
4287
|
};
|
|
4129
4288
|
|
|
@@ -4141,44 +4300,193 @@ import {
|
|
|
4141
4300
|
} from "firebase/firestore";
|
|
4142
4301
|
import { geohashForLocation as geohashForLocation3 } from "geofire-common";
|
|
4143
4302
|
import { z as z14 } from "zod";
|
|
4144
|
-
async function createClinic(db, data, creatorAdminId, clinicGroupService, clinicAdminService) {
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4303
|
+
async function createClinic(db, data, creatorAdminId, clinicGroupService, clinicAdminService, app) {
|
|
4304
|
+
var _a;
|
|
4305
|
+
console.log("[CLINIC] Starting clinic creation", { creatorAdminId });
|
|
4306
|
+
console.log("[CLINIC] Input data:", JSON.stringify(data, null, 2));
|
|
4307
|
+
try {
|
|
4308
|
+
const validatedData2 = createClinicSchema.parse(data);
|
|
4309
|
+
console.log("[CLINIC] Data validation passed");
|
|
4310
|
+
} catch (validationError) {
|
|
4311
|
+
console.error("[CLINIC] Data validation failed:", validationError);
|
|
4312
|
+
throw validationError;
|
|
4149
4313
|
}
|
|
4150
|
-
|
|
4151
|
-
|
|
4314
|
+
const validatedData = createClinicSchema.parse(data);
|
|
4315
|
+
try {
|
|
4316
|
+
console.log("[CLINIC] Checking if admin exists and belongs to group");
|
|
4317
|
+
const admin = await clinicAdminService.getClinicAdmin(creatorAdminId);
|
|
4318
|
+
if (!admin) {
|
|
4319
|
+
console.error("[CLINIC] Admin not found", { creatorAdminId });
|
|
4320
|
+
throw new Error("Admin not found");
|
|
4321
|
+
}
|
|
4322
|
+
if (admin.clinicGroupId !== validatedData.clinicGroupId) {
|
|
4323
|
+
console.error("[CLINIC] Admin does not belong to this clinic group", {
|
|
4324
|
+
adminGroupId: admin.clinicGroupId,
|
|
4325
|
+
requestedGroupId: validatedData.clinicGroupId
|
|
4326
|
+
});
|
|
4327
|
+
throw new Error("Admin does not belong to this clinic group");
|
|
4328
|
+
}
|
|
4329
|
+
console.log("[CLINIC] Admin verified");
|
|
4330
|
+
} catch (adminError) {
|
|
4331
|
+
console.error("[CLINIC] Error verifying admin:", adminError);
|
|
4332
|
+
throw adminError;
|
|
4152
4333
|
}
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4334
|
+
try {
|
|
4335
|
+
console.log("[CLINIC] Checking if clinic group exists");
|
|
4336
|
+
const group = await clinicGroupService.getClinicGroup(
|
|
4337
|
+
validatedData.clinicGroupId
|
|
4338
|
+
);
|
|
4339
|
+
if (!group) {
|
|
4340
|
+
console.error("[CLINIC] Clinic group not found", {
|
|
4341
|
+
groupId: validatedData.clinicGroupId
|
|
4342
|
+
});
|
|
4343
|
+
throw new Error("Clinic group not found");
|
|
4344
|
+
}
|
|
4345
|
+
console.log("[CLINIC] Clinic group verified");
|
|
4346
|
+
} catch (groupError) {
|
|
4347
|
+
console.error("[CLINIC] Error verifying clinic group:", groupError);
|
|
4348
|
+
throw groupError;
|
|
4158
4349
|
}
|
|
4350
|
+
console.log("[CLINIC] Generating geohash for location");
|
|
4159
4351
|
if (validatedData.location) {
|
|
4160
|
-
|
|
4161
|
-
validatedData.location.
|
|
4162
|
-
|
|
4163
|
-
|
|
4352
|
+
try {
|
|
4353
|
+
validatedData.location.geohash = geohashForLocation3([
|
|
4354
|
+
validatedData.location.latitude,
|
|
4355
|
+
validatedData.location.longitude
|
|
4356
|
+
]);
|
|
4357
|
+
console.log("[CLINIC] Geohash generated successfully", {
|
|
4358
|
+
geohash: validatedData.location.geohash
|
|
4359
|
+
});
|
|
4360
|
+
} catch (geohashError) {
|
|
4361
|
+
console.error("[CLINIC] Error generating geohash:", geohashError);
|
|
4362
|
+
throw geohashError;
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
const clinicId = doc8(collection6(db, CLINICS_COLLECTION)).id;
|
|
4366
|
+
console.log("[CLINIC] Generated clinic ID:", clinicId);
|
|
4367
|
+
console.log("[CLINIC] Processing photos");
|
|
4368
|
+
let logoUrl = null;
|
|
4369
|
+
if (validatedData.logo) {
|
|
4370
|
+
console.log("[CLINIC] Processing logo");
|
|
4371
|
+
try {
|
|
4372
|
+
logoUrl = await uploadPhoto(
|
|
4373
|
+
validatedData.logo,
|
|
4374
|
+
"clinics",
|
|
4375
|
+
clinicId,
|
|
4376
|
+
"logo",
|
|
4377
|
+
app
|
|
4378
|
+
);
|
|
4379
|
+
console.log("[CLINIC] Logo processed", { logoUrl });
|
|
4380
|
+
} catch (logoError) {
|
|
4381
|
+
console.error("[CLINIC] Error processing logo:", logoError);
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
let processedPhotos = [];
|
|
4385
|
+
if (validatedData.photos && validatedData.photos.length > 0) {
|
|
4386
|
+
console.log("[CLINIC] Processing regular photos");
|
|
4387
|
+
try {
|
|
4388
|
+
processedPhotos = await uploadMultiplePhotos(
|
|
4389
|
+
validatedData.photos,
|
|
4390
|
+
"clinics",
|
|
4391
|
+
clinicId,
|
|
4392
|
+
"photo",
|
|
4393
|
+
app
|
|
4394
|
+
);
|
|
4395
|
+
console.log("[CLINIC] Regular photos processed", {
|
|
4396
|
+
count: processedPhotos.length
|
|
4397
|
+
});
|
|
4398
|
+
} catch (photosError) {
|
|
4399
|
+
console.error("[CLINIC] Error processing regular photos:", photosError);
|
|
4400
|
+
processedPhotos = validatedData.photos.filter(
|
|
4401
|
+
(photo) => !photo.startsWith("data:")
|
|
4402
|
+
);
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
let processedFeaturedPhotos = [];
|
|
4406
|
+
if (validatedData.featuredPhotos && validatedData.featuredPhotos.length > 0) {
|
|
4407
|
+
console.log("[CLINIC] Processing featured photos");
|
|
4408
|
+
try {
|
|
4409
|
+
processedFeaturedPhotos = await uploadMultiplePhotos(
|
|
4410
|
+
validatedData.featuredPhotos,
|
|
4411
|
+
"clinics",
|
|
4412
|
+
clinicId,
|
|
4413
|
+
"featured",
|
|
4414
|
+
app
|
|
4415
|
+
);
|
|
4416
|
+
console.log("[CLINIC] Featured photos processed", {
|
|
4417
|
+
count: processedFeaturedPhotos.length
|
|
4418
|
+
});
|
|
4419
|
+
} catch (featuredError) {
|
|
4420
|
+
console.error(
|
|
4421
|
+
"[CLINIC] Error processing featured photos:",
|
|
4422
|
+
featuredError
|
|
4423
|
+
);
|
|
4424
|
+
processedFeaturedPhotos = validatedData.featuredPhotos.filter(
|
|
4425
|
+
(photo) => !photo.startsWith("data:")
|
|
4426
|
+
);
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
let processedPhotosWithTags = validatedData.photosWithTags || [];
|
|
4430
|
+
if (processedPhotosWithTags.length > 0) {
|
|
4431
|
+
console.log("[CLINIC] Processing photos with tags");
|
|
4432
|
+
try {
|
|
4433
|
+
const updatedPhotosWithTags = [];
|
|
4434
|
+
for (const photoWithTag of processedPhotosWithTags) {
|
|
4435
|
+
if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
|
|
4436
|
+
const uploadedUrl = await uploadPhoto(
|
|
4437
|
+
photoWithTag.url,
|
|
4438
|
+
"clinics",
|
|
4439
|
+
clinicId,
|
|
4440
|
+
`tagged-${photoWithTag.tag}`,
|
|
4441
|
+
app
|
|
4442
|
+
);
|
|
4443
|
+
if (uploadedUrl) {
|
|
4444
|
+
updatedPhotosWithTags.push({
|
|
4445
|
+
url: uploadedUrl,
|
|
4446
|
+
tag: photoWithTag.tag
|
|
4447
|
+
});
|
|
4448
|
+
}
|
|
4449
|
+
} else {
|
|
4450
|
+
updatedPhotosWithTags.push(photoWithTag);
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
processedPhotosWithTags = updatedPhotosWithTags;
|
|
4454
|
+
console.log("[CLINIC] Photos with tags processed", {
|
|
4455
|
+
count: processedPhotosWithTags.length
|
|
4456
|
+
});
|
|
4457
|
+
} catch (tagsError) {
|
|
4458
|
+
console.error("[CLINIC] Error processing photos with tags:", tagsError);
|
|
4459
|
+
processedPhotosWithTags = ((_a = validatedData.photosWithTags) == null ? void 0 : _a.filter(
|
|
4460
|
+
(photo) => !photo.url.startsWith("data:")
|
|
4461
|
+
)) || [];
|
|
4462
|
+
}
|
|
4164
4463
|
}
|
|
4165
4464
|
const now = Timestamp11.now();
|
|
4465
|
+
console.log("[CLINIC] Preparing clinic data object");
|
|
4166
4466
|
const clinicData = {
|
|
4167
4467
|
...validatedData,
|
|
4168
|
-
id:
|
|
4468
|
+
id: clinicId,
|
|
4169
4469
|
description: validatedData.description || void 0,
|
|
4170
4470
|
location: {
|
|
4171
|
-
|
|
4471
|
+
address: validatedData.location.address || "",
|
|
4472
|
+
city: validatedData.location.city || "",
|
|
4473
|
+
country: validatedData.location.country || "",
|
|
4474
|
+
postalCode: validatedData.location.postalCode || "",
|
|
4475
|
+
latitude: validatedData.location.latitude || 0,
|
|
4476
|
+
longitude: validatedData.location.longitude || 0,
|
|
4172
4477
|
geohash: validatedData.location.geohash || void 0
|
|
4173
4478
|
},
|
|
4174
4479
|
contactInfo: {
|
|
4175
|
-
|
|
4480
|
+
email: validatedData.contactInfo.email || "",
|
|
4481
|
+
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
4176
4482
|
alternativePhoneNumber: validatedData.contactInfo.alternativePhoneNumber || void 0,
|
|
4177
4483
|
website: validatedData.contactInfo.website || void 0
|
|
4178
4484
|
},
|
|
4485
|
+
logo: logoUrl || void 0,
|
|
4179
4486
|
tags: validatedData.tags || [],
|
|
4180
|
-
featuredPhotos: [],
|
|
4181
|
-
photos:
|
|
4487
|
+
featuredPhotos: processedFeaturedPhotos || [],
|
|
4488
|
+
photos: processedPhotos || [],
|
|
4489
|
+
photosWithTags: processedPhotosWithTags,
|
|
4182
4490
|
doctors: [],
|
|
4183
4491
|
doctorsInfo: [],
|
|
4184
4492
|
services: [],
|
|
@@ -4193,17 +4501,73 @@ async function createClinic(db, data, creatorAdminId, clinicGroupService, clinic
|
|
|
4193
4501
|
isVerified: false
|
|
4194
4502
|
};
|
|
4195
4503
|
try {
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4504
|
+
console.log("[CLINIC] Validating complete clinic object");
|
|
4505
|
+
try {
|
|
4506
|
+
clinicSchema.parse(clinicData);
|
|
4507
|
+
console.log("[CLINIC] Clinic validation passed");
|
|
4508
|
+
} catch (schemaError) {
|
|
4509
|
+
console.error(
|
|
4510
|
+
"[CLINIC] Clinic validation failed:",
|
|
4511
|
+
JSON.stringify(schemaError, null, 2)
|
|
4512
|
+
);
|
|
4513
|
+
throw schemaError;
|
|
4514
|
+
}
|
|
4515
|
+
console.log("[CLINIC] Saving clinic to Firestore", {
|
|
4516
|
+
clinicId: clinicData.id
|
|
4517
|
+
});
|
|
4518
|
+
try {
|
|
4519
|
+
await setDoc10(doc8(db, CLINICS_COLLECTION, clinicData.id), clinicData);
|
|
4520
|
+
console.log("[CLINIC] Clinic saved successfully");
|
|
4521
|
+
} catch (firestoreError) {
|
|
4522
|
+
console.error("[CLINIC] Error saving to Firestore:", firestoreError);
|
|
4523
|
+
throw firestoreError;
|
|
4524
|
+
}
|
|
4525
|
+
console.log("[CLINIC] Adding clinic to clinic group");
|
|
4526
|
+
try {
|
|
4527
|
+
const group = await clinicGroupService.getClinicGroup(
|
|
4528
|
+
validatedData.clinicGroupId
|
|
4529
|
+
);
|
|
4530
|
+
if (group) {
|
|
4531
|
+
await clinicGroupService.updateClinicGroup(
|
|
4532
|
+
validatedData.clinicGroupId,
|
|
4533
|
+
{
|
|
4534
|
+
clinics: [...group.clinics, clinicData.id]
|
|
4535
|
+
}
|
|
4536
|
+
);
|
|
4537
|
+
console.log("[CLINIC] Clinic added to group successfully");
|
|
4538
|
+
}
|
|
4539
|
+
} catch (groupUpdateError) {
|
|
4540
|
+
console.error("[CLINIC] Error adding clinic to group:", groupUpdateError);
|
|
4541
|
+
}
|
|
4542
|
+
console.log("[CLINIC] Adding clinic to admin's managed clinics");
|
|
4543
|
+
try {
|
|
4544
|
+
await clinicAdminService.addClinicToManaged(
|
|
4545
|
+
creatorAdminId,
|
|
4546
|
+
clinicData.id
|
|
4547
|
+
);
|
|
4548
|
+
console.log(
|
|
4549
|
+
"[CLINIC] Clinic added to admin's managed clinics successfully"
|
|
4550
|
+
);
|
|
4551
|
+
} catch (adminUpdateError) {
|
|
4552
|
+
console.error(
|
|
4553
|
+
"[CLINIC] Error adding clinic to admin's managed clinics:",
|
|
4554
|
+
adminUpdateError
|
|
4555
|
+
);
|
|
4556
|
+
}
|
|
4557
|
+
console.log("[CLINIC] Clinic creation completed successfully", {
|
|
4558
|
+
clinicId: clinicData.id,
|
|
4559
|
+
clinicName: clinicData.name
|
|
4200
4560
|
});
|
|
4201
|
-
await clinicAdminService.addClinicToManaged(creatorAdminId, clinicData.id);
|
|
4202
4561
|
return clinicData;
|
|
4203
4562
|
} catch (error) {
|
|
4204
4563
|
if (error instanceof z14.ZodError) {
|
|
4564
|
+
console.error(
|
|
4565
|
+
"[CLINIC] Zod validation error:",
|
|
4566
|
+
JSON.stringify(error.errors, null, 2)
|
|
4567
|
+
);
|
|
4205
4568
|
throw new Error("Invalid clinic data: " + error.message);
|
|
4206
4569
|
}
|
|
4570
|
+
console.error("[CLINIC] Unhandled error in createClinic:", error);
|
|
4207
4571
|
throw error;
|
|
4208
4572
|
}
|
|
4209
4573
|
}
|
|
@@ -4224,27 +4588,177 @@ async function getClinicsByGroup(db, groupId) {
|
|
|
4224
4588
|
const querySnapshot = await getDocs6(q);
|
|
4225
4589
|
return querySnapshot.docs.map((doc14) => doc14.data());
|
|
4226
4590
|
}
|
|
4227
|
-
async function updateClinic(db, clinicId, data, adminId, clinicAdminService) {
|
|
4591
|
+
async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
|
|
4592
|
+
console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
|
|
4228
4593
|
const clinic = await getClinic(db, clinicId);
|
|
4229
4594
|
if (!clinic) {
|
|
4595
|
+
console.error("[CLINIC] Clinic not found", { clinicId });
|
|
4230
4596
|
throw new Error("Clinic not found");
|
|
4231
4597
|
}
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4598
|
+
try {
|
|
4599
|
+
console.log("[CLINIC] Checking admin permissions");
|
|
4600
|
+
const admin = await clinicAdminService.getClinicAdmin(adminId);
|
|
4601
|
+
if (!admin) {
|
|
4602
|
+
console.error("[CLINIC] Admin not found", { adminId });
|
|
4603
|
+
throw new Error("Admin not found");
|
|
4604
|
+
}
|
|
4605
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4606
|
+
if (!hasPermission) {
|
|
4607
|
+
console.error(
|
|
4608
|
+
"[CLINIC] Admin does not have permission to update this clinic",
|
|
4609
|
+
{
|
|
4610
|
+
adminId,
|
|
4611
|
+
clinicId,
|
|
4612
|
+
isGroupOwner: admin.isGroupOwner,
|
|
4613
|
+
clinicsManaged: admin.clinicsManaged,
|
|
4614
|
+
isClinicAdmin: clinic.admins && clinic.admins.includes(adminId)
|
|
4615
|
+
}
|
|
4616
|
+
);
|
|
4617
|
+
throw new Error("Admin does not have permission to update this clinic");
|
|
4618
|
+
}
|
|
4619
|
+
console.log("[CLINIC] Admin permissions verified");
|
|
4620
|
+
} catch (adminError) {
|
|
4621
|
+
console.error("[CLINIC] Error verifying admin permissions:", adminError);
|
|
4622
|
+
throw adminError;
|
|
4623
|
+
}
|
|
4624
|
+
let updatedData = { ...data };
|
|
4625
|
+
if (data.logo && typeof data.logo === "string" && data.logo.startsWith("data:")) {
|
|
4626
|
+
console.log("[CLINIC] Processing logo update");
|
|
4627
|
+
try {
|
|
4628
|
+
const logoUrl = await uploadPhoto(
|
|
4629
|
+
data.logo,
|
|
4630
|
+
"clinics",
|
|
4631
|
+
clinicId,
|
|
4632
|
+
"logo",
|
|
4633
|
+
app
|
|
4634
|
+
);
|
|
4635
|
+
console.log("[CLINIC] Logo update processed", { logoUrl });
|
|
4636
|
+
if (logoUrl !== null) {
|
|
4637
|
+
updatedData.logo = logoUrl;
|
|
4638
|
+
}
|
|
4639
|
+
} catch (logoError) {
|
|
4640
|
+
console.error("[CLINIC] Error processing logo update:", logoError);
|
|
4641
|
+
}
|
|
4235
4642
|
}
|
|
4236
|
-
if (
|
|
4237
|
-
|
|
4643
|
+
if (data.photos && data.photos.length > 0) {
|
|
4644
|
+
console.log("[CLINIC] Processing regular photos update");
|
|
4645
|
+
try {
|
|
4646
|
+
const dataUrlPhotos = data.photos.filter(
|
|
4647
|
+
(photo) => typeof photo === "string" && photo.startsWith("data:")
|
|
4648
|
+
);
|
|
4649
|
+
const existingPhotos = data.photos.filter(
|
|
4650
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4651
|
+
);
|
|
4652
|
+
if (dataUrlPhotos.length > 0) {
|
|
4653
|
+
const uploadedPhotos = await uploadMultiplePhotos(
|
|
4654
|
+
dataUrlPhotos,
|
|
4655
|
+
"clinics",
|
|
4656
|
+
clinicId,
|
|
4657
|
+
"photo",
|
|
4658
|
+
app
|
|
4659
|
+
);
|
|
4660
|
+
console.log("[CLINIC] Regular photos update processed", {
|
|
4661
|
+
count: uploadedPhotos.length
|
|
4662
|
+
});
|
|
4663
|
+
updatedData.photos = [...existingPhotos, ...uploadedPhotos];
|
|
4664
|
+
}
|
|
4665
|
+
} catch (photosError) {
|
|
4666
|
+
console.error(
|
|
4667
|
+
"[CLINIC] Error processing regular photos update:",
|
|
4668
|
+
photosError
|
|
4669
|
+
);
|
|
4670
|
+
updatedData.photos = data.photos.filter(
|
|
4671
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4672
|
+
);
|
|
4673
|
+
}
|
|
4238
4674
|
}
|
|
4239
|
-
|
|
4240
|
-
|
|
4675
|
+
if (data.featuredPhotos && data.featuredPhotos.length > 0) {
|
|
4676
|
+
console.log("[CLINIC] Processing featured photos update");
|
|
4677
|
+
try {
|
|
4678
|
+
const dataUrlPhotos = data.featuredPhotos.filter(
|
|
4679
|
+
(photo) => typeof photo === "string" && photo.startsWith("data:")
|
|
4680
|
+
);
|
|
4681
|
+
const existingPhotos = data.featuredPhotos.filter(
|
|
4682
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4683
|
+
);
|
|
4684
|
+
if (dataUrlPhotos.length > 0) {
|
|
4685
|
+
const uploadedPhotos = await uploadMultiplePhotos(
|
|
4686
|
+
dataUrlPhotos,
|
|
4687
|
+
"clinics",
|
|
4688
|
+
clinicId,
|
|
4689
|
+
"featured",
|
|
4690
|
+
app
|
|
4691
|
+
);
|
|
4692
|
+
console.log("[CLINIC] Featured photos update processed", {
|
|
4693
|
+
count: uploadedPhotos.length
|
|
4694
|
+
});
|
|
4695
|
+
updatedData.featuredPhotos = [...existingPhotos, ...uploadedPhotos];
|
|
4696
|
+
}
|
|
4697
|
+
} catch (featuredError) {
|
|
4698
|
+
console.error(
|
|
4699
|
+
"[CLINIC] Error processing featured photos update:",
|
|
4700
|
+
featuredError
|
|
4701
|
+
);
|
|
4702
|
+
updatedData.featuredPhotos = data.featuredPhotos.filter(
|
|
4703
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4704
|
+
);
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
if (data.photosWithTags && data.photosWithTags.length > 0) {
|
|
4708
|
+
console.log("[CLINIC] Processing photos with tags update");
|
|
4709
|
+
try {
|
|
4710
|
+
const updatedPhotosWithTags = [];
|
|
4711
|
+
for (const photoWithTag of data.photosWithTags) {
|
|
4712
|
+
if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
|
|
4713
|
+
const uploadedUrl = await uploadPhoto(
|
|
4714
|
+
photoWithTag.url,
|
|
4715
|
+
"clinics",
|
|
4716
|
+
clinicId,
|
|
4717
|
+
`tagged-${photoWithTag.tag}`,
|
|
4718
|
+
app
|
|
4719
|
+
);
|
|
4720
|
+
if (uploadedUrl) {
|
|
4721
|
+
updatedPhotosWithTags.push({
|
|
4722
|
+
url: uploadedUrl,
|
|
4723
|
+
tag: photoWithTag.tag
|
|
4724
|
+
});
|
|
4725
|
+
}
|
|
4726
|
+
} else {
|
|
4727
|
+
updatedPhotosWithTags.push(photoWithTag);
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
updatedData.photosWithTags = updatedPhotosWithTags;
|
|
4731
|
+
console.log("[CLINIC] Photos with tags update processed", {
|
|
4732
|
+
count: updatedPhotosWithTags.length
|
|
4733
|
+
});
|
|
4734
|
+
} catch (tagsError) {
|
|
4735
|
+
console.error(
|
|
4736
|
+
"[CLINIC] Error processing photos with tags update:",
|
|
4737
|
+
tagsError
|
|
4738
|
+
);
|
|
4739
|
+
updatedData.photosWithTags = data.photosWithTags.filter(
|
|
4740
|
+
(photo) => !photo.url.startsWith("data:")
|
|
4741
|
+
);
|
|
4742
|
+
}
|
|
4743
|
+
}
|
|
4744
|
+
updatedData = {
|
|
4745
|
+
...updatedData,
|
|
4241
4746
|
updatedAt: Timestamp11.now()
|
|
4242
4747
|
};
|
|
4243
|
-
|
|
4748
|
+
console.log("[CLINIC] Updating clinic in Firestore");
|
|
4749
|
+
try {
|
|
4750
|
+
await updateDoc11(doc8(db, CLINICS_COLLECTION, clinicId), updatedData);
|
|
4751
|
+
console.log("[CLINIC] Clinic updated successfully");
|
|
4752
|
+
} catch (updateError) {
|
|
4753
|
+
console.error("[CLINIC] Error updating clinic in Firestore:", updateError);
|
|
4754
|
+
throw updateError;
|
|
4755
|
+
}
|
|
4244
4756
|
const updatedClinic = await getClinic(db, clinicId);
|
|
4245
4757
|
if (!updatedClinic) {
|
|
4758
|
+
console.error("[CLINIC] Failed to retrieve updated clinic");
|
|
4246
4759
|
throw new Error("Failed to retrieve updated clinic");
|
|
4247
4760
|
}
|
|
4761
|
+
console.log("[CLINIC] Clinic update completed successfully");
|
|
4248
4762
|
return updatedClinic;
|
|
4249
4763
|
}
|
|
4250
4764
|
async function deactivateClinic(db, clinicId, adminId, clinicAdminService) {
|
|
@@ -4256,7 +4770,8 @@ async function deactivateClinic(db, clinicId, adminId, clinicAdminService) {
|
|
|
4256
4770
|
if (!admin) {
|
|
4257
4771
|
throw new Error("Admin not found");
|
|
4258
4772
|
}
|
|
4259
|
-
|
|
4773
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4774
|
+
if (!hasPermission) {
|
|
4260
4775
|
throw new Error("Admin does not have permission to deactivate this clinic");
|
|
4261
4776
|
}
|
|
4262
4777
|
await updateDoc11(doc8(db, CLINICS_COLLECTION, clinicId), {
|
|
@@ -4301,27 +4816,28 @@ async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGr
|
|
|
4301
4816
|
import {
|
|
4302
4817
|
collection as collection7,
|
|
4303
4818
|
doc as doc9,
|
|
4304
|
-
|
|
4305
|
-
|
|
4819
|
+
Timestamp as Timestamp12,
|
|
4820
|
+
getDoc as getDoc13,
|
|
4821
|
+
addDoc as addDoc2
|
|
4306
4822
|
} from "firebase/firestore";
|
|
4307
|
-
async function addReview(db, clinicId, review) {
|
|
4308
|
-
const
|
|
4309
|
-
|
|
4823
|
+
async function addReview(db, clinicId, review, app) {
|
|
4824
|
+
const clinicRef = doc9(db, "clinics", clinicId);
|
|
4825
|
+
const clinicSnap = await getDoc13(clinicRef);
|
|
4826
|
+
if (!clinicSnap.exists()) {
|
|
4310
4827
|
throw new Error("Clinic not found");
|
|
4311
4828
|
}
|
|
4829
|
+
const clinic = clinicSnap.data();
|
|
4312
4830
|
const now = Timestamp12.now();
|
|
4313
4831
|
const reviewData = {
|
|
4832
|
+
...review,
|
|
4314
4833
|
id: doc9(collection7(db, "clinic_reviews")).id,
|
|
4315
4834
|
clinicId,
|
|
4316
|
-
patientId: review.patientId,
|
|
4317
|
-
rating: review.rating,
|
|
4318
|
-
comment: review.comment,
|
|
4319
4835
|
createdAt: now,
|
|
4320
4836
|
updatedAt: now,
|
|
4321
4837
|
isVerified: false
|
|
4322
4838
|
};
|
|
4323
4839
|
clinicReviewSchema.parse(reviewData);
|
|
4324
|
-
await
|
|
4840
|
+
await addDoc2(collection7(db, "clinic_reviews"), reviewData);
|
|
4325
4841
|
const newRating = clinic.rating ? {
|
|
4326
4842
|
average: (clinic.rating.average * clinic.rating.count + review.rating) / (clinic.rating.count + 1),
|
|
4327
4843
|
count: clinic.rating.count + 1
|
|
@@ -4337,28 +4853,24 @@ async function addReview(db, clinicId, review) {
|
|
|
4337
4853
|
...clinic.reviewsInfo,
|
|
4338
4854
|
{
|
|
4339
4855
|
id: reviewData.id,
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
// This should be fetched from patient service
|
|
4345
|
-
patientPhoto: "",
|
|
4346
|
-
// This should be fetched from patient service
|
|
4347
|
-
createdAt: now,
|
|
4348
|
-
updatedAt: now
|
|
4856
|
+
patientId: reviewData.patientId,
|
|
4857
|
+
rating: reviewData.rating,
|
|
4858
|
+
comment: reviewData.comment,
|
|
4859
|
+
createdAt: reviewData.createdAt
|
|
4349
4860
|
}
|
|
4350
4861
|
]
|
|
4351
4862
|
},
|
|
4352
|
-
|
|
4353
|
-
//
|
|
4354
|
-
|
|
4355
|
-
//
|
|
4863
|
+
"system",
|
|
4864
|
+
// System update, no admin ID needed
|
|
4865
|
+
null,
|
|
4866
|
+
// No clinic admin service needed for system updates
|
|
4867
|
+
app
|
|
4356
4868
|
);
|
|
4357
4869
|
return reviewData;
|
|
4358
4870
|
}
|
|
4359
4871
|
|
|
4360
4872
|
// src/services/clinic/utils/tag.utils.ts
|
|
4361
|
-
async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
4873
|
+
async function addTags(db, clinicId, adminId, newTags, clinicAdminService, app) {
|
|
4362
4874
|
const clinic = await getClinic(db, clinicId);
|
|
4363
4875
|
if (!clinic) {
|
|
4364
4876
|
throw new Error("Clinic not found");
|
|
@@ -4367,7 +4879,8 @@ async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
|
4367
4879
|
if (!admin) {
|
|
4368
4880
|
throw new Error("Admin not found");
|
|
4369
4881
|
}
|
|
4370
|
-
|
|
4882
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4883
|
+
if (!hasPermission) {
|
|
4371
4884
|
throw new Error("Admin does not have permission to update this clinic");
|
|
4372
4885
|
}
|
|
4373
4886
|
const updatedTags = [.../* @__PURE__ */ new Set([...clinic.tags, ...newTags.tags || []])];
|
|
@@ -4378,10 +4891,11 @@ async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
|
4378
4891
|
tags: updatedTags
|
|
4379
4892
|
},
|
|
4380
4893
|
adminId,
|
|
4381
|
-
clinicAdminService
|
|
4894
|
+
clinicAdminService,
|
|
4895
|
+
app
|
|
4382
4896
|
);
|
|
4383
4897
|
}
|
|
4384
|
-
async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminService) {
|
|
4898
|
+
async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminService, app) {
|
|
4385
4899
|
const clinic = await getClinic(db, clinicId);
|
|
4386
4900
|
if (!clinic) {
|
|
4387
4901
|
throw new Error("Clinic not found");
|
|
@@ -4390,14 +4904,12 @@ async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminServic
|
|
|
4390
4904
|
if (!admin) {
|
|
4391
4905
|
throw new Error("Admin not found");
|
|
4392
4906
|
}
|
|
4393
|
-
|
|
4907
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4908
|
+
if (!hasPermission) {
|
|
4394
4909
|
throw new Error("Admin does not have permission to update this clinic");
|
|
4395
4910
|
}
|
|
4396
4911
|
const updatedTags = clinic.tags.filter(
|
|
4397
|
-
(tag) =>
|
|
4398
|
-
var _a;
|
|
4399
|
-
return !((_a = tagsToRemove.tags) == null ? void 0 : _a.includes(tag));
|
|
4400
|
-
}
|
|
4912
|
+
(tag) => !tagsToRemove.tags || !tagsToRemove.tags.includes(tag)
|
|
4401
4913
|
);
|
|
4402
4914
|
return updateClinic(
|
|
4403
4915
|
db,
|
|
@@ -4406,7 +4918,8 @@ async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminServic
|
|
|
4406
4918
|
tags: updatedTags
|
|
4407
4919
|
},
|
|
4408
4920
|
adminId,
|
|
4409
|
-
clinicAdminService
|
|
4921
|
+
clinicAdminService,
|
|
4922
|
+
app
|
|
4410
4923
|
);
|
|
4411
4924
|
}
|
|
4412
4925
|
|
|
@@ -4481,7 +4994,8 @@ var ClinicService = class extends BaseService {
|
|
|
4481
4994
|
data,
|
|
4482
4995
|
creatorAdminId,
|
|
4483
4996
|
this.clinicGroupService,
|
|
4484
|
-
this.clinicAdminService
|
|
4997
|
+
this.clinicAdminService,
|
|
4998
|
+
this.app
|
|
4485
4999
|
);
|
|
4486
5000
|
}
|
|
4487
5001
|
/**
|
|
@@ -4516,14 +5030,15 @@ var ClinicService = class extends BaseService {
|
|
|
4516
5030
|
clinicId,
|
|
4517
5031
|
data,
|
|
4518
5032
|
adminId,
|
|
4519
|
-
this.clinicAdminService
|
|
5033
|
+
this.clinicAdminService,
|
|
5034
|
+
this.app
|
|
4520
5035
|
);
|
|
4521
5036
|
}
|
|
4522
5037
|
/**
|
|
4523
5038
|
* Dodaje recenziju klinici
|
|
4524
5039
|
*/
|
|
4525
5040
|
async addReview(clinicId, review) {
|
|
4526
|
-
return addReview(this.db, clinicId, review);
|
|
5041
|
+
return addReview(this.db, clinicId, review, this.app);
|
|
4527
5042
|
}
|
|
4528
5043
|
/**
|
|
4529
5044
|
* Deaktivira kliniku
|
|
@@ -4545,7 +5060,8 @@ var ClinicService = class extends BaseService {
|
|
|
4545
5060
|
clinicId,
|
|
4546
5061
|
adminId,
|
|
4547
5062
|
newTags,
|
|
4548
|
-
this.clinicAdminService
|
|
5063
|
+
this.clinicAdminService,
|
|
5064
|
+
this.app
|
|
4549
5065
|
);
|
|
4550
5066
|
}
|
|
4551
5067
|
/**
|
|
@@ -4557,7 +5073,8 @@ var ClinicService = class extends BaseService {
|
|
|
4557
5073
|
clinicId,
|
|
4558
5074
|
adminId,
|
|
4559
5075
|
tagsToRemove,
|
|
4560
|
-
this.clinicAdminService
|
|
5076
|
+
this.clinicAdminService,
|
|
5077
|
+
this.app
|
|
4561
5078
|
);
|
|
4562
5079
|
}
|
|
4563
5080
|
/**
|
|
@@ -4592,12 +5109,21 @@ var ClinicService = class extends BaseService {
|
|
|
4592
5109
|
* @returns The created clinic
|
|
4593
5110
|
*/
|
|
4594
5111
|
async createClinicBranch(clinicGroupId, setupData, adminId) {
|
|
5112
|
+
var _a, _b;
|
|
5113
|
+
console.log("[CLINIC_SERVICE] Starting clinic branch creation", {
|
|
5114
|
+
clinicGroupId,
|
|
5115
|
+
adminId
|
|
5116
|
+
});
|
|
4595
5117
|
const clinicGroup = await this.clinicGroupService.getClinicGroup(
|
|
4596
5118
|
clinicGroupId
|
|
4597
5119
|
);
|
|
4598
5120
|
if (!clinicGroup) {
|
|
5121
|
+
console.error("[CLINIC_SERVICE] Clinic group not found", {
|
|
5122
|
+
clinicGroupId
|
|
5123
|
+
});
|
|
4599
5124
|
throw new Error(`Clinic group with ID ${clinicGroupId} not found`);
|
|
4600
5125
|
}
|
|
5126
|
+
console.log("[CLINIC_SERVICE] Clinic group verified");
|
|
4601
5127
|
const createClinicData = {
|
|
4602
5128
|
clinicGroupId,
|
|
4603
5129
|
name: setupData.name,
|
|
@@ -4606,8 +5132,8 @@ var ClinicService = class extends BaseService {
|
|
|
4606
5132
|
contactInfo: setupData.contactInfo,
|
|
4607
5133
|
workingHours: setupData.workingHours,
|
|
4608
5134
|
tags: setupData.tags,
|
|
4609
|
-
photos: setupData.photos,
|
|
4610
|
-
photosWithTags: setupData.photosWithTags,
|
|
5135
|
+
photos: setupData.photos || [],
|
|
5136
|
+
photosWithTags: setupData.photosWithTags || [],
|
|
4611
5137
|
doctors: [],
|
|
4612
5138
|
services: [],
|
|
4613
5139
|
admins: [adminId],
|
|
@@ -4616,7 +5142,17 @@ var ClinicService = class extends BaseService {
|
|
|
4616
5142
|
logo: setupData.logo,
|
|
4617
5143
|
featuredPhotos: setupData.featuredPhotos || []
|
|
4618
5144
|
};
|
|
5145
|
+
console.log("[CLINIC_SERVICE] Creating clinic branch with data", {
|
|
5146
|
+
name: createClinicData.name,
|
|
5147
|
+
hasLogo: !!createClinicData.logo,
|
|
5148
|
+
photosCount: createClinicData.photos.length,
|
|
5149
|
+
featuredPhotosCount: ((_a = createClinicData.featuredPhotos) == null ? void 0 : _a.length) || 0,
|
|
5150
|
+
photosWithTagsCount: ((_b = createClinicData.photosWithTags) == null ? void 0 : _b.length) || 0
|
|
5151
|
+
});
|
|
4619
5152
|
const clinic = await this.createClinic(createClinicData, adminId);
|
|
5153
|
+
console.log("[CLINIC_SERVICE] Clinic branch created successfully", {
|
|
5154
|
+
clinicId: clinic.id
|
|
5155
|
+
});
|
|
4620
5156
|
return clinic;
|
|
4621
5157
|
}
|
|
4622
5158
|
};
|
|
@@ -4738,7 +5274,7 @@ var AuthService = class extends BaseService {
|
|
|
4738
5274
|
"Clinic group data is required when creating a new group"
|
|
4739
5275
|
);
|
|
4740
5276
|
}
|
|
4741
|
-
console.log("[AUTH] Creating clinic admin first");
|
|
5277
|
+
console.log("[AUTH] Creating clinic admin first (without group)");
|
|
4742
5278
|
const createClinicAdminData = {
|
|
4743
5279
|
userRef: firebaseUser.uid,
|
|
4744
5280
|
isGroupOwner: true,
|
|
@@ -4746,10 +5282,16 @@ var AuthService = class extends BaseService {
|
|
|
4746
5282
|
contactInfo: contactPerson,
|
|
4747
5283
|
roleTitle: data.title,
|
|
4748
5284
|
isActive: true
|
|
5285
|
+
// No clinicGroupId yet
|
|
4749
5286
|
};
|
|
5287
|
+
let adminProfile;
|
|
4750
5288
|
try {
|
|
4751
|
-
await clinicAdminService.createClinicAdmin(
|
|
4752
|
-
|
|
5289
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
5290
|
+
createClinicAdminData
|
|
5291
|
+
);
|
|
5292
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
5293
|
+
adminId: adminProfile.id
|
|
5294
|
+
});
|
|
4753
5295
|
} catch (adminCreationError) {
|
|
4754
5296
|
console.error(
|
|
4755
5297
|
"[AUTH] Clinic admin creation failed:",
|
|
@@ -4762,7 +5304,8 @@ var AuthService = class extends BaseService {
|
|
|
4762
5304
|
hqLocation: data.clinicGroupData.hqLocation,
|
|
4763
5305
|
contactInfo: data.clinicGroupData.contactInfo,
|
|
4764
5306
|
contactPerson,
|
|
4765
|
-
ownerId:
|
|
5307
|
+
ownerId: adminProfile.id,
|
|
5308
|
+
// Use admin profile ID, not user UID
|
|
4766
5309
|
isActive: true,
|
|
4767
5310
|
logo: data.clinicGroupData.logo || null,
|
|
4768
5311
|
subscriptionModel: data.clinicGroupData.subscriptionModel || "no_subscription" /* NO_SUBSCRIPTION */
|
|
@@ -4770,13 +5313,24 @@ var AuthService = class extends BaseService {
|
|
|
4770
5313
|
console.log("[AUTH] Clinic group data prepared", {
|
|
4771
5314
|
groupName: createClinicGroupData.name
|
|
4772
5315
|
});
|
|
5316
|
+
let clinicGroup;
|
|
4773
5317
|
try {
|
|
4774
|
-
await clinicGroupService.createClinicGroup(
|
|
5318
|
+
clinicGroup = await clinicGroupService.createClinicGroup(
|
|
4775
5319
|
createClinicGroupData,
|
|
4776
|
-
|
|
4777
|
-
|
|
5320
|
+
adminProfile.id,
|
|
5321
|
+
// Use admin profile ID, not user UID
|
|
5322
|
+
false
|
|
5323
|
+
// This is not a default group since we're providing complete data
|
|
4778
5324
|
);
|
|
4779
|
-
console.log("[AUTH] Clinic group created successfully"
|
|
5325
|
+
console.log("[AUTH] Clinic group created successfully", {
|
|
5326
|
+
groupId: clinicGroup.id
|
|
5327
|
+
});
|
|
5328
|
+
console.log("[AUTH] Updating admin with clinic group ID");
|
|
5329
|
+
await clinicAdminService.updateClinicAdmin(adminProfile.id, {
|
|
5330
|
+
// Use admin profile ID, not user UID
|
|
5331
|
+
clinicGroupId: clinicGroup.id
|
|
5332
|
+
});
|
|
5333
|
+
console.log("[AUTH] Admin updated with clinic group ID successfully");
|
|
4780
5334
|
} catch (groupCreationError) {
|
|
4781
5335
|
console.error(
|
|
4782
5336
|
"[AUTH] Clinic group creation failed:",
|
|
@@ -4849,9 +5403,14 @@ var AuthService = class extends BaseService {
|
|
|
4849
5403
|
roleTitle: data.title,
|
|
4850
5404
|
isActive: true
|
|
4851
5405
|
};
|
|
5406
|
+
let adminProfile;
|
|
4852
5407
|
try {
|
|
4853
|
-
await clinicAdminService.createClinicAdmin(
|
|
4854
|
-
|
|
5408
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
5409
|
+
createClinicAdminData
|
|
5410
|
+
);
|
|
5411
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
5412
|
+
adminId: adminProfile.id
|
|
5413
|
+
});
|
|
4855
5414
|
} catch (adminCreationError) {
|
|
4856
5415
|
console.error(
|
|
4857
5416
|
"[AUTH] Clinic admin creation failed:",
|
|
@@ -5160,7 +5719,7 @@ var AuthService = class extends BaseService {
|
|
|
5160
5719
|
import {
|
|
5161
5720
|
collection as collection10,
|
|
5162
5721
|
doc as doc11,
|
|
5163
|
-
getDoc as
|
|
5722
|
+
getDoc as getDoc15,
|
|
5164
5723
|
getDocs as getDocs9,
|
|
5165
5724
|
query as query9,
|
|
5166
5725
|
where as where9,
|
|
@@ -5168,8 +5727,8 @@ import {
|
|
|
5168
5727
|
deleteDoc as deleteDoc6,
|
|
5169
5728
|
orderBy,
|
|
5170
5729
|
Timestamp as Timestamp14,
|
|
5171
|
-
addDoc,
|
|
5172
|
-
writeBatch as
|
|
5730
|
+
addDoc as addDoc3,
|
|
5731
|
+
writeBatch as writeBatch3
|
|
5173
5732
|
} from "firebase/firestore";
|
|
5174
5733
|
|
|
5175
5734
|
// src/types/notifications/index.ts
|
|
@@ -5206,7 +5765,7 @@ var NotificationService = class extends BaseService {
|
|
|
5206
5765
|
isRead: false,
|
|
5207
5766
|
userRole: notification.userRole || "patient" /* PATIENT */
|
|
5208
5767
|
};
|
|
5209
|
-
const docRef = await
|
|
5768
|
+
const docRef = await addDoc3(notificationsRef, notificationData);
|
|
5210
5769
|
return {
|
|
5211
5770
|
...notificationData,
|
|
5212
5771
|
id: docRef.id
|
|
@@ -5221,7 +5780,7 @@ var NotificationService = class extends BaseService {
|
|
|
5221
5780
|
NOTIFICATIONS_COLLECTION,
|
|
5222
5781
|
notificationId
|
|
5223
5782
|
);
|
|
5224
|
-
const notificationDoc = await
|
|
5783
|
+
const notificationDoc = await getDoc15(notificationRef);
|
|
5225
5784
|
if (!notificationDoc.exists()) {
|
|
5226
5785
|
return null;
|
|
5227
5786
|
}
|
|
@@ -5280,7 +5839,7 @@ var NotificationService = class extends BaseService {
|
|
|
5280
5839
|
*/
|
|
5281
5840
|
async markAllAsRead(userId) {
|
|
5282
5841
|
const notifications = await this.getUnreadNotifications(userId);
|
|
5283
|
-
const batch =
|
|
5842
|
+
const batch = writeBatch3(this.db);
|
|
5284
5843
|
notifications.forEach((notification) => {
|
|
5285
5844
|
const notificationRef = doc11(
|
|
5286
5845
|
this.db,
|
|
@@ -5356,7 +5915,7 @@ var NotificationService = class extends BaseService {
|
|
|
5356
5915
|
import {
|
|
5357
5916
|
collection as collection11,
|
|
5358
5917
|
doc as doc12,
|
|
5359
|
-
getDoc as
|
|
5918
|
+
getDoc as getDoc16,
|
|
5360
5919
|
getDocs as getDocs10,
|
|
5361
5920
|
setDoc as setDoc13,
|
|
5362
5921
|
updateDoc as updateDoc14,
|
|
@@ -5412,7 +5971,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
5412
5971
|
*/
|
|
5413
5972
|
async getTemplateById(templateId) {
|
|
5414
5973
|
const docRef = doc12(this.collectionRef, templateId);
|
|
5415
|
-
const docSnap = await
|
|
5974
|
+
const docSnap = await getDoc16(docRef);
|
|
5416
5975
|
if (!docSnap.exists()) {
|
|
5417
5976
|
return null;
|
|
5418
5977
|
}
|
|
@@ -5551,7 +6110,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
5551
6110
|
import {
|
|
5552
6111
|
collection as collection12,
|
|
5553
6112
|
doc as doc13,
|
|
5554
|
-
getDoc as
|
|
6113
|
+
getDoc as getDoc17,
|
|
5555
6114
|
getDocs as getDocs11,
|
|
5556
6115
|
setDoc as setDoc14,
|
|
5557
6116
|
updateDoc as updateDoc15,
|
|
@@ -5608,7 +6167,7 @@ var FilledDocumentService = class extends BaseService {
|
|
|
5608
6167
|
*/
|
|
5609
6168
|
async getFilledDocumentById(documentId) {
|
|
5610
6169
|
const docRef = doc13(this.collectionRef, documentId);
|
|
5611
|
-
const docSnap = await
|
|
6170
|
+
const docSnap = await getDoc17(docRef);
|
|
5612
6171
|
if (!docSnap.exists()) {
|
|
5613
6172
|
return null;
|
|
5614
6173
|
}
|