@blackcode_sa/metaestetics-api 1.4.8 → 1.4.10
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 +31 -16
- package/dist/index.d.ts +31 -16
- package/dist/index.js +742 -187
- package/dist/index.mjs +761 -199
- 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 +8 -5
- package/src/validations/clinic.schema.ts +6 -3
package/package.json
CHANGED
|
@@ -208,8 +208,8 @@ export class AuthService extends BaseService {
|
|
|
208
208
|
);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
// First create the clinic admin
|
|
212
|
-
console.log("[AUTH] Creating clinic admin first");
|
|
211
|
+
// First create the clinic admin without a group
|
|
212
|
+
console.log("[AUTH] Creating clinic admin first (without group)");
|
|
213
213
|
const createClinicAdminData: CreateClinicAdminData = {
|
|
214
214
|
userRef: firebaseUser.uid,
|
|
215
215
|
isGroupOwner: true,
|
|
@@ -217,11 +217,17 @@ export class AuthService extends BaseService {
|
|
|
217
217
|
contactInfo: contactPerson,
|
|
218
218
|
roleTitle: data.title,
|
|
219
219
|
isActive: true,
|
|
220
|
+
// No clinicGroupId yet
|
|
220
221
|
};
|
|
221
222
|
|
|
223
|
+
let adminProfile;
|
|
222
224
|
try {
|
|
223
|
-
await clinicAdminService.createClinicAdmin(
|
|
224
|
-
|
|
225
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
226
|
+
createClinicAdminData
|
|
227
|
+
);
|
|
228
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
229
|
+
adminId: adminProfile.id,
|
|
230
|
+
});
|
|
225
231
|
} catch (adminCreationError) {
|
|
226
232
|
console.error(
|
|
227
233
|
"[AUTH] Clinic admin creation failed:",
|
|
@@ -236,7 +242,7 @@ export class AuthService extends BaseService {
|
|
|
236
242
|
hqLocation: data.clinicGroupData.hqLocation,
|
|
237
243
|
contactInfo: data.clinicGroupData.contactInfo,
|
|
238
244
|
contactPerson: contactPerson,
|
|
239
|
-
ownerId:
|
|
245
|
+
ownerId: adminProfile.id, // Use admin profile ID, not user UID
|
|
240
246
|
isActive: true,
|
|
241
247
|
logo: data.clinicGroupData.logo || null,
|
|
242
248
|
subscriptionModel:
|
|
@@ -248,13 +254,24 @@ export class AuthService extends BaseService {
|
|
|
248
254
|
});
|
|
249
255
|
|
|
250
256
|
// Create clinic group
|
|
257
|
+
let clinicGroup;
|
|
251
258
|
try {
|
|
252
|
-
await clinicGroupService.createClinicGroup(
|
|
259
|
+
clinicGroup = await clinicGroupService.createClinicGroup(
|
|
253
260
|
createClinicGroupData,
|
|
254
|
-
|
|
255
|
-
|
|
261
|
+
adminProfile.id, // Use admin profile ID, not user UID
|
|
262
|
+
false // This is not a default group since we're providing complete data
|
|
256
263
|
);
|
|
257
|
-
console.log("[AUTH] Clinic group created successfully"
|
|
264
|
+
console.log("[AUTH] Clinic group created successfully", {
|
|
265
|
+
groupId: clinicGroup.id,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Now update the admin with the group ID
|
|
269
|
+
console.log("[AUTH] Updating admin with clinic group ID");
|
|
270
|
+
await clinicAdminService.updateClinicAdmin(adminProfile.id, {
|
|
271
|
+
// Use admin profile ID, not user UID
|
|
272
|
+
clinicGroupId: clinicGroup.id,
|
|
273
|
+
});
|
|
274
|
+
console.log("[AUTH] Admin updated with clinic group ID successfully");
|
|
258
275
|
} catch (groupCreationError) {
|
|
259
276
|
console.error(
|
|
260
277
|
"[AUTH] Clinic group creation failed:",
|
|
@@ -344,9 +361,14 @@ export class AuthService extends BaseService {
|
|
|
344
361
|
isActive: true,
|
|
345
362
|
};
|
|
346
363
|
|
|
364
|
+
let adminProfile;
|
|
347
365
|
try {
|
|
348
|
-
await clinicAdminService.createClinicAdmin(
|
|
349
|
-
|
|
366
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
367
|
+
createClinicAdminData
|
|
368
|
+
);
|
|
369
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
370
|
+
adminId: adminProfile.id,
|
|
371
|
+
});
|
|
350
372
|
} catch (adminCreationError) {
|
|
351
373
|
console.error(
|
|
352
374
|
"[AUTH] Clinic admin creation failed:",
|
|
@@ -34,6 +34,7 @@ import { Auth } from "firebase/auth";
|
|
|
34
34
|
import { Firestore } from "firebase/firestore";
|
|
35
35
|
import { FirebaseApp } from "firebase/app";
|
|
36
36
|
import * as ClinicGroupUtils from "./utils/clinic-group.utils";
|
|
37
|
+
import { uploadPhoto } from "./utils/photos.utils";
|
|
37
38
|
|
|
38
39
|
export class ClinicGroupService extends BaseService {
|
|
39
40
|
private clinicAdminService: ClinicAdminService;
|
|
@@ -61,7 +62,8 @@ export class ClinicGroupService extends BaseService {
|
|
|
61
62
|
data,
|
|
62
63
|
ownerId,
|
|
63
64
|
isDefault,
|
|
64
|
-
this.clinicAdminService
|
|
65
|
+
this.clinicAdminService,
|
|
66
|
+
this.app
|
|
65
67
|
);
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -86,28 +88,38 @@ export class ClinicGroupService extends BaseService {
|
|
|
86
88
|
groupId: string,
|
|
87
89
|
data: Partial<ClinicGroup>
|
|
88
90
|
): Promise<ClinicGroup> {
|
|
89
|
-
return ClinicGroupUtils.updateClinicGroup(this.db, groupId, data);
|
|
91
|
+
return ClinicGroupUtils.updateClinicGroup(this.db, groupId, data, this.app);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
/**
|
|
93
95
|
* Dodaje admina u grupaciju
|
|
94
96
|
*/
|
|
95
97
|
async addAdminToGroup(groupId: string, adminId: string): Promise<void> {
|
|
96
|
-
return ClinicGroupUtils.addAdminToGroup(
|
|
98
|
+
return ClinicGroupUtils.addAdminToGroup(
|
|
99
|
+
this.db,
|
|
100
|
+
groupId,
|
|
101
|
+
adminId,
|
|
102
|
+
this.app
|
|
103
|
+
);
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
/**
|
|
100
107
|
* Uklanja admina iz grupacije
|
|
101
108
|
*/
|
|
102
109
|
async removeAdminFromGroup(groupId: string, adminId: string): Promise<void> {
|
|
103
|
-
return ClinicGroupUtils.removeAdminFromGroup(
|
|
110
|
+
return ClinicGroupUtils.removeAdminFromGroup(
|
|
111
|
+
this.db,
|
|
112
|
+
groupId,
|
|
113
|
+
adminId,
|
|
114
|
+
this.app
|
|
115
|
+
);
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
/**
|
|
107
119
|
* Deaktivira grupaciju klinika
|
|
108
120
|
*/
|
|
109
121
|
async deactivateClinicGroup(groupId: string): Promise<void> {
|
|
110
|
-
return ClinicGroupUtils.deactivateClinicGroup(this.db, groupId);
|
|
122
|
+
return ClinicGroupUtils.deactivateClinicGroup(this.db, groupId, this.app);
|
|
111
123
|
}
|
|
112
124
|
|
|
113
125
|
/**
|
|
@@ -121,22 +133,56 @@ export class ClinicGroupService extends BaseService {
|
|
|
121
133
|
groupId: string,
|
|
122
134
|
setupData: ClinicGroupSetupData
|
|
123
135
|
): Promise<ClinicGroup> {
|
|
136
|
+
console.log("[CLINIC_GROUP] Setting up clinic group", { groupId });
|
|
137
|
+
|
|
124
138
|
// Get the clinic group
|
|
125
139
|
const clinicGroup = await this.getClinicGroup(groupId);
|
|
126
140
|
if (!clinicGroup) {
|
|
141
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
127
142
|
throw new Error(`Clinic group with ID ${groupId} not found`);
|
|
128
143
|
}
|
|
129
144
|
|
|
145
|
+
// Process logo if it's a data URL
|
|
146
|
+
let logoUrl = setupData.logo;
|
|
147
|
+
if (logoUrl && typeof logoUrl === "string" && logoUrl.startsWith("data:")) {
|
|
148
|
+
console.log("[CLINIC_GROUP] Processing logo in setupClinicGroup");
|
|
149
|
+
try {
|
|
150
|
+
const uploadedLogoUrl = await uploadPhoto(
|
|
151
|
+
logoUrl,
|
|
152
|
+
"clinic-groups",
|
|
153
|
+
groupId,
|
|
154
|
+
"logo",
|
|
155
|
+
this.app
|
|
156
|
+
);
|
|
157
|
+
console.log("[CLINIC_GROUP] Logo processed in setupClinicGroup", {
|
|
158
|
+
uploadedLogoUrl,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Replace the data URL with the uploaded URL if upload was successful
|
|
162
|
+
if (uploadedLogoUrl !== null) {
|
|
163
|
+
logoUrl = uploadedLogoUrl;
|
|
164
|
+
}
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error(
|
|
167
|
+
"[CLINIC_GROUP] Error processing logo in setupClinicGroup:",
|
|
168
|
+
error
|
|
169
|
+
);
|
|
170
|
+
// Continue with update even if logo upload fails
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
130
174
|
// Update the clinic group with the setup data
|
|
131
175
|
const updateData = {
|
|
132
176
|
languages: setupData.languages,
|
|
133
177
|
practiceType: setupData.practiceType,
|
|
134
178
|
description: setupData.description,
|
|
135
|
-
logo:
|
|
179
|
+
logo: logoUrl,
|
|
136
180
|
calendarSyncEnabled: setupData.calendarSyncEnabled,
|
|
137
181
|
autoConfirmAppointments: setupData.autoConfirmAppointments,
|
|
138
182
|
};
|
|
139
183
|
|
|
184
|
+
console.log("[CLINIC_GROUP] Updating clinic group with setup data");
|
|
185
|
+
|
|
140
186
|
// Update the clinic group
|
|
141
187
|
return this.updateClinicGroup(groupId, updateData);
|
|
142
188
|
}
|
|
@@ -153,6 +199,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
153
199
|
this.db,
|
|
154
200
|
groupId,
|
|
155
201
|
creatorAdminId,
|
|
202
|
+
this.app,
|
|
156
203
|
data
|
|
157
204
|
);
|
|
158
205
|
}
|
|
@@ -169,7 +216,8 @@ export class ClinicGroupService extends BaseService {
|
|
|
169
216
|
this.db,
|
|
170
217
|
groupId,
|
|
171
218
|
token,
|
|
172
|
-
userRef
|
|
219
|
+
userRef,
|
|
220
|
+
this.app
|
|
173
221
|
);
|
|
174
222
|
}
|
|
175
223
|
|
|
@@ -185,7 +233,8 @@ export class ClinicGroupService extends BaseService {
|
|
|
185
233
|
this.db,
|
|
186
234
|
groupId,
|
|
187
235
|
tokenId,
|
|
188
|
-
adminId
|
|
236
|
+
adminId,
|
|
237
|
+
this.app
|
|
189
238
|
);
|
|
190
239
|
}
|
|
191
240
|
|
|
@@ -196,6 +245,11 @@ export class ClinicGroupService extends BaseService {
|
|
|
196
245
|
groupId: string,
|
|
197
246
|
adminId: string
|
|
198
247
|
): Promise<AdminToken[]> {
|
|
199
|
-
return ClinicGroupUtils.getActiveAdminTokens(
|
|
248
|
+
return ClinicGroupUtils.getActiveAdminTokens(
|
|
249
|
+
this.db,
|
|
250
|
+
groupId,
|
|
251
|
+
adminId,
|
|
252
|
+
this.app
|
|
253
|
+
);
|
|
200
254
|
}
|
|
201
255
|
}
|
|
@@ -76,7 +76,8 @@ export class ClinicService extends BaseService {
|
|
|
76
76
|
data,
|
|
77
77
|
creatorAdminId,
|
|
78
78
|
this.clinicGroupService,
|
|
79
|
-
this.clinicAdminService
|
|
79
|
+
this.clinicAdminService,
|
|
80
|
+
this.app
|
|
80
81
|
);
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -126,7 +127,8 @@ export class ClinicService extends BaseService {
|
|
|
126
127
|
clinicId,
|
|
127
128
|
data,
|
|
128
129
|
adminId,
|
|
129
|
-
this.clinicAdminService
|
|
130
|
+
this.clinicAdminService,
|
|
131
|
+
this.app
|
|
130
132
|
);
|
|
131
133
|
}
|
|
132
134
|
|
|
@@ -140,7 +142,7 @@ export class ClinicService extends BaseService {
|
|
|
140
142
|
"id" | "clinicId" | "createdAt" | "updatedAt" | "isVerified"
|
|
141
143
|
>
|
|
142
144
|
): Promise<ClinicReview> {
|
|
143
|
-
return ReviewUtils.addReview(this.db, clinicId, review);
|
|
145
|
+
return ReviewUtils.addReview(this.db, clinicId, review, this.app);
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
/**
|
|
@@ -170,7 +172,8 @@ export class ClinicService extends BaseService {
|
|
|
170
172
|
clinicId,
|
|
171
173
|
adminId,
|
|
172
174
|
newTags,
|
|
173
|
-
this.clinicAdminService
|
|
175
|
+
this.clinicAdminService,
|
|
176
|
+
this.app
|
|
174
177
|
);
|
|
175
178
|
}
|
|
176
179
|
|
|
@@ -189,7 +192,8 @@ export class ClinicService extends BaseService {
|
|
|
189
192
|
clinicId,
|
|
190
193
|
adminId,
|
|
191
194
|
tagsToRemove,
|
|
192
|
-
this.clinicAdminService
|
|
195
|
+
this.clinicAdminService,
|
|
196
|
+
this.app
|
|
193
197
|
);
|
|
194
198
|
}
|
|
195
199
|
|
|
@@ -237,13 +241,22 @@ export class ClinicService extends BaseService {
|
|
|
237
241
|
setupData: ClinicBranchSetupData,
|
|
238
242
|
adminId: string
|
|
239
243
|
): Promise<Clinic> {
|
|
244
|
+
console.log("[CLINIC_SERVICE] Starting clinic branch creation", {
|
|
245
|
+
clinicGroupId,
|
|
246
|
+
adminId,
|
|
247
|
+
});
|
|
248
|
+
|
|
240
249
|
// Validate that the clinic group exists
|
|
241
250
|
const clinicGroup = await this.clinicGroupService.getClinicGroup(
|
|
242
251
|
clinicGroupId
|
|
243
252
|
);
|
|
244
253
|
if (!clinicGroup) {
|
|
254
|
+
console.error("[CLINIC_SERVICE] Clinic group not found", {
|
|
255
|
+
clinicGroupId,
|
|
256
|
+
});
|
|
245
257
|
throw new Error(`Clinic group with ID ${clinicGroupId} not found`);
|
|
246
258
|
}
|
|
259
|
+
console.log("[CLINIC_SERVICE] Clinic group verified");
|
|
247
260
|
|
|
248
261
|
// Create the clinic data
|
|
249
262
|
const createClinicData: CreateClinicData = {
|
|
@@ -254,8 +267,8 @@ export class ClinicService extends BaseService {
|
|
|
254
267
|
contactInfo: setupData.contactInfo,
|
|
255
268
|
workingHours: setupData.workingHours,
|
|
256
269
|
tags: setupData.tags,
|
|
257
|
-
photos: setupData.photos,
|
|
258
|
-
photosWithTags: setupData.photosWithTags,
|
|
270
|
+
photos: setupData.photos || [],
|
|
271
|
+
photosWithTags: setupData.photosWithTags || [],
|
|
259
272
|
doctors: [],
|
|
260
273
|
services: [],
|
|
261
274
|
admins: [adminId],
|
|
@@ -265,11 +278,21 @@ export class ClinicService extends BaseService {
|
|
|
265
278
|
featuredPhotos: setupData.featuredPhotos || [],
|
|
266
279
|
};
|
|
267
280
|
|
|
268
|
-
|
|
281
|
+
console.log("[CLINIC_SERVICE] Creating clinic branch with data", {
|
|
282
|
+
name: createClinicData.name,
|
|
283
|
+
hasLogo: !!createClinicData.logo,
|
|
284
|
+
photosCount: createClinicData.photos.length,
|
|
285
|
+
featuredPhotosCount: createClinicData.featuredPhotos?.length || 0,
|
|
286
|
+
photosWithTagsCount: createClinicData.photosWithTags?.length || 0,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Create the clinic - the createClinic method will handle photo uploads
|
|
269
290
|
const clinic = await this.createClinic(createClinicData, adminId);
|
|
291
|
+
console.log("[CLINIC_SERVICE] Clinic branch created successfully", {
|
|
292
|
+
clinicId: clinic.id,
|
|
293
|
+
});
|
|
270
294
|
|
|
271
295
|
// Note: The createClinic method already adds the clinic to the admin's managed clinics
|
|
272
|
-
|
|
273
296
|
return clinic;
|
|
274
297
|
}
|
|
275
298
|
}
|
|
@@ -85,48 +85,10 @@ export async function createClinicAdmin(
|
|
|
85
85
|
hasGroupId: !!clinicGroupId,
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
// For owners creating a new group, we'll set the group ID later
|
|
88
89
|
if (validatedData.isGroupOwner && !clinicGroupId) {
|
|
89
|
-
console.log("[CLINIC_ADMIN]
|
|
90
|
-
//
|
|
91
|
-
const defaultGroup: CreateDefaultClinicGroupData = {
|
|
92
|
-
name: `${validatedData.contactInfo.firstName}'s Group`,
|
|
93
|
-
ownerId: validatedData.userRef,
|
|
94
|
-
contactPerson: validatedData.contactInfo,
|
|
95
|
-
contactInfo: {
|
|
96
|
-
email: validatedData.contactInfo.email,
|
|
97
|
-
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
98
|
-
},
|
|
99
|
-
hqLocation: {
|
|
100
|
-
address: "",
|
|
101
|
-
city: "",
|
|
102
|
-
country: "",
|
|
103
|
-
postalCode: "",
|
|
104
|
-
latitude: 0,
|
|
105
|
-
longitude: 0,
|
|
106
|
-
},
|
|
107
|
-
isActive: true,
|
|
108
|
-
};
|
|
109
|
-
console.log("[CLINIC_ADMIN] Default group data prepared", {
|
|
110
|
-
groupName: defaultGroup.name,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const clinicGroup = await clinicGroupService.createClinicGroup(
|
|
115
|
-
defaultGroup,
|
|
116
|
-
validatedData.userRef,
|
|
117
|
-
true
|
|
118
|
-
);
|
|
119
|
-
clinicGroupId = clinicGroup.id;
|
|
120
|
-
console.log("[CLINIC_ADMIN] Default group created successfully", {
|
|
121
|
-
groupId: clinicGroupId,
|
|
122
|
-
});
|
|
123
|
-
} catch (groupCreationError) {
|
|
124
|
-
console.error(
|
|
125
|
-
"[CLINIC_ADMIN] Error creating default group:",
|
|
126
|
-
groupCreationError
|
|
127
|
-
);
|
|
128
|
-
throw groupCreationError;
|
|
129
|
-
}
|
|
90
|
+
console.log("[CLINIC_ADMIN] Owner will be assigned to group later");
|
|
91
|
+
// Skip creating default group here - will be done in auth service
|
|
130
92
|
}
|
|
131
93
|
// Ako nije owner a nemamo groupId, to je greška
|
|
132
94
|
else if (!validatedData.isGroupOwner && !clinicGroupId) {
|
|
@@ -162,21 +124,14 @@ export async function createClinicAdmin(
|
|
|
162
124
|
|
|
163
125
|
console.log("[CLINIC_ADMIN] Preparing admin data object");
|
|
164
126
|
|
|
165
|
-
//
|
|
166
|
-
if (!clinicGroupId) {
|
|
167
|
-
console.error(
|
|
168
|
-
"[CLINIC_ADMIN] clinicGroupId is undefined, which should not happen at this point"
|
|
169
|
-
);
|
|
170
|
-
throw new Error("clinicGroupId is required but was undefined");
|
|
171
|
-
}
|
|
172
|
-
|
|
127
|
+
// Allow creating admin without a clinic group for owners
|
|
173
128
|
const adminData: Omit<ClinicAdmin, "createdAt" | "updatedAt"> & {
|
|
174
129
|
createdAt: ReturnType<typeof serverTimestamp>;
|
|
175
130
|
updatedAt: ReturnType<typeof serverTimestamp>;
|
|
176
131
|
} = {
|
|
177
|
-
id:
|
|
132
|
+
id: doc(collection(db, CLINIC_ADMINS_COLLECTION)).id, // Generate a new ID for the admin document
|
|
178
133
|
userRef: validatedData.userRef,
|
|
179
|
-
clinicGroupId: clinicGroupId,
|
|
134
|
+
clinicGroupId: clinicGroupId || "", // Empty string for now if no group ID
|
|
180
135
|
isGroupOwner: validatedData.isGroupOwner,
|
|
181
136
|
clinicsManaged: [], // Uvek krećemo od prazne liste
|
|
182
137
|
clinicsManagedInfo: [], // Empty array for clinic info
|