resolved the email and has application acccess is not populated on edit
This commit is contained in:
parent
843f394ebe
commit
a1bd9a3108
@ -72,42 +72,41 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
||||
|
||||
controller.enteredTags.assignAll(c.tags.map((e) => e.name));
|
||||
|
||||
ever(controller.isInitialized, (bool ready) {
|
||||
if (ready) {
|
||||
final projectIds = c.projectIds;
|
||||
final bucketId = c.bucketIds.firstOrNull;
|
||||
final category = c.contactCategory?.name;
|
||||
|
||||
if (category != null) controller.selectedCategory.value = category;
|
||||
|
||||
if (projectIds != null) {
|
||||
controller.selectedProjects.assignAll(
|
||||
projectIds
|
||||
.map((id) => controller.projectsMap.entries
|
||||
.firstWhereOrNull((e) => e.value == id)
|
||||
?.key)
|
||||
.whereType<String>()
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
if (bucketId != null) {
|
||||
final name = controller.bucketsMap.entries
|
||||
.firstWhereOrNull((e) => e.value == bucketId)
|
||||
ever(controller.isInitialized, (bool ready) {
|
||||
if (ready) {
|
||||
// Buckets - map all
|
||||
if (c.bucketIds.isNotEmpty) {
|
||||
final names = c.bucketIds.map((id) {
|
||||
return controller.bucketsMap.entries
|
||||
.firstWhereOrNull((e) => e.value == id)
|
||||
?.key;
|
||||
if (name != null && !controller.selectedBuckets.contains(name)) {
|
||||
controller.selectedBuckets.add(name);
|
||||
}
|
||||
}
|
||||
}).whereType<String>().toList();
|
||||
controller.selectedBuckets.assignAll(names);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
emailCtrls.add(TextEditingController());
|
||||
emailLabels.add('Office'.obs);
|
||||
phoneCtrls.add(TextEditingController());
|
||||
phoneLabels.add('Work'.obs);
|
||||
}
|
||||
// Projects and Category mapping - as before
|
||||
final projectIds = c.projectIds;
|
||||
if (projectIds != null) {
|
||||
controller.selectedProjects.assignAll(
|
||||
projectIds
|
||||
.map((id) => controller.projectsMap.entries
|
||||
.firstWhereOrNull((e) => e.value == id)
|
||||
?.key)
|
||||
.whereType<String>()
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
final category = c.contactCategory?.name;
|
||||
if (category != null) controller.selectedCategory.value = category;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showAdvanced.value = false; // Optional
|
||||
emailCtrls.add(TextEditingController());
|
||||
emailLabels.add('Office'.obs);
|
||||
phoneCtrls.add(TextEditingController());
|
||||
phoneLabels.add('Work'.obs);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -375,112 +374,110 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _multiSelectField({
|
||||
required List<FilterItem> items,
|
||||
required String fallback,
|
||||
required RxList<String> selectedValues,
|
||||
}) {
|
||||
if (items.isEmpty) return const SizedBox.shrink();
|
||||
Widget _multiSelectField({
|
||||
required List<FilterItem> items,
|
||||
required String fallback,
|
||||
required RxList<String> selectedValues,
|
||||
}) {
|
||||
if (items.isEmpty) return const SizedBox.shrink();
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Obx(() {
|
||||
final selectedNames = items
|
||||
.where((f) => selectedValues.contains(f.id))
|
||||
.map((f) => f.name)
|
||||
.join(", ");
|
||||
final displayText =
|
||||
selectedNames.isNotEmpty ? selectedNames : fallback;
|
||||
return Obx(() {
|
||||
final selectedNames = items
|
||||
.where((f) => selectedValues.contains(f.id))
|
||||
.map((f) => f.name)
|
||||
.join(", ");
|
||||
final displayText = selectedNames.isNotEmpty ? selectedNames : fallback;
|
||||
|
||||
return Builder(
|
||||
builder: (context) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final RenderBox button =
|
||||
context.findRenderObject() as RenderBox;
|
||||
final RenderBox overlay = Overlay.of(context)
|
||||
.context
|
||||
.findRenderObject() as RenderBox;
|
||||
return Builder(
|
||||
builder: (context) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final RenderBox button =
|
||||
context.findRenderObject() as RenderBox;
|
||||
final RenderBox overlay =
|
||||
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||
final position = button.localToGlobal(Offset.zero);
|
||||
|
||||
final position = button.localToGlobal(Offset.zero);
|
||||
|
||||
await showMenu(
|
||||
context: context,
|
||||
position: RelativeRect.fromLTRB(
|
||||
position.dx,
|
||||
position.dy + button.size.height,
|
||||
overlay.size.width - position.dx - button.size.width,
|
||||
0,
|
||||
),
|
||||
items: items.map((f) {
|
||||
return PopupMenuItem<String>(
|
||||
enabled: false,
|
||||
child: StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
final isChecked = selectedValues.contains(f.id);
|
||||
return CheckboxListTile(
|
||||
dense: true,
|
||||
value: isChecked,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: MyText(f.name),
|
||||
checkColor: Colors.white,
|
||||
side: const BorderSide(
|
||||
color: Colors.black, width: 1.5),
|
||||
fillColor:
|
||||
MaterialStateProperty.resolveWith<Color>(
|
||||
(states) {
|
||||
await showMenu(
|
||||
context: context,
|
||||
position: RelativeRect.fromLTRB(
|
||||
position.dx,
|
||||
position.dy + button.size.height,
|
||||
overlay.size.width - position.dx - button.size.width,
|
||||
0,
|
||||
),
|
||||
items: [
|
||||
PopupMenuItem(
|
||||
enabled: false,
|
||||
child: StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return SizedBox(
|
||||
width: 250,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: items.map((f) {
|
||||
final isChecked = selectedValues.contains(f.id);
|
||||
return CheckboxListTile(
|
||||
dense: true,
|
||||
title: Text(f.name),
|
||||
value: isChecked,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
side: const BorderSide(color: Colors.black, width: 1.5),
|
||||
fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return Colors.indigo;
|
||||
return Colors.indigo; // selected color
|
||||
}
|
||||
return Colors.white;
|
||||
return Colors.white; // unselected background
|
||||
}),
|
||||
checkColor: Colors.white, // tick color
|
||||
onChanged: (val) {
|
||||
if (val == true) {
|
||||
selectedValues.add(f.id);
|
||||
} else {
|
||||
selectedValues.remove(f.id);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
onChanged: (val) {
|
||||
if (val == true) {
|
||||
selectedValues.add(f.id);
|
||||
} else {
|
||||
selectedValues.remove(f.id);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: MySpacing.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade100,
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: MyText(
|
||||
displayText,
|
||||
style: const TextStyle(color: Colors.black87),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
MySpacing.height(16),
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: MySpacing.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade100,
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: MyText(
|
||||
displayText,
|
||||
style: const TextStyle(color: Colors.black87),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void _handleSubmit() {
|
||||
bool valid = formKey.currentState?.validate() ?? false;
|
||||
|
@ -36,7 +36,7 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_orgFieldController = TextEditingController();
|
||||
_joiningDateController = TextEditingController();
|
||||
_genderController = TextEditingController();
|
||||
_roleController = TextEditingController();
|
||||
@ -46,17 +46,33 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
if (widget.employeeData != null) {
|
||||
_controller.editingEmployeeData = widget.employeeData;
|
||||
_controller.prefillFields();
|
||||
// 👇 joining date & gender already handled in your code
|
||||
|
||||
// Prepopulate hasApplicationAccess and email
|
||||
_hasApplicationAccess =
|
||||
widget.employeeData?['hasApplicationAccess'] ?? false;
|
||||
|
||||
final email = widget.employeeData?['email'];
|
||||
if (email != null && email.toString().isNotEmpty) {
|
||||
_controller.basicValidator.getController('email')?.text =
|
||||
email.toString();
|
||||
}
|
||||
|
||||
// Trigger UI rebuild to reflect email & checkbox
|
||||
setState(() {});
|
||||
|
||||
// Joining date
|
||||
if (_controller.joiningDate != null) {
|
||||
_joiningDateController.text =
|
||||
DateFormat('dd MMM yyyy').format(_controller.joiningDate!);
|
||||
}
|
||||
|
||||
// Gender
|
||||
if (_controller.selectedGender != null) {
|
||||
_genderController.text =
|
||||
_controller.selectedGender!.name.capitalizeFirst ?? '';
|
||||
}
|
||||
|
||||
// ✅ Important part: fetch roles, then set roleController
|
||||
// Role
|
||||
_controller.fetchRoles().then((_) {
|
||||
if (_controller.selectedRoleId != null) {
|
||||
final roleName = _controller.roles.firstWhereOrNull(
|
||||
@ -65,6 +81,7 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
||||
if (roleName != null) {
|
||||
_roleController.text = roleName;
|
||||
}
|
||||
_controller.update();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -12,15 +12,17 @@ class EmployeeDetailsModel {
|
||||
final String phoneNumber;
|
||||
final String? emergencyPhoneNumber;
|
||||
final String? emergencyContactPerson;
|
||||
final String? aadharNumber;
|
||||
final bool isActive;
|
||||
final String? panNumber;
|
||||
final String? photo;
|
||||
final String? applicationUserId;
|
||||
final String jobRoleId;
|
||||
final bool isRootUser;
|
||||
final bool isSystem;
|
||||
final String jobRole;
|
||||
|
||||
final String jobRoleId;
|
||||
final String? photo;
|
||||
final String? applicationUserId;
|
||||
final bool hasApplicationAccess;
|
||||
final String? organizationId;
|
||||
final String? aadharNumber;
|
||||
final String? panNumber;
|
||||
EmployeeDetailsModel({
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
@ -35,14 +37,17 @@ class EmployeeDetailsModel {
|
||||
required this.phoneNumber,
|
||||
this.emergencyPhoneNumber,
|
||||
this.emergencyContactPerson,
|
||||
this.aadharNumber,
|
||||
required this.isActive,
|
||||
this.panNumber,
|
||||
this.photo,
|
||||
this.applicationUserId,
|
||||
required this.jobRoleId,
|
||||
required this.isRootUser,
|
||||
required this.isSystem,
|
||||
required this.jobRole,
|
||||
required this.jobRoleId,
|
||||
this.photo,
|
||||
this.applicationUserId,
|
||||
required this.hasApplicationAccess,
|
||||
this.organizationId,
|
||||
this.aadharNumber,
|
||||
this.panNumber,
|
||||
});
|
||||
|
||||
factory EmployeeDetailsModel.fromJson(Map<String, dynamic> json) {
|
||||
@ -60,24 +65,20 @@ class EmployeeDetailsModel {
|
||||
phoneNumber: json['phoneNumber'],
|
||||
emergencyPhoneNumber: json['emergencyPhoneNumber'],
|
||||
emergencyContactPerson: json['emergencyContactPerson'],
|
||||
aadharNumber: json['aadharNumber'],
|
||||
isActive: json['isActive'],
|
||||
panNumber: json['panNumber'],
|
||||
photo: json['photo'],
|
||||
applicationUserId: json['applicationUserId'],
|
||||
jobRoleId: json['jobRoleId'],
|
||||
isRootUser: json['isRootUser'],
|
||||
isSystem: json['isSystem'],
|
||||
jobRole: json['jobRole'],
|
||||
jobRoleId: json['jobRoleId'],
|
||||
photo: json['photo'],
|
||||
applicationUserId: json['applicationUserId'],
|
||||
hasApplicationAccess: json['hasApplicationAccess'],
|
||||
organizationId: json['organizationId'],
|
||||
aadharNumber: json['aadharNumber'],
|
||||
panNumber: json['panNumber'],
|
||||
);
|
||||
}
|
||||
|
||||
static DateTime? _parseDate(String? dateStr) {
|
||||
if (dateStr == null || dateStr == "0001-01-01T00:00:00") {
|
||||
return null;
|
||||
}
|
||||
return DateTime.tryParse(dateStr);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
@ -93,14 +94,24 @@ class EmployeeDetailsModel {
|
||||
'phoneNumber': phoneNumber,
|
||||
'emergencyPhoneNumber': emergencyPhoneNumber,
|
||||
'emergencyContactPerson': emergencyContactPerson,
|
||||
'aadharNumber': aadharNumber,
|
||||
'isActive': isActive,
|
||||
'panNumber': panNumber,
|
||||
'photo': photo,
|
||||
'applicationUserId': applicationUserId,
|
||||
'jobRoleId': jobRoleId,
|
||||
'isRootUser': isRootUser,
|
||||
'isSystem': isSystem,
|
||||
'jobRole': jobRole,
|
||||
'jobRoleId': jobRoleId,
|
||||
'photo': photo,
|
||||
'applicationUserId': applicationUserId,
|
||||
'hasApplicationAccess': hasApplicationAccess,
|
||||
'organizationId': organizationId,
|
||||
'aadharNumber': aadharNumber,
|
||||
'panNumber': panNumber,
|
||||
};
|
||||
}
|
||||
|
||||
static DateTime? _parseDate(String? dateStr) {
|
||||
if (dateStr == null || dateStr == "0001-01-01T00:00:00") {
|
||||
return null;
|
||||
}
|
||||
return DateTime.tryParse(dateStr);
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +261,9 @@ class _EmployeeDetailPageState extends State<EmployeeDetailPage> {
|
||||
'first_name': employee.firstName,
|
||||
'last_name': employee.lastName,
|
||||
'phone_number': employee.phoneNumber,
|
||||
'email': employee.email,
|
||||
'hasApplicationAccess':
|
||||
employee.hasApplicationAccess,
|
||||
'gender': employee.gender.toLowerCase(),
|
||||
'job_role_id': employee.jobRoleId,
|
||||
'joining_date':
|
||||
|
Loading…
x
Reference in New Issue
Block a user