update review api.

This commit is contained in:
Phuoc Nguyen
2025-11-17 17:54:32 +07:00
parent 0798b28db5
commit 0841e3bf3d
23 changed files with 4856 additions and 209 deletions

View File

@@ -0,0 +1,116 @@
/// Domain Entity: Review
///
/// Represents a product review with rating and comment.
library;
/// Review entity
///
/// Contains user feedback for a product including:
/// - Unique review ID (name field from API)
/// - Product item code
/// - Rating (0-1 from API, converted to 0-5 stars for display)
/// - Review comment text
/// - Reviewer information
/// - Review date
class Review {
const Review({
required this.id,
required this.itemId,
required this.rating,
required this.comment,
this.reviewerName,
this.reviewerEmail,
this.reviewDate,
});
/// Unique review identifier (format: ITEM-{item_id}-{user_email})
final String id;
/// Product item code being reviewed
final String itemId;
/// Rating from API (0-5 scale)
/// Note: API already provides rating on 0-5 scale, no conversion needed
final double rating;
/// Review comment text
final String comment;
/// Name of the reviewer (if available)
final String? reviewerName;
/// Email of the reviewer (if available)
final String? reviewerEmail;
/// Date when the review was created (if available)
final DateTime? reviewDate;
/// Get star rating rounded to nearest integer (0-5)
///
/// Examples:
/// - API rating 0.5 = 1 star
/// - API rating 2.25 = 2 stars
/// - API rating 4.0 = 4 stars
int get starsRating => rating.round();
/// Get rating as exact decimal (0-5 scale)
///
/// This is useful for average rating calculations and display
/// API already returns this on 0-5 scale
double get starsRatingDecimal => rating;
/// Copy with method for creating modified copies
Review copyWith({
String? id,
String? itemId,
double? rating,
String? comment,
String? reviewerName,
String? reviewerEmail,
DateTime? reviewDate,
}) {
return Review(
id: id ?? this.id,
itemId: itemId ?? this.itemId,
rating: rating ?? this.rating,
comment: comment ?? this.comment,
reviewerName: reviewerName ?? this.reviewerName,
reviewerEmail: reviewerEmail ?? this.reviewerEmail,
reviewDate: reviewDate ?? this.reviewDate,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Review &&
other.id == id &&
other.itemId == itemId &&
other.rating == rating &&
other.comment == comment &&
other.reviewerName == reviewerName &&
other.reviewerEmail == reviewerEmail &&
other.reviewDate == reviewDate;
}
@override
int get hashCode {
return Object.hash(
id,
itemId,
rating,
comment,
reviewerName,
reviewerEmail,
reviewDate,
);
}
@override
String toString() {
return 'Review(id: $id, itemId: $itemId, rating: $rating, '
'starsRating: $starsRating, comment: ${comment.substring(0, comment.length > 30 ? 30 : comment.length)}..., '
'reviewerName: $reviewerName, reviewDate: $reviewDate)';
}
}

View File

@@ -0,0 +1,49 @@
/// Domain Entity: Review Statistics
///
/// Aggregate statistics for product reviews.
library;
/// Review statistics entity
///
/// Contains aggregate data about reviews:
/// - Total number of feedbacks
/// - Average rating (0-5 scale)
class ReviewStatistics {
const ReviewStatistics({
required this.totalFeedback,
required this.averageRating,
});
/// Total number of reviews/feedbacks
final int totalFeedback;
/// Average rating (0-5 scale)
/// Note: This is already on 0-5 scale from API, no conversion needed
final double averageRating;
/// Check if there are any reviews
bool get hasReviews => totalFeedback > 0;
/// Get star rating rounded to nearest 0.5
/// Used for displaying star icons
double get displayRating {
return (averageRating * 2).round() / 2;
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ReviewStatistics &&
other.totalFeedback == totalFeedback &&
other.averageRating == averageRating;
}
@override
int get hashCode => Object.hash(totalFeedback, averageRating);
@override
String toString() {
return 'ReviewStatistics(totalFeedback: $totalFeedback, averageRating: $averageRating)';
}
}