import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:image_picker/image_picker.dart'; import 'package:proxibuy/core/config/app_colors.dart'; import 'package:proxibuy/core/gen/assets.gen.dart'; import 'package:proxibuy/presentation/comment/bloc/comment_bloc.dart'; import 'package:proxibuy/presentation/comment/bloc/comment_event.dart'; import 'package:proxibuy/presentation/comment/bloc/comment_state.dart'; import 'package:proxibuy/presentation/pages/offers_page.dart'; import 'package:flutter_animate/flutter_animate.dart'; class CommentPage extends StatefulWidget { final String discountId; const CommentPage({super.key, required this.discountId}); @override State createState() => _CommentPageState(); } class _CommentPageState extends State { final _commentController = TextEditingController(); double _rating = 0.0; final List _images = []; final ImagePicker _picker = ImagePicker(); @override void dispose() { _commentController.dispose(); super.dispose(); } void _pickImage(ImageSource source) async { if (_images.length >= 2) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('شما فقط می‌توانید ۲ عکس اضافه کنید.')), ); return; } final pickedFile = await _picker.pickImage( source: source, imageQuality: 80, ); if (pickedFile != null) { setState(() { _images.add(File(pickedFile.path)); }); } } void _removeImage(int index) { setState(() { _images.removeAt(index); }); } void _showImageSourceActionSheet() { showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), ), builder: (context) { return SafeArea( child: Wrap( children: [ ListTile( leading: const Icon( Icons.photo_library, color: AppColors.primary, ), title: const Text('انتخاب از گالری'), onTap: () { Navigator.of(context).pop(); _pickImage(ImageSource.gallery); }, ), ListTile( leading: const Icon(Icons.camera_alt, color: AppColors.primary), title: const Text('گرفتن عکس با دوربین'), onTap: () { Navigator.of(context).pop(); _pickImage(ImageSource.camera); }, ), ], ), ); }, ); } @override Widget build(BuildContext context) { return BlocProvider( create: (context) => CommentBloc(), child: Scaffold( backgroundColor: Colors.grey[50], appBar: _buildCustomAppBar(), body: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(), const SizedBox(height: 24), Center(child: _buildRatingCard()), const SizedBox(height: 16), _buildCommentCard(), const SizedBox(height: 16), _buildImagePickerSection(), const SizedBox(height: 32), _buildActionButtons(), ] .animate(interval: 100.ms) .fadeIn(duration: 400.ms) .slideY(begin: 0.2, curve: Curves.easeOut), ), ), ), ); } PreferredSizeWidget _buildCustomAppBar() { return PreferredSize( preferredSize: const Size.fromHeight(70.0), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical( bottom: Radius.circular(15), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ const Text( 'ثبت نظر', style: TextStyle( color: Colors.black, fontWeight: FontWeight.normal, fontSize: 18, ), ), IconButton( icon: SvgPicture.asset(Assets.icons.arrowLeft.path), onPressed: () => Navigator.of(context).pop(), ), ], ), ), ), ), ); } Widget _buildHeader() { return Center( child: Column( children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( shape: BoxShape.circle, color: AppColors.confirm.withOpacity(0.1), ), child: Icon( Icons.check_circle_outline, color: AppColors.confirm, size: 50, ), ), const SizedBox(height: 16), const Text( 'خریدت با موفقیت انجام شد. منتظر دیدار دوباره‌ات هستیم. لطفا نظرت رو در مورد این تخفیف بهمون بگو.', style: TextStyle(fontSize: 16, color: Colors.black, height: 1.5), textAlign: TextAlign.center, ), ], ), ); } Widget _buildRatingCard() { return Card( elevation: 1, shadowColor: Colors.black12, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ const Text( "امتیاز شما چقدره؟", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), RatingBar.builder( initialRating: 0, minRating: 1, direction: Axis.horizontal, itemCount: 5, itemPadding: const EdgeInsets.symmetric(horizontal: 7.0), itemBuilder: (context, _) => Icon(Icons.star, color: Colors.amber.shade700), onRatingUpdate: (rating) => setState(() => _rating = rating), ), ], ), ), ); } Widget _buildCommentCard() { return Padding( padding: const EdgeInsets.all(8.0), child: TextField( controller: _commentController, maxLines: 4, textAlign: TextAlign.right, decoration: InputDecoration( labelText: "گوشمون به شماست", hintText: "نظراتت رو بگو...", alignLabelWithHint: true, suffixIcon: Padding(padding: const EdgeInsets.all(12.0)), ), ), ); } Widget _buildImagePickerSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "افزودن عکس (اختیاری)", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), const Text( "می‌تونی عکس تجربه خریدت رو باهامون به اشتراک بذاری!", style: TextStyle(fontSize: 14, color: AppColors.hint), ), const SizedBox(height: 16), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ ...List.generate(_images.length, (index) { return Padding( padding: const EdgeInsets.only(left: 8.0), child: Stack( clipBehavior: Clip.none, children: [ ClipRRect( borderRadius: BorderRadius.circular(12.0), child: Image.file( _images[index], width: 80, height: 80, fit: BoxFit.cover, ), ), Positioned( top: -8, right: -8, child: GestureDetector( onTap: () => _removeImage(index), child: Container( decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, border: Border.all(color: Colors.white, width: 2), ), child: const Icon( Icons.close, color: Colors.white, size: 16, ), ), ), ), ], ), ); }), if (_images.length < 2) GestureDetector( onTap: _showImageSourceActionSheet, child: Container( width: 80, height: 80, decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.grey.shade400, width: 1.5, style: BorderStyle.solid, ), ), child: const Icon( Icons.add_a_photo_outlined, color: Colors.grey, size: 30, ), ), ), ], ), ), ], ); } Widget _buildActionButtons() { return BlocConsumer( listener: (context, state) { if (state is CommentSubmissionSuccess) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('نظر شما با موفقیت ثبت شد. ممنونیم!'), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, ), ); Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const OffersPage()), (route) => false, ); } else if (state is CommentSubmissionFailure) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(state.error), backgroundColor: Colors.red, behavior: SnackBarBehavior.floating, ), ); } }, builder: (context, state) { final isLoading = state is CommentSubmitting; return Column( children: [ SizedBox( width: double.infinity, child: ElevatedButton( onPressed: isLoading ? null : () { context.read().add( SubmitComment( discountId: widget.discountId, text: _commentController.text, score: _rating, images: _images, ), ); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.confirm, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), ), child: isLoading ? const SizedBox( width: 24, height: 24, child: CircularProgressIndicator(color: Colors.white), ) : const Text('ارسال'), ), ), const SizedBox(height: 12), TextButton( onPressed: isLoading ? null : () { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const OffersPage()), (route) => false, ); }, child: const Text( 'رد شدن', style: TextStyle(color: Colors.black), ), ), ], ); }, ); } }