@blackcode_sa/metaestetics-api 1.12.69 → 1.12.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +78 -7
- package/dist/index.mjs +78 -7
- package/package.json +1 -1
- package/src/services/reviews/TIMESTAMP_FIX.md +65 -0
- package/src/services/reviews/reviews.service.ts +102 -7
package/dist/index.d.mts
CHANGED
|
@@ -7634,6 +7634,18 @@ declare class PatientRequirementsService extends BaseService {
|
|
|
7634
7634
|
|
|
7635
7635
|
declare class ReviewService extends BaseService {
|
|
7636
7636
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp);
|
|
7637
|
+
/**
|
|
7638
|
+
* Helper function to convert Firestore Timestamps to Date objects
|
|
7639
|
+
* @param timestamp The timestamp to convert
|
|
7640
|
+
* @returns A JavaScript Date object or null
|
|
7641
|
+
*/
|
|
7642
|
+
private convertTimestamp;
|
|
7643
|
+
/**
|
|
7644
|
+
* Converts a Firestore document to a Review object with proper date handling
|
|
7645
|
+
* @param docData The raw Firestore document data
|
|
7646
|
+
* @returns A Review object with properly converted dates
|
|
7647
|
+
*/
|
|
7648
|
+
private convertDocToReview;
|
|
7637
7649
|
/**
|
|
7638
7650
|
* Creates a new review
|
|
7639
7651
|
* @param data - The review data to create
|
package/dist/index.d.ts
CHANGED
|
@@ -7634,6 +7634,18 @@ declare class PatientRequirementsService extends BaseService {
|
|
|
7634
7634
|
|
|
7635
7635
|
declare class ReviewService extends BaseService {
|
|
7636
7636
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp);
|
|
7637
|
+
/**
|
|
7638
|
+
* Helper function to convert Firestore Timestamps to Date objects
|
|
7639
|
+
* @param timestamp The timestamp to convert
|
|
7640
|
+
* @returns A JavaScript Date object or null
|
|
7641
|
+
*/
|
|
7642
|
+
private convertTimestamp;
|
|
7643
|
+
/**
|
|
7644
|
+
* Converts a Firestore document to a Review object with proper date handling
|
|
7645
|
+
* @param docData The raw Firestore document data
|
|
7646
|
+
* @returns A Review object with properly converted dates
|
|
7647
|
+
*/
|
|
7648
|
+
private convertDocToReview;
|
|
7637
7649
|
/**
|
|
7638
7650
|
* Creates a new review
|
|
7639
7651
|
* @param data - The review data to create
|
package/dist/index.js
CHANGED
|
@@ -18088,6 +18088,77 @@ var ReviewService = class extends BaseService {
|
|
|
18088
18088
|
constructor(db, auth, app) {
|
|
18089
18089
|
super(db, auth, app);
|
|
18090
18090
|
}
|
|
18091
|
+
/**
|
|
18092
|
+
* Helper function to convert Firestore Timestamps to Date objects
|
|
18093
|
+
* @param timestamp The timestamp to convert
|
|
18094
|
+
* @returns A JavaScript Date object or null
|
|
18095
|
+
*/
|
|
18096
|
+
convertTimestamp(timestamp) {
|
|
18097
|
+
if (!timestamp) {
|
|
18098
|
+
console.warn("\u26A0\uFE0F convertTimestamp received null/undefined timestamp");
|
|
18099
|
+
return /* @__PURE__ */ new Date();
|
|
18100
|
+
}
|
|
18101
|
+
console.log("\u{1F50D} convertTimestamp input:", {
|
|
18102
|
+
type: typeof timestamp,
|
|
18103
|
+
value: timestamp,
|
|
18104
|
+
hasToDate: (timestamp == null ? void 0 : timestamp.toDate) !== void 0,
|
|
18105
|
+
hasIsTimestamp: (timestamp == null ? void 0 : timestamp.__isTimestamp) !== void 0,
|
|
18106
|
+
hasSeconds: (timestamp == null ? void 0 : timestamp.seconds) !== void 0
|
|
18107
|
+
});
|
|
18108
|
+
if (timestamp && timestamp.__isTimestamp === true && typeof timestamp.seconds === "number") {
|
|
18109
|
+
const converted = new Date(timestamp.seconds * 1e3 + (timestamp.nanoseconds || 0) / 1e6);
|
|
18110
|
+
console.log("\u2705 Converted __isTimestamp:", converted);
|
|
18111
|
+
return converted;
|
|
18112
|
+
}
|
|
18113
|
+
if (timestamp && timestamp.toDate && typeof timestamp.toDate === "function") {
|
|
18114
|
+
const converted = timestamp.toDate();
|
|
18115
|
+
console.log("\u2705 Converted using toDate():", converted);
|
|
18116
|
+
return converted;
|
|
18117
|
+
}
|
|
18118
|
+
if (timestamp instanceof Date) {
|
|
18119
|
+
console.log("\u2705 Already a Date object:", timestamp);
|
|
18120
|
+
return timestamp;
|
|
18121
|
+
}
|
|
18122
|
+
if (typeof timestamp === "string" || typeof timestamp === "number") {
|
|
18123
|
+
const date = new Date(timestamp);
|
|
18124
|
+
if (!isNaN(date.getTime())) {
|
|
18125
|
+
console.log("\u2705 Converted from string/number:", date);
|
|
18126
|
+
return date;
|
|
18127
|
+
}
|
|
18128
|
+
}
|
|
18129
|
+
console.warn("\u26A0\uFE0F Could not convert timestamp, returning current date. Input was:", timestamp);
|
|
18130
|
+
return /* @__PURE__ */ new Date();
|
|
18131
|
+
}
|
|
18132
|
+
/**
|
|
18133
|
+
* Converts a Firestore document to a Review object with proper date handling
|
|
18134
|
+
* @param docData The raw Firestore document data
|
|
18135
|
+
* @returns A Review object with properly converted dates
|
|
18136
|
+
*/
|
|
18137
|
+
convertDocToReview(docData) {
|
|
18138
|
+
const review = docData;
|
|
18139
|
+
review.createdAt = this.convertTimestamp(docData.createdAt);
|
|
18140
|
+
review.updatedAt = this.convertTimestamp(docData.updatedAt);
|
|
18141
|
+
if (review.clinicReview) {
|
|
18142
|
+
review.clinicReview.createdAt = this.convertTimestamp(review.clinicReview.createdAt);
|
|
18143
|
+
review.clinicReview.updatedAt = this.convertTimestamp(review.clinicReview.updatedAt);
|
|
18144
|
+
}
|
|
18145
|
+
if (review.practitionerReview) {
|
|
18146
|
+
review.practitionerReview.createdAt = this.convertTimestamp(review.practitionerReview.createdAt);
|
|
18147
|
+
review.practitionerReview.updatedAt = this.convertTimestamp(review.practitionerReview.updatedAt);
|
|
18148
|
+
}
|
|
18149
|
+
if (review.procedureReview) {
|
|
18150
|
+
review.procedureReview.createdAt = this.convertTimestamp(review.procedureReview.createdAt);
|
|
18151
|
+
review.procedureReview.updatedAt = this.convertTimestamp(review.procedureReview.updatedAt);
|
|
18152
|
+
}
|
|
18153
|
+
if (review.extendedProcedureReviews && Array.isArray(review.extendedProcedureReviews)) {
|
|
18154
|
+
review.extendedProcedureReviews = review.extendedProcedureReviews.map((extReview) => ({
|
|
18155
|
+
...extReview,
|
|
18156
|
+
createdAt: this.convertTimestamp(extReview.createdAt),
|
|
18157
|
+
updatedAt: this.convertTimestamp(extReview.updatedAt)
|
|
18158
|
+
}));
|
|
18159
|
+
}
|
|
18160
|
+
return review;
|
|
18161
|
+
}
|
|
18091
18162
|
/**
|
|
18092
18163
|
* Creates a new review
|
|
18093
18164
|
* @param data - The review data to create
|
|
@@ -18231,7 +18302,7 @@ var ReviewService = class extends BaseService {
|
|
|
18231
18302
|
console.log("\u274C ReviewService.getReview - Review not found:", reviewId);
|
|
18232
18303
|
return null;
|
|
18233
18304
|
}
|
|
18234
|
-
const review = { ...docSnap.data(), id: reviewId };
|
|
18305
|
+
const review = { ...this.convertDocToReview(docSnap.data()), id: reviewId };
|
|
18235
18306
|
try {
|
|
18236
18307
|
const appointmentDoc = await (0, import_firestore56.getDoc)(
|
|
18237
18308
|
(0, import_firestore56.doc)(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
|
|
@@ -18296,7 +18367,7 @@ var ReviewService = class extends BaseService {
|
|
|
18296
18367
|
async getReviewsByPatient(patientId) {
|
|
18297
18368
|
const q = (0, import_firestore56.query)((0, import_firestore56.collection)(this.db, REVIEWS_COLLECTION), (0, import_firestore56.where)("patientId", "==", patientId));
|
|
18298
18369
|
const snapshot = await (0, import_firestore56.getDocs)(q);
|
|
18299
|
-
const reviews = snapshot.docs.map((doc45) => doc45.data());
|
|
18370
|
+
const reviews = snapshot.docs.map((doc45) => this.convertDocToReview(doc45.data()));
|
|
18300
18371
|
const enhancedReviews = await Promise.all(
|
|
18301
18372
|
reviews.map(async (review) => {
|
|
18302
18373
|
try {
|
|
@@ -18351,8 +18422,8 @@ var ReviewService = class extends BaseService {
|
|
|
18351
18422
|
);
|
|
18352
18423
|
const snapshot = await (0, import_firestore56.getDocs)(q);
|
|
18353
18424
|
const reviews = snapshot.docs.map((doc45) => {
|
|
18354
|
-
const
|
|
18355
|
-
return { ...
|
|
18425
|
+
const review = this.convertDocToReview(doc45.data());
|
|
18426
|
+
return { ...review, id: doc45.id };
|
|
18356
18427
|
});
|
|
18357
18428
|
console.log("\u{1F50D} ReviewService.getReviewsByClinic - Found reviews before enhancement:", {
|
|
18358
18429
|
clinicId,
|
|
@@ -18427,8 +18498,8 @@ var ReviewService = class extends BaseService {
|
|
|
18427
18498
|
);
|
|
18428
18499
|
const snapshot = await (0, import_firestore56.getDocs)(q);
|
|
18429
18500
|
const reviews = snapshot.docs.map((doc45) => {
|
|
18430
|
-
const
|
|
18431
|
-
return { ...
|
|
18501
|
+
const review = this.convertDocToReview(doc45.data());
|
|
18502
|
+
return { ...review, id: doc45.id };
|
|
18432
18503
|
});
|
|
18433
18504
|
console.log("\u{1F50D} ReviewService.getReviewsByPractitioner - Found reviews before enhancement:", {
|
|
18434
18505
|
practitionerId,
|
|
@@ -18574,7 +18645,7 @@ var ReviewService = class extends BaseService {
|
|
|
18574
18645
|
if (snapshot.empty) {
|
|
18575
18646
|
return null;
|
|
18576
18647
|
}
|
|
18577
|
-
return snapshot.docs[0].data();
|
|
18648
|
+
return this.convertDocToReview(snapshot.docs[0].data());
|
|
18578
18649
|
}
|
|
18579
18650
|
/**
|
|
18580
18651
|
* Deletes a review
|
package/dist/index.mjs
CHANGED
|
@@ -18346,6 +18346,77 @@ var ReviewService = class extends BaseService {
|
|
|
18346
18346
|
constructor(db, auth, app) {
|
|
18347
18347
|
super(db, auth, app);
|
|
18348
18348
|
}
|
|
18349
|
+
/**
|
|
18350
|
+
* Helper function to convert Firestore Timestamps to Date objects
|
|
18351
|
+
* @param timestamp The timestamp to convert
|
|
18352
|
+
* @returns A JavaScript Date object or null
|
|
18353
|
+
*/
|
|
18354
|
+
convertTimestamp(timestamp) {
|
|
18355
|
+
if (!timestamp) {
|
|
18356
|
+
console.warn("\u26A0\uFE0F convertTimestamp received null/undefined timestamp");
|
|
18357
|
+
return /* @__PURE__ */ new Date();
|
|
18358
|
+
}
|
|
18359
|
+
console.log("\u{1F50D} convertTimestamp input:", {
|
|
18360
|
+
type: typeof timestamp,
|
|
18361
|
+
value: timestamp,
|
|
18362
|
+
hasToDate: (timestamp == null ? void 0 : timestamp.toDate) !== void 0,
|
|
18363
|
+
hasIsTimestamp: (timestamp == null ? void 0 : timestamp.__isTimestamp) !== void 0,
|
|
18364
|
+
hasSeconds: (timestamp == null ? void 0 : timestamp.seconds) !== void 0
|
|
18365
|
+
});
|
|
18366
|
+
if (timestamp && timestamp.__isTimestamp === true && typeof timestamp.seconds === "number") {
|
|
18367
|
+
const converted = new Date(timestamp.seconds * 1e3 + (timestamp.nanoseconds || 0) / 1e6);
|
|
18368
|
+
console.log("\u2705 Converted __isTimestamp:", converted);
|
|
18369
|
+
return converted;
|
|
18370
|
+
}
|
|
18371
|
+
if (timestamp && timestamp.toDate && typeof timestamp.toDate === "function") {
|
|
18372
|
+
const converted = timestamp.toDate();
|
|
18373
|
+
console.log("\u2705 Converted using toDate():", converted);
|
|
18374
|
+
return converted;
|
|
18375
|
+
}
|
|
18376
|
+
if (timestamp instanceof Date) {
|
|
18377
|
+
console.log("\u2705 Already a Date object:", timestamp);
|
|
18378
|
+
return timestamp;
|
|
18379
|
+
}
|
|
18380
|
+
if (typeof timestamp === "string" || typeof timestamp === "number") {
|
|
18381
|
+
const date = new Date(timestamp);
|
|
18382
|
+
if (!isNaN(date.getTime())) {
|
|
18383
|
+
console.log("\u2705 Converted from string/number:", date);
|
|
18384
|
+
return date;
|
|
18385
|
+
}
|
|
18386
|
+
}
|
|
18387
|
+
console.warn("\u26A0\uFE0F Could not convert timestamp, returning current date. Input was:", timestamp);
|
|
18388
|
+
return /* @__PURE__ */ new Date();
|
|
18389
|
+
}
|
|
18390
|
+
/**
|
|
18391
|
+
* Converts a Firestore document to a Review object with proper date handling
|
|
18392
|
+
* @param docData The raw Firestore document data
|
|
18393
|
+
* @returns A Review object with properly converted dates
|
|
18394
|
+
*/
|
|
18395
|
+
convertDocToReview(docData) {
|
|
18396
|
+
const review = docData;
|
|
18397
|
+
review.createdAt = this.convertTimestamp(docData.createdAt);
|
|
18398
|
+
review.updatedAt = this.convertTimestamp(docData.updatedAt);
|
|
18399
|
+
if (review.clinicReview) {
|
|
18400
|
+
review.clinicReview.createdAt = this.convertTimestamp(review.clinicReview.createdAt);
|
|
18401
|
+
review.clinicReview.updatedAt = this.convertTimestamp(review.clinicReview.updatedAt);
|
|
18402
|
+
}
|
|
18403
|
+
if (review.practitionerReview) {
|
|
18404
|
+
review.practitionerReview.createdAt = this.convertTimestamp(review.practitionerReview.createdAt);
|
|
18405
|
+
review.practitionerReview.updatedAt = this.convertTimestamp(review.practitionerReview.updatedAt);
|
|
18406
|
+
}
|
|
18407
|
+
if (review.procedureReview) {
|
|
18408
|
+
review.procedureReview.createdAt = this.convertTimestamp(review.procedureReview.createdAt);
|
|
18409
|
+
review.procedureReview.updatedAt = this.convertTimestamp(review.procedureReview.updatedAt);
|
|
18410
|
+
}
|
|
18411
|
+
if (review.extendedProcedureReviews && Array.isArray(review.extendedProcedureReviews)) {
|
|
18412
|
+
review.extendedProcedureReviews = review.extendedProcedureReviews.map((extReview) => ({
|
|
18413
|
+
...extReview,
|
|
18414
|
+
createdAt: this.convertTimestamp(extReview.createdAt),
|
|
18415
|
+
updatedAt: this.convertTimestamp(extReview.updatedAt)
|
|
18416
|
+
}));
|
|
18417
|
+
}
|
|
18418
|
+
return review;
|
|
18419
|
+
}
|
|
18349
18420
|
/**
|
|
18350
18421
|
* Creates a new review
|
|
18351
18422
|
* @param data - The review data to create
|
|
@@ -18489,7 +18560,7 @@ var ReviewService = class extends BaseService {
|
|
|
18489
18560
|
console.log("\u274C ReviewService.getReview - Review not found:", reviewId);
|
|
18490
18561
|
return null;
|
|
18491
18562
|
}
|
|
18492
|
-
const review = { ...docSnap.data(), id: reviewId };
|
|
18563
|
+
const review = { ...this.convertDocToReview(docSnap.data()), id: reviewId };
|
|
18493
18564
|
try {
|
|
18494
18565
|
const appointmentDoc = await getDoc39(
|
|
18495
18566
|
doc38(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
|
|
@@ -18554,7 +18625,7 @@ var ReviewService = class extends BaseService {
|
|
|
18554
18625
|
async getReviewsByPatient(patientId) {
|
|
18555
18626
|
const q = query32(collection32(this.db, REVIEWS_COLLECTION), where32("patientId", "==", patientId));
|
|
18556
18627
|
const snapshot = await getDocs32(q);
|
|
18557
|
-
const reviews = snapshot.docs.map((doc45) => doc45.data());
|
|
18628
|
+
const reviews = snapshot.docs.map((doc45) => this.convertDocToReview(doc45.data()));
|
|
18558
18629
|
const enhancedReviews = await Promise.all(
|
|
18559
18630
|
reviews.map(async (review) => {
|
|
18560
18631
|
try {
|
|
@@ -18609,8 +18680,8 @@ var ReviewService = class extends BaseService {
|
|
|
18609
18680
|
);
|
|
18610
18681
|
const snapshot = await getDocs32(q);
|
|
18611
18682
|
const reviews = snapshot.docs.map((doc45) => {
|
|
18612
|
-
const
|
|
18613
|
-
return { ...
|
|
18683
|
+
const review = this.convertDocToReview(doc45.data());
|
|
18684
|
+
return { ...review, id: doc45.id };
|
|
18614
18685
|
});
|
|
18615
18686
|
console.log("\u{1F50D} ReviewService.getReviewsByClinic - Found reviews before enhancement:", {
|
|
18616
18687
|
clinicId,
|
|
@@ -18685,8 +18756,8 @@ var ReviewService = class extends BaseService {
|
|
|
18685
18756
|
);
|
|
18686
18757
|
const snapshot = await getDocs32(q);
|
|
18687
18758
|
const reviews = snapshot.docs.map((doc45) => {
|
|
18688
|
-
const
|
|
18689
|
-
return { ...
|
|
18759
|
+
const review = this.convertDocToReview(doc45.data());
|
|
18760
|
+
return { ...review, id: doc45.id };
|
|
18690
18761
|
});
|
|
18691
18762
|
console.log("\u{1F50D} ReviewService.getReviewsByPractitioner - Found reviews before enhancement:", {
|
|
18692
18763
|
practitionerId,
|
|
@@ -18832,7 +18903,7 @@ var ReviewService = class extends BaseService {
|
|
|
18832
18903
|
if (snapshot.empty) {
|
|
18833
18904
|
return null;
|
|
18834
18905
|
}
|
|
18835
|
-
return snapshot.docs[0].data();
|
|
18906
|
+
return this.convertDocToReview(snapshot.docs[0].data());
|
|
18836
18907
|
}
|
|
18837
18908
|
/**
|
|
18838
18909
|
* Deletes a review
|
package/package.json
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Review Date Timestamp Fix
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
All reviews in the Patient App were displaying the same date (e.g., "September 26, 2025") regardless of when they were actually created. This was causing confusion as users couldn't distinguish between reviews from different dates.
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
When fetching reviews from Firestore, the `createdAt` and `updatedAt` fields were Firestore Timestamp objects that weren't being properly converted to JavaScript Date objects. The code was using:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const reviews = snapshot.docs.map(doc => doc.data() as Review);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This direct type casting doesn't convert Firestore Timestamps (which have `seconds` and `nanoseconds` properties) into proper Date objects, leading to inconsistent date handling across the application.
|
|
14
|
+
|
|
15
|
+
## Solution
|
|
16
|
+
Added two helper methods to the `ReviewService` class:
|
|
17
|
+
|
|
18
|
+
### 1. `convertTimestamp(timestamp: any): Date`
|
|
19
|
+
Converts various timestamp formats to JavaScript Date objects:
|
|
20
|
+
- Firestore Timestamp with `__isTimestamp` flag
|
|
21
|
+
- Firestore Timestamp with `toDate()` method
|
|
22
|
+
- Regular Date objects
|
|
23
|
+
- String or number timestamps
|
|
24
|
+
- Fallback to current date for invalid inputs
|
|
25
|
+
|
|
26
|
+
### 2. `convertDocToReview(docData: any): Review`
|
|
27
|
+
Converts raw Firestore document data to a properly formatted Review object by:
|
|
28
|
+
- Converting main review timestamps (`createdAt`, `updatedAt`)
|
|
29
|
+
- Converting clinic review timestamps if present
|
|
30
|
+
- Converting practitioner review timestamps if present
|
|
31
|
+
- Converting procedure review timestamps if present
|
|
32
|
+
- Converting extended procedure reviews timestamps if present
|
|
33
|
+
|
|
34
|
+
## Changes Made
|
|
35
|
+
|
|
36
|
+
### Files Modified
|
|
37
|
+
- `Api/src/services/reviews/reviews.service.ts`
|
|
38
|
+
|
|
39
|
+
### Methods Updated
|
|
40
|
+
All review fetching methods now use `convertDocToReview()`:
|
|
41
|
+
1. `getReviewsByPatient(patientId: string)` - Line 372
|
|
42
|
+
2. `getReviewsByClinic(clinicId: string)` - Line 443
|
|
43
|
+
3. `getReviewsByPractitioner(practitionerId: string)` - Line 538
|
|
44
|
+
4. `getReview(reviewId: string)` - Line 285
|
|
45
|
+
5. `getReviewByAppointment(appointmentId: string)` - Line 723
|
|
46
|
+
|
|
47
|
+
## Package Version
|
|
48
|
+
- **Published Version**: `@blackcode_sa/metaestetics-api@1.12.70`
|
|
49
|
+
- **Change Type**: Patch (bug fix)
|
|
50
|
+
|
|
51
|
+
## Apps Updated
|
|
52
|
+
All apps have been updated to use version 1.12.70:
|
|
53
|
+
- ✅ Mobile (Patient App)
|
|
54
|
+
- ✅ DoctorMobile
|
|
55
|
+
- ✅ ClinicApp
|
|
56
|
+
|
|
57
|
+
## Testing
|
|
58
|
+
After updating, verify that:
|
|
59
|
+
1. Reviews display their actual creation dates
|
|
60
|
+
2. Each review shows a different date (if created on different days)
|
|
61
|
+
3. Dates are formatted correctly in the format: "Month Day, Year" (e.g., "September 26, 2025")
|
|
62
|
+
|
|
63
|
+
## Impact
|
|
64
|
+
This fix ensures that all review dates are properly displayed across all applications, allowing users to accurately track when feedback was submitted.
|
|
65
|
+
|
|
@@ -29,6 +29,101 @@ export class ReviewService extends BaseService {
|
|
|
29
29
|
super(db, auth, app);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Helper function to convert Firestore Timestamps to Date objects
|
|
34
|
+
* @param timestamp The timestamp to convert
|
|
35
|
+
* @returns A JavaScript Date object or null
|
|
36
|
+
*/
|
|
37
|
+
private convertTimestamp(timestamp: any): Date {
|
|
38
|
+
// Log what we receive for debugging
|
|
39
|
+
if (!timestamp) {
|
|
40
|
+
console.warn('⚠️ convertTimestamp received null/undefined timestamp');
|
|
41
|
+
return new Date();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('🔍 convertTimestamp input:', {
|
|
45
|
+
type: typeof timestamp,
|
|
46
|
+
value: timestamp,
|
|
47
|
+
hasToDate: timestamp?.toDate !== undefined,
|
|
48
|
+
hasIsTimestamp: timestamp?.__isTimestamp !== undefined,
|
|
49
|
+
hasSeconds: timestamp?.seconds !== undefined,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Firebase Timestamp object with __isTimestamp
|
|
53
|
+
if (timestamp && timestamp.__isTimestamp === true && typeof timestamp.seconds === 'number') {
|
|
54
|
+
const converted = new Date(timestamp.seconds * 1000 + (timestamp.nanoseconds || 0) / 1000000);
|
|
55
|
+
console.log('✅ Converted __isTimestamp:', converted);
|
|
56
|
+
return converted;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Firebase Firestore Timestamp with toDate method
|
|
60
|
+
if (timestamp && timestamp.toDate && typeof timestamp.toDate === 'function') {
|
|
61
|
+
const converted = timestamp.toDate();
|
|
62
|
+
console.log('✅ Converted using toDate():', converted);
|
|
63
|
+
return converted;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Already a Date object
|
|
67
|
+
if (timestamp instanceof Date) {
|
|
68
|
+
console.log('✅ Already a Date object:', timestamp);
|
|
69
|
+
return timestamp;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// String or number
|
|
73
|
+
if (typeof timestamp === 'string' || typeof timestamp === 'number') {
|
|
74
|
+
const date = new Date(timestamp);
|
|
75
|
+
if (!isNaN(date.getTime())) {
|
|
76
|
+
console.log('✅ Converted from string/number:', date);
|
|
77
|
+
return date;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.warn('⚠️ Could not convert timestamp, returning current date. Input was:', timestamp);
|
|
82
|
+
return new Date();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Converts a Firestore document to a Review object with proper date handling
|
|
87
|
+
* @param docData The raw Firestore document data
|
|
88
|
+
* @returns A Review object with properly converted dates
|
|
89
|
+
*/
|
|
90
|
+
private convertDocToReview(docData: any): Review {
|
|
91
|
+
const review = docData as Review;
|
|
92
|
+
|
|
93
|
+
// Convert main review timestamps
|
|
94
|
+
review.createdAt = this.convertTimestamp(docData.createdAt);
|
|
95
|
+
review.updatedAt = this.convertTimestamp(docData.updatedAt);
|
|
96
|
+
|
|
97
|
+
// Convert clinic review timestamps if present
|
|
98
|
+
if (review.clinicReview) {
|
|
99
|
+
review.clinicReview.createdAt = this.convertTimestamp(review.clinicReview.createdAt);
|
|
100
|
+
review.clinicReview.updatedAt = this.convertTimestamp(review.clinicReview.updatedAt);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Convert practitioner review timestamps if present
|
|
104
|
+
if (review.practitionerReview) {
|
|
105
|
+
review.practitionerReview.createdAt = this.convertTimestamp(review.practitionerReview.createdAt);
|
|
106
|
+
review.practitionerReview.updatedAt = this.convertTimestamp(review.practitionerReview.updatedAt);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Convert procedure review timestamps if present
|
|
110
|
+
if (review.procedureReview) {
|
|
111
|
+
review.procedureReview.createdAt = this.convertTimestamp(review.procedureReview.createdAt);
|
|
112
|
+
review.procedureReview.updatedAt = this.convertTimestamp(review.procedureReview.updatedAt);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Convert extended procedure reviews timestamps if present
|
|
116
|
+
if (review.extendedProcedureReviews && Array.isArray(review.extendedProcedureReviews)) {
|
|
117
|
+
review.extendedProcedureReviews = review.extendedProcedureReviews.map(extReview => ({
|
|
118
|
+
...extReview,
|
|
119
|
+
createdAt: this.convertTimestamp(extReview.createdAt),
|
|
120
|
+
updatedAt: this.convertTimestamp(extReview.updatedAt),
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return review;
|
|
125
|
+
}
|
|
126
|
+
|
|
32
127
|
/**
|
|
33
128
|
* Creates a new review
|
|
34
129
|
* @param data - The review data to create
|
|
@@ -206,7 +301,7 @@ export class ReviewService extends BaseService {
|
|
|
206
301
|
return null;
|
|
207
302
|
}
|
|
208
303
|
|
|
209
|
-
const review = { ...docSnap.data(), id: reviewId }
|
|
304
|
+
const review = { ...this.convertDocToReview(docSnap.data()), id: reviewId };
|
|
210
305
|
|
|
211
306
|
try {
|
|
212
307
|
// Fetch the associated appointment to enhance with entity names
|
|
@@ -293,7 +388,7 @@ export class ReviewService extends BaseService {
|
|
|
293
388
|
async getReviewsByPatient(patientId: string): Promise<Review[]> {
|
|
294
389
|
const q = query(collection(this.db, REVIEWS_COLLECTION), where('patientId', '==', patientId));
|
|
295
390
|
const snapshot = await getDocs(q);
|
|
296
|
-
const reviews = snapshot.docs.map(doc => doc.data()
|
|
391
|
+
const reviews = snapshot.docs.map(doc => this.convertDocToReview(doc.data()));
|
|
297
392
|
|
|
298
393
|
// Enhance reviews with entity names from appointments
|
|
299
394
|
const enhancedReviews = await Promise.all(
|
|
@@ -364,8 +459,8 @@ export class ReviewService extends BaseService {
|
|
|
364
459
|
);
|
|
365
460
|
const snapshot = await getDocs(q);
|
|
366
461
|
const reviews = snapshot.docs.map(doc => {
|
|
367
|
-
const
|
|
368
|
-
return { ...
|
|
462
|
+
const review = this.convertDocToReview(doc.data());
|
|
463
|
+
return { ...review, id: doc.id };
|
|
369
464
|
});
|
|
370
465
|
|
|
371
466
|
console.log('🔍 ReviewService.getReviewsByClinic - Found reviews before enhancement:', {
|
|
@@ -459,8 +554,8 @@ export class ReviewService extends BaseService {
|
|
|
459
554
|
);
|
|
460
555
|
const snapshot = await getDocs(q);
|
|
461
556
|
const reviews = snapshot.docs.map(doc => {
|
|
462
|
-
const
|
|
463
|
-
return { ...
|
|
557
|
+
const review = this.convertDocToReview(doc.data());
|
|
558
|
+
return { ...review, id: doc.id };
|
|
464
559
|
});
|
|
465
560
|
|
|
466
561
|
console.log('🔍 ReviewService.getReviewsByPractitioner - Found reviews before enhancement:', {
|
|
@@ -644,7 +739,7 @@ export class ReviewService extends BaseService {
|
|
|
644
739
|
return null;
|
|
645
740
|
}
|
|
646
741
|
|
|
647
|
-
return snapshot.docs[0].data()
|
|
742
|
+
return this.convertDocToReview(snapshot.docs[0].data());
|
|
648
743
|
}
|
|
649
744
|
|
|
650
745
|
/**
|