Files
mobile-app/lib/features/contact/presentation/screens/contact_screen.dart

579 lines
17 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:real_estate_mobile/core/constants/app_colors.dart';
class ContactScreen extends StatefulWidget {
const ContactScreen({super.key});
@override
State<ContactScreen> createState() => _ContactScreenState();
}
class _ContactScreenState extends State<ContactScreen> {
final _nameController = TextEditingController();
final _emailController = TextEditingController();
final _phoneController = TextEditingController();
final _messageController = TextEditingController();
bool _isSending = false;
@override
void dispose() {
_nameController.dispose();
_emailController.dispose();
_phoneController.dispose();
_messageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView(
padding: EdgeInsets.zero,
children: [
const SizedBox(height: 18),
_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 const Center(
child: Text(
'Get In Touch',
style: TextStyle(
fontFamily: 'Fractul',
fontSize: 25,
fontWeight: FontWeight.w700,
color: AppColors.primaryDark,
),
),
);
}
// -- Description --
Widget _buildDescription() {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text(
'Have a question about a property or need assistance? Fill out the form below and our team will get back to you shortly.',
textAlign: TextAlign.center,
style: 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: () => context.pop(),
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: '123support@gmail.com',
),
_buildDetailDivider(),
// Phone
_buildContactDetailRow(
svgIcon: 'assets/icons/phone_orange_icon.svg',
label: 'Phone',
value: '1234567890',
subtitle: 'Mon-Fri 9am-6pm',
),
_buildDetailDivider(),
// Office
_buildContactDetailRow(
svgIcon: 'assets/icons/location_orange_icon.svg',
label: 'Office',
value: '123 Market Street\nNew York CA 234737',
),
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: () {},
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 --
void _sendMessage() {
final name = _nameController.text.trim();
final email = _emailController.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);
// Simulate sending — replace with actual API call
Future.delayed(const Duration(seconds: 2), () {
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),
),
);
});
}
}