# Reviews API - Quick Reference Guide ## Rating Scale Conversion ### Convert UI Stars to API Rating ```dart // UI: 5 stars → API: 1.0 final apiRating = stars / 5.0; ``` ### Convert API Rating to UI Stars ```dart // API: 0.8 → UI: 4 stars final stars = (rating * 5).round(); ``` ### Helper Functions (in reviews_provider.dart) ```dart double apiRating = starsToApiRating(5); // Returns 1.0 int stars = apiRatingToStars(0.8); // Returns 4 ``` --- ## Provider Usage ### Get Reviews for Product ```dart final reviewsAsync = ref.watch(productReviewsProvider(itemId)); reviewsAsync.when( data: (reviews) => /* show reviews */, loading: () => CircularProgressIndicator(), error: (error, stack) => /* show error */, ); ``` ### Get Average Rating ```dart final avgRatingAsync = ref.watch(productAverageRatingProvider(itemId)); ``` ### Get Review Count ```dart final countAsync = ref.watch(productReviewCountProvider(itemId)); ``` ### Submit Review ```dart try { final submitUseCase = ref.read(submitReviewProvider); await submitUseCase( itemId: productId, rating: stars / 5.0, // Convert stars to 0-1 comment: comment, ); // Refresh reviews ref.invalidate(productReviewsProvider(productId)); } catch (e) { // Handle error } ``` ### Delete Review ```dart try { final deleteUseCase = ref.read(deleteReviewProvider); await deleteUseCase(name: reviewId); // Refresh reviews ref.invalidate(productReviewsProvider(productId)); } catch (e) { // Handle error } ``` --- ## API Endpoints ### Get Reviews ```dart POST /api/method/building_material.building_material.api.item_feedback.get_list Body: { "limit_page_length": 10, "limit_start": 0, "item_id": "PRODUCT_ID" } ``` ### Submit Review ```dart POST /api/method/building_material.building_material.api.item_feedback.update Body: { "item_id": "PRODUCT_ID", "rating": 0.8, // 0-1 scale "comment": "Great!", "name": "REVIEW_ID" // Optional, for updates } ``` ### Delete Review ```dart POST /api/method/building_material.building_material.api.item_feedback.delete Body: { "name": "ITEM-PRODUCT_ID-user@email.com" } ``` --- ## Review Entity ```dart class Review { final String id; // Review ID final String itemId; // Product code final double rating; // API rating (0-1) final String comment; // Review text final String? reviewerName; // Reviewer name final String? reviewerEmail; // Reviewer email final DateTime? reviewDate; // Review date // Convert to stars (0-5) int get starsRating => (rating * 5).round(); double get starsRatingDecimal => rating * 5; } ``` --- ## Error Handling ### Common Exceptions ```dart try { // API call } on NoInternetException { // No internet connection } on TimeoutException { // Request timeout } on UnauthorizedException { // Session expired } on ValidationException catch (e) { // Invalid data: e.message } on NotFoundException { // Review not found } on ServerException { // Server error (5xx) } catch (e) { // Unknown error } ``` ### Status Codes - **400**: Bad Request - Invalid data - **401**: Unauthorized - Session expired - **403**: Forbidden - No permission - **404**: Not Found - Review doesn't exist - **409**: Conflict - Review already exists - **429**: Too Many Requests - Rate limited - **500+**: Server Error --- ## Validation Rules ### Rating - Must be 0-1 for API - Must be 1-5 for UI - Cannot be empty ### Comment - Minimum: 20 characters - Maximum: 1000 characters - Cannot be empty or whitespace only --- ## Date Formatting ```dart String _formatDate(DateTime date) { final now = DateTime.now(); final diff = now.difference(date); if (diff.inDays == 0) return 'Hôm nay'; if (diff.inDays == 1) return 'Hôm qua'; if (diff.inDays < 7) return '${diff.inDays} ngày trước'; if (diff.inDays < 30) return '${(diff.inDays / 7).floor()} tuần trước'; if (diff.inDays < 365) return '${(diff.inDays / 30).floor()} tháng trước'; return '${(diff.inDays / 365).floor()} năm trước'; } ``` --- ## Review ID Format ``` ITEM-{item_id}-{user_email} ``` **Examples**: - `ITEM-GIB20 G04-john@example.com` - `ITEM-Product123-user@company.com` --- ## Testing Checklist - [ ] Reviews load correctly - [ ] Rating conversion works (0-1 ↔ 1-5) - [ ] Submit review refreshes list - [ ] Average rating calculates correctly - [ ] Empty state shows when no reviews - [ ] Loading state shows during API calls - [ ] Error messages display correctly - [ ] Date formatting works - [ ] Star ratings display correctly - [ ] Form validation works --- ## Common Issues ### Issue: Reviews not loading **Solution**: Check auth tokens (sid, csrf_token) are set ### Issue: Rating conversion wrong **Solution**: Always use `stars / 5.0` for API, `(rating * 5).round()` for UI ### Issue: Reviews not refreshing after submit **Solution**: Use `ref.invalidate(productReviewsProvider(itemId))` ### Issue: Provider not found error **Solution**: Run `dart run build_runner build` to generate .g.dart files --- ## File Locations **Domain**: - `lib/features/reviews/domain/entities/review.dart` - `lib/features/reviews/domain/repositories/reviews_repository.dart` - `lib/features/reviews/domain/usecases/*.dart` **Data**: - `lib/features/reviews/data/models/review_model.dart` - `lib/features/reviews/data/datasources/reviews_remote_datasource.dart` - `lib/features/reviews/data/repositories/reviews_repository_impl.dart` **Presentation**: - `lib/features/reviews/presentation/providers/reviews_provider.dart` **Updated**: - `lib/features/products/presentation/widgets/product_detail/product_tabs_section.dart` - `lib/features/products/presentation/pages/write_review_page.dart` - `lib/core/constants/api_constants.dart`