@blackcode_sa/metaestetics-api 1.12.21 → 1.12.22
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 +4 -0
- package/dist/admin/index.d.ts +4 -0
- package/dist/index.d.mts +15 -11
- package/dist/index.d.ts +15 -11
- package/dist/index.js +298 -19
- package/dist/index.mjs +298 -19
- package/package.json +1 -1
- package/src/services/reviews/README.md +129 -0
- package/src/services/reviews/reviews.service.ts +399 -39
- package/src/types/reviews/index.ts +5 -1
|
@@ -8,23 +8,21 @@ import {
|
|
|
8
8
|
setDoc,
|
|
9
9
|
deleteDoc,
|
|
10
10
|
serverTimestamp,
|
|
11
|
-
} from
|
|
12
|
-
import { BaseService } from
|
|
11
|
+
} from 'firebase/firestore';
|
|
12
|
+
import { BaseService } from '../base.service';
|
|
13
13
|
import {
|
|
14
14
|
Review,
|
|
15
15
|
ClinicReview,
|
|
16
16
|
PractitionerReview,
|
|
17
17
|
ProcedureReview,
|
|
18
18
|
REVIEWS_COLLECTION,
|
|
19
|
-
} from
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import { Firestore } from "firebase/firestore";
|
|
27
|
-
import { FirebaseApp } from "firebase/app";
|
|
19
|
+
} from '../../types/reviews';
|
|
20
|
+
import { createReviewSchema, reviewSchema } from '../../validations/reviews.schema';
|
|
21
|
+
import { z } from 'zod';
|
|
22
|
+
import { Auth } from 'firebase/auth';
|
|
23
|
+
import { Firestore } from 'firebase/firestore';
|
|
24
|
+
import { FirebaseApp } from 'firebase/app';
|
|
25
|
+
import { Appointment, APPOINTMENTS_COLLECTION } from '../../types/appointment';
|
|
28
26
|
|
|
29
27
|
export class ReviewService extends BaseService {
|
|
30
28
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp) {
|
|
@@ -38,13 +36,20 @@ export class ReviewService extends BaseService {
|
|
|
38
36
|
* @returns The created review
|
|
39
37
|
*/
|
|
40
38
|
async createReview(
|
|
41
|
-
data: Omit<
|
|
42
|
-
|
|
43
|
-
"id" | "createdAt" | "updatedAt" | "appointmentId" | "overallRating"
|
|
44
|
-
>,
|
|
45
|
-
appointmentId: string
|
|
39
|
+
data: Omit<Review, 'id' | 'createdAt' | 'updatedAt' | 'appointmentId' | 'overallRating'>,
|
|
40
|
+
appointmentId: string,
|
|
46
41
|
): Promise<Review> {
|
|
47
42
|
try {
|
|
43
|
+
console.log('🔍 ReviewService.createReview - Input data:', {
|
|
44
|
+
appointmentId,
|
|
45
|
+
hasClinicReview: !!data.clinicReview,
|
|
46
|
+
hasPractitionerReview: !!data.practitionerReview,
|
|
47
|
+
hasProcedureReview: !!data.procedureReview,
|
|
48
|
+
practitionerId: data.practitionerReview?.practitionerId,
|
|
49
|
+
clinicId: data.clinicReview?.clinicId,
|
|
50
|
+
procedureId: data.procedureReview?.procedureId,
|
|
51
|
+
});
|
|
52
|
+
|
|
48
53
|
// Validate input data
|
|
49
54
|
const validatedData = createReviewSchema.parse(data);
|
|
50
55
|
|
|
@@ -137,6 +142,13 @@ export class ReviewService extends BaseService {
|
|
|
137
142
|
updatedAt: serverTimestamp(),
|
|
138
143
|
});
|
|
139
144
|
|
|
145
|
+
console.log('✅ ReviewService.createReview - Review saved to Firestore:', {
|
|
146
|
+
reviewId,
|
|
147
|
+
practitionerId: review.practitionerReview?.practitionerId,
|
|
148
|
+
clinicId: review.clinicReview?.clinicId,
|
|
149
|
+
procedureId: review.procedureReview?.procedureId,
|
|
150
|
+
});
|
|
151
|
+
|
|
140
152
|
// Note: Related entity updates (clinic, practitioner, procedure) are now handled
|
|
141
153
|
// by cloud functions through the ReviewsAggregationService
|
|
142
154
|
|
|
@@ -150,75 +162,423 @@ export class ReviewService extends BaseService {
|
|
|
150
162
|
}
|
|
151
163
|
|
|
152
164
|
/**
|
|
153
|
-
* Gets a review by ID
|
|
165
|
+
* Gets a review by ID with enhanced entity names
|
|
154
166
|
* @param reviewId The ID of the review to get
|
|
155
|
-
* @returns The review if found, null otherwise
|
|
167
|
+
* @returns The review with entity names if found, null otherwise
|
|
156
168
|
*/
|
|
157
169
|
async getReview(reviewId: string): Promise<Review | null> {
|
|
170
|
+
console.log('🔍 ReviewService.getReview - Getting review:', reviewId);
|
|
171
|
+
|
|
158
172
|
const docRef = doc(this.db, REVIEWS_COLLECTION, reviewId);
|
|
159
173
|
const docSnap = await getDoc(docRef);
|
|
160
174
|
|
|
161
175
|
if (!docSnap.exists()) {
|
|
176
|
+
console.log('❌ ReviewService.getReview - Review not found:', reviewId);
|
|
162
177
|
return null;
|
|
163
178
|
}
|
|
164
179
|
|
|
165
|
-
|
|
180
|
+
const review = { ...docSnap.data(), id: reviewId } as Review;
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
// Fetch the associated appointment to enhance with entity names
|
|
184
|
+
const appointmentDoc = await getDoc(
|
|
185
|
+
doc(this.db, APPOINTMENTS_COLLECTION, review.appointmentId),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (appointmentDoc.exists()) {
|
|
189
|
+
const appointment = appointmentDoc.data() as Appointment;
|
|
190
|
+
|
|
191
|
+
// Create enhanced review with entity names
|
|
192
|
+
const enhancedReview = { ...review };
|
|
193
|
+
|
|
194
|
+
if (enhancedReview.clinicReview && appointment.clinicInfo) {
|
|
195
|
+
enhancedReview.clinicReview = {
|
|
196
|
+
...enhancedReview.clinicReview,
|
|
197
|
+
clinicName: appointment.clinicInfo.name,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
|
|
202
|
+
enhancedReview.practitionerReview = {
|
|
203
|
+
...enhancedReview.practitionerReview,
|
|
204
|
+
practitionerName: appointment.practitionerInfo.name,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (enhancedReview.procedureReview && appointment.procedureInfo) {
|
|
209
|
+
enhancedReview.procedureReview = {
|
|
210
|
+
...enhancedReview.procedureReview,
|
|
211
|
+
procedureName: appointment.procedureInfo.name,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Add patient name to the main review object
|
|
216
|
+
if (appointment.patientInfo) {
|
|
217
|
+
enhancedReview.patientName = appointment.patientInfo.fullName;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
console.log('✅ ReviewService.getReview - Enhanced review:', {
|
|
221
|
+
reviewId,
|
|
222
|
+
hasEntityNames: !!(
|
|
223
|
+
enhancedReview.clinicReview?.clinicName ||
|
|
224
|
+
enhancedReview.practitionerReview?.practitionerName ||
|
|
225
|
+
enhancedReview.procedureReview?.procedureName ||
|
|
226
|
+
enhancedReview.patientName
|
|
227
|
+
),
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return enhancedReview;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log('⚠️ ReviewService.getReview - Appointment not found for review:', reviewId);
|
|
234
|
+
return review;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.warn(`Failed to enhance review ${reviewId} with entity names:`, error);
|
|
237
|
+
return review;
|
|
238
|
+
}
|
|
166
239
|
}
|
|
167
240
|
|
|
168
241
|
/**
|
|
169
|
-
* Gets all reviews for a specific patient
|
|
242
|
+
* Gets all reviews for a specific patient with enhanced entity names
|
|
170
243
|
* @param patientId The ID of the patient
|
|
171
|
-
* @returns Array of reviews for the patient
|
|
244
|
+
* @returns Array of reviews for the patient with clinic, practitioner, and procedure names
|
|
172
245
|
*/
|
|
173
246
|
async getReviewsByPatient(patientId: string): Promise<Review[]> {
|
|
174
|
-
const q = query(
|
|
175
|
-
collection(this.db, REVIEWS_COLLECTION),
|
|
176
|
-
where("patientId", "==", patientId)
|
|
177
|
-
);
|
|
247
|
+
const q = query(collection(this.db, REVIEWS_COLLECTION), where('patientId', '==', patientId));
|
|
178
248
|
const snapshot = await getDocs(q);
|
|
179
|
-
|
|
249
|
+
const reviews = snapshot.docs.map(doc => doc.data() as Review);
|
|
250
|
+
|
|
251
|
+
// Enhance reviews with entity names from appointments
|
|
252
|
+
const enhancedReviews = await Promise.all(
|
|
253
|
+
reviews.map(async review => {
|
|
254
|
+
try {
|
|
255
|
+
// Fetch the associated appointment
|
|
256
|
+
const appointmentDoc = await getDoc(
|
|
257
|
+
doc(this.db, APPOINTMENTS_COLLECTION, review.appointmentId),
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
if (appointmentDoc.exists()) {
|
|
261
|
+
const appointment = appointmentDoc.data() as Appointment;
|
|
262
|
+
|
|
263
|
+
// Create enhanced review with entity names
|
|
264
|
+
const enhancedReview = { ...review };
|
|
265
|
+
|
|
266
|
+
if (enhancedReview.clinicReview && appointment.clinicInfo) {
|
|
267
|
+
enhancedReview.clinicReview = {
|
|
268
|
+
...enhancedReview.clinicReview,
|
|
269
|
+
clinicName: appointment.clinicInfo.name,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
|
|
274
|
+
enhancedReview.practitionerReview = {
|
|
275
|
+
...enhancedReview.practitionerReview,
|
|
276
|
+
practitionerName: appointment.practitionerInfo.name,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (enhancedReview.procedureReview && appointment.procedureInfo) {
|
|
281
|
+
enhancedReview.procedureReview = {
|
|
282
|
+
...enhancedReview.procedureReview,
|
|
283
|
+
procedureName: appointment.procedureInfo.name,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Add patient name to the main review object
|
|
288
|
+
if (appointment.patientInfo) {
|
|
289
|
+
enhancedReview.patientName = appointment.patientInfo.fullName;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return enhancedReview;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return review;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
|
|
298
|
+
return review;
|
|
299
|
+
}
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
return enhancedReviews;
|
|
180
304
|
}
|
|
181
305
|
|
|
182
306
|
/**
|
|
183
|
-
* Gets all reviews for a specific clinic
|
|
307
|
+
* Gets all reviews for a specific clinic with enhanced entity names
|
|
184
308
|
* @param clinicId The ID of the clinic
|
|
185
|
-
* @returns Array of reviews containing clinic reviews
|
|
309
|
+
* @returns Array of reviews containing clinic reviews with clinic, practitioner, and procedure names
|
|
186
310
|
*/
|
|
187
311
|
async getReviewsByClinic(clinicId: string): Promise<Review[]> {
|
|
312
|
+
console.log('🔍 ReviewService.getReviewsByClinic - Querying for clinic:', clinicId);
|
|
313
|
+
|
|
188
314
|
const q = query(
|
|
189
315
|
collection(this.db, REVIEWS_COLLECTION),
|
|
190
|
-
where(
|
|
316
|
+
where('clinicReview.clinicId', '==', clinicId),
|
|
191
317
|
);
|
|
192
318
|
const snapshot = await getDocs(q);
|
|
193
|
-
|
|
319
|
+
const reviews = snapshot.docs.map(doc => {
|
|
320
|
+
const data = doc.data() as Review;
|
|
321
|
+
return { ...data, id: doc.id };
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
console.log('🔍 ReviewService.getReviewsByClinic - Found reviews before enhancement:', {
|
|
325
|
+
clinicId,
|
|
326
|
+
reviewCount: reviews.length,
|
|
327
|
+
reviewIds: reviews.map(r => r.id),
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Enhance reviews with entity names from appointments
|
|
331
|
+
const enhancedReviews = await Promise.all(
|
|
332
|
+
reviews.map(async review => {
|
|
333
|
+
try {
|
|
334
|
+
// Fetch the associated appointment
|
|
335
|
+
const appointmentDoc = await getDoc(
|
|
336
|
+
doc(this.db, APPOINTMENTS_COLLECTION, review.appointmentId),
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
if (appointmentDoc.exists()) {
|
|
340
|
+
const appointment = appointmentDoc.data() as Appointment;
|
|
341
|
+
|
|
342
|
+
// Create enhanced review with entity names
|
|
343
|
+
const enhancedReview = { ...review };
|
|
344
|
+
|
|
345
|
+
if (enhancedReview.clinicReview && appointment.clinicInfo) {
|
|
346
|
+
enhancedReview.clinicReview = {
|
|
347
|
+
...enhancedReview.clinicReview,
|
|
348
|
+
clinicName: appointment.clinicInfo.name,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
|
|
353
|
+
enhancedReview.practitionerReview = {
|
|
354
|
+
...enhancedReview.practitionerReview,
|
|
355
|
+
practitionerName: appointment.practitionerInfo.name,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (enhancedReview.procedureReview && appointment.procedureInfo) {
|
|
360
|
+
enhancedReview.procedureReview = {
|
|
361
|
+
...enhancedReview.procedureReview,
|
|
362
|
+
procedureName: appointment.procedureInfo.name,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Add patient name to the main review object
|
|
367
|
+
if (appointment.patientInfo) {
|
|
368
|
+
enhancedReview.patientName = appointment.patientInfo.fullName;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return enhancedReview;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return review;
|
|
375
|
+
} catch (error) {
|
|
376
|
+
console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
|
|
377
|
+
return review;
|
|
378
|
+
}
|
|
379
|
+
}),
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
console.log('✅ ReviewService.getReviewsByClinic - Enhanced reviews:', {
|
|
383
|
+
clinicId,
|
|
384
|
+
reviewCount: enhancedReviews.length,
|
|
385
|
+
reviewIds: enhancedReviews.map(r => r.id),
|
|
386
|
+
hasEntityNames: enhancedReviews.some(
|
|
387
|
+
r =>
|
|
388
|
+
r.clinicReview?.clinicName ||
|
|
389
|
+
r.practitionerReview?.practitionerName ||
|
|
390
|
+
r.procedureReview?.procedureName ||
|
|
391
|
+
r.patientName,
|
|
392
|
+
),
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return enhancedReviews;
|
|
194
396
|
}
|
|
195
397
|
|
|
196
398
|
/**
|
|
197
|
-
* Gets all reviews for a specific practitioner
|
|
399
|
+
* Gets all reviews for a specific practitioner with enhanced entity names
|
|
198
400
|
* @param practitionerId The ID of the practitioner
|
|
199
|
-
* @returns Array of reviews containing practitioner reviews
|
|
401
|
+
* @returns Array of reviews containing practitioner reviews with clinic, practitioner, and procedure names
|
|
200
402
|
*/
|
|
201
403
|
async getReviewsByPractitioner(practitionerId: string): Promise<Review[]> {
|
|
404
|
+
console.log(
|
|
405
|
+
'🔍 ReviewService.getReviewsByPractitioner - Querying for practitioner:',
|
|
406
|
+
practitionerId,
|
|
407
|
+
);
|
|
408
|
+
|
|
202
409
|
const q = query(
|
|
203
410
|
collection(this.db, REVIEWS_COLLECTION),
|
|
204
|
-
where(
|
|
411
|
+
where('practitionerReview.practitionerId', '==', practitionerId),
|
|
205
412
|
);
|
|
206
413
|
const snapshot = await getDocs(q);
|
|
207
|
-
|
|
414
|
+
const reviews = snapshot.docs.map(doc => {
|
|
415
|
+
const data = doc.data() as Review;
|
|
416
|
+
return { ...data, id: doc.id };
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
console.log('🔍 ReviewService.getReviewsByPractitioner - Found reviews before enhancement:', {
|
|
420
|
+
practitionerId,
|
|
421
|
+
reviewCount: reviews.length,
|
|
422
|
+
reviewIds: reviews.map(r => r.id),
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Enhance reviews with entity names from appointments
|
|
426
|
+
const enhancedReviews = await Promise.all(
|
|
427
|
+
reviews.map(async review => {
|
|
428
|
+
try {
|
|
429
|
+
// Fetch the associated appointment
|
|
430
|
+
const appointmentDoc = await getDoc(
|
|
431
|
+
doc(this.db, APPOINTMENTS_COLLECTION, review.appointmentId),
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
if (appointmentDoc.exists()) {
|
|
435
|
+
const appointment = appointmentDoc.data() as Appointment;
|
|
436
|
+
|
|
437
|
+
// Create enhanced review with entity names
|
|
438
|
+
const enhancedReview = { ...review };
|
|
439
|
+
|
|
440
|
+
if (enhancedReview.clinicReview && appointment.clinicInfo) {
|
|
441
|
+
enhancedReview.clinicReview = {
|
|
442
|
+
...enhancedReview.clinicReview,
|
|
443
|
+
clinicName: appointment.clinicInfo.name,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
|
|
448
|
+
enhancedReview.practitionerReview = {
|
|
449
|
+
...enhancedReview.practitionerReview,
|
|
450
|
+
practitionerName: appointment.practitionerInfo.name,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (enhancedReview.procedureReview && appointment.procedureInfo) {
|
|
455
|
+
enhancedReview.procedureReview = {
|
|
456
|
+
...enhancedReview.procedureReview,
|
|
457
|
+
procedureName: appointment.procedureInfo.name,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Add patient name to the main review object
|
|
462
|
+
if (appointment.patientInfo) {
|
|
463
|
+
enhancedReview.patientName = appointment.patientInfo.fullName;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return enhancedReview;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return review;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
|
|
472
|
+
return review;
|
|
473
|
+
}
|
|
474
|
+
}),
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
console.log('✅ ReviewService.getReviewsByPractitioner - Enhanced reviews:', {
|
|
478
|
+
practitionerId,
|
|
479
|
+
reviewCount: enhancedReviews.length,
|
|
480
|
+
reviewIds: enhancedReviews.map(r => r.id),
|
|
481
|
+
hasEntityNames: enhancedReviews.some(
|
|
482
|
+
r =>
|
|
483
|
+
r.clinicReview?.clinicName ||
|
|
484
|
+
r.practitionerReview?.practitionerName ||
|
|
485
|
+
r.procedureReview?.procedureName,
|
|
486
|
+
),
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
return enhancedReviews;
|
|
208
490
|
}
|
|
209
491
|
|
|
210
492
|
/**
|
|
211
|
-
* Gets all reviews for a specific procedure
|
|
493
|
+
* Gets all reviews for a specific procedure with enhanced entity names
|
|
212
494
|
* @param procedureId The ID of the procedure
|
|
213
|
-
* @returns Array of reviews containing procedure reviews
|
|
495
|
+
* @returns Array of reviews containing procedure reviews with clinic, practitioner, and procedure names
|
|
214
496
|
*/
|
|
215
497
|
async getReviewsByProcedure(procedureId: string): Promise<Review[]> {
|
|
498
|
+
console.log('🔍 ReviewService.getReviewsByProcedure - Querying for procedure:', procedureId);
|
|
499
|
+
|
|
216
500
|
const q = query(
|
|
217
501
|
collection(this.db, REVIEWS_COLLECTION),
|
|
218
|
-
where(
|
|
502
|
+
where('procedureReview.procedureId', '==', procedureId),
|
|
219
503
|
);
|
|
220
504
|
const snapshot = await getDocs(q);
|
|
221
|
-
|
|
505
|
+
const reviews = snapshot.docs.map(doc => {
|
|
506
|
+
const data = doc.data() as Review;
|
|
507
|
+
return { ...data, id: doc.id };
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
console.log('🔍 ReviewService.getReviewsByProcedure - Found reviews before enhancement:', {
|
|
511
|
+
procedureId,
|
|
512
|
+
reviewCount: reviews.length,
|
|
513
|
+
reviewIds: reviews.map(r => r.id),
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// Enhance reviews with entity names from appointments
|
|
517
|
+
const enhancedReviews = await Promise.all(
|
|
518
|
+
reviews.map(async review => {
|
|
519
|
+
try {
|
|
520
|
+
// Fetch the associated appointment
|
|
521
|
+
const appointmentDoc = await getDoc(
|
|
522
|
+
doc(this.db, APPOINTMENTS_COLLECTION, review.appointmentId),
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
if (appointmentDoc.exists()) {
|
|
526
|
+
const appointment = appointmentDoc.data() as Appointment;
|
|
527
|
+
|
|
528
|
+
// Create enhanced review with entity names
|
|
529
|
+
const enhancedReview = { ...review };
|
|
530
|
+
|
|
531
|
+
if (enhancedReview.clinicReview && appointment.clinicInfo) {
|
|
532
|
+
enhancedReview.clinicReview = {
|
|
533
|
+
...enhancedReview.clinicReview,
|
|
534
|
+
clinicName: appointment.clinicInfo.name,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
|
|
539
|
+
enhancedReview.practitionerReview = {
|
|
540
|
+
...enhancedReview.practitionerReview,
|
|
541
|
+
practitionerName: appointment.practitionerInfo.name,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (enhancedReview.procedureReview && appointment.procedureInfo) {
|
|
546
|
+
enhancedReview.procedureReview = {
|
|
547
|
+
...enhancedReview.procedureReview,
|
|
548
|
+
procedureName: appointment.procedureInfo.name,
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Add patient name to the main review object
|
|
553
|
+
if (appointment.patientInfo) {
|
|
554
|
+
enhancedReview.patientName = appointment.patientInfo.fullName;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return enhancedReview;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
return review;
|
|
561
|
+
} catch (error) {
|
|
562
|
+
console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
|
|
563
|
+
return review;
|
|
564
|
+
}
|
|
565
|
+
}),
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
console.log('✅ ReviewService.getReviewsByProcedure - Enhanced reviews:', {
|
|
569
|
+
procedureId,
|
|
570
|
+
reviewCount: enhancedReviews.length,
|
|
571
|
+
reviewIds: enhancedReviews.map(r => r.id),
|
|
572
|
+
hasEntityNames: enhancedReviews.some(
|
|
573
|
+
r =>
|
|
574
|
+
r.clinicReview?.clinicName ||
|
|
575
|
+
r.practitionerReview?.practitionerName ||
|
|
576
|
+
r.procedureReview?.procedureName ||
|
|
577
|
+
r.patientName,
|
|
578
|
+
),
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
return enhancedReviews;
|
|
222
582
|
}
|
|
223
583
|
|
|
224
584
|
/**
|
|
@@ -229,7 +589,7 @@ export class ReviewService extends BaseService {
|
|
|
229
589
|
async getReviewByAppointment(appointmentId: string): Promise<Review | null> {
|
|
230
590
|
const q = query(
|
|
231
591
|
collection(this.db, REVIEWS_COLLECTION),
|
|
232
|
-
where(
|
|
592
|
+
where('appointmentId', '==', appointmentId),
|
|
233
593
|
);
|
|
234
594
|
const snapshot = await getDocs(q);
|
|
235
595
|
|
|
@@ -22,6 +22,7 @@ interface BaseReview {
|
|
|
22
22
|
*/
|
|
23
23
|
export interface ClinicReview extends BaseReview {
|
|
24
24
|
clinicId: string;
|
|
25
|
+
clinicName?: string; // Enhanced field: clinic name from appointment
|
|
25
26
|
cleanliness: number; // 1-5 stars
|
|
26
27
|
facilities: number; // 1-5 stars
|
|
27
28
|
staffFriendliness: number; // 1-5 stars
|
|
@@ -37,6 +38,7 @@ export interface ClinicReview extends BaseReview {
|
|
|
37
38
|
*/
|
|
38
39
|
export interface PractitionerReview extends BaseReview {
|
|
39
40
|
practitionerId: string;
|
|
41
|
+
practitionerName?: string; // Enhanced field: practitioner name from appointment
|
|
40
42
|
knowledgeAndExpertise: number; // 1-5 stars
|
|
41
43
|
communicationSkills: number; // 1-5 stars
|
|
42
44
|
bedSideManner: number; // 1-5 stars
|
|
@@ -52,6 +54,7 @@ export interface PractitionerReview extends BaseReview {
|
|
|
52
54
|
*/
|
|
53
55
|
export interface ProcedureReview extends BaseReview {
|
|
54
56
|
procedureId: string;
|
|
57
|
+
procedureName?: string; // Enhanced field: procedure name from appointment
|
|
55
58
|
effectivenessOfTreatment: number; // 1-5 stars
|
|
56
59
|
outcomeExplanation: number; // 1-5 stars
|
|
57
60
|
painManagement: number; // 1-5 stars
|
|
@@ -114,6 +117,7 @@ export interface Review {
|
|
|
114
117
|
id: string;
|
|
115
118
|
appointmentId: string;
|
|
116
119
|
patientId: string;
|
|
120
|
+
patientName?: string; // Enhanced field: patient name from appointment
|
|
117
121
|
createdAt: Date;
|
|
118
122
|
updatedAt: Date;
|
|
119
123
|
clinicReview?: ClinicReview;
|
|
@@ -123,4 +127,4 @@ export interface Review {
|
|
|
123
127
|
overallRating: number; // Average of all available ratings
|
|
124
128
|
}
|
|
125
129
|
|
|
126
|
-
export const REVIEWS_COLLECTION =
|
|
130
|
+
export const REVIEWS_COLLECTION = 'reviews';
|