feat: add complete review/rating system for events
New feature: Users can view, submit, and interact with event reviews. Components added: - ReviewModel, ReviewStatsModel, ReviewListResponse (models) - ReviewService with getReviews, submitReview, markHelpful, flagReview - StarRatingInput (interactive 5-star picker with labels) - StarDisplay (read-only fractional star display) - ReviewSummary (average rating + distribution bars) - ReviewForm (star picker + comment field + submit/update) - ReviewCard (avatar, timestamp, expandable comment, helpful/flag) - ReviewSection (main container with pagination and state mgmt) Integration: - Added to LearnMoreScreen (both mobile and desktop layouts) - Review API endpoints point to app.eventifyplus.com Node.js backend - EventModel updated with averageRating/reviewCount fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
56
lib/features/reviews/widgets/star_rating_input.dart
Normal file
56
lib/features/reviews/widgets/star_rating_input.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
// lib/features/reviews/widgets/star_rating_input.dart
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StarRatingInput extends StatelessWidget {
|
||||
final int rating;
|
||||
final ValueChanged<int> onRatingChanged;
|
||||
final double starSize;
|
||||
|
||||
const StarRatingInput({
|
||||
Key? key,
|
||||
required this.rating,
|
||||
required this.onRatingChanged,
|
||||
this.starSize = 36,
|
||||
}) : super(key: key);
|
||||
|
||||
static const _labels = ['', 'Poor', 'Fair', 'Good', 'Very Good', 'Excellent'];
|
||||
static const _starGold = Color(0xFFFBBF24);
|
||||
static const _starEmpty = Color(0xFFD1D5DB);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: List.generate(5, (i) {
|
||||
final starIndex = i + 1;
|
||||
return GestureDetector(
|
||||
onTap: () => onRatingChanged(starIndex),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: Icon(
|
||||
starIndex <= rating ? Icons.star_rounded : Icons.star_outline_rounded,
|
||||
size: starSize,
|
||||
color: starIndex <= rating ? _starGold : _starEmpty,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
if (rating > 0) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_labels[rating],
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: _starGold,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user