From 1f288160213ccd9da6f59647b092e5799a04c453 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Sat, 5 Apr 2025 14:16:08 +0530 Subject: [PATCH] policy ui changes --- lib/Screens/itnerary_list/bus_list.dart | 94 +- lib/Screens/itnerary_list/forex_list.dart | 72 +- lib/Screens/policy/policy.dart | 173 +- lib/Screens/policy/policyCriteria.dart | 82 +- .../create_user/create_user.dart | 3764 +++++++++-------- lib/Screens/userManagement/user_List.dart | 677 +-- 6 files changed, 2630 insertions(+), 2232 deletions(-) diff --git a/lib/Screens/itnerary_list/bus_list.dart b/lib/Screens/itnerary_list/bus_list.dart index 58f16f6..7fa6ed6 100644 --- a/lib/Screens/itnerary_list/bus_list.dart +++ b/lib/Screens/itnerary_list/bus_list.dart @@ -7,74 +7,72 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../../config/apiUrl.dart'; import '../../data/models/plan.dart'; - -class BusListWidget extends StatelessWidget{ +class BusListWidget extends StatelessWidget { final List> busList; final Function(bool, Map, String) onOpen; - final Function(Map) onDeleteBus; - const BusListWidget({super.key, required this.busList, required this.onOpen, required this.onDeleteBus}); - + final Function(Map) onDeleteBus; + const BusListWidget( + {super.key, + required this.busList, + required this.onOpen, + required this.onDeleteBus}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Bus Booking List", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - Container( - // color: Colors.blueGrey, - width: double.infinity, - child: Center( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Expanded( - child: SizedBox( - width: MediaQuery.of(context).size.width , - child: DataTable( - border: TableBorder( - bottom: BorderSide(color: Colors.black12), - horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines - ), - columns: const [ + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Bus Booking List", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + Container( + // color: Colors.blueGrey, + width: double.infinity, + child: Center( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + // child: Expanded( - // DataColumn(label: Text('#')), - DataColumn(label: Text('From')), - DataColumn(label: Text('To')), - DataColumn(label: Text('Date')), - DataColumn(label: Text('Time')), - - DataColumn(label: Text('Actions')), - ], - rows: _buildDataRows(), - ), + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: DataTable( + border: TableBorder( + bottom: BorderSide(color: Colors.black12), + horizontalInside: BorderSide( + color: Colors.black12), // Only horizontal lines ), + columns: const [ + // DataColumn(label: Text('#')), + DataColumn(label: Text('From')), + DataColumn(label: Text('To')), + DataColumn(label: Text('Date')), + DataColumn(label: Text('Time')), + + DataColumn(label: Text('Actions')), + ], + rows: _buildDataRows(), ), ), + + // ) ), ), - - - ], - ), + ), + ], + ), ); } List _buildDataRows() { - - List> filteredList = busList - .where((item) => item["is_active"] == "1") - .toList(); + List> filteredList = + busList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - return filteredList.asMap().entries.map((entry) { - final Map item = entry.value; return DataRow(cells: [ diff --git a/lib/Screens/itnerary_list/forex_list.dart b/lib/Screens/itnerary_list/forex_list.dart index 59b400b..5c908fb 100644 --- a/lib/Screens/itnerary_list/forex_list.dart +++ b/lib/Screens/itnerary_list/forex_list.dart @@ -2,15 +2,18 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; - -class ForexListWidget extends StatelessWidget{ - final List> forexList; - final Function(bool, Map, String)onOpen; - final Function(Map) onDeleteForex; +class ForexListWidget extends StatelessWidget { + final List> forexList; + final Function(bool, Map, String) onOpen; + final Function(Map) onDeleteForex; final List? apiCountryData; - const ForexListWidget({super.key, required this.forexList, required this.onOpen, - required this.onDeleteForex,required this.apiCountryData}); + const ForexListWidget( + {super.key, + required this.forexList, + required this.onOpen, + required this.onDeleteForex, + required this.apiCountryData}); @override Widget build(BuildContext context) { @@ -30,66 +33,61 @@ class ForexListWidget extends StatelessWidget{ child: Center( child: SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Expanded( - child: SizedBox( - width: MediaQuery.of(context).size.width , - child: DataTable( - border: TableBorder( - bottom: BorderSide(color: Colors.black12), - horizontalInside: BorderSide(color: Colors.black12), // Only horizontal lines - ), - columns: const [ - // DataColumn(label: Text('#')), - DataColumn(label: Text('Forex Start Date')), - DataColumn(label: Text('Forex End Date')), - DataColumn(label: Text('Country')), - DataColumn(label: Text('Perdiem Amount')), - DataColumn(label: Text('Actions')), - ], - rows: _buildDataRows(), + + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: DataTable( + border: TableBorder( + bottom: BorderSide(color: Colors.black12), + horizontalInside: BorderSide( + color: Colors.black12), // Only horizontal lines ), + columns: const [ + // DataColumn(label: Text('#')), + DataColumn(label: Text('Forex Start Date')), + DataColumn(label: Text('Forex End Date')), + DataColumn(label: Text('Country')), + DataColumn(label: Text('Perdiem Amount')), + DataColumn(label: Text('Actions')), + ], + rows: _buildDataRows(), ), ), + // ), ), ), - - ], ), ); } List _buildDataRows() { - List countryList = apiCountryData ?? []; + List countryList = apiCountryData ?? []; - List> filteredList = forexList - .where((item) => item["is_active"] == "1") - .toList(); + List> filteredList = + forexList.where((item) => item["is_active"] == "1").toList(); print("filteredList- $filteredList"); - String getRequestForCountry(String? countryCode) { if (countryCode == null) return "N/A"; return countryList .firstWhere( (element) => element["country_code"].toString() == countryCode, - orElse: () => {"country_name": "N/A"}, - )["country_name"] + orElse: () => {"country_name": "N/A"}, + )["country_name"] .toString(); } - return filteredList.asMap().entries.map((entry) { - - Map item = entry.value; + Map item = entry.value; return DataRow(cells: [ // DataCell(Text(item["indx"]?.toString() ?? "N/A")), // Index column DataCell(Text(item["start_date"] ?? "N/A")), DataCell(Text(item["end_date"] ?? "N/A")), - DataCell( Text(getRequestForCountry( item["country_code"]!.toString()))), + DataCell(Text(getRequestForCountry(item["country_code"]!.toString()))), // DataCell(Text(item["country_code"] ?? "N/A")), DataCell(Text(item["perdiem_amount"] ?? "N/A")), DataCell(Row( diff --git a/lib/Screens/policy/policy.dart b/lib/Screens/policy/policy.dart index 8a7c873..4fe056a 100644 --- a/lib/Screens/policy/policy.dart +++ b/lib/Screens/policy/policy.dart @@ -45,106 +45,115 @@ class _PolicyState extends State { return Container( margin: isDesktop ? EdgeInsets.all(20.0) - : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 10.0), + : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), height: MediaQuery.of(context).size.height, - // color: Colors.grey, + decoration: BoxDecoration( + border: isDesktop + ? Border.all( + width: 3, + color: Color(0xFFF7F7FB), + ) + : null, + ), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( - // color: Color(0xFFF7F7FB), + color: Color(0xFFF7F7FB), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - children: [ - Expanded( - child: Container( - // color: Colors.amber, - // color: Color(0xFFF7F7FB), - padding: EdgeInsets.all(5), - alignment: Alignment.center, - child: Text( - "Choose Policy Type", - style: TextStyle( - fontSize: 18, - ), - ), - ), - ), - ], - ), - SizedBox( - height: 10, - ), Container( + padding: isDesktop ? EdgeInsets.all(6) : EdgeInsets.all(3), + // color: Colors.white, // Background to avoid overlapping + color: isDesktop ? Color(0xFFF7F7FB) : Colors.white, child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, children: [ - Expanded( - child: GestureDetector( - onTap: () { - setState(() { - policyType = "domestic"; - }); - }, - child: Container( - padding: EdgeInsets.all(10), - color: policyType == "domestic" - ? Colors.blueAccent.shade100 - : Color(0xFFEBEBF7), - // color: Colors.blue.shade300, - child: Column( - children: [ - Text( - "Domestic", - style: TextStyle( - color: policyType == "domestic" - ? Colors.white - : Colors.black87, - fontSize: 15, - fontWeight: FontWeight.bold), - ), - ], - ), - ), + Text( + "Choose Policy Type", + style: TextStyle( + fontSize: 18, + color: Colors.black, ), ), - Expanded( - child: GestureDetector( - onTap: () { - setState(() { - policyType = "international"; - }); - }, - child: Container( - padding: EdgeInsets.all(10), - // color: Color(0xFFEBEBF7), - color: policyType == "international" - ? Colors.blueAccent.shade100 - : Color(0xFFEBEBF7), - // color: Color(0xFFE3F2FD), - - child: Column( - children: [ - Text( - "International", - style: TextStyle( - color: policyType == "international" - ? Colors.white - : Colors.black87, - fontSize: 15, - fontWeight: FontWeight.bold), - ), - ], - ), - ), - )), ], ), ), + + // Container( + // child: Row( + // children: [ + // Expanded( + // child: GestureDetector( + // onTap: () { + // setState(() { + // policyType = "domestic"; + // }); + // }, + // child: Container( + // padding: EdgeInsets.all(10), + // color: policyType == "domestic" + // ? Colors.blueAccent.shade100 + // : Color(0xFFEBEBF7), + // // color: Colors.blue.shade300, + // child: Column( + // children: [ + // Text( + // "Domestic", + // style: TextStyle( + // color: policyType == "domestic" + // ? Colors.white + // : Colors.black87, + // fontSize: 15, + // fontWeight: FontWeight.bold), + // ), + // ], + // ), + // ), + // ), + // ), + // Expanded( + // child: GestureDetector( + // onTap: () { + // setState(() { + // policyType = "international"; + // }); + // }, + // child: Container( + // padding: EdgeInsets.all(10), + // // color: Color(0xFFEBEBF7), + // color: policyType == "international" + // ? Colors.blueAccent.shade100 + // : Color(0xFFEBEBF7), + // // color: Color(0xFFE3F2FD), + // + // child: Column( + // children: [ + // Text( + // "International", + // style: TextStyle( + // color: policyType == "international" + // ? Colors.white + // : Colors.black87, + // fontSize: 15, + // fontWeight: FontWeight.bold), + // ), + // ], + // ), + // ), + // )), + // ], + // ), + // ), + // ], ), ), + SizedBox( + height: 10, + ), isDesktop ? Expanded( child: Row( @@ -215,7 +224,7 @@ class _PolicyState extends State { return SizedBox( width: isDesktop ? 180 : null, height: isDesktop - ? max((MediaQuery.of(context).size.height * 0.085), 10) + ? max((MediaQuery.of(context).size.height * 0.09), 10) : 45, child: GestureDetector( onTap: () { diff --git a/lib/Screens/policy/policyCriteria.dart b/lib/Screens/policy/policyCriteria.dart index 74481a1..85d759c 100644 --- a/lib/Screens/policy/policyCriteria.dart +++ b/lib/Screens/policy/policyCriteria.dart @@ -23,6 +23,7 @@ class PolicyCriteria extends StatefulWidget { class _PolicyCriteriaState extends State { String? selectedFirstApprovarType; String? selectedService; + String? _selectedTripType; // bool isClass = true; // bool isCost = true; @@ -42,12 +43,12 @@ class _PolicyCriteriaState extends State { return Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - SizedBox(height: 15), + widget.isDesktop ? SizedBox(height: 10) : SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "Selected Policy Criteria For ${widget.selectedTab} ", + " Policy Criteria For ${widget.selectedTab} ", style: TextStyle( fontSize: 13, color: Color(0xFF9E9DBD), @@ -55,7 +56,17 @@ class _PolicyCriteriaState extends State { ) ], ), - if (widget.isClass!) SizedBox(height: 15), + widget.isDesktop ? SizedBox(height: 15) : SizedBox(height: 5), + Padding( + padding: widget.isDesktop + ? const EdgeInsets.all(8.0) + : const EdgeInsets.all(1.0), + child: Row( + children: _buildTripType(widget.isDesktop), + ), + ), + if (widget.isClass!) + widget.isDesktop ? SizedBox(height: 15) : SizedBox(height: 5), Row( children: [ Expanded( @@ -171,21 +182,24 @@ class _PolicyCriteriaState extends State { Expanded( child: Container( width: widget.isDesktop - ? MediaQuery.of(context).size.width * 0.62 + ? MediaQuery.of(context).size.width * 0.63 : 600, child: Column( children: [ Container( + margin: const EdgeInsets.only(right: 20), decoration: BoxDecoration( color: Colors.grey.shade50, border: Border.all( color: Colors.grey.shade50, ), borderRadius: BorderRadius.circular(8)), - padding: const EdgeInsets.all(10), + padding: const EdgeInsets.only( + top: 10, bottom: 10, left: 35, right: 35), child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, + mainAxisAlignment: widget.isDesktop + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, children: [ Text( "Approver Name", @@ -217,6 +231,7 @@ class _PolicyCriteriaState extends State { scrollDirection: Axis.vertical, child: Container( // color: Colors.grey, + margin: const EdgeInsets.only(right: 20), color: Colors.grey.shade50, child: Column(children: [ Container( @@ -496,4 +511,57 @@ class _PolicyCriteriaState extends State { ], ); } + + List _buildTripType(bool isMobile) { + return [ + CustomTextFieldWrapper( + color: Color(0xFFF4F4FB), + padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), + width: 120, + isFocused: _selectedTripType == "1", + isDesktop: widget.isDesktop, + child: SizedBox( + height: 35, + child: Material( + color: Colors.transparent, + child: RadioListTile( + activeColor: Colors.blueAccent, + contentPadding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + dense: true, + title: Text("Domestic"), + value: "1", + groupValue: _selectedTripType, + onChanged: (value) { + setState(() { + _selectedTripType = value!; + }); + }, + ), + ), + ), + ), + SizedBox(width: 20), + CustomTextFieldWrapper( + color: Color(0xFFF4F4FB), + width: 150, + padding: EdgeInsets.symmetric(horizontal: 5, vertical: 2), + isFocused: _selectedTripType == "2", + isDesktop: widget.isDesktop, + child: RadioListTile( + activeColor: Colors.blueAccent, + contentPadding: EdgeInsets.zero, + dense: true, + title: Text("International"), + value: "2", + groupValue: _selectedTripType, + onChanged: (value) { + setState(() { + _selectedTripType = value!; + }); + }, + ), + ), + ]; + } } diff --git a/lib/Screens/userManagement/create_user/create_user.dart b/lib/Screens/userManagement/create_user/create_user.dart index 8956816..77c7df8 100644 --- a/lib/Screens/userManagement/create_user/create_user.dart +++ b/lib/Screens/userManagement/create_user/create_user.dart @@ -22,15 +22,12 @@ import '../../../widgets/custom_text_field.dart'; import '../../../widgets/custom_text_forex.dart'; import '../../../widgets/custom_user_form.dart'; - - - -class CreateUserForm extends StatefulWidget{ +class CreateUserForm extends StatefulWidget { @override _CreateUserFormState createState() => _CreateUserFormState(); } -class _CreateUserFormState extends State{ +class _CreateUserFormState extends State { final ApiService apiService = ApiService(); String? userId; @@ -49,7 +46,6 @@ class _CreateUserFormState extends State{ late List? apiUserData; Map? apiselectedUser; - late List userList; late Future> futureUsers; @@ -57,10 +53,8 @@ class _CreateUserFormState extends State{ late List userIdsApi; late Map userMap; - Map errorMessages = {}; - String? selectedCountry; String? selectedGender; String? selectedUserType; @@ -75,48 +69,67 @@ class _CreateUserFormState extends State{ Uint8List? passportDocumentBytes; String? base64PDF; - List dataHeader = [ - "Fname", "Lname", "email", "password", "dob","gender","mobileNumber", "alternateMobile", "address", - "postalCode","country","passportNumber", "placeOfIssue", "passportDoc","userType","roleId","deptId", - "levelId", "firstApproval", "secondApproval", "thirdApproval","employeeCode","dateOfIssue","dateOfExpiry", + "Fname", + "Lname", + "email", + "password", + "dob", + "gender", + "mobileNumber", + "alternateMobile", + "address", + "postalCode", + "country", + "passportNumber", + "placeOfIssue", + "passportDoc", + "userType", + "roleId", + "deptId", + "levelId", + "firstApproval", + "secondApproval", + "thirdApproval", + "employeeCode", + "dateOfIssue", + "dateOfExpiry", "changePassword" ]; - Map get userDetials{ - - Map data = { - "first_name" : controllers["Fname"]?.text, - "last_name" : controllers["Lname"]?.text, - "email" : controllers["email"]?.text, - "password" : controllers["password"]?.text, - "mobile_no" : controllers["mobileNumber"]?.text, + Map get userDetials { + Map data = { + "first_name": controllers["Fname"]?.text, + "last_name": controllers["Lname"]?.text, + "email": controllers["email"]?.text, + "password": controllers["password"]?.text, + "mobile_no": controllers["mobileNumber"]?.text, "alternate_mobile_no": controllers["alternateMobile"]?.text, "date_of_birth": controllers["dob"]?.text, - "address" : controllers["address"]?.text, - "gender" : selectedGender, - "postal_code" : controllers["postalCode"]?.text, - "country" : selectedCountry, + "address": controllers["address"]?.text, + "gender": selectedGender, + "postal_code": controllers["postalCode"]?.text, + "country": selectedCountry, "employee_code": controllers["employeeCode"]?.text, - "user_type" : selectedUserType, - "role_id" : selectedRole, + "user_type": selectedUserType, + "role_id": selectedRole, "department_id": selectedDepartment, - "group_id" : selectedLevel, + "group_id": selectedLevel, "first_approver": selectedFirstApprover, "second_approver": selectedSecondApprover, "third_approver": selectedThirdApprover, "passport_number": controllers["passportNumber"]?.text, "place_of_issue": controllers["placeOfIssue"]?.text, - "passport_document": base64PDF, + "passport_document": base64PDF, "date_of_issue": controllers["dateOfIssue"]?.text, "date_of_expiry": controllers["dateOfExpiry"]?.text, "created_by": userId, "is_active": "1", // "passport_fileData": base64PDF, - }; + }; return data; } @@ -124,50 +137,59 @@ class _CreateUserFormState extends State{ // Ensure apiselectedUser is not null before printing if (apiselectedUser != null) { print("API Selected User Has Data - $apiselectedUser"); - setState(() { // ✅ Wrap in setState to update the UI + setState(() { + // ✅ Wrap in setState to update the UI - controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? ""; - controllers["Lname"]?.text = apiselectedUser?["last_name"] ?? ""; - controllers["email"]?.text = apiselectedUser?["email"] ?? ""; - controllers["password"]?.text = ""; - // controllers["password"]?.text = apiselectedUser?["password"] ?? ""; - controllers["mobileNumber"]?.text = apiselectedUser?["mobile_no"] ?? ""; - controllers["alternateMobile"]?.text = apiselectedUser?["alternate_mobile_no"] ?? ""; - controllers["dob"]?.text = apiselectedUser?["date_of_birth"] ?? ""; - controllers["address"]?.text = apiselectedUser?["address"] ?? ""; - controllers["postalCode"]?.text = apiselectedUser?["postal_code"] ?? ""; - controllers["employeeCode"]?.text = apiselectedUser?["employee_code"] ?? ""; + controllers["Fname"]?.text = apiselectedUser?["first_name"] ?? ""; + controllers["Lname"]?.text = apiselectedUser?["last_name"] ?? ""; + controllers["email"]?.text = apiselectedUser?["email"] ?? ""; + controllers["password"]?.text = ""; + // controllers["password"]?.text = apiselectedUser?["password"] ?? ""; + controllers["mobileNumber"]?.text = apiselectedUser?["mobile_no"] ?? ""; + controllers["alternateMobile"]?.text = + apiselectedUser?["alternate_mobile_no"] ?? ""; + controllers["dob"]?.text = apiselectedUser?["date_of_birth"] ?? ""; + controllers["address"]?.text = apiselectedUser?["address"] ?? ""; + controllers["postalCode"]?.text = apiselectedUser?["postal_code"] ?? ""; + controllers["employeeCode"]?.text = + apiselectedUser?["employee_code"] ?? ""; - controllers["passportNumber"]?.text = apiselectedUser?["passport_number"] ?? ""; - controllers["placeOfIssue"]?.text = apiselectedUser?["place_of_issue"] ?? ""; + controllers["passportNumber"]?.text = + apiselectedUser?["passport_number"] ?? ""; + controllers["placeOfIssue"]?.text = + apiselectedUser?["place_of_issue"] ?? ""; - controllers["dateOfIssue"]?.text = apiselectedUser?["date_of_issue"] ?? ""; - controllers["dateOfExpiry"]?.text = apiselectedUser?["date_of_expiry"] ?? ""; + controllers["dateOfIssue"]?.text = + apiselectedUser?["date_of_issue"] ?? ""; + controllers["dateOfExpiry"]?.text = + apiselectedUser?["date_of_expiry"] ?? ""; + selectedCountry = apiselectedUser?["country_code"]?.toString() ?? ""; + selectedGender = apiselectedUser?["gender"]?.toString().trim() ?? ""; - selectedCountry = apiselectedUser?["country_code"]?.toString() ?? ""; - selectedGender = apiselectedUser?["gender"]?.toString().trim() ?? ""; - - base64PDF = apiselectedUser?["passport_document"]?.toString().trim() ?? ""; - selectedUserType = apiselectedUser?["user_type"]?.toString().trim() ?? ""; + base64PDF = + apiselectedUser?["passport_document"]?.toString().trim() ?? ""; + selectedUserType = + apiselectedUser?["user_type"]?.toString().trim() ?? ""; selectedRole = apiselectedUser?["role_id"]?.toString().trim() ?? ""; - selectedDepartment = apiselectedUser?["department_id"]?.toString().trim() ?? ""; + selectedDepartment = + apiselectedUser?["department_id"]?.toString().trim() ?? ""; selectedLevel = apiselectedUser?["level_id"]?.toString().trim() ?? ""; - selectedFirstApprover = apiselectedUser?["first_approver"]?.toString() ?? ""; - selectedSecondApprover = apiselectedUser?["second_approver"]?.toString() ?? ""; - selectedThirdApprover = apiselectedUser?["third_approver"]?.toString() ?? ""; + selectedFirstApprover = + apiselectedUser?["first_approver"]?.toString() ?? ""; + selectedSecondApprover = + apiselectedUser?["second_approver"]?.toString() ?? ""; + selectedThirdApprover = + apiselectedUser?["third_approver"]?.toString() ?? ""; - - print("Updated selectedGender: $selectedGender"); // Debugging + print("Updated selectedGender: $selectedGender"); // Debugging }); - } else { print("API Selected User Has Data - No data available yet"); } } - @override void initState() { super.initState(); @@ -201,17 +223,11 @@ class _CreateUserFormState extends State{ // }); // }); - - - - // Initialize controllers for each field - - WidgetsBinding.instance.addPostFrameCallback((_) async{ - final extraData = GoRouterState.of(context).extra as Map?; - - + WidgetsBinding.instance.addPostFrameCallback((_) async { + final extraData = + GoRouterState.of(context).extra as Map?; if (extraData != null) { print("extraData: ${extraData['selectedUser']}"); @@ -228,21 +244,20 @@ class _CreateUserFormState extends State{ // userIdsApi = userMap.keys.toList(); // Handle selectedUser as a Map (not a List) - apiselectedUser = extraData['selectedUser'] as Map?; // Cast it as a Map + apiselectedUser = extraData['selectedUser'] + as Map?; // Cast it as a Map isViewMode = extraData['isViewMode'] ?? false; isEditProfile = extraData['isEditProfile'] ?? false; - }); // Add another post-frame callback to check after setState - await Future.delayed(Duration(milliseconds: 100)); // Optional delay to ensure UI has updated + await Future.delayed(Duration( + milliseconds: 100)); // Optional delay to ensure UI has updated updateData(); } }); - - - for(var field in dataHeader) { + for (var field in dataHeader) { controllers[field] = TextEditingController(); } @@ -251,7 +266,6 @@ class _CreateUserFormState extends State{ fetchDepartment(); fetchUsers(); fetchRoles(); - } Future fetchCountries() async { @@ -265,7 +279,6 @@ class _CreateUserFormState extends State{ } } - Future fetchDepartment() async { try { List department = await apiService.fetchCostCenter(); @@ -283,14 +296,15 @@ class _CreateUserFormState extends State{ setState(() { // apiUserData = users; - apiUserData = users.where((user) => user["role_id"] == "3").toList(); + apiUserData = users.where((user) => user["role_id"] == "3").toList(); print("APIUSerDATa - $apiUserData"); userList = apiUserData ?? []; userMap = { for (var user in userList) - user['user_id'].toString(): "${user['first_name']} ${user['last_name']}" + user['user_id'].toString(): + "${user['first_name']} ${user['last_name']}" }; userIdsApi = userMap.keys.toList(); }); @@ -299,7 +313,6 @@ class _CreateUserFormState extends State{ } } - Future fetchRoles() async { try { final response = await apiService.fetchMasterDropdown(); @@ -318,26 +331,23 @@ class _CreateUserFormState extends State{ } } - void printFormData() { for (var field in dataHeader) { print("$field: ${controllers[field]?.text}"); } } - Future initializeData ()async{ + Future initializeData() async { token = await getToken(); userId = await getUserId(); - if(token == null || userId == null){ + if (token == null || userId == null) { print("Token or USerId missing"); print("Retrieved Token: $token"); print("Retrieved UserId: $userId"); return; - } - else{ - setState(() { - }); + } else { + setState(() {}); } } @@ -346,13 +356,11 @@ class _CreateUserFormState extends State{ return prefs.getString('auth_token'); } - // Future getUserId() async { // final prefs = await SharedPreferences.getInstance(); // return prefs.getString('userId'); // } - Future getUserId() async { final prefs = await SharedPreferences.getInstance(); final userData = prefs.getString('user_data'); @@ -366,8 +374,6 @@ class _CreateUserFormState extends State{ return null; } - - @override void dispose() { // Dispose all controllers to prevent memory leaks @@ -377,31 +383,33 @@ class _CreateUserFormState extends State{ super.dispose(); } - void handleSubmit(){ + void handleSubmit() { print("USR Detail Submit"); printFormData(); - Map data = userDetials; + Map data = userDetials; if (!isValidData(data)) { print("USERDETAILS : $userDetials"); print("Validation Failed: Required fields are missing."); setState(() {}); return; // Stop execution if validation fails - }else { + } else { print("USERDETAILS : $userDetials"); createUserData(userDetials); } - - } - bool isValidData(Map data) { errorMessages.clear(); // Reset errors // Required fields that must not be empty - List requiredFields = ["first_name", "last_name","email","mobile_no"]; + List requiredFields = [ + "first_name", + "last_name", + "email", + "mobile_no" + ]; if (apiselectedUser == null) { requiredFields.add("password"); @@ -414,24 +422,28 @@ class _CreateUserFormState extends State{ } } - // Mobile number validation for both mobile_no and alternate_mobile_no if (data["mobile_no"] != null && data["mobile_no"].toString().isNotEmpty) { if (!RegExp(r"^\d{10}$").hasMatch(data["mobile_no"].toString())) { - errorMessages["mobile_no"] = "Enter 10 digits"; // Invalid mobile number format + errorMessages["mobile_no"] = + "Enter 10 digits"; // Invalid mobile number format } } - if (data["alternate_mobile_no"] != null && data["alternate_mobile_no"].toString().isNotEmpty) { - if (!RegExp(r"^\d{10}$").hasMatch(data["alternate_mobile_no"].toString())) { - errorMessages["alternate_mobile_no"] = "Enter 10 digits"; // Invalid mobile number format + if (data["alternate_mobile_no"] != null && + data["alternate_mobile_no"].toString().isNotEmpty) { + if (!RegExp(r"^\d{10}$") + .hasMatch(data["alternate_mobile_no"].toString())) { + errorMessages["alternate_mobile_no"] = + "Enter 10 digits"; // Invalid mobile number format } } // Email validation if (data["email"] != null && data["email"].toString().isNotEmpty) { - if (!RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").hasMatch(data["email"].toString())) { - errorMessages["email"] = "Invalid email format"; // Invalid email format + if (!RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") + .hasMatch(data["email"].toString())) { + errorMessages["email"] = "Invalid email format"; // Invalid email format } } return errorMessages.isEmpty; // Valid if there are no errors @@ -445,9 +457,6 @@ class _CreateUserFormState extends State{ } } - - - void pickPDFWeb() { html.FileUploadInputElement uploadInput = html.FileUploadInputElement(); uploadInput.accept = '.pdf'; @@ -495,7 +504,6 @@ class _CreateUserFormState extends State{ }); } - // void pickPDFWeb() { // html.FileUploadInputElement uploadInput = html.FileUploadInputElement(); // uploadInput.accept = '.pdf'; @@ -539,47 +547,41 @@ class _CreateUserFormState extends State{ // }); // } - - - - Future createUserData(Map userData) async { - - bool isUpdating = apiselectedUser != null && apiselectedUser!.isNotEmpty; - final String apiUrldata = isUpdating? - '$apiUrl/api/users/update/${apiselectedUser?["user_id"]}' - :'$apiUrl/api/users/create'; + bool isUpdating = apiselectedUser != null && apiselectedUser!.isNotEmpty; + final String apiUrldata = isUpdating + ? '$apiUrl/api/users/update/${apiselectedUser?["user_id"]}' + : '$apiUrl/api/users/create'; if (token == null) { throw Exception('Token not found. Please log in.'); } - - // Add user_id only if updating - if (isUpdating) { - userData['user_id'] = apiselectedUser?["user_id"]; - } + // Add user_id only if updating + if (isUpdating) { + userData['user_id'] = apiselectedUser?["user_id"]; + } try { final response = isUpdating ? await http.put( - Uri.parse(apiUrldata), - headers: { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }, - body: jsonEncode(userData), - ) + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(userData), + ) : await http.post( - Uri.parse(apiUrldata), - headers: { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }, - body: jsonEncode(userData), - ); + Uri.parse(apiUrldata), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(userData), + ); - if (response.statusCode == 200 || response.statusCode == 201) { + if (response.statusCode == 200 || response.statusCode == 201) { print("Plan submitted successfully!"); print("Response: ${response.body}"); context.go('/listUser'); @@ -599,15 +601,19 @@ class _CreateUserFormState extends State{ print("enteredPassword - $enteredPassword "); if (hashedPassword != null && hashedPassword.isNotEmpty) { - bool isMatch = BCrypt.checkpw(enteredPassword, hashedPassword); // Compare passwords + bool isMatch = + BCrypt.checkpw(enteredPassword, hashedPassword); // Compare passwords - setState(() { // ✅ Ensure UI updates + setState(() { + // ✅ Ensure UI updates if (isMatch) { - errorMessages["password"] = "New password is not similar to old password"; + errorMessages["password"] = + "New password is not similar to old password"; print(" Password match!"); } else { print(" Password NOT match!"); - errorMessages.remove("password"); // Clear error if password is different + errorMessages + .remove("password"); // Clear error if password is different } }); } else { @@ -615,22 +621,19 @@ class _CreateUserFormState extends State{ } } - @override - Widget build(BuildContext context){ + Widget build(BuildContext context) { return ResponsiveBuilder(builder: (context, sizingInfo) { bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; return Scaffold( - appBar: isDesktop ? null : const CustomAppBar(title:'Create User '), + appBar: isDesktop ? null : const CustomAppBar(title: 'Create User '), drawer: isDesktop ? null : CustomDrawer(isDesktop: false), - body: - Container( + body: Container( color: Colors.white, child: Row( children: [ - if(isDesktop) - CustomDrawer(isDesktop: true), + if (isDesktop) CustomDrawer(isDesktop: true), // const Expanded(child: Center(child: Text("User Details Content"))), Expanded(child: buildUserTable(isDesktop)), ], @@ -638,414 +641,489 @@ class _CreateUserFormState extends State{ ), ); }); - } - Widget buildUserTable(bool isDesktop){ + Widget buildUserTable(bool isDesktop) { return Container( - margin: const EdgeInsets.only(left: 10.0, right: 15.0, top: 10.0,bottom: 10.0), + margin: const EdgeInsets.only( + left: 10.0, right: 15.0, top: 10.0, bottom: 10.0), decoration: BoxDecoration( - border: Border.all(color: Color(0xFFF7F7FB),width: 3.5) - - ), - + border: Border.all(color: Color(0xFFF7F7FB), width: 3.5)), child: Column( - children: [ - - Container( - color: Color(0xFFF7F7FB), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row(children: [ - - Text(apiselectedUser != null ? "Profile": "New User", - style: TextStyle(fontSize: 18,fontWeight: FontWeight.w200, color: Colors.black ),), - if(isEditProfile) - IconButton( - icon: Icon(Icons.edit, color: Colors.blueAccent,size: 18,), - onPressed:(){ - setState(() { - isViewMode = !isViewMode; - }); - } - ) - ], - ), - - ), - ), - - - SizedBox(height: 15 ,), - - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: _buildUserDetails(isDesktop), // Ensure this returns a scrollable widget - ), - ), - - Container( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(18.0), - child: isDesktop - ? Row( - mainAxisAlignment: MainAxisAlignment.end, - children: _buildSubmit(isDesktop),) - :Row( - mainAxisAlignment: MainAxisAlignment.center, - children: _buildSubmit(isDesktop),) - ), - ) - - ], - ), - ); - - } - - Widget _buildUserDetails(bool isDesktop){ - return Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - Icon(Icons.filter_1_outlined, color: Color(0xFF8B8FB2),size: 18,), - SizedBox(width: 10,), - Text("Personal Details", style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold, - // color: Colors.black, - color: Color(0xFF8B8FB2) - ), - ) - ],), - SizedBox(height: 20,), - - Padding( - padding: const EdgeInsets.only(left:16.0), - // padding: const EdgeInsets.all(8.0), - // color: Colors.grey, - child: SizedBox( - width: isDesktop? MediaQuery.of(context).size.width *0.7: null, - // height: isDesktop? null :MediaQuery.of(context).size.height , - child: isDesktop - ? Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: _buildFirstRowLeftColumn(isDesktop)), - SizedBox(width: 20), - Expanded(child: _buildFirstRowRightColumn(isDesktop)), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildFirstRowLeftColumn(isDesktop), - SizedBox(height: 1), - _buildFirstRowRightColumn(isDesktop), - ], - ), - ), - ), - - - ],), - - - - ], - ), - ), - - // SizedBox( - // child: Expanded( - // child: Container( - // margin: const EdgeInsets.only(left: 10.0, right: 15.0), - // child: Divider( - // color: Color(0xFF8B8FB2), - // thickness: 0.5, - // height: 50, - // ), - // ), - // ), - // ), - - SizedBox( - width: double.infinity, // Ensures the divider takes full width - child: Stack( - alignment: Alignment.center, // Centers the icon - children: [ - Divider( - color: Color(0xFF8B8FB2), - thickness: 0.5, - height: 50, - ), - Container( - // padding: EdgeInsets.all(4), - color: Colors.white, // Background to avoid overlapping - child: Row( - mainAxisSize: MainAxisSize.min, // Prevents row from taking full width - children: [ - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - ], + Container( + color: Color(0xFFF7F7FB), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Text( + apiselectedUser != null ? "Profile" : "New User", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w200, + color: Colors.black), ), - ), - ], - ), - ), - - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - Icon(Icons.filter_2_outlined, color: Color(0xFF8B8FB2),size: 18,), - SizedBox(width: 10,), - Text("Passport Details", style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold, - // color: Colors.black, - color: Color(0xFF8B8FB2) - - ), - ) - ],), - SizedBox(height: 20,), - - Padding( - padding: const EdgeInsets.only(left:16.0), - child: SizedBox( - width: isDesktop? MediaQuery.of(context).size.width *0.7: null, - // height: isDesktop? null :MediaQuery.of(context).size.height , - child: isDesktop - ? Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: _buildSecondRowLeftColumn(isDesktop)), - SizedBox(width: 20), - Expanded(child: _buildSecondRowRightColumn(isDesktop)), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - - children: [ - _buildSecondRowLeftColumn(isDesktop), - SizedBox(height: 1), - _buildSecondRowRightColumn(isDesktop), - ], + if (isEditProfile) + IconButton( + icon: Icon( + Icons.edit, + color: Colors.blueAccent, + size: 18, ), - ), - ), - ],), - ], + onPressed: () { + setState(() { + isViewMode = !isViewMode; + }); + }) + ], + ), ), ), - SizedBox( - width: double.infinity, // Ensures the divider takes full width - child: Stack( - alignment: Alignment.center, // Centers the icon - children: [ - Divider( - color: Color(0xFF8B8FB2), - thickness: 0.5, - height: 50, - ), - Container( - // padding: EdgeInsets.all(4), - color: Colors.white, // Background to avoid overlapping - child: Row( - mainAxisSize: MainAxisSize.min, // Prevents row from taking full width - children: [ - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - ], - ), - ), - ], + height: 15, + ), + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: _buildUserDetails( + isDesktop), // Ensure this returns a scrollable widget ), ), - - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - Icon(Icons.filter_3_outlined, color: Color(0xFF8B8FB2),size: 18,), - SizedBox(width: 10,), - Text("Employee Organization Details", style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold, - // color: Colors.black, - color: Color(0xFF8B8FB2) - - ), + Container( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(18.0), + child: isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + children: _buildSubmit(isDesktop), ) - ],), - SizedBox(height: 20,), - - Padding( - padding: const EdgeInsets.only(left:16.0), - child: SizedBox( - width: isDesktop? MediaQuery.of(context).size.width *0.7: null, - // height: isDesktop? null :MediaQuery.of(context).size.height , - child: isDesktop - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: _buildThirdRowLeftColumn(isDesktop)), - SizedBox(width: 20), - Expanded(child: _buildThirdRowRightColumn(isDesktop)), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildThirdRowLeftColumn(isDesktop), - SizedBox(height: 1), - _buildThirdRowRightColumn(isDesktop), - ], - ), - ), - ), - - ],), - - - - ], - ), - ), - - SizedBox( - width: double.infinity, // Ensures the divider takes full width - child: Stack( - alignment: Alignment.center, // Centers the icon - children: [ - Divider( - color: Color(0xFF8B8FB2), - thickness: 0.5, - height: 50, - ), - Container( - // padding: EdgeInsets.all(4), - color: Colors.white, // Background to avoid overlapping - child: Row( - mainAxisSize: MainAxisSize.min, // Prevents row from taking full width - children: [ - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - ], - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - Icon(Icons.filter_4_outlined, color: Color(0xFF8B8FB2),size: 18,), - SizedBox(width: 10,), - Text("Approver", style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold, - // color: Colors.black, - color: Color(0xFF8B8FB2) - - ), - ) - ],), - SizedBox(height: 20,), - - - Padding( - padding: const EdgeInsets.only(left:16.0), - child: SizedBox( - width: isDesktop? MediaQuery.of(context).size.width *0.7: null, - // height: isDesktop? null :MediaQuery.of(context).size.height , - child: isDesktop - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: _buildForthRowLeftColumn(isDesktop)), - SizedBox(width: 20), - Expanded(child: _buildForthRowRightColumn(isDesktop)), - SizedBox(width: 20), - Expanded(child: _buildForthRowLastColumn(isDesktop)), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildForthRowLeftColumn(isDesktop), - SizedBox(height: 1), - _buildForthRowRightColumn(isDesktop), - SizedBox(height: 1), - _buildForthRowLastColumn(isDesktop), - ], - ), - ), - ), - - - - ],), - - ], - ), - ), - - SizedBox( - width: double.infinity, // Ensures the divider takes full width - child: Stack( - alignment: Alignment.center, // Centers the icon - children: [ - Divider( - color: Color(0xFF8B8FB2), - thickness: 0.5, - height: 50, - ), - Container( - // padding: EdgeInsets.all(4), - color: Colors.white, // Background to avoid overlapping - child: Row( - mainAxisSize: MainAxisSize.min, // Prevents row from taking full width - children: [ - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - Icon(Icons.keyboard_arrow_right_outlined, color: Colors.blue, size: 28), SizedBox(width: 1), - ], - ), - ), - ], - ), - ), + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: _buildSubmit(isDesktop), + )), + ) ], - ); - + ), + ); } - //--------------------------------- Personal Details --------------------------- + Widget _buildUserDetails(bool isDesktop) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.filter_1_outlined, + color: Color(0xFF8B8FB2), + size: 18, + ), + SizedBox( + width: 10, + ), + Text( + "Personal Details", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + // color: Colors.black, + color: Color(0xFF8B8FB2)), + ) + ], + ), + SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + // padding: const EdgeInsets.all(8.0), + // color: Colors.grey, + child: SizedBox( + width: isDesktop + ? MediaQuery.of(context).size.width * 0.7 + : null, + // height: isDesktop? null :MediaQuery.of(context).size.height , + child: isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Expanded(child: _buildFirstRowLeftColumn(isDesktop)), + // SizedBox(width: 20), + // Expanded(child: _buildFirstRowRightColumn(isDesktop)), - Widget _buildFirstRowLeftColumn(bool isDesktop){ + _buildFirstRowLeftColumn(isDesktop), + SizedBox(width: 20), + _buildFirstRowRightColumn(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildFirstRowLeftColumn(isDesktop), + SizedBox(height: 1), + _buildFirstRowRightColumn(isDesktop), + ], + ), + ), + ), + ], + ), + ], + ), + ), + // SizedBox( + // child: Expanded( + // child: Container( + // margin: const EdgeInsets.only(left: 10.0, right: 15.0), + // child: Divider( + // color: Color(0xFF8B8FB2), + // thickness: 0.5, + // height: 50, + // ), + // ), + // ), + // ), + + SizedBox( + width: double.infinity, // Ensures the divider takes full width + child: Stack( + alignment: Alignment.center, // Centers the icon + children: [ + Divider( + color: Color(0xFF8B8FB2), + thickness: 0.5, + height: 50, + ), + Container( + // padding: EdgeInsets.all(4), + color: Colors.white, // Background to avoid overlapping + child: Row( + mainAxisSize: + MainAxisSize.min, // Prevents row from taking full width + children: [ + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + ], + ), + ), + ], + ), + ), + + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.filter_2_outlined, + color: Color(0xFF8B8FB2), + size: 18, + ), + SizedBox( + width: 10, + ), + Text( + "Passport Details", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + // color: Colors.black, + color: Color(0xFF8B8FB2)), + ) + ], + ), + SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: SizedBox( + width: isDesktop + ? MediaQuery.of(context).size.width * 0.7 + : null, + // height: isDesktop? null :MediaQuery.of(context).size.height , + child: isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSecondRowLeftColumn(isDesktop), + SizedBox(width: 20), + _buildSecondRowRightColumn(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSecondRowLeftColumn(isDesktop), + SizedBox(height: 1), + _buildSecondRowRightColumn(isDesktop), + ], + ), + ), + ), + ], + ), + ], + ), + ), + + SizedBox( + width: double.infinity, // Ensures the divider takes full width + child: Stack( + alignment: Alignment.center, // Centers the icon + children: [ + Divider( + color: Color(0xFF8B8FB2), + thickness: 0.5, + height: 50, + ), + Container( + // padding: EdgeInsets.all(4), + color: Colors.white, // Background to avoid overlapping + child: Row( + mainAxisSize: + MainAxisSize.min, // Prevents row from taking full width + children: [ + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + ], + ), + ), + ], + ), + ), + + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.filter_3_outlined, + color: Color(0xFF8B8FB2), + size: 18, + ), + SizedBox( + width: 10, + ), + Text( + "Employee Organization Details", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + // color: Colors.black, + color: Color(0xFF8B8FB2)), + ) + ], + ), + SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: SizedBox( + width: isDesktop + ? MediaQuery.of(context).size.width * 0.7 + : null, + // height: isDesktop? null :MediaQuery.of(context).size.height , + child: isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildThirdRowLeftColumn(isDesktop), + SizedBox(width: 20), + _buildThirdRowRightColumn(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildThirdRowLeftColumn(isDesktop), + SizedBox(height: 1), + _buildThirdRowRightColumn(isDesktop), + ], + ), + ), + ), + ], + ), + ], + ), + ), + + SizedBox( + width: double.infinity, // Ensures the divider takes full width + child: Stack( + alignment: Alignment.center, // Centers the icon + children: [ + Divider( + color: Color(0xFF8B8FB2), + thickness: 0.5, + height: 50, + ), + Container( + // padding: EdgeInsets.all(4), + color: Colors.white, // Background to avoid overlapping + child: Row( + mainAxisSize: + MainAxisSize.min, // Prevents row from taking full width + children: [ + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + ], + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.filter_4_outlined, + color: Color(0xFF8B8FB2), + size: 18, + ), + SizedBox( + width: 10, + ), + Text( + "Approver", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + // color: Colors.black, + color: Color(0xFF8B8FB2)), + ) + ], + ), + SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: SizedBox( + width: isDesktop + ? MediaQuery.of(context).size.width * 0.7 + : null, + // height: isDesktop? null :MediaQuery.of(context).size.height , + child: isDesktop + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildForthRowLeftColumn(isDesktop), + SizedBox(width: 20), + _buildForthRowRightColumn(isDesktop), + SizedBox(width: 20), + _buildForthRowLastColumn(isDesktop), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildForthRowLeftColumn(isDesktop), + SizedBox(height: 1), + _buildForthRowRightColumn(isDesktop), + SizedBox(height: 1), + _buildForthRowLastColumn(isDesktop), + ], + ), + ), + ), + ], + ), + ], + ), + ), + + SizedBox( + width: double.infinity, // Ensures the divider takes full width + child: Stack( + alignment: Alignment.center, // Centers the icon + children: [ + Divider( + color: Color(0xFF8B8FB2), + thickness: 0.5, + height: 50, + ), + Container( + // padding: EdgeInsets.all(4), + color: Colors.white, // Background to avoid overlapping + child: Row( + mainAxisSize: + MainAxisSize.min, // Prevents row from taking full width + children: [ + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + Icon(Icons.keyboard_arrow_right_outlined, + color: Colors.blue, size: 28), + SizedBox(width: 1), + ], + ), + ), + ], + ), + ), + ], + ); + } + + //--------------------------------- Personal Details --------------------------- + + Widget _buildFirstRowLeftColumn(bool isDesktop) { DateTime? _selectedDateOfBirth; Future _selectCheckDateOfBirth(BuildContext context) async { @@ -1054,11 +1132,10 @@ class _CreateUserFormState extends State{ DateTime? pickedDate = await showDatePicker( context: context, - - - initialDate: _selectedDateOfBirth != null && _selectedDateOfBirth!.isAfter(today) - ? _selectedDateOfBirth! - : today, + initialDate: + _selectedDateOfBirth != null && _selectedDateOfBirth!.isAfter(today) + ? _selectedDateOfBirth! + : today, firstDate: today, lastDate: DateTime(2100), ); @@ -1066,339 +1143,382 @@ class _CreateUserFormState extends State{ if (pickedDate != null && pickedDate != _selectedDateOfBirth) { setState(() { _selectedDateOfBirth = pickedDate; - controllers["dob"]?.text = DateFormat('yyyy-MM-dd').format(pickedDate); + controllers["dob"]?.text = + DateFormat('yyyy-MM-dd').format(pickedDate); }); } } - return Container( // color: Colors.yellow, color: Colors.white, - child: Expanded( // Allow first column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("First Name", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["Fname"], - enabled: !isViewMode, - onChanged: (value) {_clearError("first_name");}, - decoration: InputDecoration( - labelText: "FirstName", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + // child: Expanded( + // Allow first column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("First Name", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["Fname"], + enabled: !isViewMode, + onChanged: (value) { + _clearError("first_name"); + }, + decoration: InputDecoration( + labelText: "FirstName", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["first_name"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["first_name"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["first_name"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["first_name"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Last Name", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["Lname"], - enabled: !isViewMode, - onChanged: (value) {_clearError("last_name");}, - decoration: InputDecoration( - labelText: "LastName", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Last Name", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["Lname"], + enabled: !isViewMode, + onChanged: (value) { + _clearError("last_name"); + }, + decoration: InputDecoration( + labelText: "LastName", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["last_name"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["last_name"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], - ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Gender", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: DropdownButtonFormField( - value: selectedGender, - onChanged: isViewMode ? null : (String? newValue) { - setState(() { - selectedGender = newValue; - print("selectedGender - $selectedGender"); - }); - }, - decoration: InputDecoration( - border: InputBorder.none, - enabled: !isViewMode, // Disables input when in view mode - ), - style: TextStyle(fontSize: 12), - items: [ - DropdownMenuItem(value: "Male", child: Text("Male")), - DropdownMenuItem(value: "Female", child: Text("Female")), - ], - hint : Text( - selectedGender ?? "Select Gender", - style: TextStyle(fontSize: 12),), - ), - - // child: DropdownSearch( - // selectedItem: selectedGender, - // // key: ValueKey(selectedGender), - // popupProps: PopupProps.menu( - // fit: FlexFit.loose, // Allows flexible height - // constraints: BoxConstraints(maxHeight: 250), - // - // ), - // items: ["Male", "Female", "Others"], - // dropdownDecoratorProps: DropDownDecoratorProps( - // dropdownSearchDecoration: InputDecoration( - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(horizontal: 1,), - // ), - // ), - // dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - // alignment: Alignment.centerLeft, - // child: Text( - // selectedItem ?? "Select", - // style: TextStyle(fontSize: 12), - // ), - // ), - // onChanged: isViewMode - // ? null - // : (String? newValue) { - // setState(() { - // // Find the country_code based on selected country_name - // selectedGender = newValue; - // print("selectedGender - $selectedGender"); - // // if (selectedCountry!.isNotEmpty) { - // // errorMessages.remove("country_code"); - // // } - // }); - // }, - // - // - // ), - ), + ), + if (errorMessages["last_name"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["last_name"]!, + style: TextStyle(color: Colors.red, fontSize: 12), ), ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Date of Birth", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: isViewMode ? null :()async{ - await _selectCheckDateOfBirth(context); - if (controllers["dob"]!.text.isNotEmpty) { - setState(() { - // errorMessages.remove("start_date"); - }); - } + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Gender", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: DropdownButtonFormField( + value: selectedGender, + onChanged: isViewMode + ? null + : (String? newValue) { + setState(() { + selectedGender = newValue; + print("selectedGender - $selectedGender"); + }); + }, + decoration: InputDecoration( + border: InputBorder.none, + enabled: + !isViewMode, // Disables input when in view mode + ), + style: TextStyle(fontSize: 12), + items: [ + DropdownMenuItem(value: "Male", child: Text("Male")), + DropdownMenuItem( + value: "Female", child: Text("Female")), + ], + hint: Text( + selectedGender ?? "Select Gender", + style: TextStyle(fontSize: 12), + ), + ), - }, - child: AbsorbPointer( - child: TextField( - controller: controllers["dob"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, - color: Color(0xFF8B8FB2) + // child: DropdownSearch( + // selectedItem: selectedGender, + // // key: ValueKey(selectedGender), + // popupProps: PopupProps.menu( + // fit: FlexFit.loose, // Allows flexible height + // constraints: BoxConstraints(maxHeight: 250), + // + // ), + // items: ["Male", "Female", "Others"], + // dropdownDecoratorProps: DropDownDecoratorProps( + // dropdownSearchDecoration: InputDecoration( + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(horizontal: 1,), + // ), + // ), + // dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item + // alignment: Alignment.centerLeft, + // child: Text( + // selectedItem ?? "Select", + // style: TextStyle(fontSize: 12), + // ), + // ), + // onChanged: isViewMode + // ? null + // : (String? newValue) { + // setState(() { + // // Find the country_code based on selected country_name + // selectedGender = newValue; + // print("selectedGender - $selectedGender"); + // // if (selectedCountry!.isNotEmpty) { + // // errorMessages.remove("country_code"); + // // } + // }); + // }, + // + // + // ), + ), + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Date of Birth", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: isViewMode + ? null + : () async { + await _selectCheckDateOfBirth(context); + if (controllers["dob"]!.text.isNotEmpty) { + setState(() { + // errorMessages.remove("start_date"); + }); + } + }, + child: AbsorbPointer( + child: TextField( + controller: controllers["dob"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: + EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon(Icons.calendar_today, + size: 16, color: Color(0xFF8B8FB2)), ), ), ), ), ), - - ), - ), - ], - ), - ], - ), - - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Email", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["email"], - onChanged: (value) {_clearError("email");}, - enabled: !isViewMode, - decoration: InputDecoration( - labelText: "Email", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Email", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["email"], + onChanged: (value) { + _clearError("email"); + }, + enabled: !isViewMode, + decoration: InputDecoration( + labelText: "Email", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["email"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["email"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["email"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["email"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ), - ], - ), - - SizedBox(height: 3), - - - apiselectedUser != null? - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, + ], + ), + ], + ), + SizedBox(height: 3), + apiselectedUser != null + ? Row( children: [ - Text("Change Password", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Change Password", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + ], + ), ], - ), - ], - ): - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, + ) + : Row( children: [ - Text("Password", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["password"], - enabled: !isViewMode, - onChanged: (value) {_clearError("password");}, - decoration: InputDecoration( - labelText: "Password", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Password", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["password"], + enabled: !isViewMode, + onChanged: (value) { + _clearError("password"); + }, + decoration: InputDecoration( + labelText: "Password", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: + EdgeInsets.symmetric(vertical: 16), + ), + ), ), ), - ), + if (errorMessages["password"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["password"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + ], + ], ), - if (errorMessages["password"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["password"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], ], ), - ], + if (!isDesktop) + SizedBox( + height: 3, ), - - - if(!isDesktop) SizedBox(height: 3,), - ], - ), + ], ), + // ), ); } - Widget _buildFirstRowRightColumn(bool isDesktop){ - + Widget _buildFirstRowRightColumn(bool isDesktop) { late Map countryMap; // Mapping country_code -> country_name late List countryCodes; // List of country codes - List countryList = apiCountryData ?? []; + List countryList = apiCountryData ?? []; countryList = apiCountryData ?? []; // Map country codes to country names countryMap = { - for (var item in countryList) item['country_code'] as String: item['country_name'] as String + for (var item in countryList) + item['country_code'] as String: item['country_name'] as String }; // Extract only country codes for processing @@ -1406,334 +1526,381 @@ class _CreateUserFormState extends State{ selectedCountry ??= null; - return Container( + return Container( // color: Colors.yellow, color: Colors.white, - child: Expanded( // Allow second column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - - children: [ - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Mobile Number", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["mobileNumber"], - enabled: !isViewMode, - onChanged: (value) {_clearError("mobile_no");}, - keyboardType: TextInputType.numberWithOptions(decimal: true), - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal - ], - decoration: InputDecoration( - labelText: "Mobile Number", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + // child: Expanded( + // Allow second column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Mobile Number", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["mobileNumber"], + enabled: !isViewMode, + onChanged: (value) { + _clearError("mobile_no"); + }, + keyboardType: + TextInputType.numberWithOptions(decimal: true), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp( + r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal + ], + decoration: InputDecoration( + labelText: "Mobile Number", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["mobile_no"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["mobile_no"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["mobile_no"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["mobile_no"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Alternate Mobile Number", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["alternateMobile"], - enabled: !isViewMode, - keyboardType: TextInputType.numberWithOptions(decimal: true), - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal - ], - decoration: InputDecoration( - labelText: "Alternate Number", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Alternate Mobile Number", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["alternateMobile"], + enabled: !isViewMode, + keyboardType: + TextInputType.numberWithOptions(decimal: true), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp( + r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal + ], + decoration: InputDecoration( + labelText: "Alternate Number", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - if (errorMessages["alternate_mobile_no"] != null) ...[ - SizedBox(height: 5), // Space before error message - Text( - errorMessages["alternate_mobile_no"]!, - style: TextStyle(color: Colors.red, fontSize: 12), - ), - ], + ), + if (errorMessages["alternate_mobile_no"] != null) ...[ + SizedBox(height: 5), // Space before error message + Text( + errorMessages["alternate_mobile_no"]!, + style: TextStyle(color: Colors.red, fontSize: 12), + ), ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Address", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 110, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["address"], - enabled: !isViewMode, - maxLines: 4, - keyboardType: TextInputType.multiline, - decoration: InputDecoration( - labelText: "Address", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 16), - contentPadding: EdgeInsets.symmetric(vertical: 4), - ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Address", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 110, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["address"], + enabled: !isViewMode, + maxLines: 4, + keyboardType: TextInputType.multiline, + decoration: InputDecoration( + labelText: "Address", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + contentPadding: EdgeInsets.symmetric(vertical: 4), ), ), ), - ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Postal Code", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["postalCode"], - enabled: !isViewMode, - keyboardType: TextInputType.numberWithOptions(decimal: true), - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal - ], - decoration: InputDecoration( - labelText: "Postal Code", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Postal Code", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["postalCode"], + enabled: !isViewMode, + keyboardType: + TextInputType.numberWithOptions(decimal: true), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp( + r'^\d*\.?\d*$')), // Allow only positive numbers with optional decimal + ], + decoration: InputDecoration( + labelText: "Postal Code", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Country", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: DropdownSearch( - selectedItem: countryMap[selectedCountry], - enabled: !isViewMode, + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Country", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: DropdownSearch( + selectedItem: countryMap[selectedCountry], + enabled: !isViewMode, popupProps: PopupProps.menu( - showSearchBox: true, // Enables search functionality + showSearchBox: true, // Enables search functionality fit: FlexFit.loose, // Allows flexible height constraints: BoxConstraints(maxHeight: 250), searchFieldProps: TextFieldProps( decoration: InputDecoration( hintText: "Search Country...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), + contentPadding: + EdgeInsets.symmetric(horizontal: 10), ), ), - ), - items: countryMap.values.toList(), + items: countryMap.values.toList(), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + ), ), ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item alignment: Alignment.centerLeft, child: Text( selectedItem ?? "Select Country", style: TextStyle(fontSize: 12), ), ), - onChanged: isViewMode ? null: (String? newValue) { - setState(() { - // Find the country_code based on selected country_name - selectedCountry = countryMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; + onChanged: isViewMode + ? null + : (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedCountry = countryMap.entries + .firstWhere( + (entry) => entry.value == newValue) + .key; - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, - ), + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), ), - ], - ), - ], + ), + ], + ), + ], + ), + if (!isDesktop) + SizedBox( + height: 3, ), - - - - if(!isDesktop) SizedBox(height: 3,), - ], - ), + ], ), + // ), ); -} - - + } //--------------------------------- Passport Details ----------------------------- - Widget _buildSecondRowLeftColumn(bool isDesktop){ - return Container( + Widget _buildSecondRowLeftColumn(bool isDesktop) { + return Container( color: Colors.white, - child: Expanded( // Allow first column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + // child: Expanded( + // Allow first column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Passport Number", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["passportNumber"], + enabled: !isViewMode, + decoration: InputDecoration( + labelText: "Passport Number", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), + ), + ], + ), + ], + ), + SizedBox( + height: 3, + ), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Passport Document", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Passport Number", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["passportNumber"], - enabled: !isViewMode, - decoration: InputDecoration( - labelText: "Passport Number", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: pickPDFWeb, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + alignment: Alignment.centerLeft, + child: Text( + selectedFileNames ?? "Select Document", + style: TextStyle(fontSize: 12, color: Colors.black), + overflow: TextOverflow + .ellipsis, // Prevents overflow issues ), ), ), ), - ], - ), - ], - ), - SizedBox(height: 3,), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Passport Document", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), + ), + SizedBox(height: 10), + if (base64PDF != null) - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: pickPDFWeb, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 10), - alignment: Alignment.centerLeft, - - child: Text( - selectedFileNames?? "Select Document", - style: TextStyle(fontSize: 12, color: Colors.black), - overflow: TextOverflow.ellipsis, // Prevents overflow issues - ), - ), - ), - ), - ), - SizedBox(height: 10), - if(base64PDF != null) - - // Centers the text - Container( - color: Colors.white, - width : isDesktop - ? MediaQuery.of(context).size.width * 0.25 - : MediaQuery.of(context).size.width * 0.8, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - GestureDetector(onTap: (){ + // Centers the text + Container( + color: Colors.white, + width: isDesktop + ? MediaQuery.of(context).size.width * 0.25 + : MediaQuery.of(context).size.width * 0.8, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { print('DOWLOAS- $base64PDF '); if (base64PDF != null && base64PDF!.isNotEmpty) { try { // ✅ Step 1: Clean the Base64 string String cleanedBase64 = base64PDF! - .replaceAll("\n", "") // Remove newlines - .replaceAll("\r", "") // Remove carriage returns - .replaceAll(" ", "") // Remove spaces - .trim(); // Trim any whitespace + .replaceAll("\n", "") // Remove newlines + .replaceAll( + "\r", "") // Remove carriage returns + .replaceAll(" ", "") // Remove spaces + .trim(); // Trim any whitespace // ✅ Step 2: Ensure valid Base64 length (multiple of 4) while (cleanedBase64.length % 4 != 0) { @@ -1750,12 +1917,15 @@ class _CreateUserFormState extends State{ } // ✅ Step 4: Create a Blob for download - final blob = html.Blob([bytes], 'application/pdf'); - final url = html.Url.createObjectUrlFromBlob(blob); + final blob = + html.Blob([bytes], 'application/pdf'); + final url = + html.Url.createObjectUrlFromBlob(blob); // ✅ Step 5: Trigger the file download final anchor = html.AnchorElement(href: url) - ..setAttribute("download", selectedFileNames ?? "document.pdf") + ..setAttribute("download", + selectedFileNames ?? "document.pdf") ..style.display = "none"; html.document.body!.append(anchor); @@ -1772,74 +1942,74 @@ class _CreateUserFormState extends State{ } else { print("No file to download."); } - - } , - - child: Container( - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.green.shade300, + }, + child: Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.green.shade300, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + "Download", + style: TextStyle( + fontSize: 12, + color: Colors.white, + fontWeight: FontWeight.bold), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign + .end, // Ensures text is centered within the Text widget ), + SizedBox(width: 5), + Icon( + Icons.download, + size: 13, + color: Colors.white, + ) + ], + ), + ), + ) + ], + ), + ), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - "Download", - style: TextStyle(fontSize: 12, color: Colors.white,fontWeight: FontWeight.bold), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.end, // Ensures text is centered within the Text widget - ), - SizedBox(width: 5), - Icon(Icons.download ,size: 13, color: Colors.white,) - ], - ), - - - ), - ) - - ], - ), - ), - - - - - // CustomTextFieldUserWrapper( - // isFocused: false, - // isDesktop: isDesktop, - // child: SizedBox( - // height: 40, - // child: TextField( - // style: TextStyle(fontSize: 12), - // controller: controllers["passportDoc"], - // decoration: InputDecoration( - // labelText: "Select Document", - // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - // floatingLabelBehavior: FloatingLabelBehavior.never, - // border: InputBorder.none, - // contentPadding: EdgeInsets.symmetric(vertical: 16), - // ), - // ), - // ), - // ), - ], - ), - ], + // CustomTextFieldUserWrapper( + // isFocused: false, + // isDesktop: isDesktop, + // child: SizedBox( + // height: 40, + // child: TextField( + // style: TextStyle(fontSize: 12), + // controller: controllers["passportDoc"], + // decoration: InputDecoration( + // labelText: "Select Document", + // labelStyle: TextStyle(fontSize: 12, color: Colors.grey), + // floatingLabelBehavior: FloatingLabelBehavior.never, + // border: InputBorder.none, + // contentPadding: EdgeInsets.symmetric(vertical: 16), + // ), + // ), + // ), + // ), + ], + ), + ], + ), + if (!isDesktop) + SizedBox( + height: 3, ), - if(!isDesktop) SizedBox(height: 3,), - ], - ), + ], ), + // ), ); - } - Widget _buildSecondRowRightColumn(bool isDesktop){ - + Widget _buildSecondRowRightColumn(bool isDesktop) { DateTime? _selectedDateOfIssue; Future _selectCheckDateOfIssue(BuildContext context) async { @@ -1848,11 +2018,10 @@ class _CreateUserFormState extends State{ DateTime? pickedDate = await showDatePicker( context: context, - - - initialDate: _selectedDateOfIssue != null && _selectedDateOfIssue!.isAfter(today) - ? _selectedDateOfIssue! - : today, + initialDate: + _selectedDateOfIssue != null && _selectedDateOfIssue!.isAfter(today) + ? _selectedDateOfIssue! + : today, firstDate: today, lastDate: DateTime(2100), ); @@ -1860,7 +2029,8 @@ class _CreateUserFormState extends State{ if (pickedDate != null && pickedDate != _selectedDateOfIssue) { setState(() { _selectedDateOfIssue = pickedDate; - controllers["dateOfIssue"]?.text = DateFormat('yyyy-MM-dd').format(pickedDate); + controllers["dateOfIssue"]?.text = + DateFormat('yyyy-MM-dd').format(pickedDate); }); } } @@ -1873,9 +2043,8 @@ class _CreateUserFormState extends State{ DateTime? pickedDate = await showDatePicker( context: context, - - - initialDate: _selectedDateOfExpiry != null && _selectedDateOfExpiry!.isAfter(today) + initialDate: _selectedDateOfExpiry != null && + _selectedDateOfExpiry!.isAfter(today) ? _selectedDateOfExpiry! : today, firstDate: today, @@ -1885,672 +2054,748 @@ class _CreateUserFormState extends State{ if (pickedDate != null && pickedDate != _selectedDateOfExpiry) { setState(() { _selectedDateOfExpiry = pickedDate; - controllers["dateOfExpiry"]?.text = DateFormat('yyyy-MM-dd').format(pickedDate); + controllers["dateOfExpiry"]?.text = + DateFormat('yyyy-MM-dd').format(pickedDate); }); } } - - return Container( + return Container( color: Colors.white, - child: Expanded( // Allow second column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Place of Issue", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["placeOfIssue"], - enabled: !isViewMode, - decoration: InputDecoration( - labelText: "Place Of Issue", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), + // child: Expanded( + // Allow second column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Place of Issue", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["placeOfIssue"], + enabled: !isViewMode, + decoration: InputDecoration( + labelText: "Place Of Issue", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), - ], - ), - ], - ), - SizedBox(height: 3,), - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Date of Issue", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: isViewMode? null : ()async{ - await _selectCheckDateOfIssue(context); - if (controllers["dateOfIssue"]!.text.isNotEmpty) { - setState(() { - // errorMessages.remove("start_date"); - }); - } - - }, - child: AbsorbPointer( - child: TextField( - controller: controllers["dateOfIssue"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, - color: Color(0xFF8B8FB2) - ), - ), - ), - ), - ), - - - - ), - ), - ], - ), - ], - ), - SizedBox(height: 3,), - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Date of Expiry", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: GestureDetector( - onTap: isViewMode? null : ()async{ - await _selectCheckDateOfExpiry(context); - if (controllers["dateOfExpiry"]!.text.isNotEmpty) { - setState(() { - // errorMessages.remove("start_date"); - }); - } - - }, - child: AbsorbPointer( - child: TextField( - controller: controllers["dateOfExpiry"], - style: const TextStyle(fontSize: 12), - decoration: const InputDecoration( - labelText: "Select Date", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - suffixIcon: Icon(Icons.calendar_today, - size: 16, - color: Color(0xFF8B8FB2) - ), - ), + ), + ], + ), + ], + ), + SizedBox( + height: 3, + ), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Date of Issue", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: isViewMode + ? null + : () async { + await _selectCheckDateOfIssue(context); + if (controllers["dateOfIssue"]! + .text + .isNotEmpty) { + setState(() { + // errorMessages.remove("start_date"); + }); + } + }, + child: AbsorbPointer( + child: TextField( + controller: controllers["dateOfIssue"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: + EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon(Icons.calendar_today, + size: 16, color: Color(0xFF8B8FB2)), ), ), ), ), ), - ], - ), - ], + ), + ], + ), + ], + ), + SizedBox( + height: 3, + ), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Date of Expiry", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: GestureDetector( + onTap: isViewMode + ? null + : () async { + await _selectCheckDateOfExpiry(context); + if (controllers["dateOfExpiry"]! + .text + .isNotEmpty) { + setState(() { + // errorMessages.remove("start_date"); + }); + } + }, + child: AbsorbPointer( + child: TextField( + controller: controllers["dateOfExpiry"], + style: const TextStyle(fontSize: 12), + decoration: const InputDecoration( + labelText: "Select Date", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: + FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: + EdgeInsets.symmetric(vertical: 16), + suffixIcon: Icon(Icons.calendar_today, + size: 16, color: Color(0xFF8B8FB2)), + ), + ), + ), + ), + ), + ), + ], + ), + ], + ), + if (!isDesktop) + SizedBox( + height: 3, ), - if(!isDesktop) SizedBox(height: 3,), - - ], - ), + ], ), + // ), ); } - //----------------------------------- Employee Organization Details ------------------ - Widget _buildThirdRowLeftColumn(bool isDesktop){ + Widget _buildThirdRowLeftColumn(bool isDesktop) { return Container( color: Colors.white, - child: Expanded( // Allow first column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Employee Code", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: TextField( - style: TextStyle(fontSize: 12), - controller: controllers["employeeCode"], - enabled: !isViewMode, - decoration: InputDecoration( - labelText: "Employee Code", - labelStyle: TextStyle(fontSize: 12, color: Colors.grey), - floatingLabelBehavior: FloatingLabelBehavior.never, + // child: Expanded( + // Allow first column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Employee Code", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: TextField( + style: TextStyle(fontSize: 12), + controller: controllers["employeeCode"], + enabled: !isViewMode, + decoration: InputDecoration( + labelText: "Employee Code", + labelStyle: + TextStyle(fontSize: 12, color: Colors.grey), + floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 16), + ), + ), + ), + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("User Type", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: DropdownSearch( + selectedItem: selectedUserType, + enabled: !isViewMode, + popupProps: PopupProps.menu( + // showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + constraints: BoxConstraints(maxHeight: 250), + ), + items: [ + "Normal", + "Privilege", + ], + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 16), - ), - ), - ), - ), - ], - ), - ], - ), - - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("User Type", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: DropdownSearch( - selectedItem: selectedUserType, - enabled: !isViewMode, - popupProps: PopupProps.menu( - // showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - constraints: BoxConstraints(maxHeight: 250), - - ), - items: ["Normal", "Privilege",], - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), + contentPadding: EdgeInsets.symmetric( + horizontal: 1, ), ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), - ), - ), - onChanged: (String? newValue) { - setState(() { - // Find the country_code based on selected country_name - selectedUserType = newValue; - - // print("selectedUserType - $selectedUserType"); - - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, ), + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: TextStyle(fontSize: 12), + ), + ), + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedUserType = newValue; + + // print("selectedUserType - $selectedUserType"); + + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), ), - ], - ), - ], - ), - if(!isDesktop) - SizedBox(height: 3), - ], - ), + ), + ], + ), + ], + ), + if (!isDesktop) SizedBox(height: 3), + ], ), + // ), ); } - Widget _buildThirdRowRightColumn(bool isDesktop){ + Widget _buildThirdRowRightColumn(bool isDesktop) { return Container( color: Colors.white, - child: Expanded( // Allow second column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + // child: Expanded( + // Allow second column to take available space - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Role ", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, // Dropdown doesn't use focus - isDesktop: isDesktop, - child: SizedBox( - height: 45, // Set appropriate height - child: DropdownButtonFormField( - value: selectedRole, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( - border: InputBorder.none, - contentPadding: - EdgeInsets.symmetric(horizontal: 10), // Proper padding - ), - onChanged: isViewMode ? null : (newValue) { - setState(() { - selectedRole = newValue; - }); - }, - - items:apiRoleData?.map>((item){ - return DropdownMenuItem( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Role ", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, // Dropdown doesn't use focus + isDesktop: isDesktop, + child: SizedBox( + height: 45, // Set appropriate height + child: DropdownButtonFormField( + value: selectedRole, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 10), // Proper padding + ), + onChanged: isViewMode + ? null + : (newValue) { + setState(() { + selectedRole = newValue; + }); + }, + items: + apiRoleData?.map>((item) { + return DropdownMenuItem( value: item['dropdown_key'], // ID as value - child:Text(item['dropdown_value'] ?? "Select") - - ); - }).toList(), - hint: Text("Select"), - ), + child: Text(item['dropdown_value'] ?? "Select")); + }).toList(), + hint: Text("Select"), ), ), - ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Group", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - child: SizedBox( - height: 40, - child: DropdownSearch( - selectedItem: selectedLevel, - enabled: !isViewMode, - popupProps: PopupProps.menu( - // showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - constraints: BoxConstraints(maxHeight: 250), - - ), - items: ["Level 1", "Level 2", "Level 3"], - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), - ), - ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), - ), - ), - onChanged: (String? newValue) { - setState(() { - // Find the country_code based on selected country_name - selectedLevel = newValue; - - - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Group", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + child: SizedBox( + height: 40, + child: DropdownSearch( + selectedItem: selectedLevel, + enabled: !isViewMode, + popupProps: PopupProps.menu( + // showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + constraints: BoxConstraints(maxHeight: 250), ), - ), - ), - ], - ), - ], - ), - SizedBox(height: 3), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Department", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, // Dropdown doesn't use focus - isDesktop: isDesktop, - child: SizedBox( - height: 45, // Set appropriate height - child: DropdownButtonFormField( - value: selectedDepartment, - style: TextStyle(fontSize: 12), - decoration: InputDecoration( + items: ["Level 1", "Level 2", "Level 3"], + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( border: InputBorder.none, - contentPadding: - EdgeInsets.symmetric(horizontal: 10), // Proper padding + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + ), ), - onChanged: isViewMode ? null : (newValue) { - setState(() { - selectedDepartment = newValue; - }); - }, - items:apiCostData?.map>((item){ - return DropdownMenuItem( - value: item['department_id'], // ID as value - child: Text(item['name'] ?? "Unknown"), - ); - }).toList(), - hint: Text("Select"), ), + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: TextStyle(fontSize: 12), + ), + ), + onChanged: (String? newValue) { + setState(() { + // Find the country_code based on selected country_name + selectedLevel = newValue; + + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), ), - ], - ), - ], - ), - - ], - ), + ), + ], + ), + ], + ), + SizedBox(height: 3), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Department", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, // Dropdown doesn't use focus + isDesktop: isDesktop, + child: SizedBox( + height: 45, // Set appropriate height + child: DropdownButtonFormField( + value: selectedDepartment, + style: TextStyle(fontSize: 12), + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 10), // Proper padding + ), + onChanged: isViewMode + ? null + : (newValue) { + setState(() { + selectedDepartment = newValue; + }); + }, + items: + apiCostData?.map>((item) { + return DropdownMenuItem( + value: item['department_id'], // ID as value + child: Text(item['name'] ?? "Unknown"), + ); + }).toList(), + hint: Text("Select"), + ), + ), + ), + ], + ), + ], + ), + ], ), + + // ), ); } - - //----------------------------------- Approver --------------------------------------- - Widget _buildForthRowLeftColumn(bool isDesktop){ - - + Widget _buildForthRowLeftColumn(bool isDesktop) { return Container( color: Colors.white, - child: Expanded( // Allow first column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("First Approver", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - width: isDesktop? MediaQuery.of(context).size.width * 0.2 : MediaQuery.of(context).size.width * 0.8, - child: SizedBox( - height: 40, - child: apiUserData == null - ? Center(child: Transform.scale(scale: 0.5, child: CircularProgressIndicator(),),) - : DropdownSearch( - selectedItem: userMap[selectedFirstApprover], - enabled: !isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), + // child: Expanded( + // Allow first column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("First Approver", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + width: isDesktop + ? MediaQuery.of(context).size.width * 0.2 + : MediaQuery.of(context).size.width * 0.8, + child: SizedBox( + height: 40, + child: apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), ), + ) + : DropdownSearch( + selectedItem: userMap[selectedFirstApprover], + enabled: !isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + constraints: BoxConstraints(maxHeight: 250), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: + EdgeInsets.symmetric(horizontal: 10), + ), + ), + ), + items: apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + ), + ), + ), + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: TextStyle(fontSize: 12), + ), + ), + onChanged: (String? newValue) { + setState(() { + selectedFirstApprover = userMap.entries + .firstWhere( + (entry) => entry.value == newValue) + .key; + + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), - ), - items: apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), - ), - - - ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), - ), - ), - onChanged: (String? newValue) { - setState(() { - - selectedFirstApprover = userMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, - ), - ), ), - ], - ), - ], - ), - ], - ), + ), + ], + ), + ], + ), + ], ), + // ), ); } - Widget _buildForthRowRightColumn(bool isDesktop){ + Widget _buildForthRowRightColumn(bool isDesktop) { return Container( - color: Colors.white, - child: Expanded( // Allow second column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + color: Colors.white, + // child: Expanded( + // Allow second column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( children: [ - Row( + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Second Approver", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - width: isDesktop? MediaQuery.of(context).size.width * 0.2 : MediaQuery.of(context).size.width * 0.8, - child: SizedBox( - height: 40, - child: apiUserData == null - ? Center(child: Transform.scale(scale: 0.5, child: CircularProgressIndicator(),),) - : DropdownSearch( - selectedItem: userMap[selectedSecondApprover], - enabled: !isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), + Text("Second Approver", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + width: isDesktop + ? MediaQuery.of(context).size.width * 0.2 + : MediaQuery.of(context).size.width * 0.8, + child: SizedBox( + height: 40, + child: apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: userMap[selectedSecondApprover], + enabled: !isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + constraints: BoxConstraints(maxHeight: 250), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: + EdgeInsets.symmetric(horizontal: 10), + ), ), ), - ), - items: apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), + items: apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + ), + ), ), - - - ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: TextStyle(fontSize: 12), + ), ), + onChanged: (String? newValue) { + setState(() { + selectedSecondApprover = userMap.entries + .firstWhere( + (entry) => entry.value == newValue) + .key; + + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), - onChanged: (String? newValue) { - setState(() { - - selectedSecondApprover = userMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, - ), - ), - - ), - ], + ), ), ], ), - ], ), - ), + ], + ), + // ), ); } - Widget _buildForthRowLastColumn(bool isDesktop){ + Widget _buildForthRowLastColumn(bool isDesktop) { return Container( - color: Colors.white, - child: Expanded( // Allow second column to take available space - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + color: Colors.white, + // child: Expanded( + // Allow second column to take available space + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( children: [ - Row( + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Third Approver", style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200, color: Colors.black)), - SizedBox(height: 5), - CustomTextFieldUserWrapper( - isFocused: false, - isDesktop: isDesktop, - width: isDesktop? MediaQuery.of(context).size.width * 0.2 : MediaQuery.of(context).size.width * 0.8, - child: SizedBox( - height: 40, - child: apiUserData == null - ? Center(child: Transform.scale(scale: 0.5, child: CircularProgressIndicator(),),) - : DropdownSearch( - selectedItem: userMap[selectedThirdApprover], - enabled: !isViewMode, - popupProps: PopupProps.menu( - showSearchBox: true, - fit: FlexFit.loose, // Allows flexible height - constraints: BoxConstraints(maxHeight: 250), - searchFieldProps: TextFieldProps( - decoration: InputDecoration( - hintText: "Search User...", - contentPadding: EdgeInsets.symmetric(horizontal: 10), + Text("Third Approver", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w200, + color: Colors.black)), + SizedBox(height: 5), + CustomTextFieldUserWrapper( + isFocused: false, + isDesktop: isDesktop, + width: isDesktop + ? MediaQuery.of(context).size.width * 0.2 + : MediaQuery.of(context).size.width * 0.8, + child: SizedBox( + height: 40, + child: apiUserData == null + ? Center( + child: Transform.scale( + scale: 0.5, + child: CircularProgressIndicator(), + ), + ) + : DropdownSearch( + selectedItem: userMap[selectedThirdApprover], + enabled: !isViewMode, + popupProps: PopupProps.menu( + showSearchBox: true, + fit: FlexFit.loose, // Allows flexible height + constraints: BoxConstraints(maxHeight: 250), + searchFieldProps: TextFieldProps( + decoration: InputDecoration( + hintText: "Search User...", + contentPadding: + EdgeInsets.symmetric(horizontal: 10), + ), ), ), - ), - items: apiUserData!.map((user) { - return "${user['first_name']} ${user['last_name']}"; - }).toList(), - - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 1,), + items: apiUserData!.map((user) { + return "${user['first_name']} ${user['last_name']}"; + }).toList(), + dropdownDecoratorProps: DropDownDecoratorProps( + dropdownSearchDecoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 1, + ), + ), ), - - - ), - dropdownBuilder: (context, selectedItem) => Align( // Center-align selected item - alignment: Alignment.centerLeft, - child: Text( - selectedItem ?? "Select", - style: TextStyle(fontSize: 12), + dropdownBuilder: (context, selectedItem) => Align( + // Center-align selected item + alignment: Alignment.centerLeft, + child: Text( + selectedItem ?? "Select", + style: TextStyle(fontSize: 12), + ), ), + onChanged: (String? newValue) { + setState(() { + selectedThirdApprover = userMap.entries + .firstWhere( + (entry) => entry.value == newValue) + .key; + + // if (selectedCountry!.isNotEmpty) { + // errorMessages.remove("country_code"); + // } + }); + }, ), - onChanged: (String? newValue) { - setState(() { - - selectedThirdApprover = userMap.entries - .firstWhere((entry) => entry.value == newValue) - .key; - - // if (selectedCountry!.isNotEmpty) { - // errorMessages.remove("country_code"); - // } - - }); - }, - ), - ), - ), - ], + ), ), ], ), - ], ), - ), + ], + ), + // ), ); } - //----------------------------------- Submit --------------------------------------- - List _buildSubmit(isDesktop){ - return[ + List _buildSubmit(isDesktop) { + return [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.white, @@ -2561,20 +2806,26 @@ class _CreateUserFormState extends State{ ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), - onPressed: (){ + onPressed: () { context.go('/listUser'); }, - child: Text("Cancel") - + child: Text("Cancel")), + SizedBox( + width: 20, ), - SizedBox(width: 20,), MouseRegion( - cursor: isViewMode ? SystemMouseCursors.forbidden : SystemMouseCursors.click, + cursor: isViewMode + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, child: ElevatedButton( style: ElevatedButton.styleFrom( - backgroundColor: isViewMode ? Colors.blueAccent : Colors.blueAccent, // Keep original color - foregroundColor: isViewMode ? Colors.white : Colors.white, // Keep original color - disabledBackgroundColor: Colors.blueAccent, // Ensure color remains when disabled + backgroundColor: isViewMode + ? Colors.blueAccent + : Colors.blueAccent, // Keep original color + foregroundColor: + isViewMode ? Colors.white : Colors.white, // Keep original color + disabledBackgroundColor: + Colors.blueAccent, // Ensure color remains when disabled disabledForegroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -2582,18 +2833,13 @@ class _CreateUserFormState extends State{ ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), - onPressed: isViewMode ? null : handleSubmit, // Disable when in view mode + onPressed: + isViewMode ? null : handleSubmit, // Disable when in view mode child: Text("Submit"), ), ) - - ]; } - - - - } class DatabaseHelper { @@ -2610,4 +2856,4 @@ class DatabaseHelper { Future fetchData() async { // Implement data fetching logic } -} \ No newline at end of file +} diff --git a/lib/Screens/userManagement/user_List.dart b/lib/Screens/userManagement/user_List.dart index 32e4e2d..c6657df 100644 --- a/lib/Screens/userManagement/user_List.dart +++ b/lib/Screens/userManagement/user_List.dart @@ -22,7 +22,6 @@ class _UserListScreenState extends State { Future getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('auth_token'); - } Future> fetchUsers() async { @@ -74,11 +73,12 @@ class _UserListScreenState extends State { final data = json.decode(response.body); print("Country - $data"); - if (!data.containsKey('data') || data['data'] is!List) { - throw Exception("Invalid response format: 'data' field is missing or not a List"); + if (!data.containsKey('data') || data['data'] is! List) { + throw Exception( + "Invalid response format: 'data' field is missing or not a List"); } - List plansJson = data['data']; // 'data' is a Map, not a List + List plansJson = data['data']; // 'data' is a Map, not a List if (data['data'] is List) { List plansJson = data['data']; @@ -91,7 +91,6 @@ class _UserListScreenState extends State { apiCountryData = plansJson; // Store API response in state }); print('plansJSONContry - $plansJson'); - } catch (e) { throw Exception('Error parsing response: $e'); } @@ -100,7 +99,6 @@ class _UserListScreenState extends State { } } - @override void initState() { super.initState(); @@ -108,15 +106,15 @@ class _UserListScreenState extends State { fetchCountryList(); } - void handleDelete(userId){ + void handleDelete(userId) { print("handDel - $userId"); } - void handleToggleUserStatus(String userId, String currentStatus) async { print("Toggling user status - $userId (Current: $currentStatus)"); - final String apiUrlData = '$apiUrl/api/users/update/$userId'; // API for updating user + final String apiUrlData = + '$apiUrl/api/users/update/$userId'; // API for updating user final String? token = await getToken(); if (token == null) { @@ -158,331 +156,412 @@ class _UserListScreenState extends State { }); } - @override Widget build(BuildContext context) { return ResponsiveBuilder(builder: (context, sizingInfo) { bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; - return Scaffold( - appBar: isDesktop ? null : const CustomAppBar(title:'User Management'), + appBar: isDesktop ? null : const CustomAppBar(title: 'User Management'), drawer: isDesktop ? null : CustomDrawer(isDesktop: false), - body: - Container( + body: Container( color: Colors.white, child: Row( children: [ - if(isDesktop) - CustomDrawer(isDesktop: true), + if (isDesktop) CustomDrawer(isDesktop: true), // const Expanded(child: Center(child: Text("User Page Content"))), Expanded(child: buildUserTable(isDesktop)), ], ), ), ); - - }); } Widget buildUserTable(bool isDesktop) { - - - return Padding( padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + child: + Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - const Text('User List', - style: - TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - IconButton( - icon: const Icon(Icons.keyboard_arrow_down), - onPressed: () { - - }, - ), - ], - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Colors.blueAccent), - onPressed: () async { - - List users = await futureUsers; - - // Print the resolved value - print("CREATELIAS - $users"); - - context.go("/CreateUserDetails", - extra: { - // 'apiCountryData': apiCountryData, - 'apiUserData' :users, - } - ); - if (!isDesktop) Navigator.pop(context); - }, - child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( children: [ - Icon(Icons.add_circle,color: Colors.white,), - SizedBox(width: 5,), - Text('New User'), + const Text('User List', + style: + TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + IconButton( + icon: const Icon(Icons.keyboard_arrow_down), + onPressed: () {}, + ), ], ), - ), - ], - ), - const SizedBox(height: 10), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Colors.blueAccent), + onPressed: () async { + List users = await futureUsers; - FutureBuilder>( - future: futureUsers, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text("Error: ${snapshot.error}")); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text("No users found")); - } + // Print the resolved value + print("CREATELIAS - $users"); - List users = snapshot.data!; - Color borderColor = Color(0xFF9E9DBD); + context.go("/CreateUserDetails", extra: { + // 'apiCountryData': apiCountryData, + 'apiUserData': users, + }); + if (!isDesktop) Navigator.pop(context); + }, + child: Row( + children: [ + Icon( + Icons.add_circle, + color: Colors.white, + ), + SizedBox( + width: 5, + ), + Text('New User'), + ], + ), + ), + ], + ), + const SizedBox(height: 10), + FutureBuilder>( + future: futureUsers, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text("Error: ${snapshot.error}")); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center(child: Text("No users found")); + } - return Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SizedBox( - width: MediaQuery.of(context).size.width * 1.5, - child: SingleChildScrollView( + List users = snapshot.data!; + Color borderColor = Color(0xFF9E9DBD); - scrollDirection: Axis.horizontal, // Inner wrapper for vertical scrolling + return Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: SizedBox( + width: MediaQuery.of(context).size.width * 1.5, + child: SingleChildScrollView( + scrollDirection: Axis + .horizontal, // Inner wrapper for vertical scrolling - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: MediaQuery.of(context).size.width), - // constraints: BoxConstraints(minWidth: 1300), - // width: MediaQuery.of(context).size.width , + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: MediaQuery.of(context).size.width * 0.8), + // constraints: BoxConstraints(minWidth: 1300), + // width: MediaQuery.of(context).size.width , - child: Container( - // color: Colors.amber, - child: DataTable( - columnSpacing: 20.0, // Adjust spacing between columns - dividerThickness: 0.5, - dataRowMinHeight: 60.0, // Minimum row height - dataRowMaxHeight: 100.0, - border: TableBorder( - horizontalInside: BorderSide(width: 0.5, color: Colors.grey.shade200), - ), - columns: const [ + child: Container( + // color: Colors.grey, + // color: Colors.amber, + child: DataTable( + columnSpacing: + 20.0, // Adjust spacing between columns + dividerThickness: 0.5, + dataRowMinHeight: 60.0, // Minimum row height + dataRowMaxHeight: 100.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, color: Colors.grey.shade200), + ), + columns: const [ + DataColumn( + label: Text( + 'User Details', + style: TextStyle( + color: Color(0xFF9E9DBD), + fontSize: 15, + fontWeight: FontWeight.bold), + )), + DataColumn( + label: Text( + 'Role', + style: TextStyle( + color: Color(0xFF9E9DBD), + fontSize: 15, + fontWeight: FontWeight.bold), + )), + DataColumn( + label: Text( + 'Level', + style: TextStyle( + color: Color(0xFF9E9DBD), + fontSize: 15, + fontWeight: FontWeight.bold), + )), + DataColumn( + label: Text( + 'Status', + style: TextStyle( + color: Color(0xFF9E9DBD), + fontSize: 15, + fontWeight: FontWeight.bold), + )), + DataColumn( + label: Text( + 'Actions', + style: TextStyle( + color: Color(0xFF9E9DBD), + fontSize: 15, + fontWeight: FontWeight.bold), + )), + ], - DataColumn(label: Text('User Details',style: TextStyle(color: Color(0xFF9E9DBD),fontSize: 15, fontWeight: FontWeight.bold),)), - DataColumn(label: Text('Role',style: TextStyle(color: Color(0xFF9E9DBD),fontSize: 15, fontWeight: FontWeight.bold),)), - DataColumn(label: Text('Level',style: TextStyle(color: Color(0xFF9E9DBD),fontSize: 15, fontWeight: FontWeight.bold),)), - DataColumn(label: Text('Status',style: TextStyle(color: Color(0xFF9E9DBD),fontSize: 15, fontWeight: FontWeight.bold),)), - DataColumn(label: Text('Actions',style: TextStyle(color: Color(0xFF9E9DBD),fontSize: 15, fontWeight: FontWeight.bold),)), + rows: users.map((user) { + String userId = + user['user_id'].toString(); // Get user ID + bool isSelected = selectedUserId == userId; - ], + return DataRow(cells: [ + // DataCell(Text(user['user_id'].toString())), + DataCell(Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.center, + child: GestureDetector( + onTap: () { + setState(() { + selectedUserId = + userId; // Store clicked user ID + }); + }, + child: Container( + width: 15, // Adjust size + height: 15, + decoration: BoxDecoration( + // Background color + shape: BoxShape.rectangle, + border: Border.all( + color: isSelected + ? Colors.blueAccent + : Color(0xFF9E9DBD), + // color: Color(0xFF9E9DBD), + // color: Color.fromRGBO(128, 128, 128, 0.6), + width: isSelected + ? 2 + : 1), // Grey outline + ), + ), + ), + ), + SizedBox( + width: 50, + ), + Align( + alignment: Alignment.center, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Color(0xFF9E9DBD), + width: 1), // Grey outline + ), + child: Padding( + padding: const EdgeInsets.all(2.0), + child: Container( + width: 40, // Adjust size + height: 40, + decoration: BoxDecoration( + color: Colors + .amber, // Inner circle background + shape: BoxShape.circle, + ), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Text( + (user['first_name'] != + null && + user['first_name']! + .isNotEmpty) + ? user['first_name']![0] + .toUpperCase() + : "?", + style: TextStyle( + fontSize: 18, + fontWeight: + FontWeight.bold, + color: Colors.white, + ), + ), + ], + ), + ), + )), + ), + SizedBox( + width: 20, + ), + Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "${user['first_name'] ?? ''} ${user['last_name'] ?? ''}", + style: TextStyle( + color: Colors.blueAccent, + fontSize: 16), + ), + ], + ), + SizedBox(height: 5), + Row( + children: [ + Icon(Icons.mail_outline, + size: 15, + color: Color(0xFF9E9EBE)), + SizedBox( + width: 10, + ), + Text(user['email'] ?? '') + ], + ), + SizedBox(height: 5), + Row( + children: [ + Icon(Icons.account_tree_outlined, + size: 15, + color: Color(0xFF9E9EBE)), + SizedBox( + width: 10, + ), + Text(user['user_type'] ?? '') + ], + ), + ], + ), + ], + )), - rows: users.map((user) { - String userId = user['user_id'].toString(); // Get user ID - bool isSelected = selectedUserId == userId; + DataCell(Text( + user['role_id'] ?? 'N/A', + style: TextStyle( + color: user['is_active'] == "1" + ? Colors.black + : Colors.grey, + fontWeight: FontWeight.bold), + )), + DataCell(Text( + user['level_id'] ?? 'N/A', + style: TextStyle( + color: user['is_active'] == "1" + ? Colors.black + : Colors.grey, + fontWeight: FontWeight.bold), + )), + DataCell(GestureDetector( + onTap: () { + handleToggleUserStatus( + user['user_id'], user['is_active']); + }, + child: Text( + user['is_active'] == "1" + ? "Active" + : "Inactive", + style: TextStyle( + color: user['is_active'] == "1" + ? Colors.lightGreen + : Colors.grey, + fontWeight: FontWeight.bold), + ))), - return DataRow(cells: [ - // DataCell(Text(user['user_id'].toString())), - DataCell( - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Align(alignment: Alignment.center, - child: GestureDetector( - onTap: () { - setState(() { - selectedUserId = userId; // Store clicked user ID - }); - }, - child: Container( - width: 15, // Adjust size - height: 15, - decoration: BoxDecoration( - // Background color - shape: BoxShape.rectangle, - border: Border.all( - color: isSelected ? Colors.blueAccent : Color(0xFF9E9DBD), - // color: Color(0xFF9E9DBD), - // color: Color.fromRGBO(128, 128, 128, 0.6), - width: isSelected ?2:1), // Grey outline - ), - ), - ), - ), - - - - SizedBox(width: 50,), - Align( - alignment: Alignment.center, - child: Container( - - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: Color(0xFF9E9DBD), width: 1), // Grey outline - ), - - child: Padding( - padding: const EdgeInsets.all(2.0), - child: Container( - - width: 40, // Adjust size - height: 40, - decoration: BoxDecoration( - color: Colors.amber, // Inner circle background - shape: BoxShape.circle, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - (user['first_name'] != null && user['first_name']!.isNotEmpty) - ? user['first_name']![0].toUpperCase() - : "?", - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), - ),], - - - ), - ), - )), - ), - SizedBox(width: 20,), - - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - Text("${user['first_name'] ?? ''} ${user['last_name'] ?? ''}", - style: TextStyle( color: Colors.blueAccent,fontSize: 16),), - ],), - - SizedBox(height: 5), - - Row(children: [ - Icon(Icons.mail_outline, size: 15,color: Color(0xFF9E9EBE)), - SizedBox(width: 10,), - Text(user['email'] ?? '') - ],), - - SizedBox(height: 5), - Row(children: [ - Icon(Icons.account_tree_outlined, size: 15,color:Color(0xFF9E9EBE)), - SizedBox(width: 10,), - Text(user['user_type'] ?? '') ],), - ],), - ], - ) - ), - - DataCell(Text(user['role_id'] ?? 'N/A',style: TextStyle(color: user['is_active'] == "1" ? Colors.black :Colors.grey, fontWeight: FontWeight.bold),)), - DataCell(Text(user['level_id'] ?? 'N/A',style: TextStyle(color: user['is_active'] == "1" ? Colors.black :Colors.grey, fontWeight: FontWeight.bold),)), - DataCell( - GestureDetector( onTap :(){ - handleToggleUserStatus(user['user_id'], user['is_active']); - }, - child: Text( - user['is_active'] == "1" ? "Active" : "Inactive", - style: TextStyle(color: user['is_active'] == "1" ? Colors.lightGreen :Colors.grey , - - fontWeight: FontWeight.bold),) - - ) - - ), - - - DataCell( - Row( - children: [ - MouseRegion( - cursor: user['is_active'] == "0" ? SystemMouseCursors.forbidden : SystemMouseCursors.click, - child: IconButton( - icon: Icon(Icons.remove_red_eye, color: user['is_active'] == "0" ? Colors.grey : Colors.blueAccent), - onPressed: user['is_active'] == "0" - ? null - : () { - context.go( - "/CreateUserDetails", - extra: { - "selectedUser": user, - "isViewMode": true - - }, - ); - }, - ), - ), - MouseRegion( - cursor: user['is_active'] == "0" ? SystemMouseCursors.forbidden : SystemMouseCursors.click, - child: IconButton( - icon: Icon(Icons.edit, color: user['is_active'] == "0" ? Colors.grey : Colors.green), - onPressed: user['is_active'] == "0" - ? null - : () { - print("USER: $user"); - context.go( - "/CreateUserDetails", - extra: { - "selectedUser": user, - "isViewMode": false - - }, - ); - }, - ), - ), - MouseRegion( - cursor: user['is_active'] == "0" ? SystemMouseCursors.forbidden : SystemMouseCursors.click, - child: IconButton( - icon: Icon(Icons.delete, color: user['is_active'] == "0" ? Colors.grey : Colors.redAccent), - onPressed: user['is_active'] == "0" - ? null - : () { - print("USER ID: ${user['user_id']}"); - var userId = user['user_id']; - handleDelete(userId); - }, - ), - ), - ], - ), - ), - - ]); - }).toList(), - - ), - ), - ), - ), - ), - ), - ); - - }, - ), - - - - - ])); + DataCell( + Row( + children: [ + MouseRegion( + cursor: user['is_active'] == "0" + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, + child: IconButton( + icon: Icon(Icons.remove_red_eye, + color: user['is_active'] == "0" + ? Colors.grey + : Colors.blueAccent), + onPressed: user['is_active'] == "0" + ? null + : () { + context.go( + "/CreateUserDetails", + extra: { + "selectedUser": user, + "isViewMode": true + }, + ); + }, + ), + ), + MouseRegion( + cursor: user['is_active'] == "0" + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, + child: IconButton( + icon: Icon(Icons.edit, + color: user['is_active'] == "0" + ? Colors.grey + : Colors.green), + onPressed: user['is_active'] == "0" + ? null + : () { + print("USER: $user"); + context.go( + "/CreateUserDetails", + extra: { + "selectedUser": user, + "isViewMode": false + }, + ); + }, + ), + ), + MouseRegion( + cursor: user['is_active'] == "0" + ? SystemMouseCursors.forbidden + : SystemMouseCursors.click, + child: IconButton( + icon: Icon(Icons.delete, + color: user['is_active'] == "0" + ? Colors.grey + : Colors.redAccent), + onPressed: user['is_active'] == "0" + ? null + : () { + print( + "USER ID: ${user['user_id']}"); + var userId = user['user_id']; + handleDelete(userId); + }, + ), + ), + ], + ), + ), + ]); + }).toList(), + ), + ), + ), + ), + ), + ), + ); + }, + ), + ])); } }