@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
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Firestore,
|
|
13
13
|
serverTimestamp,
|
|
14
14
|
} from "firebase/firestore";
|
|
15
|
+
import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";
|
|
15
16
|
import {
|
|
16
17
|
ClinicGroup,
|
|
17
18
|
CreateClinicGroupData,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
AdminToken,
|
|
20
21
|
AdminTokenStatus,
|
|
21
22
|
CreateAdminTokenData,
|
|
23
|
+
SubscriptionModel,
|
|
22
24
|
} from "../../../types/clinic";
|
|
23
25
|
import { geohashForLocation } from "geofire-common";
|
|
24
26
|
import {
|
|
@@ -26,6 +28,8 @@ import {
|
|
|
26
28
|
createClinicGroupSchema,
|
|
27
29
|
} from "../../../validations/clinic.schema";
|
|
28
30
|
import { z } from "zod";
|
|
31
|
+
import { uploadPhoto } from "./photos.utils";
|
|
32
|
+
import { FirebaseApp } from "firebase/app";
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
35
|
* Generates a unique ID for documents
|
|
@@ -50,6 +54,7 @@ function generateId(): string {
|
|
|
50
54
|
* @param ownerId - ID of the owner
|
|
51
55
|
* @param isDefault - Whether this is a default group
|
|
52
56
|
* @param clinicAdminService - Service for clinic admin operations
|
|
57
|
+
* @param app - Firebase app instance
|
|
53
58
|
* @returns The created clinic group
|
|
54
59
|
*/
|
|
55
60
|
export async function createClinicGroup(
|
|
@@ -57,7 +62,8 @@ export async function createClinicGroup(
|
|
|
57
62
|
data: CreateClinicGroupData,
|
|
58
63
|
ownerId: string,
|
|
59
64
|
isDefault: boolean = false,
|
|
60
|
-
clinicAdminService: any
|
|
65
|
+
clinicAdminService: any,
|
|
66
|
+
app: FirebaseApp
|
|
61
67
|
): Promise<ClinicGroup> {
|
|
62
68
|
console.log("[CLINIC_GROUP] Starting clinic group creation", {
|
|
63
69
|
ownerId,
|
|
@@ -122,22 +128,43 @@ export async function createClinicGroup(
|
|
|
122
128
|
const now = Timestamp.now();
|
|
123
129
|
console.log("[CLINIC_GROUP] Preparing clinic group data object");
|
|
124
130
|
|
|
131
|
+
// Generate a unique ID for the clinic group
|
|
132
|
+
const groupId = doc(collection(db, CLINIC_GROUPS_COLLECTION)).id;
|
|
133
|
+
|
|
125
134
|
// Log the logo value to debug null vs undefined issue
|
|
126
135
|
console.log("[CLINIC_GROUP] Logo value:", {
|
|
127
136
|
logoValue: validatedData.logo,
|
|
128
137
|
logoType: validatedData.logo === null ? "null" : typeof validatedData.logo,
|
|
129
138
|
});
|
|
130
139
|
|
|
140
|
+
// Handle logo upload if provided
|
|
141
|
+
let logoUrl = await uploadPhoto(
|
|
142
|
+
validatedData.logo || null,
|
|
143
|
+
"clinic-groups",
|
|
144
|
+
groupId,
|
|
145
|
+
"logo",
|
|
146
|
+
app
|
|
147
|
+
);
|
|
148
|
+
console.log("[CLINIC_GROUP] Logo processed", { logoUrl });
|
|
149
|
+
|
|
131
150
|
const groupData: ClinicGroup = {
|
|
132
151
|
...validatedData,
|
|
133
|
-
id:
|
|
152
|
+
id: groupId,
|
|
153
|
+
name: validatedData.name,
|
|
154
|
+
logo: logoUrl, // Use the uploaded logo URL or the original value
|
|
134
155
|
description: isDefault ? undefined : validatedData.description || undefined,
|
|
135
156
|
hqLocation: {
|
|
136
|
-
|
|
157
|
+
address: validatedData.hqLocation.address || "",
|
|
158
|
+
city: validatedData.hqLocation.city || "",
|
|
159
|
+
country: validatedData.hqLocation.country || "",
|
|
160
|
+
postalCode: validatedData.hqLocation.postalCode || "",
|
|
161
|
+
latitude: validatedData.hqLocation.latitude || 0,
|
|
162
|
+
longitude: validatedData.hqLocation.longitude || 0,
|
|
137
163
|
geohash: validatedData.hqLocation.geohash || undefined,
|
|
138
164
|
},
|
|
139
165
|
contactInfo: {
|
|
140
|
-
|
|
166
|
+
email: validatedData.contactInfo.email || "",
|
|
167
|
+
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
141
168
|
alternativePhoneNumber: isDefault
|
|
142
169
|
? undefined
|
|
143
170
|
: validatedData.contactInfo.alternativePhoneNumber || undefined,
|
|
@@ -145,6 +172,15 @@ export async function createClinicGroup(
|
|
|
145
172
|
? undefined
|
|
146
173
|
: validatedData.contactInfo.website || undefined,
|
|
147
174
|
},
|
|
175
|
+
contactPerson: {
|
|
176
|
+
firstName: validatedData.contactPerson?.firstName || "",
|
|
177
|
+
lastName: validatedData.contactPerson?.lastName || "",
|
|
178
|
+
email: validatedData.contactPerson?.email || "",
|
|
179
|
+
title: validatedData.contactPerson?.title || null,
|
|
180
|
+
phoneNumber: validatedData.contactPerson?.phoneNumber || null,
|
|
181
|
+
},
|
|
182
|
+
subscriptionModel:
|
|
183
|
+
validatedData.subscriptionModel || SubscriptionModel.NO_SUBSCRIPTION,
|
|
148
184
|
clinics: [],
|
|
149
185
|
clinicsInfo: [],
|
|
150
186
|
admins: [ownerId],
|
|
@@ -266,29 +302,64 @@ export async function getAllActiveGroups(
|
|
|
266
302
|
* @param db - Firestore database instance
|
|
267
303
|
* @param groupId - ID of the clinic group
|
|
268
304
|
* @param data - Data to update
|
|
305
|
+
* @param app - Firebase app instance
|
|
269
306
|
* @returns The updated clinic group
|
|
270
307
|
*/
|
|
271
308
|
export async function updateClinicGroup(
|
|
272
309
|
db: Firestore,
|
|
273
310
|
groupId: string,
|
|
274
|
-
data: Partial<ClinicGroup
|
|
311
|
+
data: Partial<ClinicGroup>,
|
|
312
|
+
app: FirebaseApp
|
|
275
313
|
): Promise<ClinicGroup> {
|
|
314
|
+
console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
|
|
315
|
+
|
|
276
316
|
const group = await getClinicGroup(db, groupId);
|
|
277
317
|
if (!group) {
|
|
318
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
278
319
|
throw new Error("Clinic group not found");
|
|
279
320
|
}
|
|
280
321
|
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
322
|
+
// Process logo if it's a data URL
|
|
323
|
+
let updatedData = { ...data };
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
data.logo &&
|
|
327
|
+
typeof data.logo === "string" &&
|
|
328
|
+
data.logo.startsWith("data:")
|
|
329
|
+
) {
|
|
330
|
+
console.log("[CLINIC_GROUP] Processing logo for update");
|
|
331
|
+
try {
|
|
332
|
+
const logoUrl = await uploadPhoto(
|
|
333
|
+
data.logo,
|
|
334
|
+
"clinic-groups",
|
|
335
|
+
groupId,
|
|
336
|
+
"logo",
|
|
337
|
+
app
|
|
338
|
+
);
|
|
339
|
+
console.log("[CLINIC_GROUP] Logo processed for update", { logoUrl });
|
|
340
|
+
|
|
341
|
+
// Replace the data URL with the uploaded URL
|
|
342
|
+
updatedData.logo = logoUrl;
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error("[CLINIC_GROUP] Error processing logo for update:", error);
|
|
345
|
+
// Continue with update even if logo upload fails
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Add timestamp
|
|
350
|
+
updatedData = {
|
|
351
|
+
...updatedData,
|
|
284
352
|
updatedAt: Timestamp.now(),
|
|
285
353
|
};
|
|
286
354
|
|
|
355
|
+
console.log("[CLINIC_GROUP] Updating clinic group in Firestore");
|
|
287
356
|
await updateDoc(doc(db, CLINIC_GROUPS_COLLECTION, groupId), updatedData);
|
|
357
|
+
console.log("[CLINIC_GROUP] Clinic group updated successfully");
|
|
288
358
|
|
|
289
|
-
//
|
|
359
|
+
// Return updated data
|
|
290
360
|
const updatedGroup = await getClinicGroup(db, groupId);
|
|
291
361
|
if (!updatedGroup) {
|
|
362
|
+
console.error("[CLINIC_GROUP] Failed to retrieve updated clinic group");
|
|
292
363
|
throw new Error("Failed to retrieve updated clinic group");
|
|
293
364
|
}
|
|
294
365
|
|
|
@@ -299,25 +370,46 @@ export async function updateClinicGroup(
|
|
|
299
370
|
* Adds an admin to a clinic group
|
|
300
371
|
* @param db - Firestore database instance
|
|
301
372
|
* @param groupId - ID of the clinic group
|
|
302
|
-
* @param adminId - ID of the admin to add
|
|
373
|
+
* @param adminId - ID of the admin to add (this is the admin document ID, not the user UID)
|
|
374
|
+
* @param app - Firebase app instance
|
|
303
375
|
*/
|
|
304
376
|
export async function addAdminToGroup(
|
|
305
377
|
db: Firestore,
|
|
306
378
|
groupId: string,
|
|
307
|
-
adminId: string
|
|
379
|
+
adminId: string,
|
|
380
|
+
app: FirebaseApp
|
|
308
381
|
): Promise<void> {
|
|
309
|
-
|
|
310
|
-
if (!group) {
|
|
311
|
-
throw new Error("Clinic group not found");
|
|
312
|
-
}
|
|
382
|
+
console.log("[CLINIC_GROUP] Adding admin to group", { groupId, adminId });
|
|
313
383
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
384
|
+
try {
|
|
385
|
+
const group = await getClinicGroup(db, groupId);
|
|
386
|
+
if (!group) {
|
|
387
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
388
|
+
throw new Error("Clinic group not found");
|
|
389
|
+
}
|
|
317
390
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
391
|
+
if (group.admins.includes(adminId)) {
|
|
392
|
+
console.log("[CLINIC_GROUP] Admin is already in the group", {
|
|
393
|
+
adminId,
|
|
394
|
+
groupId,
|
|
395
|
+
});
|
|
396
|
+
return; // Admin is already in the group
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
console.log("[CLINIC_GROUP] Updating group with new admin");
|
|
400
|
+
await updateClinicGroup(
|
|
401
|
+
db,
|
|
402
|
+
groupId,
|
|
403
|
+
{
|
|
404
|
+
admins: [...group.admins, adminId],
|
|
405
|
+
},
|
|
406
|
+
app
|
|
407
|
+
);
|
|
408
|
+
console.log("[CLINIC_GROUP] Admin added to group successfully");
|
|
409
|
+
} catch (error) {
|
|
410
|
+
console.error("[CLINIC_GROUP] Error adding admin to group:", error);
|
|
411
|
+
throw error;
|
|
412
|
+
}
|
|
321
413
|
}
|
|
322
414
|
|
|
323
415
|
/**
|
|
@@ -325,11 +417,13 @@ export async function addAdminToGroup(
|
|
|
325
417
|
* @param db - Firestore database instance
|
|
326
418
|
* @param groupId - ID of the clinic group
|
|
327
419
|
* @param adminId - ID of the admin to remove
|
|
420
|
+
* @param app - Firebase app instance
|
|
328
421
|
*/
|
|
329
422
|
export async function removeAdminFromGroup(
|
|
330
423
|
db: Firestore,
|
|
331
424
|
groupId: string,
|
|
332
|
-
adminId: string
|
|
425
|
+
adminId: string,
|
|
426
|
+
app: FirebaseApp
|
|
333
427
|
): Promise<void> {
|
|
334
428
|
const group = await getClinicGroup(db, groupId);
|
|
335
429
|
if (!group) {
|
|
@@ -344,29 +438,40 @@ export async function removeAdminFromGroup(
|
|
|
344
438
|
return; // Admin is not in the group
|
|
345
439
|
}
|
|
346
440
|
|
|
347
|
-
await updateClinicGroup(
|
|
348
|
-
|
|
349
|
-
|
|
441
|
+
await updateClinicGroup(
|
|
442
|
+
db,
|
|
443
|
+
groupId,
|
|
444
|
+
{
|
|
445
|
+
admins: group.admins.filter((id) => id !== adminId),
|
|
446
|
+
},
|
|
447
|
+
app
|
|
448
|
+
);
|
|
350
449
|
}
|
|
351
450
|
|
|
352
451
|
/**
|
|
353
452
|
* Deactivates a clinic group
|
|
354
453
|
* @param db - Firestore database instance
|
|
355
454
|
* @param groupId - ID of the clinic group
|
|
455
|
+
* @param app - Firebase app instance
|
|
356
456
|
*/
|
|
357
457
|
export async function deactivateClinicGroup(
|
|
358
458
|
db: Firestore,
|
|
359
|
-
groupId: string
|
|
459
|
+
groupId: string,
|
|
460
|
+
app: FirebaseApp
|
|
360
461
|
): Promise<void> {
|
|
361
462
|
const group = await getClinicGroup(db, groupId);
|
|
362
463
|
if (!group) {
|
|
363
464
|
throw new Error("Clinic group not found");
|
|
364
465
|
}
|
|
365
466
|
|
|
366
|
-
await
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
467
|
+
await updateClinicGroup(
|
|
468
|
+
db,
|
|
469
|
+
groupId,
|
|
470
|
+
{
|
|
471
|
+
isActive: false,
|
|
472
|
+
},
|
|
473
|
+
app
|
|
474
|
+
);
|
|
370
475
|
}
|
|
371
476
|
|
|
372
477
|
/**
|
|
@@ -374,6 +479,7 @@ export async function deactivateClinicGroup(
|
|
|
374
479
|
* @param db - Firestore database instance
|
|
375
480
|
* @param groupId - ID of the clinic group
|
|
376
481
|
* @param creatorAdminId - ID of the admin creating the token
|
|
482
|
+
* @param app - Firebase app instance
|
|
377
483
|
* @param data - Token data
|
|
378
484
|
* @returns The created admin token
|
|
379
485
|
*/
|
|
@@ -381,6 +487,7 @@ export async function createAdminToken(
|
|
|
381
487
|
db: Firestore,
|
|
382
488
|
groupId: string,
|
|
383
489
|
creatorAdminId: string,
|
|
490
|
+
app: FirebaseApp,
|
|
384
491
|
data?: CreateAdminTokenData
|
|
385
492
|
): Promise<AdminToken> {
|
|
386
493
|
const group = await getClinicGroup(db, groupId);
|
|
@@ -409,9 +516,14 @@ export async function createAdminToken(
|
|
|
409
516
|
};
|
|
410
517
|
|
|
411
518
|
// Dodajemo token u grupu
|
|
412
|
-
await updateClinicGroup(
|
|
413
|
-
|
|
414
|
-
|
|
519
|
+
await updateClinicGroup(
|
|
520
|
+
db,
|
|
521
|
+
groupId,
|
|
522
|
+
{
|
|
523
|
+
adminTokens: [...group.adminTokens, token],
|
|
524
|
+
},
|
|
525
|
+
app
|
|
526
|
+
);
|
|
415
527
|
|
|
416
528
|
return token;
|
|
417
529
|
}
|
|
@@ -422,13 +534,15 @@ export async function createAdminToken(
|
|
|
422
534
|
* @param groupId - ID of the clinic group
|
|
423
535
|
* @param token - Token to verify
|
|
424
536
|
* @param userRef - User reference
|
|
537
|
+
* @param app - Firebase app instance
|
|
425
538
|
* @returns Whether the token was successfully used
|
|
426
539
|
*/
|
|
427
540
|
export async function verifyAndUseAdminToken(
|
|
428
541
|
db: Firestore,
|
|
429
542
|
groupId: string,
|
|
430
543
|
token: string,
|
|
431
|
-
userRef: string
|
|
544
|
+
userRef: string,
|
|
545
|
+
app: FirebaseApp
|
|
432
546
|
): Promise<boolean> {
|
|
433
547
|
const group = await getClinicGroup(db, groupId);
|
|
434
548
|
if (!group) {
|
|
@@ -451,9 +565,14 @@ export async function verifyAndUseAdminToken(
|
|
|
451
565
|
t.id === adminToken.id ? { ...t, status: AdminTokenStatus.EXPIRED } : t
|
|
452
566
|
);
|
|
453
567
|
|
|
454
|
-
await updateClinicGroup(
|
|
455
|
-
|
|
456
|
-
|
|
568
|
+
await updateClinicGroup(
|
|
569
|
+
db,
|
|
570
|
+
groupId,
|
|
571
|
+
{
|
|
572
|
+
adminTokens: updatedTokens,
|
|
573
|
+
},
|
|
574
|
+
app
|
|
575
|
+
);
|
|
457
576
|
|
|
458
577
|
throw new Error("Admin token has expired");
|
|
459
578
|
}
|
|
@@ -469,9 +588,14 @@ export async function verifyAndUseAdminToken(
|
|
|
469
588
|
: t
|
|
470
589
|
);
|
|
471
590
|
|
|
472
|
-
await updateClinicGroup(
|
|
473
|
-
|
|
474
|
-
|
|
591
|
+
await updateClinicGroup(
|
|
592
|
+
db,
|
|
593
|
+
groupId,
|
|
594
|
+
{
|
|
595
|
+
adminTokens: updatedTokens,
|
|
596
|
+
},
|
|
597
|
+
app
|
|
598
|
+
);
|
|
475
599
|
|
|
476
600
|
return true;
|
|
477
601
|
}
|
|
@@ -482,12 +606,14 @@ export async function verifyAndUseAdminToken(
|
|
|
482
606
|
* @param groupId - ID of the clinic group
|
|
483
607
|
* @param tokenId - ID of the token to delete
|
|
484
608
|
* @param adminId - ID of the admin making the deletion
|
|
609
|
+
* @param app - Firebase app instance
|
|
485
610
|
*/
|
|
486
611
|
export async function deleteAdminToken(
|
|
487
612
|
db: Firestore,
|
|
488
613
|
groupId: string,
|
|
489
614
|
tokenId: string,
|
|
490
|
-
adminId: string
|
|
615
|
+
adminId: string,
|
|
616
|
+
app: FirebaseApp
|
|
491
617
|
): Promise<void> {
|
|
492
618
|
const group = await getClinicGroup(db, groupId);
|
|
493
619
|
if (!group) {
|
|
@@ -502,9 +628,14 @@ export async function deleteAdminToken(
|
|
|
502
628
|
// Uklanjamo token
|
|
503
629
|
const updatedTokens = group.adminTokens.filter((t) => t.id !== tokenId);
|
|
504
630
|
|
|
505
|
-
await updateClinicGroup(
|
|
506
|
-
|
|
507
|
-
|
|
631
|
+
await updateClinicGroup(
|
|
632
|
+
db,
|
|
633
|
+
groupId,
|
|
634
|
+
{
|
|
635
|
+
adminTokens: updatedTokens,
|
|
636
|
+
},
|
|
637
|
+
app
|
|
638
|
+
);
|
|
508
639
|
}
|
|
509
640
|
|
|
510
641
|
/**
|
|
@@ -512,12 +643,14 @@ export async function deleteAdminToken(
|
|
|
512
643
|
* @param db - Firestore database instance
|
|
513
644
|
* @param groupId - ID of the clinic group
|
|
514
645
|
* @param adminId - ID of the admin requesting the tokens
|
|
646
|
+
* @param app - Firebase app instance (not used but included for consistency)
|
|
515
647
|
* @returns Array of active admin tokens
|
|
516
648
|
*/
|
|
517
649
|
export async function getActiveAdminTokens(
|
|
518
650
|
db: Firestore,
|
|
519
651
|
groupId: string,
|
|
520
|
-
adminId: string
|
|
652
|
+
adminId: string,
|
|
653
|
+
app: FirebaseApp
|
|
521
654
|
): Promise<AdminToken[]> {
|
|
522
655
|
const group = await getClinicGroup(db, groupId);
|
|
523
656
|
if (!group) {
|