@blackcode_sa/metaestetics-api 1.5.27 → 1.5.29
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 +1199 -1
- package/dist/admin/index.d.ts +1199 -1
- package/dist/admin/index.js +1337 -2
- package/dist/admin/index.mjs +1333 -2
- package/dist/backoffice/index.d.mts +99 -7
- package/dist/backoffice/index.d.ts +99 -7
- package/dist/index.d.mts +4184 -2426
- package/dist/index.d.ts +4184 -2426
- package/dist/index.js +2692 -1546
- package/dist/index.mjs +2663 -1502
- package/package.json +1 -1
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +642 -0
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -0
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -0
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +508 -0
- package/src/admin/index.ts +53 -4
- package/src/index.ts +28 -4
- package/src/services/calendar/calendar-refactored.service.ts +1 -1
- package/src/services/clinic/clinic.service.ts +344 -77
- package/src/services/clinic/utils/clinic.utils.ts +187 -8
- package/src/services/clinic/utils/filter.utils.d.ts +23 -0
- package/src/services/clinic/utils/filter.utils.ts +264 -0
- package/src/services/practitioner/practitioner.service.ts +616 -5
- package/src/services/procedure/procedure.service.ts +678 -52
- package/src/services/reviews/reviews.service.ts +842 -0
- package/src/types/clinic/index.ts +24 -56
- package/src/types/practitioner/index.ts +34 -33
- package/src/types/procedure/index.ts +39 -0
- package/src/types/profile/index.ts +1 -1
- package/src/types/reviews/index.ts +126 -0
- package/src/validations/clinic.schema.ts +37 -64
- package/src/validations/practitioner.schema.ts +42 -32
- package/src/validations/procedure.schema.ts +14 -3
- package/src/validations/reviews.schema.ts +189 -0
- package/src/services/clinic/utils/review.utils.ts +0 -93
|
@@ -13,19 +13,29 @@ import {
|
|
|
13
13
|
GeoPoint,
|
|
14
14
|
QueryConstraint,
|
|
15
15
|
FieldValue,
|
|
16
|
+
writeBatch,
|
|
17
|
+
arrayUnion,
|
|
18
|
+
arrayRemove,
|
|
16
19
|
} from "firebase/firestore";
|
|
17
20
|
import { BaseService } from "../base.service";
|
|
18
21
|
import {
|
|
19
22
|
Clinic,
|
|
20
23
|
CreateClinicData,
|
|
21
24
|
CLINICS_COLLECTION,
|
|
22
|
-
ClinicReview,
|
|
23
25
|
ClinicTag,
|
|
24
26
|
ClinicTags,
|
|
25
27
|
ClinicGroup,
|
|
28
|
+
CLINIC_GROUPS_COLLECTION,
|
|
26
29
|
ClinicBranchSetupData,
|
|
27
30
|
CLINIC_ADMINS_COLLECTION,
|
|
31
|
+
DoctorInfo,
|
|
32
|
+
// Remove incorrect imports below
|
|
33
|
+
// ProcedureSummaryInfo,
|
|
34
|
+
// ClinicInfo
|
|
28
35
|
} from "../../types/clinic";
|
|
36
|
+
// Correct imports
|
|
37
|
+
import { ProcedureSummaryInfo } from "../../types/procedure";
|
|
38
|
+
import { ClinicInfo } from "../../types/profile";
|
|
29
39
|
import { ClinicGroupService } from "./clinic-group.service";
|
|
30
40
|
import { ClinicAdminService } from "./clinic-admin.service";
|
|
31
41
|
import {
|
|
@@ -36,17 +46,18 @@ import {
|
|
|
36
46
|
import {
|
|
37
47
|
clinicSchema,
|
|
38
48
|
createClinicSchema,
|
|
39
|
-
clinicReviewSchema,
|
|
40
49
|
} from "../../validations/clinic.schema";
|
|
41
50
|
import { z } from "zod";
|
|
42
51
|
import { Auth } from "firebase/auth";
|
|
43
52
|
import { Firestore } from "firebase/firestore";
|
|
44
53
|
import { FirebaseApp } from "firebase/app";
|
|
45
54
|
import * as ClinicUtils from "./utils/clinic.utils";
|
|
46
|
-
import * as ReviewUtils from "./utils/review.utils";
|
|
47
55
|
import * as TagUtils from "./utils/tag.utils";
|
|
48
56
|
import * as SearchUtils from "./utils/search.utils";
|
|
49
57
|
import * as AdminUtils from "./utils/admin.utils";
|
|
58
|
+
import * as FilterUtils from "./utils/filter.utils";
|
|
59
|
+
import { ClinicReviewInfo } from "../../types/reviews";
|
|
60
|
+
import { PRACTITIONERS_COLLECTION } from "../../types/practitioner";
|
|
50
61
|
|
|
51
62
|
export class ClinicService extends BaseService {
|
|
52
63
|
private clinicGroupService: ClinicGroupService;
|
|
@@ -64,23 +75,290 @@ export class ClinicService extends BaseService {
|
|
|
64
75
|
this.clinicGroupService = clinicGroupService;
|
|
65
76
|
}
|
|
66
77
|
|
|
78
|
+
// --- Helper Functions ---
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Creates an aggregated ClinicInfo object from Clinic data.
|
|
82
|
+
* @param clinic The clinic object
|
|
83
|
+
* @returns ClinicInfo object
|
|
84
|
+
*/
|
|
85
|
+
private _createClinicInfoForAggregation(clinic: Clinic): ClinicInfo {
|
|
86
|
+
return {
|
|
87
|
+
id: clinic.id,
|
|
88
|
+
featuredPhoto:
|
|
89
|
+
clinic.featuredPhotos && clinic.featuredPhotos.length > 0
|
|
90
|
+
? clinic.featuredPhotos[0]
|
|
91
|
+
: clinic.coverPhoto || "",
|
|
92
|
+
name: clinic.name,
|
|
93
|
+
description: clinic.description || "",
|
|
94
|
+
location: clinic.location,
|
|
95
|
+
contactInfo: clinic.contactInfo,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Updates the ClinicInfo within the clinicsInfo array for multiple practitioners.
|
|
101
|
+
* @param practitionerIds IDs of practitioners to update
|
|
102
|
+
* @param clinicInfo The updated ClinicInfo object
|
|
103
|
+
*/
|
|
104
|
+
private async _updateClinicInfoInPractitioners(
|
|
105
|
+
practitionerIds: string[],
|
|
106
|
+
clinicInfo: ClinicInfo
|
|
107
|
+
): Promise<void> {
|
|
108
|
+
const batch = writeBatch(this.db);
|
|
109
|
+
const clinicId = clinicInfo.id;
|
|
110
|
+
|
|
111
|
+
for (const practitionerId of practitionerIds) {
|
|
112
|
+
const practitionerRef = doc(
|
|
113
|
+
this.db,
|
|
114
|
+
PRACTITIONERS_COLLECTION,
|
|
115
|
+
practitionerId
|
|
116
|
+
);
|
|
117
|
+
// Remove old clinic info based on ID
|
|
118
|
+
batch.update(practitionerRef, {
|
|
119
|
+
clinicsInfo: arrayRemove(...[{ id: clinicId }]),
|
|
120
|
+
updatedAt: serverTimestamp(),
|
|
121
|
+
});
|
|
122
|
+
// Add updated clinic info
|
|
123
|
+
batch.update(practitionerRef, {
|
|
124
|
+
clinicsInfo: arrayUnion(clinicInfo),
|
|
125
|
+
updatedAt: serverTimestamp(),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
await batch.commit();
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(
|
|
132
|
+
`Error updating clinic info in practitioners for clinic ${clinicId}:`,
|
|
133
|
+
error
|
|
134
|
+
);
|
|
135
|
+
// Decide on error handling
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// --- Core Service Methods (Updated) ---
|
|
140
|
+
|
|
67
141
|
/**
|
|
68
|
-
*
|
|
142
|
+
* Creates a new clinic.
|
|
143
|
+
* Initializes empty doctorsInfo and proceduresInfo.
|
|
144
|
+
* Aggregation into Clinic happens via PractitionerService and ProcedureService.
|
|
69
145
|
*/
|
|
70
146
|
async createClinic(
|
|
71
147
|
data: CreateClinicData,
|
|
72
148
|
creatorAdminId: string
|
|
73
149
|
): Promise<Clinic> {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
150
|
+
try {
|
|
151
|
+
const validatedData = createClinicSchema.parse(data);
|
|
152
|
+
const group = await this.clinicGroupService.getClinicGroup(
|
|
153
|
+
validatedData.clinicGroupId
|
|
154
|
+
);
|
|
155
|
+
if (!group)
|
|
156
|
+
throw new Error(
|
|
157
|
+
`Clinic group ${validatedData.clinicGroupId} not found`
|
|
158
|
+
);
|
|
159
|
+
const location = validatedData.location;
|
|
160
|
+
const hash = geohashForLocation([location.latitude, location.longitude]);
|
|
161
|
+
const defaultReviewInfo: ClinicReviewInfo = {
|
|
162
|
+
totalReviews: 0,
|
|
163
|
+
averageRating: 0,
|
|
164
|
+
cleanliness: 0,
|
|
165
|
+
facilities: 0,
|
|
166
|
+
staffFriendliness: 0,
|
|
167
|
+
waitingTime: 0,
|
|
168
|
+
accessibility: 0,
|
|
169
|
+
recommendationPercentage: 0,
|
|
170
|
+
};
|
|
171
|
+
const clinicId = this.generateId();
|
|
172
|
+
|
|
173
|
+
const clinicData: Omit<Clinic, "createdAt" | "updatedAt"> & {
|
|
174
|
+
createdAt: FieldValue;
|
|
175
|
+
updatedAt: FieldValue;
|
|
176
|
+
} = {
|
|
177
|
+
id: clinicId,
|
|
178
|
+
clinicGroupId: validatedData.clinicGroupId,
|
|
179
|
+
name: validatedData.name,
|
|
180
|
+
description: validatedData.description,
|
|
181
|
+
location: { ...location, geohash: hash },
|
|
182
|
+
contactInfo: validatedData.contactInfo,
|
|
183
|
+
workingHours: validatedData.workingHours,
|
|
184
|
+
tags: validatedData.tags,
|
|
185
|
+
featuredPhotos: validatedData.featuredPhotos || [],
|
|
186
|
+
coverPhoto: validatedData.coverPhoto,
|
|
187
|
+
photosWithTags: validatedData.photosWithTags,
|
|
188
|
+
doctors: [],
|
|
189
|
+
procedures: [],
|
|
190
|
+
doctorsInfo: [],
|
|
191
|
+
proceduresInfo: [],
|
|
192
|
+
reviewInfo: defaultReviewInfo,
|
|
193
|
+
admins: [creatorAdminId],
|
|
194
|
+
isActive: validatedData.isActive,
|
|
195
|
+
isVerified: validatedData.isVerified,
|
|
196
|
+
logo: validatedData.logo,
|
|
197
|
+
createdAt: serverTimestamp(),
|
|
198
|
+
updatedAt: serverTimestamp(),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// Re-validate before saving (ensure schema matches the final object)
|
|
202
|
+
clinicSchema.parse({
|
|
203
|
+
...clinicData,
|
|
204
|
+
createdAt: Timestamp.now(),
|
|
205
|
+
updatedAt: Timestamp.now(),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const batch = writeBatch(this.db);
|
|
209
|
+
const clinicRef = doc(this.db, CLINICS_COLLECTION, clinicId);
|
|
210
|
+
batch.set(clinicRef, clinicData);
|
|
211
|
+
|
|
212
|
+
const groupRef = doc(
|
|
213
|
+
this.db,
|
|
214
|
+
CLINIC_GROUPS_COLLECTION,
|
|
215
|
+
validatedData.clinicGroupId
|
|
216
|
+
);
|
|
217
|
+
const newClinicInfoForGroup = this._createClinicInfoForAggregation({
|
|
218
|
+
...clinicData,
|
|
219
|
+
id: clinicId,
|
|
220
|
+
} as Clinic);
|
|
221
|
+
batch.update(groupRef, {
|
|
222
|
+
clinics: arrayUnion(clinicId),
|
|
223
|
+
clinicsInfo: arrayUnion(newClinicInfoForGroup),
|
|
224
|
+
updatedAt: serverTimestamp(),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const adminRef = doc(this.db, CLINIC_ADMINS_COLLECTION, creatorAdminId);
|
|
228
|
+
batch.update(adminRef, {
|
|
229
|
+
clinicsManaged: arrayUnion(clinicId),
|
|
230
|
+
updatedAt: serverTimestamp(),
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
await batch.commit();
|
|
234
|
+
const savedClinic = await this.getClinic(clinicId);
|
|
235
|
+
if (!savedClinic) throw new Error("Failed to retrieve created clinic");
|
|
236
|
+
return savedClinic;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof z.ZodError) {
|
|
239
|
+
throw new Error("Invalid clinic data: " + error.message);
|
|
240
|
+
}
|
|
241
|
+
console.error("Error creating clinic:", error);
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Updates a clinic and propagates changes (ClinicInfo) to associated practitioners.
|
|
248
|
+
*/
|
|
249
|
+
async updateClinic(
|
|
250
|
+
clinicId: string,
|
|
251
|
+
data: Partial<Omit<Clinic, "id" | "createdAt" | "clinicGroupId">>,
|
|
252
|
+
adminId: string
|
|
253
|
+
): Promise<Clinic> {
|
|
254
|
+
const clinicRef = doc(this.db, CLINICS_COLLECTION, clinicId);
|
|
255
|
+
const clinicDoc = await getDoc(clinicRef);
|
|
256
|
+
if (!clinicDoc.exists()) {
|
|
257
|
+
throw new Error(`Clinic ${clinicId} not found`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
const currentClinic = clinicDoc.data() as Clinic;
|
|
262
|
+
// Explicitly Omit fields managed by other services or internally
|
|
263
|
+
const { doctorsInfo, proceduresInfo, ...updatePayload } =
|
|
264
|
+
data as Partial<Clinic>;
|
|
265
|
+
|
|
266
|
+
if (updatePayload.location) {
|
|
267
|
+
const loc = updatePayload.location;
|
|
268
|
+
updatePayload.location = {
|
|
269
|
+
...loc,
|
|
270
|
+
geohash: geohashForLocation([loc.latitude, loc.longitude]),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Merge with current data for validation and aggregation, preserving arrays managed elsewhere
|
|
275
|
+
const finalStateForValidation = {
|
|
276
|
+
...currentClinic,
|
|
277
|
+
...updatePayload, // Apply safe updates
|
|
278
|
+
// Explicitly keep arrays managed by other services from current state
|
|
279
|
+
doctorsInfo: currentClinic.doctorsInfo,
|
|
280
|
+
proceduresInfo: currentClinic.proceduresInfo,
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// Ensure required fields for validation are present
|
|
284
|
+
clinicSchema.parse({
|
|
285
|
+
...finalStateForValidation,
|
|
286
|
+
updatedAt: Timestamp.now(), // Use current time for validation
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Prepare final update data for Firestore, including timestamp
|
|
290
|
+
const updateDataForFirestore = {
|
|
291
|
+
...updatePayload,
|
|
292
|
+
updatedAt: serverTimestamp(),
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const batch = writeBatch(this.db);
|
|
296
|
+
batch.update(clinicRef, updateDataForFirestore);
|
|
297
|
+
|
|
298
|
+
const groupRef = doc(
|
|
299
|
+
this.db,
|
|
300
|
+
CLINIC_GROUPS_COLLECTION,
|
|
301
|
+
currentClinic.clinicGroupId
|
|
302
|
+
);
|
|
303
|
+
// Use the validated final state for aggregation
|
|
304
|
+
const updatedClinicInfoForGroup = this._createClinicInfoForAggregation(
|
|
305
|
+
finalStateForValidation as Clinic
|
|
306
|
+
);
|
|
307
|
+
batch.update(groupRef, {
|
|
308
|
+
clinicsInfo: arrayRemove(...[{ id: clinicId }]),
|
|
309
|
+
updatedAt: serverTimestamp(),
|
|
310
|
+
});
|
|
311
|
+
batch.update(groupRef, {
|
|
312
|
+
clinicsInfo: arrayUnion(updatedClinicInfoForGroup),
|
|
313
|
+
updatedAt: serverTimestamp(),
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const practitionerIds = currentClinic.doctors || [];
|
|
317
|
+
if (practitionerIds.length > 0) {
|
|
318
|
+
// Pass the aggregated info based on the final validated state
|
|
319
|
+
await this._updateClinicInfoInPractitioners(
|
|
320
|
+
practitionerIds,
|
|
321
|
+
updatedClinicInfoForGroup
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
await batch.commit();
|
|
326
|
+
const updatedClinic = await this.getClinic(clinicId);
|
|
327
|
+
if (!updatedClinic) throw new Error("Failed to retrieve updated clinic");
|
|
328
|
+
return updatedClinic;
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (error instanceof z.ZodError) {
|
|
331
|
+
throw new Error(
|
|
332
|
+
"Invalid clinic update data: " +
|
|
333
|
+
error.errors
|
|
334
|
+
.map((e) => `${e.path.join(".")} - ${e.message}`)
|
|
335
|
+
.join(", ")
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
console.error(`Error updating clinic ${clinicId}:`, error);
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Deactivates a clinic.
|
|
345
|
+
* Note: Does not currently remove ClinicInfo from practitioners (might be desired).
|
|
346
|
+
*/
|
|
347
|
+
async deactivateClinic(clinicId: string, adminId: string): Promise<void> {
|
|
348
|
+
// Permission check omitted
|
|
349
|
+
const clinicRef = doc(this.db, CLINICS_COLLECTION, clinicId);
|
|
350
|
+
await updateDoc(clinicRef, {
|
|
351
|
+
isActive: false,
|
|
352
|
+
updatedAt: serverTimestamp(),
|
|
353
|
+
});
|
|
354
|
+
// Consider whether to also update ClinicInfo in practitioners to reflect inactive status
|
|
82
355
|
}
|
|
83
356
|
|
|
357
|
+
// --- Other Methods ---
|
|
358
|
+
// (getClinic, getClinicsByGroup, findClinicsInRadius, addTags, removeTags, getClinicsByAdmin, etc.)
|
|
359
|
+
// Review these methods to ensure they don't rely on outdated aggregation logic (e.g., filtering ServiceInfo)
|
|
360
|
+
// and update them to use proceduresInfo if necessary for filtering.
|
|
361
|
+
|
|
84
362
|
/**
|
|
85
363
|
* Dohvata kliniku po ID-u
|
|
86
364
|
*/
|
|
@@ -97,15 +375,21 @@ export class ClinicService extends BaseService {
|
|
|
97
375
|
|
|
98
376
|
/**
|
|
99
377
|
* Pretražuje klinike u određenom radijusu
|
|
378
|
+
* REVIEW: SearchUtils.findClinicsInRadius might need updating for filters.
|
|
100
379
|
*/
|
|
101
380
|
async findClinicsInRadius(
|
|
102
381
|
center: { latitude: number; longitude: number },
|
|
103
382
|
radiusInKm: number,
|
|
104
383
|
filters?: {
|
|
105
|
-
|
|
384
|
+
procedures?: string[];
|
|
106
385
|
tags?: ClinicTag[];
|
|
386
|
+
// Add other relevant filters based on Clinic/ProcedureSummaryInfo fields
|
|
107
387
|
}
|
|
108
388
|
): Promise<Clinic[]> {
|
|
389
|
+
console.warn(
|
|
390
|
+
"SearchUtils.findClinicsInRadius filter logic might need updating for proceduresInfo."
|
|
391
|
+
);
|
|
392
|
+
// Pass filters directly, assuming SearchUtils handles it.
|
|
109
393
|
return SearchUtils.findClinicsInRadius(
|
|
110
394
|
this.db,
|
|
111
395
|
center,
|
|
@@ -114,52 +398,6 @@ export class ClinicService extends BaseService {
|
|
|
114
398
|
);
|
|
115
399
|
}
|
|
116
400
|
|
|
117
|
-
/**
|
|
118
|
-
* Ažurira kliniku
|
|
119
|
-
*/
|
|
120
|
-
async updateClinic(
|
|
121
|
-
clinicId: string,
|
|
122
|
-
data: Partial<Clinic>,
|
|
123
|
-
adminId: string
|
|
124
|
-
): Promise<Clinic> {
|
|
125
|
-
return ClinicUtils.updateClinic(
|
|
126
|
-
this.db,
|
|
127
|
-
clinicId,
|
|
128
|
-
data,
|
|
129
|
-
adminId,
|
|
130
|
-
this.clinicAdminService,
|
|
131
|
-
this.app
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Dodaje recenziju klinici
|
|
137
|
-
*/
|
|
138
|
-
async addReview(
|
|
139
|
-
clinicId: string,
|
|
140
|
-
review: Omit<
|
|
141
|
-
ClinicReview,
|
|
142
|
-
"id" | "clinicId" | "createdAt" | "updatedAt" | "isVerified"
|
|
143
|
-
>
|
|
144
|
-
): Promise<ClinicReview> {
|
|
145
|
-
return ReviewUtils.addReview(this.db, clinicId, review, this.app);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Deaktivira kliniku
|
|
150
|
-
*/
|
|
151
|
-
async deactivateClinic(clinicId: string, adminId: string): Promise<void> {
|
|
152
|
-
return ClinicUtils.deactivateClinic(
|
|
153
|
-
this.db,
|
|
154
|
-
clinicId,
|
|
155
|
-
adminId,
|
|
156
|
-
this.clinicAdminService
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Dodaje tagove klinici
|
|
162
|
-
*/
|
|
163
401
|
async addTags(
|
|
164
402
|
clinicId: string,
|
|
165
403
|
adminId: string,
|
|
@@ -177,9 +415,6 @@ export class ClinicService extends BaseService {
|
|
|
177
415
|
);
|
|
178
416
|
}
|
|
179
417
|
|
|
180
|
-
/**
|
|
181
|
-
* Uklanja tagove iz klinike
|
|
182
|
-
*/
|
|
183
418
|
async removeTags(
|
|
184
419
|
clinicId: string,
|
|
185
420
|
adminId: string,
|
|
@@ -197,9 +432,6 @@ export class ClinicService extends BaseService {
|
|
|
197
432
|
);
|
|
198
433
|
}
|
|
199
434
|
|
|
200
|
-
/**
|
|
201
|
-
* Dohvata sve klinike gde je korisnik admin
|
|
202
|
-
*/
|
|
203
435
|
async getClinicsByAdmin(
|
|
204
436
|
adminId: string,
|
|
205
437
|
options?: {
|
|
@@ -216,9 +448,6 @@ export class ClinicService extends BaseService {
|
|
|
216
448
|
);
|
|
217
449
|
}
|
|
218
450
|
|
|
219
|
-
/**
|
|
220
|
-
* Dohvata sve aktivne klinike gde je korisnik admin
|
|
221
|
-
*/
|
|
222
451
|
async getActiveClinicsByAdmin(adminId: string): Promise<Clinic[]> {
|
|
223
452
|
return ClinicUtils.getActiveClinicsByAdmin(
|
|
224
453
|
this.db,
|
|
@@ -228,14 +457,6 @@ export class ClinicService extends BaseService {
|
|
|
228
457
|
);
|
|
229
458
|
}
|
|
230
459
|
|
|
231
|
-
/**
|
|
232
|
-
* Creates a new clinic branch for a clinic group
|
|
233
|
-
*
|
|
234
|
-
* @param clinicGroupId - The ID of the clinic group
|
|
235
|
-
* @param setupData - The setup data for the clinic branch
|
|
236
|
-
* @param adminId - The ID of the admin creating the branch
|
|
237
|
-
* @returns The created clinic
|
|
238
|
-
*/
|
|
239
460
|
async createClinicBranch(
|
|
240
461
|
clinicGroupId: string,
|
|
241
462
|
setupData: ClinicBranchSetupData,
|
|
@@ -276,7 +497,7 @@ export class ClinicService extends BaseService {
|
|
|
276
497
|
coverPhoto: setupData.coverPhoto || null,
|
|
277
498
|
photosWithTags: setupData.photosWithTags || [],
|
|
278
499
|
doctors: [],
|
|
279
|
-
|
|
500
|
+
procedures: [],
|
|
280
501
|
admins: [adminId],
|
|
281
502
|
isActive: true,
|
|
282
503
|
isVerified: false,
|
|
@@ -301,4 +522,50 @@ export class ClinicService extends BaseService {
|
|
|
301
522
|
// Note: The createClinic method already adds the clinic to the admin's managed clinics
|
|
302
523
|
return clinic;
|
|
303
524
|
}
|
|
525
|
+
|
|
526
|
+
async getClinicById(clinicId: string): Promise<Clinic | null> {
|
|
527
|
+
return ClinicUtils.getClinicById(this.db, clinicId);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async getAllClinics(
|
|
531
|
+
pagination?: number,
|
|
532
|
+
lastDoc?: any
|
|
533
|
+
): Promise<{ clinics: Clinic[]; lastDoc: any }> {
|
|
534
|
+
return ClinicUtils.getAllClinics(this.db, pagination, lastDoc);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
async getAllClinicsInRange(
|
|
538
|
+
center: { latitude: number; longitude: number },
|
|
539
|
+
rangeInKm: number,
|
|
540
|
+
pagination?: number,
|
|
541
|
+
lastDoc?: any
|
|
542
|
+
): Promise<{ clinics: (Clinic & { distance: number })[]; lastDoc: any }> {
|
|
543
|
+
return ClinicUtils.getAllClinicsInRange(
|
|
544
|
+
this.db,
|
|
545
|
+
center,
|
|
546
|
+
rangeInKm,
|
|
547
|
+
pagination,
|
|
548
|
+
lastDoc
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
async getClinicsByFilters(filters: {
|
|
553
|
+
center?: { latitude: number; longitude: number };
|
|
554
|
+
radiusInKm?: number;
|
|
555
|
+
tags?: ClinicTag[];
|
|
556
|
+
procedureFamily?: string;
|
|
557
|
+
procedureCategory?: string;
|
|
558
|
+
procedureSubcategory?: string;
|
|
559
|
+
procedureTechnology?: string;
|
|
560
|
+
minRating?: number;
|
|
561
|
+
maxRating?: number;
|
|
562
|
+
pagination?: number;
|
|
563
|
+
lastDoc?: any;
|
|
564
|
+
isActive?: boolean;
|
|
565
|
+
}): Promise<{
|
|
566
|
+
clinics: (Clinic & { distance?: number })[];
|
|
567
|
+
lastDoc: any;
|
|
568
|
+
}> {
|
|
569
|
+
return FilterUtils.getClinicsByFilters(this.db, filters);
|
|
570
|
+
}
|
|
304
571
|
}
|