second commit

This commit is contained in:
Anbarasu
2026-05-27 10:35:09 +05:30
parent c53794c04c
commit 1435ac47b0
501 changed files with 52818 additions and 0 deletions

View File

@@ -0,0 +1,446 @@
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<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
@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<CreateUserController>(
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<TextInputFormatter>? 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);
},
);
},
),
),
),
],
),
),
);
}
}