/// 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( Ref ref, ) async { final dioClient = await ref.watch(dioClientProvider.future); return ReviewsRemoteDataSourceImpl(dioClient); } /// Provider for reviews repository @riverpod Future 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(Ref ref) async { final repository = await ref.watch(reviewsRepositoryProvider.future); return GetProductReviews(repository); } /// Provider for submit review use case @riverpod Future submitReview(Ref ref) async { final repository = await ref.watch(reviewsRepositoryProvider.future); return SubmitReview(repository); } /// Provider for delete review use case @riverpod Future 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> 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 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 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 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 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(); }