made chnages in add contach for assignment bucket
This commit is contained in:
parent
a18c4dad45
commit
2b8196b216
@ -10,7 +10,7 @@ class AddContactController extends GetxController {
|
|||||||
final RxList<String> tags = <String>[].obs;
|
final RxList<String> tags = <String>[].obs;
|
||||||
|
|
||||||
final RxString selectedCategory = ''.obs;
|
final RxString selectedCategory = ''.obs;
|
||||||
final RxString selectedBucket = ''.obs;
|
final RxList<String> selectedBuckets = <String>[].obs;
|
||||||
final RxString selectedProject = ''.obs;
|
final RxString selectedProject = ''.obs;
|
||||||
|
|
||||||
final RxList<String> enteredTags = <String>[].obs;
|
final RxList<String> enteredTags = <String>[].obs;
|
||||||
@ -50,7 +50,7 @@ class AddContactController extends GetxController {
|
|||||||
void resetForm() {
|
void resetForm() {
|
||||||
selectedCategory.value = '';
|
selectedCategory.value = '';
|
||||||
selectedProject.value = '';
|
selectedProject.value = '';
|
||||||
selectedBucket.value = '';
|
selectedBuckets.clear();
|
||||||
enteredTags.clear();
|
enteredTags.clear();
|
||||||
filteredSuggestions.clear();
|
filteredSuggestions.clear();
|
||||||
filteredOrgSuggestions.clear();
|
filteredOrgSuggestions.clear();
|
||||||
@ -100,7 +100,21 @@ class AddContactController extends GetxController {
|
|||||||
isSubmitting.value = true;
|
isSubmitting.value = true;
|
||||||
|
|
||||||
final categoryId = categoriesMap[selectedCategory.value];
|
final categoryId = categoriesMap[selectedCategory.value];
|
||||||
final bucketId = bucketsMap[selectedBucket.value];
|
final bucketIds = selectedBuckets
|
||||||
|
.map((name) => bucketsMap[name])
|
||||||
|
.whereType<String>()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (bucketIds.isEmpty) {
|
||||||
|
showAppSnackbar(
|
||||||
|
title: "Missing Buckets",
|
||||||
|
message: "Please select at least one bucket.",
|
||||||
|
type: SnackbarType.warning,
|
||||||
|
);
|
||||||
|
isSubmitting.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final projectIds = selectedProjects
|
final projectIds = selectedProjects
|
||||||
.map((name) => projectsMap[name])
|
.map((name) => projectsMap[name])
|
||||||
.whereType<String>()
|
.whereType<String>()
|
||||||
@ -126,10 +140,10 @@ class AddContactController extends GetxController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedBucket.value.trim().isEmpty || bucketId == null) {
|
if (selectedBuckets.isEmpty) {
|
||||||
showAppSnackbar(
|
showAppSnackbar(
|
||||||
title: "Missing Bucket",
|
title: "Missing Bucket",
|
||||||
message: "Please select a bucket.",
|
message: "Please select at least one bucket.",
|
||||||
type: SnackbarType.warning,
|
type: SnackbarType.warning,
|
||||||
);
|
);
|
||||||
isSubmitting.value = false;
|
isSubmitting.value = false;
|
||||||
@ -151,7 +165,7 @@ class AddContactController extends GetxController {
|
|||||||
if (selectedCategory.value.isNotEmpty && categoryId != null)
|
if (selectedCategory.value.isNotEmpty && categoryId != null)
|
||||||
"contactCategoryId": categoryId,
|
"contactCategoryId": categoryId,
|
||||||
if (projectIds.isNotEmpty) "projectIds": projectIds,
|
if (projectIds.isNotEmpty) "projectIds": projectIds,
|
||||||
"bucketIds": [bucketId],
|
"bucketIds": bucketIds,
|
||||||
if (enteredTags.isNotEmpty) "tags": tagObjects,
|
if (enteredTags.isNotEmpty) "tags": tagObjects,
|
||||||
if (emails.isNotEmpty) "contactEmails": emails,
|
if (emails.isNotEmpty) "contactEmails": emails,
|
||||||
if (phones.isNotEmpty) "contactPhones": phones,
|
if (phones.isNotEmpty) "contactPhones": phones,
|
||||||
|
@ -73,7 +73,8 @@ class AddEmployeeController extends MyController {
|
|||||||
controller: TextEditingController(),
|
controller: TextEditingController(),
|
||||||
);
|
);
|
||||||
|
|
||||||
logSafe('Fields initialized for first_name, phone_number, last_name, email.');
|
logSafe(
|
||||||
|
'Fields initialized for first_name, phone_number, last_name, email.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefill fields in edit mode
|
// Prefill fields in edit mode
|
||||||
@ -87,7 +88,8 @@ class AddEmployeeController extends MyController {
|
|||||||
editingEmployeeData?['phone_number'] ?? '';
|
editingEmployeeData?['phone_number'] ?? '';
|
||||||
|
|
||||||
selectedGender = editingEmployeeData?['gender'] != null
|
selectedGender = editingEmployeeData?['gender'] != null
|
||||||
? Gender.values.firstWhereOrNull((g) => g.name == editingEmployeeData!['gender'])
|
? Gender.values
|
||||||
|
.firstWhereOrNull((g) => g.name == editingEmployeeData!['gender'])
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
basicValidator.getController('email')?.text =
|
basicValidator.getController('email')?.text =
|
||||||
@ -121,12 +123,24 @@ class AddEmployeeController extends MyController {
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
roles = List<Map<String, dynamic>>.from(result);
|
roles = List<Map<String, dynamic>>.from(result);
|
||||||
logSafe('Roles fetched successfully.');
|
logSafe('Roles fetched successfully.');
|
||||||
|
|
||||||
|
// ✅ If editing, and role already selected, update the role controller text here
|
||||||
|
if (editingEmployeeData != null && selectedRoleId != null) {
|
||||||
|
final selectedRole = roles.firstWhereOrNull(
|
||||||
|
(r) => r['id'] == selectedRoleId,
|
||||||
|
);
|
||||||
|
if (selectedRole != null) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
logSafe('Failed to fetch roles: null result', level: LogLevel.error);
|
logSafe('Failed to fetch roles: null result', level: LogLevel.error);
|
||||||
}
|
}
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
logSafe('Error fetching roles', level: LogLevel.error, error: e, stackTrace: st);
|
logSafe('Error fetching roles',
|
||||||
|
level: LogLevel.error, error: e, stackTrace: st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +170,8 @@ class AddEmployeeController extends MyController {
|
|||||||
|
|
||||||
final firstName = basicValidator.getController('first_name')?.text.trim();
|
final firstName = basicValidator.getController('first_name')?.text.trim();
|
||||||
final lastName = basicValidator.getController('last_name')?.text.trim();
|
final lastName = basicValidator.getController('last_name')?.text.trim();
|
||||||
final phoneNumber = basicValidator.getController('phone_number')?.text.trim();
|
final phoneNumber =
|
||||||
|
basicValidator.getController('phone_number')?.text.trim();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// sanitize orgId before sending
|
// sanitize orgId before sending
|
||||||
@ -216,7 +231,8 @@ class AddEmployeeController extends MyController {
|
|||||||
|
|
||||||
showAppSnackbar(
|
showAppSnackbar(
|
||||||
title: 'Permission Required',
|
title: 'Permission Required',
|
||||||
message: 'Please allow Contacts permission from settings to pick a contact.',
|
message:
|
||||||
|
'Please allow Contacts permission from settings to pick a contact.',
|
||||||
type: SnackbarType.warning,
|
type: SnackbarType.warning,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
@ -95,7 +95,9 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
|||||||
final name = controller.bucketsMap.entries
|
final name = controller.bucketsMap.entries
|
||||||
.firstWhereOrNull((e) => e.value == bucketId)
|
.firstWhereOrNull((e) => e.value == bucketId)
|
||||||
?.key;
|
?.key;
|
||||||
if (name != null) controller.selectedBucket.value = name;
|
if (name != null && !controller.selectedBuckets.contains(name)) {
|
||||||
|
controller.selectedBuckets.add(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -363,10 +365,127 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _bucketMultiSelectField() {
|
||||||
|
return _multiSelectField(
|
||||||
|
items: controller.buckets
|
||||||
|
.map((name) => FilterItem(id: name, name: name))
|
||||||
|
.toList(),
|
||||||
|
fallback: "Choose Buckets",
|
||||||
|
selectedValues: controller.selectedBuckets,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return Colors.indigo;
|
||||||
|
}
|
||||||
|
return Colors.white;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val == true) {
|
||||||
|
selectedValues.add(f.id);
|
||||||
|
} else {
|
||||||
|
selectedValues.remove(f.id);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).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),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _handleSubmit() {
|
void _handleSubmit() {
|
||||||
bool valid = formKey.currentState?.validate() ?? false;
|
bool valid = formKey.currentState?.validate() ?? false;
|
||||||
|
|
||||||
if (controller.selectedBucket.value.isEmpty) {
|
if (controller.selectedBuckets.isEmpty) {
|
||||||
bucketError.value = "Bucket is required";
|
bucketError.value = "Bucket is required";
|
||||||
valid = false;
|
valid = false;
|
||||||
} else {
|
} else {
|
||||||
@ -430,29 +549,14 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
|||||||
MySpacing.height(16),
|
MySpacing.height(16),
|
||||||
_textField("Organization", orgCtrl, required: true),
|
_textField("Organization", orgCtrl, required: true),
|
||||||
MySpacing.height(16),
|
MySpacing.height(16),
|
||||||
_labelWithStar("Bucket", required: true),
|
_labelWithStar("Buckets", required: true),
|
||||||
MySpacing.height(8),
|
MySpacing.height(8),
|
||||||
Stack(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
_popupSelector(controller.selectedBucket, controller.buckets,
|
_bucketMultiSelectField(),
|
||||||
"Choose Bucket"),
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
top: 56,
|
|
||||||
child: Obx(() => bucketError.value.isEmpty
|
|
||||||
? const SizedBox.shrink()
|
|
||||||
: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Text(bucketError.value,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.red, fontSize: 12)),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
MySpacing.height(24),
|
MySpacing.height(12),
|
||||||
Obx(() => GestureDetector(
|
Obx(() => GestureDetector(
|
||||||
onTap: () => showAdvanced.toggle(),
|
onTap: () => showAdvanced.toggle(),
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -562,3 +666,9 @@ class _AddContactBottomSheetState extends State<AddContactBottomSheet> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FilterItem {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
FilterItem({required this.id, required this.name});
|
||||||
|
}
|
||||||
|
@ -37,36 +37,39 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_controller = Get.put(
|
_joiningDateController = TextEditingController();
|
||||||
AddEmployeeController(),
|
_genderController = TextEditingController();
|
||||||
// Unique tag to avoid clashes, but stable for this widget instance
|
_roleController = TextEditingController();
|
||||||
tag: UniqueKey().toString(),
|
|
||||||
);
|
|
||||||
|
|
||||||
_orgFieldController = TextEditingController(text: '');
|
_controller = Get.put(AddEmployeeController(), tag: UniqueKey().toString());
|
||||||
_joiningDateController = TextEditingController(text: '');
|
|
||||||
_genderController = TextEditingController(text: '');
|
|
||||||
_roleController = TextEditingController(text: '');
|
|
||||||
|
|
||||||
// Prefill when editing
|
|
||||||
if (widget.employeeData != null) {
|
if (widget.employeeData != null) {
|
||||||
_controller.editingEmployeeData = widget.employeeData;
|
_controller.editingEmployeeData = widget.employeeData;
|
||||||
_controller.prefillFields();
|
_controller.prefillFields();
|
||||||
|
// 👇 joining date & gender already handled in your code
|
||||||
if (_controller.joiningDate != null) {
|
if (_controller.joiningDate != null) {
|
||||||
_joiningDateController.text =
|
_joiningDateController.text =
|
||||||
DateFormat('dd MMM yyyy').format(_controller.joiningDate!);
|
DateFormat('dd MMM yyyy').format(_controller.joiningDate!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_controller.selectedGender != null) {
|
if (_controller.selectedGender != null) {
|
||||||
_genderController.text =
|
_genderController.text =
|
||||||
_controller.selectedGender!.name.capitalizeFirst ?? '';
|
_controller.selectedGender!.name.capitalizeFirst ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
final roleName = _controller.roles.firstWhereOrNull(
|
// ✅ Important part: fetch roles, then set roleController
|
||||||
(r) => r['id'] == _controller.selectedRoleId)?['name'] ??
|
_controller.fetchRoles().then((_) {
|
||||||
'';
|
if (_controller.selectedRoleId != null) {
|
||||||
_roleController.text = roleName;
|
final roleName = _controller.roles.firstWhereOrNull(
|
||||||
} else {}
|
(r) => r['id'] == _controller.selectedRoleId,
|
||||||
|
)?['name'];
|
||||||
|
if (roleName != null) {
|
||||||
|
_roleController.text = roleName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_controller.fetchRoles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -422,7 +425,7 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
|||||||
context: context,
|
context: context,
|
||||||
initialDate: _controller.joiningDate ?? DateTime.now(),
|
initialDate: _controller.joiningDate ?? DateTime.now(),
|
||||||
firstDate: DateTime(2000),
|
firstDate: DateTime(2000),
|
||||||
lastDate: DateTime(2100),
|
lastDate: DateTime.now(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
@ -435,6 +438,15 @@ class _AddEmployeeBottomSheetState extends State<AddEmployeeBottomSheet>
|
|||||||
Future<void> _handleSubmit() async {
|
Future<void> _handleSubmit() async {
|
||||||
final isValid =
|
final isValid =
|
||||||
_controller.basicValidator.formKey.currentState?.validate() ?? false;
|
_controller.basicValidator.formKey.currentState?.validate() ?? false;
|
||||||
|
if (_controller.joiningDate != null &&
|
||||||
|
_controller.joiningDate!.isAfter(DateTime.now())) {
|
||||||
|
showAppSnackbar(
|
||||||
|
title: 'Invalid Date',
|
||||||
|
message: 'Joining Date cannot be in the future.',
|
||||||
|
type: SnackbarType.warning,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isValid ||
|
if (!isValid ||
|
||||||
_controller.joiningDate == null ||
|
_controller.joiningDate == null ||
|
||||||
|
@ -204,14 +204,6 @@ class _AddExpenseBottomSheetState extends State<_AddExpenseBottomSheet> {
|
|||||||
],
|
],
|
||||||
_gap(),
|
_gap(),
|
||||||
|
|
||||||
_buildTextFieldSection(
|
|
||||||
icon: Icons.confirmation_number_outlined,
|
|
||||||
title: "GST No.",
|
|
||||||
controller: controller.gstController,
|
|
||||||
hint: "Enter GST No.",
|
|
||||||
),
|
|
||||||
_gap(),
|
|
||||||
|
|
||||||
_buildDropdownField<PaymentModeModel>(
|
_buildDropdownField<PaymentModeModel>(
|
||||||
icon: Icons.payment,
|
icon: Icons.payment,
|
||||||
title: "Payment Mode",
|
title: "Payment Mode",
|
||||||
@ -252,20 +244,11 @@ class _AddExpenseBottomSheetState extends State<_AddExpenseBottomSheet> {
|
|||||||
),
|
),
|
||||||
_gap(),
|
_gap(),
|
||||||
|
|
||||||
_buildTextFieldSection(
|
|
||||||
icon: Icons.confirmation_number_outlined,
|
|
||||||
title: "Transaction ID",
|
|
||||||
controller: controller.transactionIdController,
|
|
||||||
hint: "Enter Transaction ID",
|
|
||||||
validator: (v) => (v != null && v.isNotEmpty)
|
|
||||||
? Validators.transactionIdValidator(v)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
_gap(),
|
|
||||||
|
|
||||||
_buildTransactionDateField(),
|
_buildTransactionDateField(),
|
||||||
_gap(),
|
_gap(),
|
||||||
|
|
||||||
|
_buildTransactionIdField(),
|
||||||
|
_gap(),
|
||||||
_buildLocationField(),
|
_buildLocationField(),
|
||||||
_gap(),
|
_gap(),
|
||||||
|
|
||||||
@ -288,6 +271,39 @@ class _AddExpenseBottomSheetState extends State<_AddExpenseBottomSheet> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildTransactionIdField() {
|
||||||
|
final paymentMode =
|
||||||
|
controller.selectedPaymentMode.value?.name.toLowerCase() ?? '';
|
||||||
|
final isRequired = paymentMode.isNotEmpty &&
|
||||||
|
paymentMode != 'cash' &&
|
||||||
|
paymentMode != 'cheque';
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SectionTitle(
|
||||||
|
icon: Icons.confirmation_number_outlined,
|
||||||
|
title: "Transaction ID",
|
||||||
|
requiredField: isRequired,
|
||||||
|
),
|
||||||
|
MySpacing.height(6),
|
||||||
|
CustomTextField(
|
||||||
|
controller: controller.transactionIdController,
|
||||||
|
hint: "Enter Transaction ID",
|
||||||
|
validator: (v) {
|
||||||
|
if (isRequired) {
|
||||||
|
if (v == null || v.isEmpty) {
|
||||||
|
return "Transaction ID is required for this payment mode";
|
||||||
|
}
|
||||||
|
return Validators.transactionIdValidator(v);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _gap([double h = 16]) => MySpacing.height(h);
|
Widget _gap([double h = 16]) => MySpacing.height(h);
|
||||||
|
|
||||||
Widget _buildDropdownField<T>({
|
Widget _buildDropdownField<T>({
|
||||||
@ -326,8 +342,7 @@ class _AddExpenseBottomSheetState extends State<_AddExpenseBottomSheet> {
|
|||||||
CustomTextField(
|
CustomTextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
hint: hint ?? "",
|
hint: hint ?? "",
|
||||||
keyboardType:
|
keyboardType: keyboardType ?? TextInputType.text,
|
||||||
keyboardType ?? TextInputType.text,
|
|
||||||
validator: validator,
|
validator: validator,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user