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,178 @@
/// Providers: Reviews
///
/// Riverpod providers for review management.
library;
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/features/reviews/data/datasources/reviews_remote_datasource.dart';
import 'package:worker/features/reviews/data/repositories/reviews_repository_impl.dart';
import 'package:worker/features/reviews/domain/entities/review.dart';
import 'package:worker/features/reviews/domain/entities/review_statistics.dart';
import 'package:worker/features/reviews/domain/repositories/reviews_repository.dart';
import 'package:worker/features/reviews/domain/usecases/delete_review.dart';
import 'package:worker/features/reviews/domain/usecases/get_product_reviews.dart';
import 'package:worker/features/reviews/domain/usecases/submit_review.dart';
part 'reviews_provider.g.dart';
// ============================================================================
// Data Layer Providers
// ============================================================================
/// Provider for reviews remote data source
@riverpod
Future<ReviewsRemoteDataSource> reviewsRemoteDataSource(
Ref ref,
) async {
final dioClient = await ref.watch(dioClientProvider.future);
return ReviewsRemoteDataSourceImpl(dioClient);
}
/// Provider for reviews repository
@riverpod
Future<ReviewsRepository> reviewsRepository(Ref ref) async {
final remoteDataSource = await ref.watch(reviewsRemoteDataSourceProvider.future);
return ReviewsRepositoryImpl(remoteDataSource);
}
// ============================================================================
// Use Case Providers
// ============================================================================
/// Provider for get product reviews use case
@riverpod
Future<GetProductReviews> getProductReviews(Ref ref) async {
final repository = await ref.watch(reviewsRepositoryProvider.future);
return GetProductReviews(repository);
}
/// Provider for submit review use case
@riverpod
Future<SubmitReview> submitReview(Ref ref) async {
final repository = await ref.watch(reviewsRepositoryProvider.future);
return SubmitReview(repository);
}
/// Provider for delete review use case
@riverpod
Future<DeleteReview> deleteReview(Ref ref) async {
final repository = await ref.watch(reviewsRepositoryProvider.future);
return DeleteReview(repository);
}
// ============================================================================
// State Providers
// ============================================================================
/// Provider for fetching reviews for a specific product
///
/// This is a family provider that takes a product ID and returns
/// the list of reviews for that product.
///
/// Usage:
/// ```dart
/// final reviewsAsync = ref.watch(productReviewsProvider('PRODUCT_ID'));
/// ```
@riverpod
Future<List<Review>> productReviews(
Ref ref,
String itemId,
) async {
final getProductReviewsUseCase = await ref.watch(getProductReviewsProvider.future);
return await getProductReviewsUseCase(
itemId: itemId,
limitPageLength: 50, // Fetch more reviews
limitStart: 0,
);
}
/// Provider for review statistics (from API)
///
/// Gets statistics directly from API including:
/// - Total feedback count
/// - Average rating (0-5 scale, already calculated by server)
///
/// This is more efficient than calculating client-side
@riverpod
Future<ReviewStatistics> productReviewStatistics(
Ref ref,
String itemId,
) async {
final repository = await ref.watch(reviewsRepositoryProvider.future);
return await repository.getProductReviewStatistics(itemId: itemId);
}
/// Provider for average rating (convenience wrapper)
///
/// Gets the average rating from API statistics
/// Returns 0.0 if there are no reviews.
@riverpod
Future<double> productAverageRating(
Ref ref,
String itemId,
) async {
final stats = await ref.watch(productReviewStatisticsProvider(itemId).future);
return stats.averageRating;
}
/// Provider for counting reviews (convenience wrapper)
///
/// Gets the total count from API statistics
@riverpod
Future<int> productReviewCount(
Ref ref,
String itemId,
) async {
final stats = await ref.watch(productReviewStatisticsProvider(itemId).future);
return stats.totalFeedback;
}
/// Provider for checking if user can submit a review
///
/// This can be extended to check if user has already reviewed
/// the product and enforce one-review-per-user policy.
///
/// For now, it always returns true.
@riverpod
Future<bool> canSubmitReview(
Ref ref,
String itemId,
) async {
// TODO: Implement logic to check if user already reviewed this product
// This would require user email from auth state
return true;
}
// ============================================================================
// Helper Functions
// ============================================================================
/// Convert star rating (1-5) to API rating (0-1)
///
/// Example:
/// - 1 star = 0.2
/// - 2 stars = 0.4
/// - 3 stars = 0.6
/// - 4 stars = 0.8
/// - 5 stars = 1.0
double starsToApiRating(int stars) {
if (stars < 1 || stars > 5) {
throw ArgumentError('Stars must be between 1 and 5. Got: $stars');
}
return stars / 5.0;
}
/// Convert API rating (0-1) to star rating (1-5)
///
/// Example:
/// - 0.2 = 1 star
/// - 0.5 = 2.5 stars (rounded to 3)
/// - 1.0 = 5 stars
int apiRatingToStars(double rating) {
if (rating < 0 || rating > 1) {
throw ArgumentError('Rating must be between 0 and 1. Got: $rating');
}
return (rating * 5).round();
}