@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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.4.8",
4
+ "version": "1.4.10",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -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(createClinicAdminData);
224
- console.log("[AUTH] Clinic admin created successfully");
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: firebaseUser.uid,
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
- firebaseUser.uid,
255
- true
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(createClinicAdminData);
349
- console.log("[AUTH] Clinic admin created successfully");
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(this.db, groupId, adminId);
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(this.db, groupId, adminId);
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: setupData.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(this.db, groupId, adminId);
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
- // Create the clinic
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] Creating default group for owner");
90
- // Kreiramo default grupu
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
- // Ensure clinicGroupId is not undefined
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: validatedData.userRef,
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