import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:real_estate_mobile/core/constants/api_constants.dart'; import 'package:real_estate_mobile/core/constants/app_colors.dart'; import 'package:real_estate_mobile/core/network/api_client.dart'; class ContactScreen extends StatefulWidget { const ContactScreen({super.key}); @override State createState() => _ContactScreenState(); } class _ContactScreenState extends State { final _nameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); final _messageController = TextEditingController(); bool _isSending = false; // CMS data with defaults String _contactEmail = '123support@gmail.com'; String _contactPhone = '1234567890'; String _contactPhoneHours = 'Mon-Fri 9am-6pm'; String _contactOfficeAddress = '123 Market Street'; String _contactOfficeCity = 'New York CA 234737'; String _pageTitle = 'Get In Touch'; String _pageDescription = 'Have a question about a property or need assistance? Fill out the form below and our team will get back to you shortly.'; String _directionsUrl = 'https://maps.google.com/?q=123+Market+Street+New+York+CA+234737'; @override void initState() { super.initState(); _loadContactCms(); } Future _loadContactCms() async { try { final dio = ApiClient.instance.dio; final response = await dio.get(ApiConstants.cmsPageContact); final data = response.data['data'] as List?; if (data == null) return; for (final section in data) { final sectionKey = section['sectionKey'] as String?; final content = section['content'] as Map?; if (sectionKey == 'contactDetails' && content != null) { setState(() { _contactEmail = content['email'] as String? ?? _contactEmail; _contactPhone = content['phone'] as String? ?? _contactPhone; _contactPhoneHours = content['phoneHours'] as String? ?? _contactPhoneHours; _contactOfficeAddress = content['officeAddress'] as String? ?? _contactOfficeAddress; _contactOfficeCity = content['officeCity'] as String? ?? _contactOfficeCity; _pageTitle = content['title'] as String? ?? _pageTitle; _pageDescription = content['description'] as String? ?? _pageDescription; _directionsUrl = content['directionsUrl'] as String? ?? _directionsUrl; }); } } } catch (_) { // Use defaults on error } } @override void dispose() { _nameController.dispose(); _emailController.dispose(); _phoneController.dispose(); _messageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ListView( padding: EdgeInsets.zero, children: [ // Back button Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), child: Align( alignment: Alignment.centerLeft, child: GestureDetector( onTap: () { if (Navigator.of(context).canPop()) { Navigator.of(context).pop(); } else { context.go('/home'); } }, child: Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.primaryDark.withValues(alpha: 0.08), shape: BoxShape.circle, ), child: const Icon( Icons.arrow_back_ios_new_rounded, color: AppColors.primaryDark, size: 18, ), ), ), ), ), const SizedBox(height: 10), _buildTitle(), const SizedBox(height: 10), _buildDescription(), const SizedBox(height: 40), _buildContactForm(), const SizedBox(height: 20), _buildContactDetails(), const SizedBox(height: 40), _buildFindAgentSection(), const SizedBox(height: 30), ], ); } // -- Title -- Widget _buildTitle() { return Center( child: Text( _pageTitle, style: const TextStyle( fontFamily: 'Fractul', fontSize: 25, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), ); } // -- Description -- Widget _buildDescription() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Text( _pageDescription, textAlign: TextAlign.center, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), ); } // -- Contact Form -- Widget _buildContactForm() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 23), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildLabel('Your Name'), const SizedBox(height: 8), _buildTextField( controller: _nameController, hintText: 'Brain Neeland', ), const SizedBox(height: 24), _buildLabel('Email Address'), const SizedBox(height: 8), _buildTextField( controller: _emailController, hintText: '123@gmail.com', keyboardType: TextInputType.emailAddress, svgIcon: 'assets/icons/email_orange_icon.svg', ), const SizedBox(height: 24), _buildLabel('Phone Number'), const SizedBox(height: 8), _buildTextField( controller: _phoneController, hintText: '12345678990', keyboardType: TextInputType.phone, svgIcon: 'assets/icons/phone_orange_icon.svg', ), const SizedBox(height: 24), _buildLabel('Message'), const SizedBox(height: 8), _buildMessageField(), const SizedBox(height: 30), _buildFormButtons(), ], ), ); } Widget _buildLabel(String text) { return Text( text, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.primaryDark, ), ); } Widget _buildTextField({ required TextEditingController controller, required String hintText, TextInputType? keyboardType, String? svgIcon, }) { final borderSide = BorderSide( color: AppColors.primaryDark.withValues(alpha: 0.1), width: 1, ); final border = OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: borderSide, ); return SizedBox( height: 52, child: TextField( controller: controller, keyboardType: keyboardType, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black, ), decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric( horizontal: 20, vertical: 14, ), hintText: hintText, hintStyle: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black.withValues(alpha: 0.4), ), border: border, enabledBorder: border, focusedBorder: border, disabledBorder: border, prefixIcon: svgIcon != null ? Padding( padding: const EdgeInsets.all(14), child: SvgPicture.asset( svgIcon, width: 22, height: 22, ), ) : null, prefixIconConstraints: svgIcon != null ? const BoxConstraints(minWidth: 48) : null, ), ), ); } Widget _buildMessageField() { final borderSide = BorderSide( color: AppColors.primaryDark.withValues(alpha: 0.1), width: 1, ); final border = OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: borderSide, ); return SizedBox( height: 183, child: TextField( controller: _messageController, maxLines: null, expands: true, textAlignVertical: TextAlignVertical.top, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black, ), decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric( horizontal: 20, vertical: 16, ), hintText: 'Write your message here...', hintStyle: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w200, color: Colors.black.withValues(alpha: 0.4), ), border: border, enabledBorder: border, focusedBorder: border, disabledBorder: border, ), ), ); } Widget _buildFormButtons() { return Row( children: [ Expanded( child: GestureDetector( onTap: () { _nameController.clear(); _emailController.clear(); _phoneController.clear(); _messageController.clear(); }, child: Container( height: 46, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), border: Border.all( color: AppColors.primaryDark.withValues(alpha: 0.1), width: 1, ), ), alignment: Alignment.center, child: const Text( 'Cancel', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), ), ), ), const SizedBox(width: 23), Expanded( child: GestureDetector( onTap: _isSending ? null : _sendMessage, child: Container( height: 46, decoration: BoxDecoration( color: AppColors.accentOrange, borderRadius: BorderRadius.circular(15), ), alignment: Alignment.center, child: _isSending ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: AppColors.primaryDark, ), ) : const Text( 'Send Message', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), ), ), ), ], ); } // -- Contact Details Section -- Widget _buildContactDetails() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), border: Border.all( color: AppColors.primaryDark.withValues(alpha: 0.1), width: 1, ), ), child: Column( children: [ const SizedBox(height: 17), // Title const Text( 'Contact Details', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.primaryDark, ), ), const SizedBox(height: 12), _buildDetailDivider(), // Email Support _buildContactDetailRow( svgIcon: 'assets/icons/email_orange_icon.svg', label: 'Email Support', value: _contactEmail, ), _buildDetailDivider(), // Phone _buildContactDetailRow( svgIcon: 'assets/icons/phone_orange_icon.svg', label: 'Phone', value: _contactPhone, subtitle: _contactPhoneHours, ), _buildDetailDivider(), // Office _buildContactDetailRow( svgIcon: 'assets/icons/location_orange_icon.svg', label: 'Office', value: '$_contactOfficeAddress\n$_contactOfficeCity', ), const SizedBox(height: 16), // Map image Padding( padding: const EdgeInsets.symmetric(horizontal: 36), child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset( 'assets/images/contact_map.jpg', height: 166, width: double.infinity, fit: BoxFit.cover, ), ), ), const SizedBox(height: 16), // Get Directions button GestureDetector( onTap: () async { final uri = Uri.parse(_directionsUrl); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } }, child: Container( width: 139, height: 35, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), border: Border.all( color: AppColors.accentOrange, width: 1, ), ), alignment: Alignment.center, child: const Text( 'Get Directions', style: TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.accentOrange, ), ), ), ), const SizedBox(height: 20), ], ), ), ); } Widget _buildDetailDivider() { return Divider( color: AppColors.primaryDark.withValues(alpha: 0.1), height: 1, thickness: 1, indent: 1, endIndent: 1, ); } Widget _buildContactDetailRow({ required String svgIcon, required String label, required String value, String? subtitle, }) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SvgPicture.asset( svgIcon, width: 20, height: 20, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.primaryDark, ), ), const SizedBox(height: 4), Text( value, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), if (subtitle != null) ...[ const SizedBox(height: 4), Text( subtitle, style: const TextStyle( fontFamily: 'SourceSerif4', fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), ], ], ), ), ], ), ); } // -- Find Agent Section -- Widget _buildFindAgentSection() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: Column( children: [ const Text( 'Ready to find an agent?', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Fractul', fontSize: 25, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), const SizedBox(height: 16), const Text( 'Discover trusted agents and start your property journey with confidence.', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'SourceSerif4', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), const SizedBox(height: 24), // Agent illustration ClipOval( child: Image.asset( 'assets/images/agent_illustration.png', width: 254, height: 254, fit: BoxFit.cover, ), ), const SizedBox(height: 24), // Start Your Search button GestureDetector( onTap: () => context.push('/agents/search'), child: Container( height: 46, width: 220, decoration: BoxDecoration( color: AppColors.accentOrange, borderRadius: BorderRadius.circular(15), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Start Your Search', style: TextStyle( fontFamily: 'Fractul', fontSize: 16, fontWeight: FontWeight.w700, color: AppColors.primaryDark, ), ), const SizedBox(width: 8), const Icon( Icons.arrow_forward_rounded, size: 16, color: AppColors.primaryDark, ), ], ), ), ), ], ), ); } // -- Send Message -- Future _sendMessage() async { final name = _nameController.text.trim(); final email = _emailController.text.trim(); final phone = _phoneController.text.trim(); final message = _messageController.text.trim(); if (name.isEmpty || email.isEmpty || message.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Please fill in all required fields'), backgroundColor: Colors.red, ), ); return; } setState(() => _isSending = true); try { final dio = ApiClient.instance.dio; await dio.post('/contact', data: { 'name': name, 'email': email, if (phone.isNotEmpty) 'phone': phone, 'message': message, }); if (!mounted) return; setState(() => _isSending = false); _nameController.clear(); _emailController.clear(); _phoneController.clear(); _messageController.clear(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Message sent successfully!'), backgroundColor: Color(0xFF638559), ), ); } catch (e) { if (!mounted) return; setState(() => _isSending = false); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Failed to send message. Please try again.'), backgroundColor: Colors.red, ), ); } } }