@blackcode_sa/metaestetics-api 1.14.77 → 1.14.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +5 -0
- package/dist/admin/index.d.ts +5 -0
- package/dist/admin/index.js +48 -6
- package/dist/admin/index.mjs +48 -6
- package/dist/index.js +7 -5
- package/dist/index.mjs +7 -5
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +59 -6
- package/src/admin/mailing/clinicWelcome/clinicWelcome.mailing.ts +1 -1
- package/src/services/__tests__/auth/auth.mock.test.ts +2 -2
- package/src/services/__tests__/auth/auth.setup.ts +6 -1
- package/src/services/__tests__/auth.service.test.ts +8 -44
- package/src/services/__tests__/base.service.test.ts +4 -45
- package/src/services/__tests__/user.service.test.ts +6 -4
- package/src/services/appointment/utils/appointment.utils.ts +0 -3
- package/src/services/appointment/utils/extended-procedure.utils.ts +1 -0
- package/src/services/auth/auth.v2.service.ts +7 -7
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +11 -33
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +21 -151
- package/src/services/clinic/__tests__/clinic.service.test.ts +17 -69
- package/src/services/clinic/utils/clinic-group.utils.ts +2 -2
- package/src/services/clinic/utils/clinic.utils.ts +28 -22
- package/src/services/clinic/utils/index.ts +0 -1
- package/src/services/notifications/__tests__/notification.service.test.ts +5 -5
- package/src/services/patient/__tests__/patient.service.test.ts +17 -25
- package/src/services/patient/utils/docs.utils.ts +1 -1
- package/src/services/user/user.v2.service.ts +4 -3
|
@@ -424,7 +424,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
424
424
|
>(functions, "createAnonymousPatientProfile");
|
|
425
425
|
|
|
426
426
|
const result = await createAnonymousPatientProfile({});
|
|
427
|
-
return result.data.user;
|
|
427
|
+
return (result.data as any).user;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
@@ -450,7 +450,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
450
450
|
);
|
|
451
451
|
|
|
452
452
|
const result = await createAnonymousPatientProfile({});
|
|
453
|
-
return result.data.user;
|
|
453
|
+
return (result.data as any).user;
|
|
454
454
|
}
|
|
455
455
|
}
|
|
456
456
|
|
|
@@ -468,7 +468,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
468
468
|
);
|
|
469
469
|
|
|
470
470
|
const result = await createAnonymousPatientProfile({});
|
|
471
|
-
return result.data.user;
|
|
471
|
+
return (result.data as any).user;
|
|
472
472
|
}
|
|
473
473
|
|
|
474
474
|
/**
|
|
@@ -545,7 +545,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
545
545
|
},
|
|
546
546
|
});
|
|
547
547
|
|
|
548
|
-
return result.data.user;
|
|
548
|
+
return (result.data as any).user;
|
|
549
549
|
} catch (error) {
|
|
550
550
|
if (error instanceof z.ZodError) {
|
|
551
551
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
@@ -598,7 +598,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
598
598
|
},
|
|
599
599
|
});
|
|
600
600
|
|
|
601
|
-
return result.data.user;
|
|
601
|
+
return (result.data as any).user;
|
|
602
602
|
} catch (error: unknown) {
|
|
603
603
|
const firebaseError = error as FirebaseError;
|
|
604
604
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -645,7 +645,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
645
645
|
},
|
|
646
646
|
});
|
|
647
647
|
|
|
648
|
-
return result.data.user;
|
|
648
|
+
return (result.data as any).user;
|
|
649
649
|
} catch (error: unknown) {
|
|
650
650
|
const firebaseError = error as FirebaseError;
|
|
651
651
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -693,7 +693,7 @@ export class AuthServiceV2 extends BaseService {
|
|
|
693
693
|
},
|
|
694
694
|
});
|
|
695
695
|
|
|
696
|
-
return result.data.user;
|
|
696
|
+
return (result.data as any).user;
|
|
697
697
|
} catch (error: unknown) {
|
|
698
698
|
const firebaseError = error as FirebaseError;
|
|
699
699
|
if (firebaseError.code === FirebaseErrorCode.POPUP_CLOSED_BY_USER) {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
CreateClinicAdminData,
|
|
16
16
|
ClinicAdmin,
|
|
17
|
-
} from "../../../types/clinic
|
|
17
|
+
} from "../../../types/clinic";
|
|
18
18
|
import { CLINIC_ADMIN_ERRORS } from "../../../errors/clinic.errors";
|
|
19
19
|
|
|
20
20
|
// Mock Firebase
|
|
@@ -30,6 +30,7 @@ describe("ClinicAdminService", () => {
|
|
|
30
30
|
clinicGroupId: "test-group-id",
|
|
31
31
|
isGroupOwner: false,
|
|
32
32
|
clinicsManaged: ["clinic-1", "clinic-2"],
|
|
33
|
+
clinicsManagedInfo: [],
|
|
33
34
|
contactInfo: {
|
|
34
35
|
firstName: "John",
|
|
35
36
|
lastName: "Doe",
|
|
@@ -39,8 +40,8 @@ describe("ClinicAdminService", () => {
|
|
|
39
40
|
},
|
|
40
41
|
roleTitle: "Clinic Administrator",
|
|
41
42
|
isActive: true,
|
|
42
|
-
createdAt: mockTimestamp.now()
|
|
43
|
-
updatedAt: mockTimestamp.now()
|
|
43
|
+
createdAt: mockTimestamp.now(),
|
|
44
|
+
updatedAt: mockTimestamp.now(),
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
beforeEach(() => {
|
|
@@ -53,7 +54,11 @@ describe("ClinicAdminService", () => {
|
|
|
53
54
|
analytics: null,
|
|
54
55
|
});
|
|
55
56
|
|
|
56
|
-
clinicAdminService = new ClinicAdminService(
|
|
57
|
+
clinicAdminService = new ClinicAdminService(
|
|
58
|
+
{} as any,
|
|
59
|
+
{} as any,
|
|
60
|
+
{} as any
|
|
61
|
+
);
|
|
57
62
|
|
|
58
63
|
// Mock Firestore functions
|
|
59
64
|
(doc as jest.Mock).mockReturnValue("doc-ref");
|
|
@@ -218,41 +223,15 @@ describe("ClinicAdminService", () => {
|
|
|
218
223
|
});
|
|
219
224
|
});
|
|
220
225
|
|
|
221
|
-
describe("setActive", () => {
|
|
222
|
-
it("treba da aktivira/deaktivira clinic admina", async () => {
|
|
223
|
-
await clinicAdminService.setActive(mockClinicAdmin.id, false);
|
|
224
|
-
|
|
225
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
226
|
-
expect(updateDoc).toHaveBeenCalledWith(
|
|
227
|
-
"doc-ref",
|
|
228
|
-
expect.objectContaining({
|
|
229
|
-
isActive: false,
|
|
230
|
-
updatedAt: expect.any(Date),
|
|
231
|
-
})
|
|
232
|
-
);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("treba da baci grešku ako admin ne postoji", async () => {
|
|
236
|
-
(getDoc as jest.Mock).mockResolvedValueOnce({
|
|
237
|
-
exists: () => false,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
await expect(
|
|
241
|
-
clinicAdminService.setActive("non-existent", false)
|
|
242
|
-
).rejects.toThrow(CLINIC_ADMIN_ERRORS.NOT_FOUND);
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
|
|
246
226
|
describe("addClinicToManaged", () => {
|
|
247
227
|
it("treba da doda kliniku admin-u", async () => {
|
|
248
228
|
const clinicId = "new-clinic-id";
|
|
249
|
-
|
|
229
|
+
await clinicAdminService.addClinicToManaged(
|
|
250
230
|
mockClinicAdmin.id,
|
|
251
231
|
clinicId
|
|
252
232
|
);
|
|
253
233
|
|
|
254
234
|
expect(updateDoc).toHaveBeenCalled();
|
|
255
|
-
expect(result.clinicsManaged).toContain(clinicId);
|
|
256
235
|
});
|
|
257
236
|
|
|
258
237
|
it("treba da baci grešku ako klinika već postoji", async () => {
|
|
@@ -267,13 +246,12 @@ describe("ClinicAdminService", () => {
|
|
|
267
246
|
describe("removeClinicFromManaged", () => {
|
|
268
247
|
it("treba da ukloni kliniku iz admin-a", async () => {
|
|
269
248
|
const clinicId = mockClinicAdmin.clinicsManaged[0];
|
|
270
|
-
|
|
249
|
+
await clinicAdminService.removeClinicFromManaged(
|
|
271
250
|
mockClinicAdmin.id,
|
|
272
251
|
clinicId
|
|
273
252
|
);
|
|
274
253
|
|
|
275
254
|
expect(updateDoc).toHaveBeenCalled();
|
|
276
|
-
expect(result.clinicsManaged).not.toContain(clinicId);
|
|
277
255
|
});
|
|
278
256
|
|
|
279
257
|
it("treba da baci grešku ako klinika ne postoji", async () => {
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
query,
|
|
10
10
|
where,
|
|
11
11
|
updateDoc,
|
|
12
|
-
deleteDoc,
|
|
13
12
|
setDoc,
|
|
14
13
|
} from "firebase/firestore";
|
|
15
14
|
|
|
@@ -48,7 +47,12 @@ describe("ClinicGroupService", () => {
|
|
|
48
47
|
analytics: null,
|
|
49
48
|
});
|
|
50
49
|
|
|
51
|
-
clinicGroupService = new ClinicGroupService(
|
|
50
|
+
clinicGroupService = new ClinicGroupService(
|
|
51
|
+
{} as any,
|
|
52
|
+
{} as any,
|
|
53
|
+
{} as any,
|
|
54
|
+
{} as any
|
|
55
|
+
);
|
|
52
56
|
|
|
53
57
|
// Mock Firestore functions
|
|
54
58
|
(doc as jest.Mock).mockReturnValue("doc-ref");
|
|
@@ -57,8 +61,6 @@ describe("ClinicGroupService", () => {
|
|
|
57
61
|
(where as jest.Mock).mockReturnValue("where-clause");
|
|
58
62
|
(setDoc as jest.Mock).mockResolvedValue(undefined);
|
|
59
63
|
(updateDoc as jest.Mock).mockResolvedValue(undefined);
|
|
60
|
-
(deleteDoc as jest.Mock).mockResolvedValue(undefined);
|
|
61
|
-
|
|
62
64
|
// Mock getDoc response
|
|
63
65
|
(getDoc as jest.Mock).mockResolvedValue({
|
|
64
66
|
exists: () => true,
|
|
@@ -92,13 +94,24 @@ describe("ClinicGroupService", () => {
|
|
|
92
94
|
name: "New Clinic Group",
|
|
93
95
|
description: "New Description",
|
|
94
96
|
logo: "new-logo-url",
|
|
95
|
-
|
|
97
|
+
hqLocation: {
|
|
98
|
+
address: "New Address",
|
|
99
|
+
city: "New City",
|
|
100
|
+
country: "New Country",
|
|
101
|
+
postalCode: "12345",
|
|
102
|
+
latitude: 45.0,
|
|
103
|
+
longitude: 20.0,
|
|
104
|
+
},
|
|
96
105
|
contactInfo: {
|
|
97
106
|
email: "contact@new.com",
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
phoneNumber: "+0987654321",
|
|
108
|
+
},
|
|
109
|
+
contactPerson: {
|
|
110
|
+
firstName: "John",
|
|
111
|
+
lastName: "Doe",
|
|
112
|
+
email: "john@new.com",
|
|
100
113
|
},
|
|
101
|
-
|
|
114
|
+
ownerId: null,
|
|
102
115
|
isActive: true,
|
|
103
116
|
};
|
|
104
117
|
|
|
@@ -148,30 +161,6 @@ describe("ClinicGroupService", () => {
|
|
|
148
161
|
});
|
|
149
162
|
});
|
|
150
163
|
|
|
151
|
-
describe("getClinicGroupsByOwner", () => {
|
|
152
|
-
it("treba da vrati kliničke grupe po vlasniku", async () => {
|
|
153
|
-
const result = await clinicGroupService.getClinicGroupsByOwner(
|
|
154
|
-
mockClinicGroup.ownerId
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
expect(collection).toHaveBeenCalled();
|
|
158
|
-
expect(query).toHaveBeenCalled();
|
|
159
|
-
expect(where).toHaveBeenCalledWith(
|
|
160
|
-
"ownerId",
|
|
161
|
-
"==",
|
|
162
|
-
mockClinicGroup.ownerId
|
|
163
|
-
);
|
|
164
|
-
expect(result).toEqual(
|
|
165
|
-
expect.arrayContaining([
|
|
166
|
-
expect.objectContaining({
|
|
167
|
-
id: mockClinicGroup.id,
|
|
168
|
-
ownerId: mockClinicGroup.ownerId,
|
|
169
|
-
}),
|
|
170
|
-
])
|
|
171
|
-
);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
164
|
describe("updateClinicGroup", () => {
|
|
176
165
|
it("treba da ažurira kliničku grupu", async () => {
|
|
177
166
|
const updates = {
|
|
@@ -205,74 +194,6 @@ describe("ClinicGroupService", () => {
|
|
|
205
194
|
});
|
|
206
195
|
});
|
|
207
196
|
|
|
208
|
-
describe("deleteClinicGroup", () => {
|
|
209
|
-
it("treba da obriše kliničku grupu", async () => {
|
|
210
|
-
await clinicGroupService.deleteClinicGroup(mockClinicGroup.id);
|
|
211
|
-
|
|
212
|
-
expect(deleteDoc).toHaveBeenCalledWith("doc-ref");
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it("treba da baci grešku ako grupa ne postoji", async () => {
|
|
216
|
-
(getDoc as jest.Mock).mockResolvedValueOnce({
|
|
217
|
-
exists: () => false,
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
await expect(
|
|
221
|
-
clinicGroupService.deleteClinicGroup("non-existent")
|
|
222
|
-
).rejects.toThrow();
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
describe("addClinicToGroup", () => {
|
|
227
|
-
it("treba da doda kliniku u grupu", async () => {
|
|
228
|
-
const clinicId = "new-clinic-id";
|
|
229
|
-
const result = await clinicGroupService.addClinicToGroup(
|
|
230
|
-
mockClinicGroup.id,
|
|
231
|
-
clinicId
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
235
|
-
expect(result.clinics).toContain(clinicId);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
describe("removeClinicFromGroup", () => {
|
|
240
|
-
it("treba da ukloni kliniku iz grupe", async () => {
|
|
241
|
-
const clinicId = mockClinicGroup.clinics[0];
|
|
242
|
-
const result = await clinicGroupService.removeClinicFromGroup(
|
|
243
|
-
mockClinicGroup.id,
|
|
244
|
-
clinicId
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
248
|
-
expect(result.clinics).not.toContain(clinicId);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
describe("getClinicGroupByAdmin", () => {
|
|
253
|
-
it("treba da vrati kliničke grupe po admin ID-u", async () => {
|
|
254
|
-
const result = await clinicGroupService.getClinicGroupByAdmin(
|
|
255
|
-
mockClinicGroup.ownerId
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
expect(collection).toHaveBeenCalled();
|
|
259
|
-
expect(query).toHaveBeenCalled();
|
|
260
|
-
expect(where).toHaveBeenCalledWith(
|
|
261
|
-
"admins",
|
|
262
|
-
"array-contains",
|
|
263
|
-
mockClinicGroup.ownerId
|
|
264
|
-
);
|
|
265
|
-
expect(result).toEqual(
|
|
266
|
-
expect.arrayContaining([
|
|
267
|
-
expect.objectContaining({
|
|
268
|
-
id: mockClinicGroup.id,
|
|
269
|
-
ownerId: mockClinicGroup.ownerId,
|
|
270
|
-
}),
|
|
271
|
-
])
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
197
|
describe("deactivateClinicGroup", () => {
|
|
277
198
|
it("treba da deaktivira kliničku grupu", async () => {
|
|
278
199
|
await clinicGroupService.deactivateClinicGroup(mockClinicGroup.id);
|
|
@@ -298,55 +219,4 @@ describe("ClinicGroupService", () => {
|
|
|
298
219
|
});
|
|
299
220
|
});
|
|
300
221
|
|
|
301
|
-
describe("addClinic", () => {
|
|
302
|
-
it("treba da doda kliniku u grupu", async () => {
|
|
303
|
-
const clinicId = "new-clinic-id";
|
|
304
|
-
const result = await clinicGroupService.addClinic(
|
|
305
|
-
mockClinicGroup.id,
|
|
306
|
-
clinicId
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
310
|
-
expect(result.clinics).toContain(clinicId);
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe("removeClinic", () => {
|
|
315
|
-
it("treba da ukloni kliniku iz grupe", async () => {
|
|
316
|
-
const clinicId = mockClinicGroup.clinics[0];
|
|
317
|
-
const result = await clinicGroupService.removeClinic(
|
|
318
|
-
mockClinicGroup.id,
|
|
319
|
-
clinicId
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
323
|
-
expect(result.clinics).not.toContain(clinicId);
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
describe("addAdmin", () => {
|
|
328
|
-
it("treba da doda admina u grupu", async () => {
|
|
329
|
-
const adminId = "new-admin-id";
|
|
330
|
-
const result = await clinicGroupService.addAdmin(
|
|
331
|
-
mockClinicGroup.id,
|
|
332
|
-
adminId
|
|
333
|
-
);
|
|
334
|
-
|
|
335
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
336
|
-
expect(result.admins).toContain(adminId);
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
describe("removeAdmin", () => {
|
|
341
|
-
it("treba da ukloni admina iz grupe", async () => {
|
|
342
|
-
const adminId = "admin-to-remove";
|
|
343
|
-
const result = await clinicGroupService.removeAdmin(
|
|
344
|
-
mockClinicGroup.id,
|
|
345
|
-
adminId
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
349
|
-
expect(result.admins).not.toContain(adminId);
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
222
|
});
|
|
@@ -50,7 +50,7 @@ describe("ClinicService", () => {
|
|
|
50
50
|
saturday: null,
|
|
51
51
|
sunday: null,
|
|
52
52
|
},
|
|
53
|
-
tags: [ClinicTag.PARKING, ClinicTag.
|
|
53
|
+
tags: [ClinicTag.PARKING, ClinicTag.WIFI],
|
|
54
54
|
customTags: ["special-service"],
|
|
55
55
|
isActive: true,
|
|
56
56
|
createdAt: mockTimestamp.now().toDate(),
|
|
@@ -67,7 +67,14 @@ describe("ClinicService", () => {
|
|
|
67
67
|
analytics: null,
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
clinicService = new ClinicService(
|
|
70
|
+
clinicService = new ClinicService(
|
|
71
|
+
{} as any,
|
|
72
|
+
{} as any,
|
|
73
|
+
{} as any,
|
|
74
|
+
{} as any,
|
|
75
|
+
{} as any,
|
|
76
|
+
{} as any
|
|
77
|
+
);
|
|
71
78
|
|
|
72
79
|
// Mock Firestore functions
|
|
73
80
|
(doc as jest.Mock).mockReturnValue("doc-ref");
|
|
@@ -107,14 +114,14 @@ describe("ClinicService", () => {
|
|
|
107
114
|
|
|
108
115
|
describe("createClinic", () => {
|
|
109
116
|
it("treba da kreira novu kliniku", async () => {
|
|
110
|
-
const clinicData = {
|
|
117
|
+
const clinicData: any = {
|
|
111
118
|
name: "New Clinic",
|
|
112
119
|
description: "New Description",
|
|
113
120
|
logo: "new-logo-url",
|
|
114
|
-
|
|
121
|
+
clinicGroupId: "new-group-id",
|
|
115
122
|
contactInfo: {
|
|
116
123
|
email: "new@clinic.test",
|
|
117
|
-
|
|
124
|
+
phoneNumber: "+0987654321",
|
|
118
125
|
website: "https://new.clinic",
|
|
119
126
|
},
|
|
120
127
|
location: {
|
|
@@ -136,7 +143,7 @@ describe("ClinicService", () => {
|
|
|
136
143
|
sunday: null,
|
|
137
144
|
},
|
|
138
145
|
tags: [ClinicTag.PARKING],
|
|
139
|
-
|
|
146
|
+
admins: ["test-admin-id"],
|
|
140
147
|
isActive: true,
|
|
141
148
|
};
|
|
142
149
|
|
|
@@ -260,40 +267,14 @@ describe("ClinicService", () => {
|
|
|
260
267
|
});
|
|
261
268
|
});
|
|
262
269
|
|
|
263
|
-
describe("searchClinics", () => {
|
|
264
|
-
it("treba da pronađe klinike po tagovima", async () => {
|
|
265
|
-
const searchParams = {
|
|
266
|
-
tags: [ClinicTag.PARKING],
|
|
267
|
-
isActive: true,
|
|
268
|
-
};
|
|
269
|
-
const result = await clinicService.searchClinics(searchParams);
|
|
270
|
-
|
|
271
|
-
expect(collection).toHaveBeenCalled();
|
|
272
|
-
expect(query).toHaveBeenCalled();
|
|
273
|
-
expect(where).toHaveBeenCalledWith(
|
|
274
|
-
"tags",
|
|
275
|
-
"array-contains-any",
|
|
276
|
-
searchParams.tags
|
|
277
|
-
);
|
|
278
|
-
expect(result).toEqual(
|
|
279
|
-
expect.arrayContaining([
|
|
280
|
-
expect.objectContaining({
|
|
281
|
-
id: mockClinic.id,
|
|
282
|
-
tags: expect.arrayContaining(searchParams.tags),
|
|
283
|
-
}),
|
|
284
|
-
])
|
|
285
|
-
);
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
270
|
describe("addTags", () => {
|
|
290
271
|
it("treba da doda tagove klinici", async () => {
|
|
291
272
|
const newTags = [ClinicTag.WIFI];
|
|
292
273
|
const adminId = "test-admin-id";
|
|
293
274
|
const result = await clinicService.addTags(
|
|
294
275
|
mockClinic.id,
|
|
295
|
-
|
|
296
|
-
|
|
276
|
+
adminId,
|
|
277
|
+
{ tags: newTags }
|
|
297
278
|
);
|
|
298
279
|
|
|
299
280
|
expect(updateDoc).toHaveBeenCalled();
|
|
@@ -309,8 +290,8 @@ describe("ClinicService", () => {
|
|
|
309
290
|
const adminId = "test-admin-id";
|
|
310
291
|
const result = await clinicService.removeTags(
|
|
311
292
|
mockClinic.id,
|
|
312
|
-
|
|
313
|
-
|
|
293
|
+
adminId,
|
|
294
|
+
{ tags: tagsToRemove }
|
|
314
295
|
);
|
|
315
296
|
|
|
316
297
|
expect(updateDoc).toHaveBeenCalled();
|
|
@@ -318,37 +299,4 @@ describe("ClinicService", () => {
|
|
|
318
299
|
});
|
|
319
300
|
});
|
|
320
301
|
|
|
321
|
-
describe("addCustomTags", () => {
|
|
322
|
-
it("treba da doda custom tagove klinici", async () => {
|
|
323
|
-
const newCustomTags = ["new-service"];
|
|
324
|
-
const adminId = "test-admin-id";
|
|
325
|
-
const result = await clinicService.addCustomTags(
|
|
326
|
-
mockClinic.id,
|
|
327
|
-
newCustomTags,
|
|
328
|
-
adminId
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
332
|
-
expect(result.customTags).toEqual(
|
|
333
|
-
expect.arrayContaining([...mockClinic.customTags, ...newCustomTags])
|
|
334
|
-
);
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
describe("removeCustomTags", () => {
|
|
339
|
-
it("treba da ukloni custom tagove iz klinike", async () => {
|
|
340
|
-
const customTagsToRemove = [mockClinic.customTags[0]];
|
|
341
|
-
const adminId = "test-admin-id";
|
|
342
|
-
const result = await clinicService.removeCustomTags(
|
|
343
|
-
mockClinic.id,
|
|
344
|
-
customTagsToRemove,
|
|
345
|
-
adminId
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
expect(updateDoc).toHaveBeenCalled();
|
|
349
|
-
expect(result.customTags).not.toEqual(
|
|
350
|
-
expect.arrayContaining(customTagsToRemove)
|
|
351
|
-
);
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
302
|
});
|
|
@@ -74,7 +74,7 @@ export async function createClinicGroup(
|
|
|
74
74
|
let validatedData: CreateClinicGroupData;
|
|
75
75
|
// Validacija podataka
|
|
76
76
|
try {
|
|
77
|
-
validatedData = createClinicGroupSchema.parse(data);
|
|
77
|
+
validatedData = createClinicGroupSchema.parse(data) as CreateClinicGroupData;
|
|
78
78
|
console.log("[CLINIC_GROUP] Data validation passed");
|
|
79
79
|
} catch (validationError) {
|
|
80
80
|
console.error("[CLINIC_GROUP] Data validation failed:", validationError);
|
|
@@ -138,7 +138,7 @@ export async function createClinicGroup(
|
|
|
138
138
|
|
|
139
139
|
// Handle logo upload if provided
|
|
140
140
|
let logoUrl = await uploadPhoto(
|
|
141
|
-
validatedData.logo || null,
|
|
141
|
+
(validatedData.logo as string) || null,
|
|
142
142
|
"clinic-groups",
|
|
143
143
|
groupId,
|
|
144
144
|
"logo",
|
|
@@ -145,7 +145,7 @@ export async function createClinic(
|
|
|
145
145
|
console.log("[CLINIC] Processing logo");
|
|
146
146
|
try {
|
|
147
147
|
logoUrl = await uploadPhoto(
|
|
148
|
-
validatedData.logo,
|
|
148
|
+
validatedData.logo as string,
|
|
149
149
|
"clinics",
|
|
150
150
|
clinicId,
|
|
151
151
|
"logo",
|
|
@@ -164,7 +164,7 @@ export async function createClinic(
|
|
|
164
164
|
console.log("[CLINIC] Processing cover photo");
|
|
165
165
|
try {
|
|
166
166
|
processedCoverPhoto = await uploadPhoto(
|
|
167
|
-
validatedData.coverPhoto,
|
|
167
|
+
validatedData.coverPhoto as string,
|
|
168
168
|
"clinics",
|
|
169
169
|
clinicId,
|
|
170
170
|
"cover",
|
|
@@ -176,19 +176,21 @@ export async function createClinic(
|
|
|
176
176
|
} catch (coverPhotoError) {
|
|
177
177
|
console.error("[CLINIC] Error processing cover photo:", coverPhotoError);
|
|
178
178
|
// Continue with clinic creation even if cover photo upload fails
|
|
179
|
-
|
|
179
|
+
const coverPhotoStr = validatedData.coverPhoto as string;
|
|
180
|
+
processedCoverPhoto = coverPhotoStr.startsWith("data:")
|
|
180
181
|
? null
|
|
181
|
-
:
|
|
182
|
+
: coverPhotoStr;
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
// Handle featured photos upload
|
|
186
187
|
let processedFeaturedPhotos: string[] = [];
|
|
187
|
-
|
|
188
|
+
const featuredPhotosStr = (validatedData.featuredPhotos || []) as string[];
|
|
189
|
+
if (featuredPhotosStr.length > 0) {
|
|
188
190
|
console.log("[CLINIC] Processing featured photos");
|
|
189
191
|
try {
|
|
190
192
|
processedFeaturedPhotos = await uploadMultiplePhotos(
|
|
191
|
-
|
|
193
|
+
featuredPhotosStr,
|
|
192
194
|
"clinics",
|
|
193
195
|
clinicId,
|
|
194
196
|
"featured",
|
|
@@ -203,22 +205,23 @@ export async function createClinic(
|
|
|
203
205
|
featuredError
|
|
204
206
|
);
|
|
205
207
|
// Continue with clinic creation even if featured photos upload fails
|
|
206
|
-
processedFeaturedPhotos =
|
|
208
|
+
processedFeaturedPhotos = featuredPhotosStr.filter(
|
|
207
209
|
(photo) => !photo.startsWith("data:")
|
|
208
210
|
);
|
|
209
211
|
}
|
|
210
212
|
}
|
|
211
213
|
|
|
212
214
|
// Handle photos with tags
|
|
213
|
-
let processedPhotosWithTags = validatedData.photosWithTags || [];
|
|
215
|
+
let processedPhotosWithTags: any[] = validatedData.photosWithTags || [];
|
|
214
216
|
if (processedPhotosWithTags.length > 0) {
|
|
215
217
|
console.log("[CLINIC] Processing photos with tags");
|
|
216
218
|
try {
|
|
217
|
-
const updatedPhotosWithTags = [];
|
|
219
|
+
const updatedPhotosWithTags: any[] = [];
|
|
218
220
|
for (const photoWithTag of processedPhotosWithTags) {
|
|
219
|
-
|
|
221
|
+
const photoUrl = photoWithTag.url as string;
|
|
222
|
+
if (photoUrl && photoUrl.startsWith("data:")) {
|
|
220
223
|
const uploadedUrl = await uploadPhoto(
|
|
221
|
-
|
|
224
|
+
photoUrl,
|
|
222
225
|
"clinics",
|
|
223
226
|
clinicId,
|
|
224
227
|
`tagged-${photoWithTag.tag}`,
|
|
@@ -243,7 +246,7 @@ export async function createClinic(
|
|
|
243
246
|
// Continue with clinic creation even if photos with tags upload fails
|
|
244
247
|
processedPhotosWithTags =
|
|
245
248
|
validatedData.photosWithTags?.filter(
|
|
246
|
-
(photo) => !photo.url.startsWith("data:")
|
|
249
|
+
(photo) => !(photo.url as string).startsWith("data:")
|
|
247
250
|
) || [];
|
|
248
251
|
}
|
|
249
252
|
}
|
|
@@ -254,6 +257,7 @@ export async function createClinic(
|
|
|
254
257
|
const clinicData: Clinic = {
|
|
255
258
|
...validatedData,
|
|
256
259
|
id: clinicId,
|
|
260
|
+
nameLower: (validatedData.name || "").toLowerCase(),
|
|
257
261
|
description: validatedData.description || "",
|
|
258
262
|
location: {
|
|
259
263
|
address: validatedData.location.address || "",
|
|
@@ -617,10 +621,11 @@ export async function updateClinic(
|
|
|
617
621
|
console.log("[CLINIC] Processing featured photos update");
|
|
618
622
|
try {
|
|
619
623
|
// Filter out only data URLs that need to be uploaded
|
|
620
|
-
const
|
|
624
|
+
const allPhotos = data.featuredPhotos as string[];
|
|
625
|
+
const dataUrlPhotos = allPhotos.filter(
|
|
621
626
|
(photo) => typeof photo === "string" && photo.startsWith("data:")
|
|
622
627
|
);
|
|
623
|
-
const existingPhotos =
|
|
628
|
+
const existingPhotos = allPhotos.filter(
|
|
624
629
|
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
625
630
|
);
|
|
626
631
|
|
|
@@ -637,10 +642,10 @@ export async function updateClinic(
|
|
|
637
642
|
});
|
|
638
643
|
|
|
639
644
|
// Combine existing photos with newly uploaded ones
|
|
640
|
-
updatedData.featuredPhotos = [...existingPhotos, ...uploadedPhotos];
|
|
645
|
+
updatedData.featuredPhotos = [...existingPhotos, ...uploadedPhotos] as any;
|
|
641
646
|
} else {
|
|
642
647
|
// If no new photos to upload, just use the existing ones
|
|
643
|
-
updatedData.featuredPhotos = existingPhotos;
|
|
648
|
+
updatedData.featuredPhotos = existingPhotos as any;
|
|
644
649
|
}
|
|
645
650
|
} catch (featuredError) {
|
|
646
651
|
console.error(
|
|
@@ -648,9 +653,9 @@ export async function updateClinic(
|
|
|
648
653
|
featuredError
|
|
649
654
|
);
|
|
650
655
|
// Continue with update even if featured photos upload fails
|
|
651
|
-
updatedData.featuredPhotos = data.featuredPhotos.filter(
|
|
656
|
+
updatedData.featuredPhotos = (data.featuredPhotos as string[]).filter(
|
|
652
657
|
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
653
|
-
);
|
|
658
|
+
) as any;
|
|
654
659
|
}
|
|
655
660
|
}
|
|
656
661
|
|
|
@@ -658,14 +663,15 @@ export async function updateClinic(
|
|
|
658
663
|
if (data.photosWithTags && data.photosWithTags.length > 0) {
|
|
659
664
|
console.log("[CLINIC] Processing photos with tags update");
|
|
660
665
|
try {
|
|
661
|
-
const updatedPhotosWithTags = [];
|
|
666
|
+
const updatedPhotosWithTags: any[] = [];
|
|
662
667
|
|
|
663
668
|
// Process each photo with tag
|
|
664
669
|
for (const photoWithTag of data.photosWithTags) {
|
|
665
|
-
|
|
670
|
+
const photoUrl = photoWithTag.url as string;
|
|
671
|
+
if (photoUrl && photoUrl.startsWith("data:")) {
|
|
666
672
|
// Upload new photo
|
|
667
673
|
const uploadedUrl = await uploadPhoto(
|
|
668
|
-
|
|
674
|
+
photoUrl,
|
|
669
675
|
"clinics",
|
|
670
676
|
clinicId,
|
|
671
677
|
`tagged-${photoWithTag.tag}`,
|
|
@@ -695,7 +701,7 @@ export async function updateClinic(
|
|
|
695
701
|
);
|
|
696
702
|
// Continue with update even if photos with tags upload fails
|
|
697
703
|
updatedData.photosWithTags = data.photosWithTags.filter(
|
|
698
|
-
(photo) => !photo.url.startsWith("data:")
|
|
704
|
+
(photo) => !(photo.url as string).startsWith("data:")
|
|
699
705
|
);
|
|
700
706
|
}
|
|
701
707
|
}
|