import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import '../../Notifier/HelpAndEnquiryProvider.dart'; import '../../Utility/AppColors.dart'; import '../../Utility/Reusablewidgets.dart'; import 'package:image_picker/image_picker.dart'; class TicketChatScreen extends StatefulWidget { final String sessionId; final String accId; final String ticketId; final String status; const TicketChatScreen({ super.key, required this.sessionId, required this.accId, required this.ticketId, required this.status, }); @override State createState() => _TicketChatScreenState(); } class _TicketChatScreenState extends State { final TextEditingController _messageController = TextEditingController(); List _selectedImages = []; List _selectedImagesFiles = []; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final provider = Provider.of(context, listen: false); provider.fetchTicketChatDisplay( sessionId: widget.sessionId, accId: widget.accId, ticketId: widget.ticketId, ); }); } @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { final chatData = provider.chatResponse; final isLoading = provider.isLoading; final status = widget.status.toLowerCase() == "in process"; 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: 25, ), ), const SizedBox(width: 10), const Text( "Help?", style: TextStyle( fontSize: 16, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w600, color: Colors.black87, ), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: status ? Colors.green.shade50 : Colors.red.shade50, borderRadius: BorderRadius.circular(16), ), child: Text( widget.status, style: TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w500, color: status ? Colors.green : Colors.red, ), ), ), ], ), ), body: isLoading ? const Center(child: CircularProgressIndicator()) : (chatData?.feedBacks == null || chatData!.feedBacks!.isEmpty) ? const Center(child: Text("No messages yet")) : Column( children: [ Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: chatData.feedBacks!.map((msg) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: _chatBubble( name: msg.userName ?? "Unknown", imageName: msg.imgNames ?? [], images: msg.images ?? [], date: msg.createdDatetime ?? "", message: msg.text ?? "", userIcon: msg.userImg ?? "", isUser: msg.user?.toLowerCase() == "user", ), ); }).toList(), ), ), ), Container( width: double.infinity, padding: const EdgeInsets.all(16), color: Colors.white, child: ElevatedButton( onPressed: () => _openMessageSheet(ticketId: chatData.ticketId.toString()), style: ElevatedButton.styleFrom( backgroundColor: AppColors.buttonColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), elevation: 0, ), child: const Text( "Send a Message", style: TextStyle( fontSize: 16, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w600, ), ), ), ), ], ), ), ); }, ); } /// Chat bubble widget Widget _chatBubble({ required String name, required List imageName, required List images, required String date, required String message, required String userIcon, required bool isUser, }) { debugPrint(" Images ${images.length}"); return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Profile Icon Container( height: 42, width: 42, decoration: const BoxDecoration( color: Color(0xFFE6F6FF), shape: BoxShape.circle, ), clipBehavior: Clip.antiAlias, child: (userIcon.isNotEmpty) ? Image.network( userIcon, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return const Icon(Icons.person, color: Color(0xFF2d2d2d)); }, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const Center( child: CircularProgressIndicator(strokeWidth: 2)); }, ) : CircleAvatar( radius: 26, backgroundColor: Colors.blue.shade100, child: SvgPicture.asset( "assets/svg/person_ic.svg", height: 23, width: 23, ), ), ), const SizedBox(width: 10), // Message Content Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, style: const TextStyle( fontSize: 14, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w600, color: Colors.black, ), ), const SizedBox(height: 2), Text( date, style: TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w400, color: Colors.grey[600], ), ), const SizedBox(height: 6), Text( message, style: const TextStyle( fontSize: 13, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w400, color: Colors.black87, height: 1.5, ), ), const SizedBox(height: 8), // 🔹 Image container section if (images.isNotEmpty) Container( margin: const EdgeInsets.only(top: 4, bottom: 8), child: Wrap( spacing: 8, runSpacing: 8, children: List.generate(images.length, (index) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(12), child: Image.network( images[index], width: 100, height: 80, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( width: 100, height: 80, color: Colors.grey.shade200, child: const Icon(Icons.broken_image, color: Colors.grey), ); }, ), ), if (imageName.length > index) Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( imageName[index], style: const TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w500, color: Colors.black54, ), ), ), ], ); }), ), ), // Divider line Container( height: 1, width: double.infinity, color: Colors.grey.shade300, ), ], ), ), ], ), ); } /// Bottom Sheet for sending message void _openMessageSheet({required String ticketId}) { final ImagePicker _picker = ImagePicker(); showModalBottomSheet( isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), context: context, builder: (context) { return Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, top: 16, left: 16, right: 16, ), child: StatefulBuilder( builder: (context, setSheetState) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(4), ), ), ), const SizedBox(height: 12), const Center( child: Text( "Send a Message", style: TextStyle( fontSize: 16, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w600, color: Colors.black, ), ), ), const SizedBox(height: 16), Text( "Message", style: TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w500, color: Colors.grey[700], ), ), const SizedBox(height: 6), Container( decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(12), ), child: TextFormField( controller: _messageController, maxLines: 5, decoration: InputDecoration( hintText: "Write your message", hintStyle: TextStyle( fontSize: 14, color: Colors.grey[400], fontFamily: "Plus Jakarta Sans", ), border: InputBorder.none, contentPadding: const EdgeInsets.all(12), ), ), ), const SizedBox(height: 16), Text( "Attach Screenshot (optional)", style: TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w500, color: Colors.grey[700], ), ), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 8, children: [ // Add Image Button with multiple options PopupMenuButton( onSelected: (source) async { if (source == 'camera') { final XFile? image = await _picker.pickImage( source: ImageSource.camera, imageQuality: 80, maxWidth: 1024, maxHeight: 1024, ); if (image != null) { setSheetState(() { _selectedImages.add(image.path); _selectedImagesFiles.add(File(image.path)); }); } } else if (source == 'gallery') { final List? images = await _picker.pickMultiImage( imageQuality: 80, maxWidth: 1024, maxHeight: 1024, ); if (images != null && images.isNotEmpty) { setSheetState(() { for (var image in images) { _selectedImages.add(image.path); _selectedImagesFiles.add(File(image.path)); } }); } } }, itemBuilder: (BuildContext context) => [ const PopupMenuItem( value: 'camera', child: Row( children: [ Icon(Icons.camera_alt, size: 20), SizedBox(width: 8), Text('Take Photo'), ], ), ), const PopupMenuItem( value: 'gallery', child: Row( children: [ Icon(Icons.photo_library, size: 20), SizedBox(width: 8), Text('Choose from Gallery'), ], ), ), ], child: Container( width: 60, height: 60, decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(8), border: Border.all( color: Colors.grey.shade300, width: 1, ), ), child: Icon( Icons.add, color: Colors.grey[600], ), ), ), // Selected Images ..._selectedImages.asMap().entries.map((entry) { final index = entry.key; final imagePath = entry.value; return Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( File(imagePath), width: 60, height: 60, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( width: 60, height: 60, color: Colors.grey.shade200, child: Icon( Icons.broken_image, color: Colors.grey[400], ), ); }, ), ), Positioned( top: 2, right: 2, child: GestureDetector( onTap: () { setSheetState(() { _selectedImages.removeAt(index); _selectedImagesFiles.removeAt(index); }); }, child: Container( padding: const EdgeInsets.all(2), decoration: const BoxDecoration( color: Colors.black54, shape: BoxShape.circle, ), child: const Icon( Icons.close, size: 14, color: Colors.white, ), ), ), ), ], ); }), ], ), // Show file names if needed if (_selectedImages.isNotEmpty) ...[ const SizedBox(height: 8), Text( '${_selectedImages.length} file(s) selected', style: TextStyle( fontSize: 12, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w400, color: Colors.grey[600], ), ), ], const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { if (_messageController.text.trim().isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Please enter a message'), duration: Duration(seconds: 2), ), ); return; } final provider = Provider.of(context, listen: false); provider.sendMessage( context, sessionId: widget.sessionId, accId: widget.accId, ticketId: ticketId, msgText: _messageController.text.trim(), images: _selectedImagesFiles, ); // Clear and close setState(() { _selectedImages.clear(); _selectedImagesFiles.clear(); }); _messageController.clear(); Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.buttonColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), elevation: 0, ), child: const Text( "Send Message", style: TextStyle( fontSize: 16, fontFamily: "Plus Jakarta Sans", fontWeight: FontWeight.w600, ), ), ), ), const SizedBox(height: 16), ], ); }, ), ); }, ); } @override void dispose() { _messageController.dispose(); super.dispose(); } }