5.7 KiB
5.7 KiB
Reviews API - Quick Reference Guide
Rating Scale Conversion
Convert UI Stars to API Rating
// UI: 5 stars → API: 1.0
final apiRating = stars / 5.0;
Convert API Rating to UI Stars
// API: 0.8 → UI: 4 stars
final stars = (rating * 5).round();
Helper Functions (in reviews_provider.dart)
double apiRating = starsToApiRating(5); // Returns 1.0
int stars = apiRatingToStars(0.8); // Returns 4
Provider Usage
Get Reviews for Product
final reviewsAsync = ref.watch(productReviewsProvider(itemId));
reviewsAsync.when(
data: (reviews) => /* show reviews */,
loading: () => CircularProgressIndicator(),
error: (error, stack) => /* show error */,
);
Get Average Rating
final avgRatingAsync = ref.watch(productAverageRatingProvider(itemId));
Get Review Count
final countAsync = ref.watch(productReviewCountProvider(itemId));
Submit Review
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
try {
final deleteUseCase = ref.read(deleteReviewProvider);
await deleteUseCase(name: reviewId);
// Refresh reviews
ref.invalidate(productReviewsProvider(productId));
} catch (e) {
// Handle error
}
API Endpoints
Get Reviews
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
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
POST /api/method/building_material.building_material.api.item_feedback.delete
Body: {
"name": "ITEM-PRODUCT_ID-user@email.com"
}
Review Entity
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
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
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.comITEM-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.dartlib/features/reviews/domain/repositories/reviews_repository.dartlib/features/reviews/domain/usecases/*.dart
Data:
lib/features/reviews/data/models/review_model.dartlib/features/reviews/data/datasources/reviews_remote_datasource.dartlib/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.dartlib/features/products/presentation/pages/write_review_page.dartlib/core/constants/api_constants.dart