import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:intl/intl.dart'; import 'package:onufitness/constants/asset_constants.dart'; import 'package:onufitness/constants/color_constant.dart'; import 'package:onufitness/constants/text_constant.dart'; import 'package:onufitness/screens/echoboard/models/coach_reviews_response_model.dart'; class ReviewCard extends StatelessWidget { final UserReviewRating review; const ReviewCard({super.key, required this.review}); @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), padding: EdgeInsets.all(16.sp), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8.r), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 5, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // User info and rating Row( children: [ // Profile image ClipRRect( borderRadius: BorderRadius.circular(20.r), child: review.profilePicture != null ? Image.network( review.profilePicture!, height: 40.r, width: 40.r, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Image.asset( AssetConstants.dummyUserImage, height: 40.r, width: 40.r, fit: BoxFit.cover, ); }, ) : Image.asset( AssetConstants.dummyUserImage, height: 40.r, width: 40.r, fit: BoxFit.cover, ), ), SizedBox(width: 12.w), // User name and date Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( review.fullName ?? 'Anonymous User', style: TextStyle( fontSize: mediumSizeText, fontWeight: FontWeight.bold, ), ), Text( DateFormat('dd MMM yyyy').format(review.createdAt!), style: TextStyle( fontSize: smallSizeText, color: Colors.grey, ), ), ], ), ), // Rating stars Row( children: List.generate( 5, (index) => Icon( index < (review.rating ?? 0) ? Icons.star : Icons.star_border, color: index < (review.rating ?? 0) ? const Color(primaryColor) : Colors.grey, size: 18.sp, ), ), ), ], ), SizedBox(height: 12.h), // Review text Text( review.reviewDescription ?? 'No comments provided', style: TextStyle(fontSize: regularSizeText, color: Colors.black87), ), ], ), ); } } class RatingStatsWidget extends StatelessWidget { final double avgRating; final int totalReviews; final String userName; const RatingStatsWidget({ super.key, required this.avgRating, required this.totalReviews, required this.userName, }); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(16.sp), child: Column( children: [ // Average Rating display Text( avgRating.toStringAsFixed(1), style: TextStyle( fontSize: 48.sp, fontWeight: FontWeight.bold, color: Colors.black, ), ), SizedBox(height: 8.h), // Star Rating Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(5, (index) { // Calculate if star should be full, half, or empty double threshold = index + 0.5; IconData icon; if (avgRating >= index + 1) { icon = Icons.star; } else if (avgRating >= threshold) { icon = Icons.star_half; } else { icon = Icons.star_border; } return Icon(icon, color: const Color(primaryColor), size: 24.sp); }), ), SizedBox(height: 8.h), // Total reviews count Text( '$totalReviews ${totalReviews == 1 ? 'Review' : 'Reviews'}', style: TextStyle(fontSize: mediumSizeText, color: Colors.grey[600]), ), SizedBox(height: 12.h), // User name description Text( 'Ratings & reviews for $userName', style: TextStyle(fontSize: smallSizeText, color: Colors.grey[700]), textAlign: TextAlign.center, ), ], ), ); } } class ReviewInputDialog extends StatefulWidget { final Function(int, String) onSubmit; const ReviewInputDialog({super.key, required this.onSubmit}); @override State createState() => _ReviewInputDialogState(); } class _ReviewInputDialogState extends State { int _selectedRating = 0; final TextEditingController _reviewController = TextEditingController(); final _formKey = GlobalKey(); @override void dispose() { _reviewController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Padding( padding: EdgeInsets.all(16.sp), child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Dialog title Text( 'Write a Review', style: TextStyle( fontSize: largeSizeText, fontWeight: FontWeight.bold, ), ), SizedBox(height: 16.h), // Rating selector Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Rating', style: TextStyle( fontSize: mediumSizeText, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( 5, (index) => GestureDetector( onTap: () { setState(() { _selectedRating = index + 1; }); }, child: Padding( padding: EdgeInsets.symmetric(horizontal: 4.w), child: Icon( index < _selectedRating ? Icons.star : Icons.star_border, color: index < _selectedRating ? const Color(primaryColor) : Colors.grey, size: 32.sp, ), ), ), ), ), if (_selectedRating == 0) Padding( padding: EdgeInsets.only(top: 8.h), child: Text( 'Please select a rating', style: TextStyle( color: Colors.red, fontSize: smallSizeText, ), ), ), ], ), SizedBox(height: 16.h), // Review text input Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Your Review', style: TextStyle( fontSize: mediumSizeText, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), TextFormField( controller: _reviewController, maxLines: 5, decoration: InputDecoration( hintText: 'Share your experience...', border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: Color(darkGreyColor)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: lightGreyColor), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide( color: lightGreyColor, width: 2, ), ), ), validator: (value) { if (value == null || value.trim().isEmpty) { return 'Please enter your review'; } return null; }, ), ], ), SizedBox(height: 24.h), // Action buttons Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () { Navigator.pop(context); }, child: Text( 'Cancel', style: TextStyle( color: Colors.grey[700], fontSize: regularSizeText, ), ), ), SizedBox(width: 8.w), ElevatedButton( onPressed: () { if (_selectedRating == 0) { setState(() {}); return; } if (_formKey.currentState!.validate()) { widget.onSubmit( _selectedRating, _reviewController.text.trim(), ); Navigator.pop(context); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.black, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), padding: EdgeInsets.symmetric( horizontal: 16.w, vertical: 12.h, ), ), child: Text( 'SUBMIT', style: TextStyle(fontSize: regularSizeText), ), ), ], ), ], ), ), ), ), ); } }