import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:gen_rentals/Utility/CustomSnackbar.dart'; import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; import '../../Notifier/HelpAndEnquiryProvider.dart'; import '../../Utility/AppColors.dart'; import '../../Utility/Reusablewidgets.dart'; class HelpTicketScreen extends StatefulWidget { final String? reason; final String sessionId; final String accId; final String orderId; const HelpTicketScreen({ super.key, this.reason, required this.sessionId, required this.accId, required this.orderId }); @override State createState() => _HelpTicketScreenState(); } class _HelpTicketScreenState extends State { final TextEditingController _issueController = TextEditingController(); final TextEditingController _otherReasonController = TextEditingController(); final ImagePicker _picker = ImagePicker(); List _selectedImages = []; String _selectedReason = 'Payment Issues'; // Success dialog state bool _showSuccessDialog = false; final List> createNewTickets = [ { 'title': 'Payment \nIssues', 'description': 'Get help with payment related problems', 'icon': "assets/svg/rupee_coin_ic.svg", 'color': Color(0xFFFFEFBE), }, { 'title': 'Bill Related \nIssues', 'description': 'Resolve bill and invoice matters', 'icon': "assets/svg/know_pay.svg", 'color': Color(0xFFCEF9FF), }, { 'title': 'Other \nIssues', 'description': 'Any other support you need', 'icon': 'assets/svg/help_ic.svg', 'color': Color(0xFFE4E5FF), }, ]; // Responsive text size function double getResponsiveTextSize(BuildContext context, double baseSize) { final double scale = MediaQuery.of(context).textScaleFactor; final double width = MediaQuery.of(context).size.width; if (width < 360) { // Small phones return baseSize * 0.85; } else if (width < 400) { // Medium phones return baseSize; } else { // Large phones return baseSize * 1.1; } } // Responsive padding function double getResponsivePadding(BuildContext context) { final double width = MediaQuery.of(context).size.width; return width * 0.04; // 4% of screen width } // Responsive icon size function double getResponsiveIconSize(BuildContext context, double baseSize) { final double width = MediaQuery.of(context).size.width; if (width < 360) { return baseSize * 0.8; } else if (width < 400) { return baseSize; } else { return baseSize * 1.2; } } // Responsive button height function double getResponsiveButtonHeight(BuildContext context) { final double height = MediaQuery.of(context).size.height; return height * 0.06; // 6% of screen height } @override void initState() { super.initState(); if (widget.reason != null) { _selectedReason = widget.reason!; } } @override Widget build(BuildContext context) { final showOtherReasonField = _selectedReason == 'Other Issues'; final helpProvider = Provider.of(context); final screenWidth = MediaQuery.of(context).size.width; final screenHeight = MediaQuery.of(context).size.height; final isSmallScreen = screenWidth < 360; return SafeArea( top: false, child: Scaffold( backgroundColor: AppColors.backgroundRegular, appBar: AppBar( automaticallyImplyLeading: false, backgroundColor: Colors.white, elevation: 0, title: Row( children: [ InkResponse( onTap: () => Navigator.pop(context, true), child: SvgPicture.asset( "assets/svg/continue_left_ic.svg", height: getResponsiveIconSize(context, 25), ), ), SizedBox(width: getResponsivePadding(context) * 0.5), Text( "Help?", style: TextStyle( fontSize: getResponsiveTextSize(context, 16), fontFamily: "Poppins", fontWeight: FontWeight.w500, color: Colors.black87, ), ), ], ), ), body: Stack( children: [ SingleChildScrollView( padding: EdgeInsets.all(getResponsivePadding(context)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SectionHeading( title: 'Create New Ticket', textStyle: TextStyle( fontFamily: "Poppins", fontSize: getResponsiveTextSize(context, 16), fontWeight: FontWeight.w500 ), ), Container( padding: EdgeInsets.symmetric( horizontal: getResponsivePadding(context) * 1.12, vertical: getResponsiveButtonHeight(context) * 0.2, ), decoration: BoxDecoration( color: Color(0xFFE0F4FF), borderRadius: BorderRadius.circular(screenWidth * 0.025), ), child: Text( "Order #${widget.orderId}", style: TextStyle( fontSize: getResponsiveTextSize(context, 12), fontFamily: "Poppins", fontWeight: FontWeight.w400, color: Colors.black87, ), ), ), ], ), SizedBox(height: screenHeight * 0.015), _fieldLabel("Reason"), SizedBox(height: screenHeight * 0.008), GestureDetector( onTap: _showReasonBottomSheet, child: Container( width: screenWidth * 0.46, // 50% of screen width padding: EdgeInsets.symmetric( horizontal: getResponsivePadding(context), vertical: screenHeight * 0.010, ), decoration: BoxDecoration( color: const Color(0xffFFF3D1), borderRadius: BorderRadius.circular(screenWidth * 0.03), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( _selectedReason, style: TextStyle( fontSize: getResponsiveTextSize(context, 14), fontStyle: FontStyle.normal, fontFamily: "Poppins", fontWeight: FontWeight.w400, color: Colors.black87, ), overflow: TextOverflow.ellipsis, ), ), SizedBox(width: screenWidth * 0.008), SvgPicture.asset( "assets/svg/edit_ic.svg", height: getResponsiveIconSize(context, 19), ), ], ), ), ), SizedBox(height: screenHeight * 0.02), if (showOtherReasonField) ...[ _fieldLabel("Enter Reason"), SizedBox(height: screenHeight * 0.008), _textField( controller: _otherReasonController, hint: "Write your reason", ), SizedBox(height: screenHeight * 0.02), ], _fieldLabel("Tell us your issue?"), SizedBox(height: screenHeight * 0.008), _textField( controller: _issueController, hint: "Write your issue", maxLines: 5, ), SizedBox(height: screenHeight * 0.02), _fieldLabel("Add Screenshot (optional)"), SizedBox(height: screenHeight * 0.008), Container( width: double.infinity, padding: EdgeInsets.symmetric( horizontal: getResponsivePadding(context), vertical: screenHeight * 0.015, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(screenWidth * 0.03), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Add file button Container( width: getResponsiveIconSize(context, 60), height: getResponsiveIconSize(context, 60), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(screenWidth * 0.02), ), child: IconButton( onPressed: _pickImage, icon: Icon( Icons.add, size: getResponsiveIconSize(context, 24), color: Colors.grey[600], ), ), ), SizedBox(width: screenWidth * 0.02), // Attached images in horizontal scroll if (_selectedImages.isNotEmpty) Expanded( child: SizedBox( height: getResponsiveIconSize(context, 60), child: ListView.builder( scrollDirection: Axis.horizontal, shrinkWrap: true, itemCount: _selectedImages.length, itemBuilder: (context, index) { return Container( margin: EdgeInsets.only(right: screenWidth * 0.02), width: getResponsiveIconSize(context, 60), height: getResponsiveIconSize(context, 60), child: Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(screenWidth * 0.02), child: Image.file( _selectedImages[index], fit: BoxFit.cover, width: double.infinity, height: double.infinity, ), ), Positioned( top: screenHeight * 0.005, right: screenHeight * 0.005, child: GestureDetector( onTap: () => _removeImage(index), child: Container( padding: EdgeInsets.all(screenWidth * 0.01), decoration: const BoxDecoration( color: Colors.black54, shape: BoxShape.circle, ), child: Icon( Icons.close, size: getResponsiveIconSize(context, 14), color: Colors.white, ), ), ), ), ], ), ); }, ), ), ), ], ), SizedBox(height: screenHeight * 0.01), ], ), ), SizedBox(height: screenHeight * 0.03), ], ), ), // Success Dialog if (_showSuccessDialog) Container( color: Colors.black54, child: Center( child: Container( width: MediaQuery.of(context).size.width * 0.8, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( "Submitted", style: TextStyle( fontSize: 18, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Colors.black, ), ), const SizedBox(height: 16), Text( "Thanks for reaching out!", textAlign: TextAlign.center, style: TextStyle( fontSize: 12, fontFamily: "Poppins", fontWeight: FontWeight.w400, color: AppColors.subtitleText, ), ), const Text( "Our team will review your ticket and reply to you soon.", textAlign: TextAlign.center, style: TextStyle( fontSize: 14, fontFamily: "Poppins", fontWeight: FontWeight.w400, color: Colors.black87, ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { setState(() { _showSuccessDialog = false; }); Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.buttonColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), ), child: const Text( "Close", style: TextStyle( fontFamily: "Poppins", fontSize: 15, fontWeight: FontWeight.w400, ), ), ), ), ], ), ), ), ), ], ), bottomNavigationBar: Padding( padding: const EdgeInsets.all(15.0), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: helpProvider.isLoading ? null : _submitTicket, style: ElevatedButton.styleFrom( backgroundColor: AppColors.buttonColor, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: getResponsiveButtonHeight(context) * 0.32), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(screenWidth * 0.07), ), elevation: 0, ), child: helpProvider.isLoading ? SizedBox( height: getResponsiveIconSize(context, 22), width: getResponsiveIconSize(context, 22), child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2, ), ) : Text( 'Submit', style: TextStyle( fontFamily: "Poppins", fontSize: getResponsiveTextSize(context, 14), fontWeight: FontWeight.w500, ), ), ), ), ), ), ); } Widget _fieldLabel(String text) => Text( text, style: TextStyle( fontFamily: "Poppins", fontSize: getResponsiveTextSize(context, 14), fontStyle: FontStyle.normal, fontWeight: FontWeight.w400, color: Colors.black87, ), ); Widget _textField({ required TextEditingController controller, required String hint, int maxLines = 1, }) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(MediaQuery.of(context).size.width * 0.03), ), child: TextFormField( controller: controller, maxLines: maxLines, style: TextStyle( fontSize: getResponsiveTextSize(context, 14), fontWeight: FontWeight.w400, fontFamily: "Poppins", color: Colors.black87, ), decoration: InputDecoration( hintText: hint, hintStyle: TextStyle( fontFamily: "Poppins", fontSize: getResponsiveTextSize(context, 14), fontWeight: FontWeight.w400, color: Colors.grey[400], ), border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: getResponsivePadding(context), vertical: MediaQuery.of(context).size.height * 0.015, ), ), ), ); } Future _pickImage() async { final pickedFile = await _picker.pickImage(source: ImageSource.gallery, imageQuality: 70); if (pickedFile != null) { setState(() { _selectedImages.add(File(pickedFile.path)); }); } } void _removeImage(int index) { setState(() { _selectedImages.removeAt(index); }); } Future _submitTicket() async { final issue = _issueController.text.trim(); final otherReason = _otherReasonController.text.trim(); if (issue.isEmpty) { CustomSnackBar.showWarning( context: context, message: "Please describe your issue", ); return; } if (_selectedReason == 'Other Issues' && otherReason.isEmpty) { CustomSnackBar.showWarning( context: context, message: "Please enter your reason", ); return; } // Determine the reason type based on selected reason String reason; if (_selectedReason == "Payment Issues") { reason = "Payment"; } else if (_selectedReason == "Bill Related Issues") { reason = "Bill"; } else { reason = "Other"; } final customReason = _selectedReason == 'Other Issues' ? otherReason : null; final helpProvider = Provider.of(context, listen: false); // Show success dialog setState(() { _showSuccessDialog = true; }); // Clear form _issueController.clear(); _otherReasonController.clear(); setState(() { _selectedImages.clear(); }); // Wait for 2 seconds to show the success dialog await Future.delayed(Duration(seconds: 2)); if (!mounted) return; // Close the dialog setState(() { _showSuccessDialog = false; }); // Wait a brief moment for dialog to close, then call the API await Future.delayed(Duration(milliseconds: 300)); if (!mounted) return; // Now call the provider method which will handle navigation await helpProvider.createTicket( sessionId: widget.sessionId, accId: widget.accId, type: reason, description: issue, orderId: widget.orderId, otherReason: customReason?.toString() ?? "", images: _selectedImages, context: context, ); } void _showReasonBottomSheet() { final screenWidth = MediaQuery.of(context).size.width; final screenHeight = MediaQuery.of(context).size.height; final isSmallScreen = screenWidth < 360; showModalBottomSheet( context: context, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), ), ), builder: (context) { return SafeArea( child: Container( height: 250, padding: EdgeInsets.all(getResponsivePadding(context)), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Select Your Reason", style: TextStyle( fontSize: getResponsiveTextSize(context, 16), fontFamily: "Poppins", fontWeight: FontWeight.w500, color: Colors.black87, ), ), SizedBox(height: screenHeight * 0.02), GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: screenWidth * 0.03, mainAxisSpacing: screenWidth * 0.03, childAspectRatio: 0.85, ), itemCount: createNewTickets.length, itemBuilder: (context, index) { final ticket = createNewTickets[index]; return _buildReasonCard( title: ticket['title'], icon: ticket['icon'], color: ticket['color'], ); }, ), SizedBox(height: screenHeight * 0.03), ], ), ), ); }, ); } Widget _buildReasonCard({ required String title, required String icon, required Color color, }) { final screenWidth = MediaQuery.of(context).size.width; final isSmallScreen = screenWidth < 360; final iconSize = screenWidth * 0.20; // Same as _buildFeatureCard final imageSize = screenWidth * 0.09; // Same as _buildFeatureCard return GestureDetector( onTap: () { setState(() => _selectedReason = title); Navigator.pop(context); }, child: Container( padding: EdgeInsets.symmetric( horizontal: screenWidth * 0.005, vertical: screenWidth * 0.002 ), child: Column( mainAxisSize: MainAxisSize.min, // Same as _buildFeatureCard crossAxisAlignment: CrossAxisAlignment.center, children: [ // Icon container Container( width: iconSize, height: iconSize, decoration: BoxDecoration( color: color.withOpacity(0.7), // Same opacity as _buildFeatureCard borderRadius: BorderRadius.circular(screenWidth * 0.03), ), child: Center( child: SizedBox( height: imageSize, width: imageSize, child: SvgPicture.asset(icon, fit: BoxFit.fitWidth), ), ), ), SizedBox(height: screenWidth * 0.015), // Same spacing as _buildFeatureCard // Title Flexible( // Same as _buildFeatureCard child: Text( title, textAlign: TextAlign.center, style: TextStyle( color: AppColors.nearDarkText, fontSize: isSmallScreen ? 11 : 13, // Same font sizing logic fontStyle: FontStyle.normal, fontWeight: FontWeight.w400, fontFamily: "Poppins", ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), SizedBox(height: screenWidth * 0.005), // Same spacing as _buildFeatureCard ], ), ), ); } @override void dispose() { _issueController.dispose(); _otherReasonController.dispose(); super.dispose(); } }