@blackcode_sa/metaestetics-api 1.14.78 → 1.15.2

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.
Files changed (42) hide show
  1. package/dist/admin/index.d.mts +5 -0
  2. package/dist/admin/index.d.ts +5 -0
  3. package/dist/admin/index.js +47 -5
  4. package/dist/admin/index.mjs +47 -5
  5. package/dist/index.d.mts +302 -1
  6. package/dist/index.d.ts +302 -1
  7. package/dist/index.js +2655 -1754
  8. package/dist/index.mjs +1880 -983
  9. package/package.json +1 -1
  10. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +59 -6
  11. package/src/services/__tests__/auth/auth.mock.test.ts +2 -2
  12. package/src/services/__tests__/auth/auth.setup.ts +6 -1
  13. package/src/services/__tests__/auth.service.test.ts +8 -44
  14. package/src/services/__tests__/base.service.test.ts +4 -45
  15. package/src/services/__tests__/user.service.test.ts +6 -4
  16. package/src/services/appointment/utils/appointment.utils.ts +0 -3
  17. package/src/services/appointment/utils/extended-procedure.utils.ts +1 -0
  18. package/src/services/auth/auth.v2.service.ts +7 -7
  19. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +11 -33
  20. package/src/services/clinic/__tests__/clinic-group.service.test.ts +21 -151
  21. package/src/services/clinic/__tests__/clinic.service.test.ts +17 -69
  22. package/src/services/clinic/utils/clinic-group.utils.ts +2 -2
  23. package/src/services/clinic/utils/clinic.utils.ts +28 -22
  24. package/src/services/clinic/utils/index.ts +0 -1
  25. package/src/services/notifications/__tests__/notification.service.test.ts +5 -5
  26. package/src/services/patient/__tests__/patient.service.test.ts +17 -25
  27. package/src/services/patient/patient.service.ts +136 -0
  28. package/src/services/patient/utils/body-assessment.utils.ts +159 -0
  29. package/src/services/patient/utils/docs.utils.ts +1 -1
  30. package/src/services/patient/utils/hair-scalp-assessment.utils.ts +158 -0
  31. package/src/services/patient/utils/pre-surgical-assessment.utils.ts +161 -0
  32. package/src/services/patient/utils/skin-quality-assessment.utils.ts +160 -0
  33. package/src/services/user/user.v2.service.ts +4 -3
  34. package/src/types/patient/body-assessment.types.ts +93 -0
  35. package/src/types/patient/hair-scalp-assessment.types.ts +98 -0
  36. package/src/types/patient/index.ts +4 -0
  37. package/src/types/patient/pre-surgical-assessment.types.ts +95 -0
  38. package/src/types/patient/skin-quality-assessment.types.ts +105 -0
  39. package/src/validations/patient/body-assessment.schema.ts +82 -0
  40. package/src/validations/patient/hair-scalp-assessment.schema.ts +70 -0
  41. package/src/validations/patient/pre-surgical-assessment.schema.ts +78 -0
  42. package/src/validations/patient/skin-quality-assessment.schema.ts +70 -0
@@ -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
- website: "https://new.com",
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
- phone: "+0987654321",
99
- address: "New Address",
107
+ phoneNumber: "+0987654321",
108
+ },
109
+ contactPerson: {
110
+ firstName: "John",
111
+ lastName: "Doe",
112
+ email: "john@new.com",
100
113
  },
101
- clinics: [],
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.WHEELCHAIR_ACCESS],
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
- groupId: "new-group-id",
121
+ clinicGroupId: "new-group-id",
115
122
  contactInfo: {
116
123
  email: "new@clinic.test",
117
- phoneNumbers: ["+0987654321"],
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
- customTags: [],
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
- newTags,
296
- adminId
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
- tagsToRemove,
313
- adminId
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
- processedCoverPhoto = validatedData.coverPhoto.startsWith("data:")
179
+ const coverPhotoStr = validatedData.coverPhoto as string;
180
+ processedCoverPhoto = coverPhotoStr.startsWith("data:")
180
181
  ? null
181
- : validatedData.coverPhoto;
182
+ : coverPhotoStr;
182
183
  }
183
184
  }
184
185
 
185
186
  // Handle featured photos upload
186
187
  let processedFeaturedPhotos: string[] = [];
187
- if (validatedData.featuredPhotos && validatedData.featuredPhotos.length > 0) {
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
- validatedData.featuredPhotos,
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 = validatedData.featuredPhotos.filter(
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
- if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
221
+ const photoUrl = photoWithTag.url as string;
222
+ if (photoUrl && photoUrl.startsWith("data:")) {
220
223
  const uploadedUrl = await uploadPhoto(
221
- photoWithTag.url,
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 dataUrlPhotos = data.featuredPhotos.filter(
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 = data.featuredPhotos.filter(
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
- if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
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
- photoWithTag.url,
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
  }
@@ -6,6 +6,5 @@
6
6
  export * from "./clinic.utils";
7
7
  export * from "./clinic-group.utils";
8
8
  export * from "./admin.utils";
9
- export * from "./review.utils";
10
9
  export * from "./tag.utils";
11
10
  export * from "./search.utils";
@@ -4,7 +4,7 @@ import {
4
4
  NotificationStatus,
5
5
  NotificationType,
6
6
  NOTIFICATIONS_COLLECTION,
7
- AppointmentNotification,
7
+ AppointmentStatusChangeNotification,
8
8
  } from "../../../types/notifications";
9
9
  import { UserRole } from "../../../types";
10
10
  import {
@@ -37,18 +37,18 @@ jest.mock("../../../config/firebase", () => ({
37
37
  describe("NotificationService", () => {
38
38
  let service: NotificationService;
39
39
  const mockNotification: Omit<
40
- AppointmentNotification,
40
+ AppointmentStatusChangeNotification,
41
41
  "id" | "createdAt" | "updatedAt"
42
42
  > = {
43
43
  title: "Test Notification",
44
44
  body: "Test Body",
45
- notificationType: NotificationType.APPOINTMENT_NOTIFICATION,
45
+ notificationType: NotificationType.APPOINTMENT_STATUS_CHANGE,
46
46
  userId: "test-user-id",
47
47
  status: NotificationStatus.PENDING,
48
48
  isRead: false,
49
49
  userRole: UserRole.PATIENT,
50
50
  appointmentId: "test-appointment-id",
51
- appointmentStatus: "confirmed",
51
+ newStatus: "confirmed",
52
52
  previousStatus: "pending",
53
53
  notificationTime: Timestamp.now(),
54
54
  notificationTokens: ["test-token"],
@@ -64,7 +64,7 @@ describe("NotificationService", () => {
64
64
 
65
65
  beforeEach(async () => {
66
66
  jest.clearAllMocks();
67
- service = new NotificationService();
67
+ service = new NotificationService({} as any, {} as any, {} as any);
68
68
  await (service as any).initialized;
69
69
  }, 10000);
70
70
 
@@ -4,7 +4,7 @@ import {
4
4
  CreatePatientProfileData,
5
5
  PATIENTS_COLLECTION,
6
6
  Gender,
7
- Location,
7
+ LocationData,
8
8
  } from "../../../types/patient";
9
9
  import { UserRole } from "../../../types";
10
10
  import {
@@ -44,7 +44,7 @@ jest.mock("../../../config/firebase");
44
44
 
45
45
  describe("PatientService", () => {
46
46
  let service: PatientService;
47
- const mockLocation: Location = {
47
+ const mockLocation: LocationData = {
48
48
  latitude: 44.8125,
49
49
  longitude: 20.4612,
50
50
  geohash: "mock-geohash",
@@ -52,28 +52,26 @@ describe("PatientService", () => {
52
52
 
53
53
  const mockCreateData: CreatePatientProfileData = {
54
54
  userRef: "test-user-id",
55
- firstName: "Test",
56
- lastName: "Patient",
57
- gender: Gender.MALE,
58
- contactInfo: {
59
- email: "test@example.com",
60
- phoneNumber: "+381601234567",
61
- },
62
- location: {
63
- latitude: mockLocation.latitude,
64
- longitude: mockLocation.longitude,
65
- geohash: mockLocation.geohash,
66
- },
55
+ displayName: "Test Patient",
67
56
  expoTokens: [],
68
57
  isActive: true,
69
58
  isVerified: false,
59
+ isManual: false,
70
60
  };
71
61
 
72
62
  const mockPatientProfile: PatientProfile = {
73
63
  ...mockCreateData,
74
- id: mockCreateData.userRef,
75
- location: mockLocation,
64
+ id: mockCreateData.userRef as string,
65
+ displayName: "Test Patient",
76
66
  gamification: { level: 1, points: 0 },
67
+ expoTokens: [],
68
+ isActive: true,
69
+ isVerified: false,
70
+ isManual: false,
71
+ doctors: [],
72
+ clinics: [],
73
+ doctorIds: [],
74
+ clinicIds: [],
77
75
  createdAt: Timestamp.now(),
78
76
  updatedAt: Timestamp.now(),
79
77
  };
@@ -90,7 +88,7 @@ describe("PatientService", () => {
90
88
  analytics: null,
91
89
  });
92
90
 
93
- service = new PatientService();
91
+ service = new PatientService(mockDb as any, mockAuth as any, {} as any);
94
92
 
95
93
  // Mock Firestore functions
96
94
  (doc as jest.Mock).mockReturnValue("doc-ref");
@@ -159,10 +157,6 @@ describe("PatientService", () => {
159
157
  expect.objectContaining({
160
158
  ...mockCreateData,
161
159
  id: mockCreateData.userRef,
162
- location: {
163
- ...mockCreateData.location,
164
- geohash: "hash123",
165
- },
166
160
  gamification: { level: 1, points: 0 },
167
161
  })
168
162
  );
@@ -174,8 +168,7 @@ describe("PatientService", () => {
174
168
  it("treba da vrati profil pacijenta ako postoji", async () => {
175
169
  const mockProfile = {
176
170
  id: "test-user-id",
177
- firstName: "Test",
178
- lastName: "User",
171
+ displayName: "Test User",
179
172
  createdAt: mockTimestamp.now().toDate(),
180
173
  updatedAt: mockTimestamp.now().toDate(),
181
174
  };
@@ -214,8 +207,7 @@ describe("PatientService", () => {
214
207
  describe("updatePatientProfile", () => {
215
208
  it("treba da ažurira profil pacijenta", async () => {
216
209
  const updates = {
217
- firstName: "Updated",
218
- lastName: "Name",
210
+ displayName: "Updated Name",
219
211
  };
220
212
  const mockTimestamp = new Date();
221
213
  (serverTimestamp as jest.Mock).mockReturnValue(mockTimestamp);