// lib/features/reviews/widgets/review_form.dart import 'package:flutter/material.dart'; import '../../../core/storage/token_storage.dart'; import '../../../core/utils/error_utils.dart'; import '../models/review_models.dart'; import 'star_rating_input.dart'; class ReviewForm extends StatefulWidget { final int eventId; final ReviewModel? existingReview; final Future Function(int rating, String? comment) onSubmit; const ReviewForm({ Key? key, required this.eventId, this.existingReview, required this.onSubmit, }) : super(key: key); @override State createState() => _ReviewFormState(); } enum _FormState { idle, loading, success } class _ReviewFormState extends State with SingleTickerProviderStateMixin { int _rating = 0; final _commentController = TextEditingController(); _FormState _state = _FormState.idle; bool _isLoggedIn = false; String? _error; late final AnimationController _checkController; late final Animation _checkScale; @override void initState() { super.initState(); _checkAuth(); if (widget.existingReview != null) { _rating = widget.existingReview!.rating; _commentController.text = widget.existingReview!.comment ?? ''; } _checkController = AnimationController(vsync: this, duration: const Duration(milliseconds: 600)); _checkScale = CurvedAnimation(parent: _checkController, curve: Curves.elasticOut); } Future _checkAuth() async { final token = await TokenStorage.getToken(); final username = await TokenStorage.getUsername(); if (mounted) setState(() => _isLoggedIn = token != null && username != null); } Future _handleSubmit() async { if (_rating == 0) { setState(() => _error = 'Please select a rating'); return; } setState(() { _state = _FormState.loading; _error = null; }); try { await widget.onSubmit(_rating, _commentController.text); if (mounted) { setState(() => _state = _FormState.success); _checkController.forward(from: 0); Future.delayed(const Duration(seconds: 3), () { if (mounted) setState(() => _state = _FormState.idle); }); } } catch (e) { if (mounted) setState(() { _state = _FormState.idle; _error = userFriendlyError(e); }); } } @override void dispose() { _commentController.dispose(); _checkController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { if (!_isLoggedIn) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFFF8FAFC), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0xFFE2E8F0)), ), child: Row( children: [ const Icon(Icons.login, color: Color(0xFF64748B), size: 20), const SizedBox(width: 8), const Expanded( child: Text('Log in to write a review', style: TextStyle(color: Color(0xFF64748B), fontSize: 14)), ), ], ), ); } return AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: _state == _FormState.success ? Container( key: const ValueKey('success'), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: const Color(0xFFF0FDF4), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0xFF86EFAC)), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ScaleTransition( scale: _checkScale, child: const Icon(Icons.check_circle, color: Color(0xFF10B981), size: 24), ), const SizedBox(width: 8), const Text('Review submitted!', style: TextStyle(color: Color(0xFF10B981), fontWeight: FontWeight.w600, fontSize: 15)), ], ), ) : Container( key: const ValueKey('form'), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow(color: Colors.black.withValues(alpha: 0.05), blurRadius: 8, offset: const Offset(0, 2)), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.existingReview != null ? 'Update your review' : 'Write a review', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1E293B)), ), const SizedBox(height: 12), Center(child: StarRatingInput(rating: _rating, onRatingChanged: (r) => setState(() { _rating = r; _error = null; }))), const SizedBox(height: 12), TextField( controller: _commentController, maxLength: 500, maxLines: 3, decoration: InputDecoration( hintText: 'Share your experience (optional)', hintStyle: const TextStyle(color: Color(0xFF94A3B8), fontSize: 14), filled: true, fillColor: const Color(0xFFF8FAFC), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFFE2E8F0))), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFFE2E8F0))), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF0F45CF), width: 1.5)), counterStyle: const TextStyle(color: Color(0xFF94A3B8), fontSize: 11), ), ), if (_error != null) ...[ const SizedBox(height: 4), Text(_error!, style: const TextStyle(color: Color(0xFFEF4444), fontSize: 12)), ], const SizedBox(height: 12), SizedBox( width: double.infinity, height: 46, child: ElevatedButton( onPressed: _state == _FormState.loading ? null : _handleSubmit, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0F45CF), foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), disabledBackgroundColor: const Color(0xFF0F45CF).withValues(alpha: 0.5), ), child: _state == _FormState.loading ? const SizedBox(width: 22, height: 22, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) : Text( widget.existingReview != null ? 'Update Review' : 'Submit Review', style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 15), ), ), ), ], ), ), ); } }