913 lines
31 KiB
Dart
913 lines
31 KiB
Dart
import 'dart:math' show min;
|
|
|
|
import 'package:dropdown_search/dropdown_search.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:nhance_partner/data/utils/toastNotification.dart';
|
|
|
|
import '../../../core/services/api_service.dart';
|
|
import '../../layouts/responsive_layout.dart';
|
|
import '../../providers/manager_provider.dart';
|
|
import '../../providers/userRoleProvider.dart';
|
|
import '../../themes/indicators/date_range_picker_field.dart';
|
|
import '../../themes/indicators/input_field_decoration.dart';
|
|
|
|
class DateFilterRowPayout extends ConsumerStatefulWidget {
|
|
final bool showBrokerFilter;
|
|
final TextEditingController startController;
|
|
final String? selectedBroker;
|
|
final List<dynamic>? selectedParnter;
|
|
final String? selectedStaffId;
|
|
final TextEditingController endController;
|
|
final ValueChanged<String?>? onBrokerChanged;
|
|
final ValueChanged<List<String>>? onPartnerChanges;
|
|
final String? dataFrom;
|
|
final VoidCallback onFilter;
|
|
final VoidCallback onRefresh;
|
|
final GlobalKey<FormState> formKey;
|
|
final bool isMobile;
|
|
final role;
|
|
final id;
|
|
|
|
/// When non-null, toggles filter layout for payout details:
|
|
/// - `false` — no table rows: show date range only (hide partner + actions).
|
|
/// - `true` — table has rows: show partner (+ broker if [showBrokerFilter]) and
|
|
/// search/reset aligned to the right; hide date range.
|
|
/// When `null`, legacy: date range and partner row together.
|
|
final bool? policyTableHasRows;
|
|
|
|
/// Optional per-column table search fields (shown between date range and partner).
|
|
final Widget? tableSearchFields;
|
|
|
|
/// When true, [getAgentUnusedCommissionList] receives [startController]/[endController] dates.
|
|
final bool passDateRangeToAgentList;
|
|
|
|
const DateFilterRowPayout({
|
|
super.key,
|
|
this.showBrokerFilter = true,
|
|
required this.startController,
|
|
required this.endController,
|
|
required this.onFilter,
|
|
required this.onRefresh,
|
|
this.onBrokerChanged,
|
|
this.onPartnerChanges,
|
|
required this.selectedStaffId,
|
|
required this.selectedParnter,
|
|
this.selectedBroker,
|
|
required this.formKey,
|
|
required this.role,
|
|
required this.id,
|
|
this.isMobile = false,
|
|
this.dataFrom,
|
|
this.policyTableHasRows,
|
|
this.tableSearchFields,
|
|
this.passDateRangeToAgentList = false,
|
|
});
|
|
|
|
@override
|
|
ConsumerState<DateFilterRowPayout> createState() => _DateFilterRowState();
|
|
}
|
|
|
|
class _DateFilterRowState extends ConsumerState<DateFilterRowPayout> {
|
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
|
|
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyBroker =
|
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
|
|
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
|
dropDownKeyPartner = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
|
|
|
late ApiService apiService;
|
|
// List<dynamic>? selectedPartnerIds = [];
|
|
List<Map<String, dynamic>> getPartnerData = [];
|
|
List<Map<String, dynamic>> filteredPartnerData = [];
|
|
|
|
List<Map<String, dynamic>> getBrokerData = [];
|
|
List<Map<String, dynamic>> filteredBrokerData = [];
|
|
|
|
String? selectedStaff;
|
|
String? selectedBroker;
|
|
String? selectedPartner;
|
|
String? selectedStaffName;
|
|
dynamic role;
|
|
dynamic managerId;
|
|
|
|
bool isLoading = false;
|
|
bool isLoadingBroker = false;
|
|
bool isLoadingAgentList = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
apiService = ApiService();
|
|
|
|
Future.microtask(() {
|
|
managerId = ref.watch(managerIdProvider);
|
|
final userID = ref.watch(userIdProvider);
|
|
role = ref.watch(userRoleProvider);
|
|
print("managerId - $managerId");
|
|
// if (userID != null && role != null) {
|
|
// print('hansles');
|
|
// getPartnerDetails(userID);
|
|
// }
|
|
|
|
if (widget.showBrokerFilter &&
|
|
managerId != null &&
|
|
widget.selectedBroker != null) {
|
|
print('managerId - $managerId');
|
|
print('SelectedBroker - $widget.selectedBroker');
|
|
getAgentList(managerId);
|
|
}
|
|
|
|
if (!widget.showBrokerFilter && managerId != null) {
|
|
// Broker filter hidden: load partner list directly by manager.
|
|
if (!_shouldDeferAgentListUntilDateRange()) {
|
|
getAgentList(managerId);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (widget.showBrokerFilter) {
|
|
getBroker();
|
|
}
|
|
}
|
|
|
|
Future<void> getBroker() async {
|
|
print('getBroker called');
|
|
setState(() {
|
|
isLoadingBroker = true;
|
|
});
|
|
|
|
try {
|
|
final response = await apiService.fetchMasterDropDown('Broker');
|
|
|
|
if (response['status'] == 200) {
|
|
print('getBroker - ${response['data']}');
|
|
setState(() {
|
|
getBrokerData = List<Map<String, dynamic>>.from(response['data']);
|
|
print('API Data - $getBrokerData');
|
|
|
|
filteredBrokerData = List.from(getBrokerData);
|
|
print('originalData - $filteredBrokerData');
|
|
});
|
|
} else {
|
|
getBrokerData = [];
|
|
filteredBrokerData = [];
|
|
}
|
|
} catch (e) {
|
|
print('Exception occurred: $e');
|
|
} finally {
|
|
setState(() {
|
|
isLoadingBroker = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
bool _hasSelectedDateRange() {
|
|
return widget.startController.text.trim().isNotEmpty &&
|
|
widget.endController.text.trim().isNotEmpty;
|
|
}
|
|
|
|
bool _shouldDeferAgentListUntilDateRange() {
|
|
return widget.passDateRangeToAgentList && !_hasSelectedDateRange();
|
|
}
|
|
|
|
String? _agentListFromDate() {
|
|
if (!widget.passDateRangeToAgentList) return null;
|
|
final value = widget.startController.text.trim();
|
|
return value.isEmpty ? null : value;
|
|
}
|
|
|
|
String? _agentListToDate() {
|
|
if (!widget.passDateRangeToAgentList) return null;
|
|
final value = widget.endController.text.trim();
|
|
return value.isEmpty ? null : value;
|
|
}
|
|
|
|
Future<void> getAgentList(id) async {
|
|
if (_shouldDeferAgentListUntilDateRange()) {
|
|
setState(() {
|
|
getPartnerData = [];
|
|
filteredPartnerData = [];
|
|
});
|
|
return;
|
|
}
|
|
|
|
print('getAgentListData called');
|
|
setState(() {
|
|
isLoadingAgentList = true;
|
|
});
|
|
|
|
try {
|
|
final response = await apiService.fetchAgentUnusedCommissionList(
|
|
id,
|
|
fromDate: _agentListFromDate(),
|
|
toDate: _agentListToDate(),
|
|
);
|
|
print('getAgentListData called response');
|
|
print('get Agent- ${response['data']}');
|
|
if (response['status'] == 'success') {
|
|
print('get Agent- ${response['data']}');
|
|
setState(() {
|
|
// 1. Convert the response to a list
|
|
final rawList = List<Map<String, dynamic>>.from(response['data']);
|
|
print('API Data - rawList');
|
|
// 2. Filter out items where agent_id is null or empty
|
|
getPartnerData = rawList.where((item) {
|
|
final id = item['agent_id'];
|
|
return id != null && id.toString().isNotEmpty;
|
|
}).toList();
|
|
print('Filtered API Data (No Null IDs) - $getPartnerData');
|
|
// 3. Sync the filtered data to your display list
|
|
filteredPartnerData = List.from(getPartnerData);
|
|
});
|
|
} else {
|
|
getPartnerData = [];
|
|
filteredPartnerData = [];
|
|
}
|
|
} catch (e) {
|
|
print('Exception occurred: $e');
|
|
} finally {
|
|
setState(() {
|
|
isLoadingAgentList = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
// Future<void> getPartnerDetails(int id) async {
|
|
// print('getPartnerDetails called By handler');
|
|
// setState(() {
|
|
// isLoading = true;
|
|
// });
|
|
//
|
|
// try {
|
|
// // final response = await apiService.fetchStaffUserList(id, role);
|
|
// final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
|
// managerId,
|
|
// id,
|
|
// role,
|
|
// );
|
|
// if (response['status'] == 'success') {
|
|
// print('getStaffDetails - ${response['data']}');
|
|
// setState(() {
|
|
// getPartnerData = List<Map<String, dynamic>>.from(response['data']);
|
|
// print('API Data - $getPartnerData');
|
|
//
|
|
// filteredPartnerData = List.from(getPartnerData);
|
|
// print('originalData - $filteredPartnerData');
|
|
// });
|
|
// } else {
|
|
// getPartnerData = [];
|
|
// filteredPartnerData = [];
|
|
// }
|
|
// } catch (e) {
|
|
// print('Exception occurred: $e');
|
|
// } finally {
|
|
// setState(() {
|
|
// isLoading = false;
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final spacing = 5.0;
|
|
|
|
List<Widget> getRowChildren(bool isMobile, double spacing) {
|
|
final hasDateRange = widget.startController.text.trim().isNotEmpty &&
|
|
widget.endController.text.trim().isNotEmpty;
|
|
|
|
double partnerMaxWidth() {
|
|
final sw = MediaQuery.sizeOf(context).width;
|
|
return min(sw * 0.32, 420);
|
|
}
|
|
|
|
final buttons = [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 0.0),
|
|
child: Tooltip(
|
|
message: 'Filter',
|
|
child: IconButton(
|
|
icon: const Icon(
|
|
Icons.search_rounded,
|
|
size: 18,
|
|
color: const Color(0xFF94A3B8),
|
|
),
|
|
onPressed: () {
|
|
if (widget.formKey.currentState?.validate() != true) return;
|
|
final partners = widget.selectedParnter;
|
|
final hasPartner = partners != null &&
|
|
partners.isNotEmpty &&
|
|
partners.any((e) => e.toString().trim().isNotEmpty);
|
|
if (!hasPartner) {
|
|
ToastHelper.showWarningToast(
|
|
context,
|
|
'Please select a partner before searching.',
|
|
);
|
|
return;
|
|
}
|
|
widget.onFilter();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(0.0),
|
|
child: Tooltip(
|
|
message: 'Refresh',
|
|
child: IconButton(
|
|
onPressed: () {
|
|
if (widget.passDateRangeToAgentList) {
|
|
setState(() {
|
|
getPartnerData = [];
|
|
filteredPartnerData = [];
|
|
});
|
|
}
|
|
widget.onRefresh();
|
|
},
|
|
icon: const Icon(
|
|
Icons.refresh,
|
|
size: 18,
|
|
color: const Color(0xFF94A3B8),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
];
|
|
|
|
final partnerActionsRow = <Widget>[
|
|
if (widget.showBrokerFilter) ...[
|
|
buildBroker(context),
|
|
SizedBox(width: spacing),
|
|
],
|
|
buildPartner(context, maxWidth: partnerMaxWidth()),
|
|
SizedBox(width: spacing),
|
|
...buttons,
|
|
];
|
|
|
|
if (!hasDateRange) {
|
|
return [buildDateRangeFilter(context)];
|
|
}
|
|
|
|
if (isMobile) {
|
|
return [
|
|
buildDateRangeFilter(context),
|
|
if (widget.tableSearchFields != null) ...[
|
|
const SizedBox(height: 10),
|
|
widget.tableSearchFields!,
|
|
],
|
|
const SizedBox(height: 10),
|
|
Wrap(
|
|
spacing: spacing,
|
|
runSpacing: 8,
|
|
crossAxisAlignment: WrapCrossAlignment.end,
|
|
children: partnerActionsRow,
|
|
),
|
|
];
|
|
}
|
|
return [
|
|
buildDateRangeFilter(context),
|
|
if (widget.tableSearchFields != null) ...[
|
|
SizedBox(width: spacing),
|
|
widget.tableSearchFields!,
|
|
],
|
|
SizedBox(width: spacing),
|
|
Spacer(),
|
|
...partnerActionsRow,
|
|
];
|
|
}
|
|
|
|
return Form(
|
|
key: widget.formKey,
|
|
child: widget.isMobile
|
|
? Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: getRowChildren(widget.isMobile, spacing),
|
|
)
|
|
: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
|
|
children: getRowChildren(widget.isMobile, spacing),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget buildDateRangeFilter(BuildContext context) {
|
|
final w = ResponsiveLayout.isMobile(context)
|
|
? null
|
|
: MediaQuery.of(context).size.width * 0.15;
|
|
return DateRangePickerField(
|
|
startController: widget.startController,
|
|
endController: widget.endController,
|
|
hintText: 'Select date range',
|
|
txtwidth: w,
|
|
txtheight: 32,
|
|
lastDate: DateTime.now(),
|
|
rangeValidator: DateRangePickerField.defaultFilterValidator,
|
|
onRangeSelected: (_) => Future.microtask(() {
|
|
if (widget.passDateRangeToAgentList && managerId != null) {
|
|
getAgentList(managerId);
|
|
}
|
|
widget.onFilter();
|
|
}),
|
|
);
|
|
}
|
|
|
|
Widget buildBroker(BuildContext context) {
|
|
Map<String, dynamic>? selectedBrokers = filteredBrokerData.firstWhere(
|
|
(item) => item['id'].toString() == widget.selectedBroker,
|
|
orElse: () => {},
|
|
);
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Broker *', style: _textStyle),
|
|
SizedBox(height: 5),
|
|
SizedBox(
|
|
height: 35,
|
|
width: MediaQuery.of(context).size.width * 0.15,
|
|
child: DropdownSearch<Map<String, dynamic>>(
|
|
key: dropDownKeyBroker,
|
|
selectedItem: selectedBrokers.isNotEmpty ? selectedBrokers : null,
|
|
items: (filter, infiniteScrollProps) {
|
|
return filteredBrokerData;
|
|
},
|
|
|
|
itemAsString: (val) => val['name'].toString(), // what to show
|
|
compareFn: (item, selectedItem) =>
|
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
|
// validator: (val) {
|
|
// if (val == null) {
|
|
// return "Required"; // ✅ error message
|
|
// }
|
|
// return null;
|
|
// },
|
|
suffixProps: DropdownSuffixProps(
|
|
// make sure the dropdown button is visible
|
|
dropdownButtonProps: DropdownButtonProps(
|
|
isVisible: true,
|
|
padding: EdgeInsets.zero, // remove default padding
|
|
constraints: const BoxConstraints(
|
|
// shrink icon tap area
|
|
minWidth: 12,
|
|
minHeight: 12,
|
|
),
|
|
iconSize: 15, // smaller icon
|
|
// icon: const Icon(Icons.arrow_drop_down),
|
|
),
|
|
),
|
|
dropdownBuilder: (context, selectedItem) => Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
selectedItem != null ? selectedItem['name'].toString() : "",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 11,
|
|
color: Colors.black,
|
|
// color: Color(0XFF6366F1),
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
softWrap: false,
|
|
),
|
|
),
|
|
decoratorProps: DropDownDecoratorProps(
|
|
decoration:
|
|
AppInputDecorations.dropdownDecoration(
|
|
label: "Broker",
|
|
).copyWith(
|
|
filled: true,
|
|
fillColor:
|
|
Colors.white, // 👈 makes the dropdown input white
|
|
isDense: true,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: const BorderSide(
|
|
color: Color(0xFFE2E8F0),
|
|
width: 0.1,
|
|
),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: const BorderSide(
|
|
color: Color(0xFFE2E8F0),
|
|
width: 0.5,
|
|
),
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 6,
|
|
),
|
|
),
|
|
),
|
|
|
|
popupProps: PopupProps.menu(
|
|
fit: FlexFit.loose,
|
|
constraints: BoxConstraints(maxHeight: 250),
|
|
menuProps: MenuProps(
|
|
backgroundColor:
|
|
Colors.white, // 👈 sets dropdown background to white
|
|
),
|
|
showSearchBox: true,
|
|
searchFieldProps: TextFieldProps(
|
|
autofocus: true,
|
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
|
decoration: InputDecoration(
|
|
contentPadding: EdgeInsets.all(1),
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
hintText: "Search Broker...",
|
|
hintStyle: GoogleFonts.inter(
|
|
fontSize: 12,
|
|
color: Colors.black,
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Colors.white,
|
|
), // 👈 Normal border
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Colors.white,
|
|
width: 1.5,
|
|
), // 👈 Focused border
|
|
),
|
|
),
|
|
),
|
|
|
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
|
return Container(
|
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 3,
|
|
),
|
|
child: Text(
|
|
item['name'].toString(),
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
|
),
|
|
);
|
|
},
|
|
// constraints: BoxConstraints(),
|
|
),
|
|
// onChanged: (val) {
|
|
// if (val != null) {
|
|
// print("Selected Broker : ${val['name']}");
|
|
// print("Id: ${val['id']}");
|
|
// // selectedBroker = val['id'];
|
|
// widget.onBrokerChanged?.call(val['id'].toString());
|
|
// // widget.onBrokerChanged?.call(val['id']);
|
|
// // controllers['agentId']?.text = val['agent_code'];
|
|
// // agentId = agent['id'];
|
|
// }
|
|
// },
|
|
onChanged: (val) {
|
|
if (val != null) {
|
|
String selectedId = val['id'].toString();
|
|
|
|
// 1. Notify parent of the change
|
|
widget.onBrokerChanged?.call(selectedId);
|
|
|
|
// 2. Clear current partner list so user doesn't see old data
|
|
setState(() {
|
|
filteredPartnerData = [];
|
|
});
|
|
|
|
// 3. Fetch new agents based on this broker
|
|
getAgentList(managerId!);
|
|
}
|
|
},
|
|
|
|
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget buildPartner(BuildContext context, {double? maxWidth}) {
|
|
final w = maxWidth ?? MediaQuery.of(context).size.width * 0.4;
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("Partner", style: _textStyle),
|
|
SizedBox(height: 5),
|
|
SizedBox(
|
|
height: 35,
|
|
width: w,
|
|
child: DropdownSearch<Map<String, dynamic>>.multiSelection(
|
|
key: dropDownKeyPartner,
|
|
|
|
// selectedItem: selectedHandlered.isNotEmpty
|
|
// ? selectedHandlered
|
|
// : null,
|
|
selectedItems: filteredPartnerData
|
|
.where(
|
|
(item) => (widget.selectedParnter ?? []).contains(item['agent_id']),
|
|
)
|
|
.toList(),
|
|
|
|
// selectedItems: filteredPartnerData
|
|
// .where(
|
|
// (item) => (selectedPartnerIds ?? []).contains(item['id']),
|
|
// )
|
|
// .toList(),
|
|
items: (filter, infiniteScrollProps) {
|
|
return filteredPartnerData;
|
|
},
|
|
|
|
itemAsString: (val) => // what to show
|
|
"${val['agent_name']} | ${val['unused_commission_amount']} (${val['total_policies']})",
|
|
compareFn: (item, selectedItem) =>
|
|
item['agent_id'] == selectedItem['agent_id'], // ✅ compare by id
|
|
dropdownBuilder: (context, selectedItems) {
|
|
final safeItems = selectedItems;
|
|
final text = safeItems.isEmpty
|
|
? 'Select Partner'
|
|
: safeItems.length == 1
|
|
? "${safeItems.first['agent_name']} | ${safeItems.first['unused_commission_amount']} (${safeItems.first['total_policies']})"
|
|
: '${safeItems.length} partners selected';
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
text,
|
|
style: GoogleFonts.inter(
|
|
fontSize: 12,
|
|
color: safeItems.isEmpty
|
|
? const Color(0xFF64748B)
|
|
: Colors.black,
|
|
),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
);
|
|
},
|
|
// validator: (val) {
|
|
// if (val == null) {
|
|
// return "Required"; // ✅ error message
|
|
// }
|
|
// return null;
|
|
// },
|
|
// validator: (val) {
|
|
// if (val == null || val.isEmpty) {
|
|
// return ""; // 👈 triggers error border, no text
|
|
// }
|
|
// return null;
|
|
//
|
|
// // if (val == null || val.isEmpty) {
|
|
// // return "Required";
|
|
// // }
|
|
// // return null;
|
|
// },
|
|
|
|
decoratorProps: DropDownDecoratorProps(
|
|
decoration:
|
|
AppInputDecorations.dropdownDecoration(
|
|
label: "",
|
|
).copyWith(
|
|
hintText: null,
|
|
hintStyle: GoogleFonts.inter(
|
|
fontSize: 12,
|
|
color: Colors.black,
|
|
),
|
|
filled: true,
|
|
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
|
fillColor:
|
|
Colors.white, // 👈 makes the dropdown input white
|
|
enabledBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Color(0xFFE2E8F0),
|
|
// color: Colors.white,
|
|
), // 👈 Normal border
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Color(0xFFE2E8F0),
|
|
// color: Colors.white,
|
|
width: 1.5,
|
|
), // 👈 Focused border
|
|
),
|
|
|
|
contentPadding: EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 6,
|
|
),
|
|
),
|
|
),
|
|
popupProps: PopupPropsMultiSelection.menu(
|
|
fit: FlexFit.loose,
|
|
constraints: BoxConstraints(maxHeight: 250),
|
|
showSearchBox: true,
|
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
|
|
|
searchFieldProps: TextFieldProps(
|
|
autofocus: true,
|
|
decoration: InputDecoration(
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
hintText: "Search Partner...",
|
|
hintStyle: GoogleFonts.inter(
|
|
fontSize: 11,
|
|
color: Colors.black,
|
|
),
|
|
|
|
enabledBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.white),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
// color: Colors.blue,
|
|
color: Color(0xFFEDF6F5),
|
|
width: 1.5,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
|
return Container(
|
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 3,
|
|
),
|
|
child: Text(
|
|
"${item['agent_name']} | ${item['unused_commission_amount']} (${item['total_policies']})",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
|
|
onChanged: (List<Map<String, dynamic>> selectedVals) {
|
|
// selectedPartnerIds = selectedVals
|
|
// .map((v) => v['id'].toString())
|
|
// .toList();
|
|
final ids = selectedVals.map((v) => v['agent_id'].toString()).toList();
|
|
print("Selected PArnter IDs: $widget.selectedPartnerIds");
|
|
widget.onPartnerChanges?.call(ids);
|
|
// widget.onPartnerChanges!(v['id']);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
// Widget buildSelectStaffMem(BuildContext context) {
|
|
// Map<String, dynamic>? selectedVehicle;
|
|
// if (widget.selectedStaffId == null) {
|
|
// selectedVehicle = null;
|
|
// } else if (widget.selectedStaffId != null) {
|
|
// selectedVehicle = filteredPartnerData.firstWhere(
|
|
// (item) => item['id'] == widget.selectedStaffId,
|
|
// orElse: () => {}, // empty map
|
|
// );
|
|
// if (selectedVehicle.isEmpty) selectedVehicle = null;
|
|
// } else if (selectedStaff != null) {
|
|
// selectedVehicle = filteredPartnerData.firstWhere(
|
|
// (item) => item['id'] == selectedStaff,
|
|
// orElse: () => {}, // empty map
|
|
// );
|
|
// if (selectedVehicle.isEmpty) selectedVehicle = null;
|
|
// } else {
|
|
// selectedVehicle = null;
|
|
// }
|
|
// return Column(
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// // Text("Staff Name", style: _textStyle),
|
|
// // SizedBox(height: 10),
|
|
// SizedBox(
|
|
// height: 35,
|
|
// child: Container(
|
|
// decoration: BoxDecoration(
|
|
// borderRadius: BorderRadius.circular(5.0),
|
|
// border: Border.all(color: Color(0xFFE2E8F0)),
|
|
// // color: Colors.black,
|
|
// ),
|
|
//
|
|
// width: ResponsiveLayout.isMobile(context)
|
|
// ? null
|
|
// : MediaQuery.of(context).size.width * 0.13,
|
|
// // height: 45,
|
|
// child: DropdownSearch<Map<String, dynamic>>(
|
|
// // key: dropDownKey,
|
|
// key: ValueKey(selectedStaff),
|
|
// // selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
|
// selectedItem: selectedVehicle,
|
|
//
|
|
// items: (filter, infiniteScrollProps) {
|
|
// return filteredPartnerData;
|
|
// },
|
|
//
|
|
// itemAsString: (val) => val['name'].toString(),
|
|
// compareFn: (item, selectedItem) =>
|
|
// item['id'] == selectedItem['id'], // ✅ compare by id
|
|
// dropdownBuilder: (context, selectedItem) => Align(
|
|
// alignment: Alignment.centerLeft,
|
|
// child: Text(
|
|
// selectedItem != null ? selectedItem['name'].toString() : "",
|
|
// style: GoogleFonts.poppins(fontSize: 11, color: Colors.black),
|
|
// overflow: TextOverflow.ellipsis,
|
|
// maxLines: 1,
|
|
// softWrap: false,
|
|
// ),
|
|
// ),
|
|
// decoratorProps: DropDownDecoratorProps(
|
|
// decoration:
|
|
// AppInputDecorations.dropdownDecoration(
|
|
// label: "Select Staff ",
|
|
// ).copyWith(
|
|
// filled: true,
|
|
// fillColor:
|
|
// Colors.white, // 👈 makes the dropdown input white
|
|
// contentPadding: const EdgeInsets.symmetric(
|
|
// horizontal: 6,
|
|
// vertical: 1, // 👈 adjust this to make the field shorter
|
|
// ),
|
|
// ),
|
|
// ),
|
|
//
|
|
// popupProps: PopupProps.menu(
|
|
// fit: FlexFit.loose,
|
|
// constraints: BoxConstraints(maxHeight: 250),
|
|
// menuProps: MenuProps(
|
|
// backgroundColor:
|
|
// Colors.white, // 👈 sets dropdown background to white
|
|
// ),
|
|
// showSearchBox: true,
|
|
// searchFieldProps: TextFieldProps(
|
|
// decoration: InputDecoration(
|
|
// filled: true,
|
|
// fillColor: Colors.white,
|
|
// hintText: "Search Staff ...",
|
|
// hintStyle: GoogleFonts.inter(
|
|
// fontSize: 12,
|
|
// color: Colors.black,
|
|
// ),
|
|
// enabledBorder: OutlineInputBorder(
|
|
// borderSide: BorderSide(
|
|
// color: Colors.white,
|
|
// ), // 👈 Normal border
|
|
// ),
|
|
// focusedBorder: OutlineInputBorder(
|
|
// borderSide: BorderSide(
|
|
// color: Colors.white,
|
|
// width: 1.5,
|
|
// ), // 👈 Focused border
|
|
// ),
|
|
// ),
|
|
// ),
|
|
//
|
|
// itemBuilder: (context, item, isDisabled, isSelected) {
|
|
// return Container(
|
|
// // color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
|
// padding: const EdgeInsets.symmetric(
|
|
// horizontal: 8,
|
|
// vertical: 3,
|
|
// ),
|
|
// child: Text(
|
|
// item['name'].toString(),
|
|
// style: GoogleFonts.inter(
|
|
// fontSize: 13,
|
|
// color: Colors.black,
|
|
// ),
|
|
// ),
|
|
// );
|
|
// },
|
|
//
|
|
// // constraints: BoxConstraints(),
|
|
// ),
|
|
//
|
|
// onChanged: (val) {
|
|
// if (val != null) {
|
|
// print("Selected Staff : ${val['name']}");
|
|
// print("Id: ${val['id']}");
|
|
// // selectedStaffName = val['name'];
|
|
// // selectedStaff = val['id'];
|
|
// widget.onBrokerChanged!(val['id']);
|
|
// // if (widget.onFilterStaff != null)
|
|
// // widget.onFilterStaff!(val['id']);
|
|
//
|
|
// // Future.microtask(() => widget.onFilter());
|
|
// // controllers['agentId']?.text = val['agent_code'];
|
|
// // agentId = agent['id'];
|
|
// }
|
|
// },
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// );
|
|
// }
|
|
|
|
static final _textStyle = GoogleFonts.poppins(
|
|
fontSize: 11,
|
|
fontWeight: FontWeight.w500,
|
|
);
|
|
}
|