import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../Controller/Authentication/Createtenantusercontroller.dart'; import '../../../Globalwidgets/textwidget.dart'; import '../../../Helper/Constants/AssetConstants.dart'; import '../../../Helper/Constants/Colorconstants.dart'; import '../../../Helper/Logger.dart'; import '../../../Helper/custombutton.dart'; import '../../../Helper/customederaction.dart'; import 'package:flutter/services.dart'; import '../Logiview.dart'; class CreateUserView extends StatelessWidget { final String? phNumber; CreateUserView({super.key, this.phNumber}); final CreateUserController controller = Get.put(CreateUserController()); final ScrollController listScrollController = ScrollController(); final GlobalKey scaffoldKey = GlobalKey(); @override Widget build(BuildContext context) { return SafeArea( top: false, child: Scaffold( key: scaffoldKey, appBar: AppBar( automaticallyImplyLeading: true, leading: InkWell( onTap: () { Get.to(() => LoginView()); }, child: Icon( Icons.arrow_back, color: ColorConstants.blackColor, ), ), title: TextWidget( text: 'Create Account', fontSize: 20, fontWeight: FontWeight.w700, ), ), backgroundColor: Colors.white, body: GetBuilder( initState: (_) { controller.contactNoController.text = phNumber ?? ''; logger.i('Phone Number: ${controller.contactNoController.text}'); controller.getAppLocations(); controller.getCurrentLocation(); controller.getAppCategory(); logger.i('Cat Name Is empty : ${controller.catName}'); }, builder: (controller) => Column( children: [ // _buildHeader(), // const SizedBox(height: 10,), Expanded( child: ListView( controller: listScrollController, padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), children: [ SizedBox(height: 10,), Center( child: Stack( children: [ InkWell( onTap: () { controller.getProfileImage(); }, child: Container( width: 100, // Set the size to match the CircleAvatar's diameter height: 100, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: ColorConstants.primaryColor, // Border color width: 2.0, // Border width ), ), child: CircleAvatar( radius: 30, backgroundColor: ColorConstants.secondaryColor, child: ClipOval( child: controller.profileImage == null ? Image.asset( AssetConstants.noProfile, width: 70, height: 70, color: ColorConstants.primaryColor, ) : Image.file( width: 100, height: 100, File(controller.profileImage?.path ?? ''), fit: BoxFit.cover, ), ), ), ), ), const Positioned( bottom: 0, right: 0, child: CircleAvatar( radius: 15, backgroundColor: ColorConstants.primaryColor, child: Icon( Icons.camera_alt_outlined, color: Colors.white, ), ), ), ], ), ), const SizedBox( height: 8, ), Center( child: TextWidget( text: 'Upload Company Logo', )), const SizedBox(height: 30,), _buildTextField( controller: controller.firstnameController, label: 'Contact Name', icon: Icons.person, formatters: [UpperCaseTextFormatter()], ), const SizedBox(height: 20), _buildTextField( controller: controller.companyNameController, label: 'Company Name', icon: Icons.business, formatters: [UpperCaseTextFormatter()], ), const SizedBox(height: 20), _buildTextField( controller: controller.emailController, label: 'Email', icon: Icons.email_outlined, validator: _validateEmail, ), const SizedBox(height: 20), _buildSelectionField( context: context, label: controller.selectedCategoryName.isEmpty ? 'Select Category' : controller.selectedCategoryName, icon: Icons.category, onTap: () async { var result = await SubCategoryService().fetchSubCategories(); if (result != null && result.details != null) { final categories = result.details! .map((e) => e.catgeoryname ?? '') .toSet() .toList(); if (context.mounted) { showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) { return ListView.builder( itemCount: categories.length, itemBuilder: (context, index) { final categoryName = categories[index]; return ListTile( title: Text(categoryName), trailing: controller.selectedCategoryName == categoryName ? Icon(Icons.check, color: ColorConstants.primaryColor) : null, onTap: () { // Update controller controller.selectedCategoryName = categoryName; controller.update(); // Trigger UI rebuild Navigator.pop(context); }, ); }, ); }, ); } } }, ), const SizedBox(height: 20), _buildTextField( controller: controller.gstinNumberController, label: 'GSTIN', icon: Icons.verified_user, ), const SizedBox(height: 20), _buildAddressSection(context, controller), const SizedBox(height: 20), if (controller.isEnterAddress) ...[ _buildTextField(controller: controller.suburbController, label: 'Suburb', icon: Icons.location_on), const SizedBox(height: 15), _buildTextField(controller: controller.cityController, label: 'City', icon: Icons.location_on), const SizedBox(height: 15), _buildTextField(controller: controller.stateController, label: 'State', icon: Icons.location_on), const SizedBox(height: 15), ], _buildTextField(controller: controller.postcodeController, label: 'Pincode', icon: Icons.location_on), ], ), ), ], ), ), bottomNavigationBar: _buildBottomBar(controller), ), ); } Widget _buildTextField({ required TextEditingController controller, required String label, required IconData icon, List? formatters, String? Function(String?)? validator, }) { return Container( height: Get.height * 0.07, decoration: BoxDecoration(color: ColorConstants.secondaryColor), child: TextFormField( controller: controller, textCapitalization: TextCapitalization.sentences, inputFormatters: formatters, validator: validator, onFieldSubmitted: (_) { FocusManager.instance.primaryFocus?.unfocus(); // Removes focus and hides keyboard }, style: const TextStyle(fontFamily: 'Inter'), decoration: CustomDecoration.textFieldStyle(labelTextStr: label, prefixIcon: Icon(icon, color: ColorConstants.darkGreyColor)), onEditingComplete: () => FocusScope.of(Get.context!).requestFocus(FocusNode()), ), ); } Widget _buildSelectionField({ required BuildContext context, required String label, required IconData icon, required VoidCallback onTap, }) { return InkWell( onTap: onTap, child: Container( height: 60, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey[200]!, width: 2), ), child: Padding( padding: const EdgeInsets.only(left: 10), child: Row( children: [ Icon(icon, color: ColorConstants.darkGreyColor), const SizedBox(width: 10), Expanded(child: Text(label, style: TextStyle(fontSize: 17, color: Colors.grey[500]))), Icon(Icons.arrow_drop_down, color: Colors.grey[600], size: 20), ], ), ), ), ); } Widget _buildAddressSection(BuildContext context, CreateUserController controller) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.location_on, color: ColorConstants.darkGreyColor, size: 23), const SizedBox(width: 5), const Text('Address', style: TextStyle(color: Colors.black54, fontSize: 16)), const Spacer(), InkWell( onTap: () { // Toggle the isEnterAddress state if needed for other UI logic controller.isEnterAddress = !controller.isEnterAddress; controller.update(); }, child: Icon( controller.isEnterAddress ? Icons.check : Icons.keyboard_arrow_down_sharp, color: Colors.grey[600], size: 23, ), ), ], ), const SizedBox(height: 5), TextFormField( controller: controller.addressController, maxLines: 3, cursorColor: ColorConstants.textFieldColor, style: TextStyle(color: ColorConstants.textFieldColor), decoration: CustomDecoration.textFieldStyle(), readOnly: true, // Make it read-only to prevent direct editing onTap: () async { // Navigate to the address search screen and wait for the result final selectedAddress = await Get.to(() => AddressSearchScreen(controller: controller)); if (selectedAddress != null) { controller.addressController.text = selectedAddress['description']; controller.getPlaceDetails(selectedAddress['place_id'], selectedAddress['description']); controller.update(); } }, ), ], ); } Widget _buildBottomBar(CreateUserController controller) { return Container( height: Get.height * 0.1, child: RoundedButton( height: Get.height * 0.06, width: Get.width * 0.9, onPressed: controller.doSomething, color: ColorConstants.primaryColor, title: 'Create', controller: controller.btnController, textStyle: const TextStyle(fontSize: 18, fontFamily: 'Inter', color: Colors.white, fontWeight: FontWeight.bold), ), ); } String? _validateEmail(String? value) { const simplePattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'; final regex = RegExp(simplePattern); return value!.isNotEmpty && !regex.hasMatch(value) ? 'Enter a valid email address' : null; } } class UpperCaseTextFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { return TextEditingValue(text: capitalize(newValue.text), selection: newValue.selection); } } String capitalize(String value) { if (value.trim().isEmpty) return ''; return '${value[0].toUpperCase()}${value.substring(1)}'; } class AddressSearchScreen extends StatelessWidget { final CreateUserController controller; const AddressSearchScreen({Key? key, required this.controller}) : super(key: key); @override Widget build(BuildContext context) { // Initialize a new TextEditingController with the initial address final searchController = TextEditingController(text: controller.addressController.text); return Scaffold( appBar: AppBar( title: TextWidget( text: 'Search Address', fontWeight: FontWeight.bold, fontSize: 20, ), leading: IconButton( icon: Icon(Icons.arrow_back, color: ColorConstants.blackColor), onPressed: () => Get.back(), // Return without selecting an address ), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextFormField( controller: searchController, autofocus: true, cursorColor: ColorConstants.textFieldColor, style: TextStyle(color: ColorConstants.textFieldColor), decoration: CustomDecoration.textFieldStyle().copyWith( hintText: 'Enter address', suffixIcon: IconButton( icon: Icon(Icons.cancel, color: ColorConstants.blackColor), onPressed: () { searchController.clear(); // Clear the search field controller.predictions.clear(); // Clear predictions controller.update(); // Notify UI to update }, ), ), onChanged: (text) { if (text.isEmpty) { controller.predictions.clear(); controller.update(); } controller.onSearchTextChanged(text); }, ), const SizedBox(height: 8), Expanded( child: Obx( () => controller.predictions.isEmpty ? const Center(child: Text('No results found')) : ListView.builder( itemCount: controller.predictions.length, itemBuilder: (context, index) { final prediction = controller.predictions[index]['description']; return ListTile( title: Text(prediction), onTap: () { final selectedAddress = controller.predictions[index]; controller.addressController.text = selectedAddress['description']; controller.getPlaceDetails(selectedAddress['place_id'], selectedAddress['description']); Get.back(result: selectedAddress); }, ); }, ), ), ), ], ), ), ); } }