STAFF_ENQ_REDESIGN

This commit is contained in:
venbaittech 2025-10-15 18:03:49 +05:30
parent 25d9e1d0dd
commit c6a212bc65
23 changed files with 4300 additions and 679 deletions

View File

@ -338,7 +338,7 @@ class ApiService {
}
// ----------------------------------- Dashboard -------------------------------------------------
Future<Map<String, dynamic>> fetchDashboard(int id, role) async {
Future<Map<String, dynamic>> fetchDashboard(int id, role, userId) async {
// print(_token);
if (_token == null) {
await _initializeToken();
@ -349,11 +349,13 @@ class ApiService {
if (role == 'manager') {
url = Uri.parse('${Env.apiUrl}dashboard/managerDashboard?manager_id=$id');
} else if (role == 'handler') {
url = Uri.parse('${Env.apiUrl}dashboard/handlerDashboard?handler_id=$id');
url = Uri.parse(
'${Env.apiUrl}dashboard/handlerDashboard?manager_id=$id&handler_id=$userId',
);
} else if (role == 'staff') {
url = Uri.parse('${Env.apiUrl}dashboard/staffDashboard?staff_id=$id');
url = Uri.parse('${Env.apiUrl}dashboard/staffDashboard?staff_id=$userId');
} else {
url = Uri.parse('${Env.apiUrl}dashboard/agentDashboard?agent_id=$id');
url = Uri.parse('${Env.apiUrl}dashboard/agentDashboard?agent_id=$userId');
}
// final url = Uri.parse(
// 'https://venbait.in/nhance/partner/dev/api/agent/agentList?manager_id=${managerId}',
@ -559,9 +561,13 @@ class ApiService {
final String query;
if (role == 'manager') {
if (role == 'manager' || role == 'handler') {
query = 'manager_id=$id';
} else if (role == 'staff') {
}
// else if (role == 'handler') {
// query = 'handler_id=$id';
// }
else if (role == 'staff') {
query = 'staff_id=$id';
} else {
query = 'agent_id=$id';
@ -595,9 +601,11 @@ class ApiService {
}
Future<Map<String, dynamic>> findEnqQuotePolicyView(id) async {
print('findEnqQuotePolicyView - $id');
print('findEnqQuotePolicyVie2w - $id');
if (_token == null) {
print('findEnqQuotePolicyVie2w 1');
await _initializeToken();
print('findEnqQuotePolicyVie2w 2');
}
final url = Uri.parse(
'${Env.apiUrl}enquiry/enquiryQuotePolicyView?enquiry_id=$id',
@ -606,7 +614,17 @@ class ApiService {
'Authorization': 'Bearer $_token' ?? '',
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
};
print('findEnqQuotePolicyVie2w 3');
final response = await _makeGetRequest(url, headers);
if (response.containsKey('error')) {
print(
'❌ API returned invalid JSON or HTML. Raw response: ${response['raw']}',
);
return {}; // return empty map on error
}
print('findEnqQuotePolicyView 1');
print('findEnqQuotePolicyView 1 - $response');
return response;
}
@ -844,7 +862,7 @@ class ApiService {
return response;
}
// --------------------------------- MASTER DATA ----------------------------------------------
// --------------------------------- MASTER DATA DROPDOWN----------------------------------------------
Future<Map<String, dynamic>> fetchMasterDropDown(String val) async {
// print(_token);
@ -925,4 +943,26 @@ class ApiService {
print('fetchHandlerNameDropDown 4 - $response');
return response;
}
Future<Map<String, dynamic>> fetchAgentNameDropDown(id) async {
print('fetchAGENTNameDropDown');
if (_token == null) {
await _initializeToken();
}
dynamic url;
print('fetchAGENTNameDropDown 1');
url = Uri.parse(
'${Env.apiUrl}agent/agentListForEnquiryCreationDropdown?manager_id=$id',
);
print('fetchAGENTNameDropDown 2');
final headers = {
'Authorization': 'Bearer $_token' ?? '',
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
};
print('fetchAGENTNameDropDown 3');
final response = await _makeGetRequest(url, headers);
print('fetchAGENTNameDropDown 4 - $response');
return response;
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
final managerIdProvider = StateProvider<int?>((ref) => null);
final handlerIdProvider = StateProvider<int?>((ref) => null);
// final handlerIdProvider = StateProvider<int?>((ref) => null);
final userIdProvider = StateProvider<int?>((ref) => null);
final enquiryIdProvider = StateProvider<String?>((ref) => null);
final navFromEnqStaffProvider = StateProvider<String?>((ref) => null);

View File

@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/presentation/layouts/responsive_layout.dart';
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
import 'package:toastification/toastification.dart';
import 'package:universal_html/html.dart' as html;
@ -45,6 +46,8 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
dropDownKeyInsurer = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyAgent =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
List<String> tabHeader = [
'name',
@ -79,26 +82,32 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
String? selectedVehicleType;
// int? selectedVehicleTypeId;
String? selectedInsurer;
String? selectedAgent;
Map<String, TextEditingController> controllers = {};
String? _token;
dynamic userId;
dynamic managerId;
dynamic role;
List<Map<String, dynamic>> getVehicleTypeData = [];
List<Map<String, dynamic>> filteredVechicleData = [];
List<Map<String, dynamic>> getAgentListData = [];
List<Map<String, dynamic>> filteredAgentData = [];
List<Map<String, dynamic>> getInsurersData = [];
List<Map<String, dynamic>> filteredInsurersData = [];
Map<String, dynamic> dataDetails() {
final data = {
"agent_id": userId,
"agent_id": role == 'handler' ? selectedAgent : userId,
"name": controllers["name"]?.text,
"mobile": controllers["mobile"]?.text,
"email": controllers["email"]?.text,
"reg_no": controllers["regNo"]?.text,
"vehicle_type_id": selectedVehicleType,
"is_data_created_by_handler": role == 'handler' ? '1' : '0',
// "insurer_id": selectedInsurer,
// "rc_file_name": "rc_doc.pdf",
// "id_proof_file_name": "id_proof.pdf",
@ -129,6 +138,12 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
Future.microtask(() {
managerId = ref.watch(managerIdProvider);
userId = ref.watch(userIdProvider);
role = ref.watch(userRoleProvider);
if (managerId != null) {
print('managerId - $managerId');
getAgentList(managerId);
}
});
getVehicleType();
@ -215,6 +230,38 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
}
}
Future<void> getAgentList(id) async {
print('getAgentListData called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchAgentNameDropDown(id);
print('getAgentListData called response');
print('get Agent- ${response['data']}');
if (response['status'] == 'success') {
print('get Agent- ${response['data']}');
setState(() {
getAgentListData = List<Map<String, dynamic>>.from(response['data']);
print('API Data - $getAgentListData');
filteredAgentData = List.from(getAgentListData);
print('originalAgentData - $filteredAgentData');
});
} else {
getAgentListData = [];
filteredAgentData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
void updateData() async {
if (widget.data != null && widget.data != 'tab' && widget.id != null) {
// dynamic response = await apiService.findEnqQuotePolicyView(widget.id!);
@ -234,6 +281,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
isActive = data["is_active"];
selectedVehicleType = data['vehicle_type_id'] ?? '';
selectedInsurer = data['insurer_id'] ?? '';
selectedAgent = data['agent_id'] ?? '';
String? apiDocPath = data["certificate_file_name"];
@ -325,26 +373,6 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
final dataSet = dataDetails();
// check RC file
// if ((docUploadedRCFile == null ||
// (docUploadedRCFile?.bytes == null &&
// docUploadedRCFile?.path == null)) &&
// (rcFileUrlFromApi == null || rcFileUrlFromApi!.isEmpty)) {
// setState(() => isSaving = false); // reset button
// ToastHelper.showErrorToast(context, "Please upload RC Document");
// return;
// }
//
// // check ID proof
// if ((docUploadedIDProof == null ||
// (docUploadedIDProof?.bytes == null &&
// docUploadedIDProof?.path == null)) &&
// (idProofFileUrlFromApi == null || idProofFileUrlFromApi!.isEmpty)) {
// setState(() => isSaving = false); // reset button
// ToastHelper.showErrorToast(context, "Please upload ID Proof");
// return;
// }
try {
await createUserData(dataSet); // API call
// ToastHelper.showInfoToast(context, "Enquiry saved successfully");
@ -484,13 +512,24 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
ToastHelper.showSuccessToast(context, 'Saved Enquiry');
print("Response: ${response.body}");
if (isUpdating) {
context.go(AppRoutes.tabEnquiry);
if (role == 'handler') {
print('Im handler');
print('ROle - $role');
if (isUpdating) {
context.go(AppRoutes.enquiryHandlerLst);
} else {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryHandlerLst);
}
} else {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
print('Im agent');
if (isUpdating) {
context.go(AppRoutes.tabEnquiry);
} else {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
}
}
setState(() => isSaving = false);
} else {
print("❌ Submission failed. Status: ${response.statusCode}");
@ -582,16 +621,28 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
?(role == 'handler')
? _buildResponsiveRow(
context,
buildAgentName(context),
SizedBox.shrink(),
)
: null,
?(role == 'handler')
? isMobile
? SizedBox(height: 5)
: SizedBox(height: 15)
: null,
_buildResponsiveRow(context, buildName(context), buildEmail(context)),
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
isMobile ? SizedBox(height: 5) : SizedBox(height: 15),
_buildResponsiveRow(
context,
buildPhNumber(context),
buildId(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
isMobile ? SizedBox(height: 5) : SizedBox(height: 15),
_buildResponsiveRow(
context,
@ -599,7 +650,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
// buildInsurer(context),
buildUploadRCDocument(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
isMobile ? SizedBox(height: 5) : SizedBox(height: 15),
_buildResponsiveRow(
context,
@ -608,7 +659,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
buildUploadPolicyDocument(context),
),
isMobile ? SizedBox(height: 5) : SizedBox(height: 20),
isMobile ? SizedBox(height: 5) : SizedBox(height: 15),
_buildResponsiveRow(
context,
// buildUploadPolicyDocument(context),
@ -927,6 +978,91 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
);
}
Widget buildAgentName(BuildContext context) {
Map<String, dynamic>? selectedAgntName = filteredAgentData.firstWhere(
(item) => item['id'].toString() == selectedAgent,
orElse: () => {},
);
return buildResponsiveField(
label: "Select Partner *",
field: Container(
decoration: BoxDecoration(
// color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
),
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// height: 40,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyAgent,
selectedItem: selectedAgntName.isNotEmpty ? selectedAgntName : null,
items: (filter, infiniteScrollProps) {
return filteredAgentData;
},
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;
},
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Partner",
).copyWith(
filled: true,
fillColor: Colors.white, // 👈 makes the dropdown input white
),
),
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 Partner...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
print("Selected Partner : ${val['name']}");
print("Id: ${val['id']}");
selectedAgent = val['id'];
// controllers['agentId']?.text = val['agent_code'];
// agentId = agent['id'];
}
},
),
),
);
}
// Widget buildUploadRCDocument(BuildContext context) {
// return buildResponsiveUploadField(
// label: "Upload RC Document",

View File

@ -6,6 +6,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
import 'package:nhance_partner/presentation/screens/Enquiry/enquiry/tabs.dart';
import '../../../../core/config/env.dart';
import '../../../../core/services/api_service.dart';
@ -78,6 +79,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
String? _token;
dynamic userId;
dynamic managerId;
dynamic role;
List<Map<String, dynamic>> getVehicleTypeData = [];
List<Map<String, dynamic>> filteredVechicleData = [];
@ -116,6 +118,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
Future.microtask(() {
managerId = ref.watch(managerIdProvider);
userId = ref.watch(userIdProvider);
role = ref.watch(userRoleProvider);
getQuotationList();
});
@ -159,10 +162,11 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
filteredData = List.from(originalData);
print('quoationListData - $getQuotationData');
blockKey = getQuotationData.any((item) => item['status'] == 'Accepted');
blockKey = getQuotationData.any(
(item) => item['status'] == 'Accepted',
);
print('blockKey- $blockKey');
// blockKey = getQuotationData.any(
// (item) => (item['status']?.toString().toLowerCase() ?? '') == 'approved',
// );
@ -275,7 +279,12 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
throw Exception('Token not found. Please log in.');
}
final Map<String, dynamic> data = {"id": selectedId, "status": val};
final Map<String, dynamic> data = {
"id": selectedId,
"status": val,
"action_by": userId,
"action_user": (role == 'agent') ? 'agent' : 'handler',
};
// data['id'] = selectedId; // Add plan_id for update
// data['status'] = val;
@ -307,7 +316,6 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
await widget.onRefresh!();
}
// refresh();
// WidgetsBinding.instance.addPostFrameCallback((_) {
// tabKey.currentState?.loadQuotationTab(widget.id ?? "");
@ -598,7 +606,8 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
_buildResponsiveRow(
context,
buildPlanType(context),
buildDocuments(context),
SizedBox.shrink(),
// buildDocuments(context),
),
// if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
@ -698,7 +707,6 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
);
}
Widget buildDocuments(BuildContext context) {
return buildResponsiveUploadField(
label: 'Quotation Documents',

View File

@ -224,8 +224,8 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2,
horizontal: 1,
vertical: 1,
),
child: GestureDetector(
onTap: () {
@ -243,7 +243,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
children: [
const Icon(
Icons.arrow_left_sharp,
size: 25,
size: 20,
color: Color(0xFF425B5B),
),
// const SizedBox(width: 8),
@ -417,12 +417,20 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 2),
child: GestureDetector(
onTap: () {
// context.go(AppRoutes.dashboard);
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
// ref.read(enquiryIdProvider.notifier).state = null;
// context.go(AppRoutes.enquiryLst);
if (role == 'handler') {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryHandlerLst);
} else {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
}
},
child: Row(
children: [
@ -431,12 +439,20 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
child: IconButton(
icon: const Icon(
Icons.arrow_left_sharp,
size: 35,
size: 25,
color: Color(0xFF425B5B),
),
onPressed: () {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
if (role == 'handler') {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryHandlerLst);
} else {
ref.read(enquiryIdProvider.notifier).state = null;
context.go(AppRoutes.enquiryLst);
}
// ref.read(enquiryIdProvider.notifier).state = null;
// context.go(AppRoutes.enquiryLst);
},
splashRadius: 28,
hoverColor: Colors.black12,

View File

@ -350,7 +350,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 40,
height: 30,
width: MediaQuery.of(context).size.width,
child: GestureDetector(
onTap: () {
@ -395,7 +395,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
),
),
SizedBox(height: ResponsiveLayout.isMobile(context) ? 5 : 10),
SizedBox(height: ResponsiveLayout.isMobile(context) ? 5 : 5),
ResponsiveLayout.isMobile(context)
? Container(
height: MediaQuery.of(context).size.height * 0.7,
@ -593,14 +593,18 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
Expanded(flex: 1, child: Text('S.No.', style: _headerStyle)),
Expanded(
flex: 2,
child: Text('Created Date', style: _headerStyle),
child: Text('Received Date & Time', style: _headerStyle),
),
Expanded(
flex: 2,
child: Text('Vehicle.No.', style: _headerStyle),
),
Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)),
Expanded(
flex: 2,
child: Text('Updated Date', style: _headerStyle),
),
Expanded(flex: 1, child: Text('Reg.No.', style: _headerStyle)),
Expanded(flex: 3, child: Text('Company', style: _headerStyle)),
Expanded(flex: 2, child: Text('Status', style: _headerStyle)),
Expanded(flex: 2, child: Text('Remarks', style: _headerStyle)),
Expanded(flex: 1, child: Text('Action', style: _headerStyle)),
@ -707,15 +711,9 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
style: _dataBold,
),
),
Expanded(
flex: 2,
child: Text(
_formatDate(item['updated_on']) ?? '-',
style: _dataBold,
),
),
Expanded(
flex: 1,
child: Text(item['reg_no'] ?? '-', style: _dataBold),
),
Expanded(
@ -727,7 +725,13 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
maxLines: 3,
),
),
Expanded(
flex: 2,
child: Text(
_formatDate(item['updated_on']) ?? '-',
style: _dataBold,
),
),
Expanded(
flex: 2,
child: Text(item['status'] ?? '-', style: _dataBold),
@ -919,7 +923,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Company", style: _cardheaderStyle),
Text("Insurer", style: _cardheaderStyle),
Text(
item['insurer_name'] ?? '-',
style: _cardBodyStyle,

View File

@ -178,7 +178,7 @@ class claimListState extends ConsumerState<claimList> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 40,
height: 30,
width: MediaQuery.of(context).size.width,
child: GestureDetector(
onTap: () {
@ -191,8 +191,14 @@ class claimListState extends ConsumerState<claimList> {
Tooltip(
message: 'Back',
child: IconButton(
icon: const Icon(Icons.arrow_left_sharp,size: 25,color: Color(0xFF425B5B)),
onPressed: () { context.go(AppRoutes.dashboard); },
icon: const Icon(
Icons.arrow_left_sharp,
size: 25,
color: Color(0xFF425B5B),
),
onPressed: () {
context.go(AppRoutes.dashboard);
},
splashRadius: 18,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(4),
@ -212,7 +218,7 @@ class claimListState extends ConsumerState<claimList> {
),
),
SizedBox(height: 10),
SizedBox(height: 5),
Expanded(
child: Container(
@ -301,7 +307,7 @@ class claimListState extends ConsumerState<claimList> {
],
),
),
SizedBox(height: 10),
SizedBox(height: 5),
if (!ResponsiveLayout.isMobile(context))
Container(
decoration: BoxDecoration(
@ -320,11 +326,11 @@ class claimListState extends ConsumerState<claimList> {
),
Expanded(
flex: 2,
child: Text('Reg.No.', style: _headerStyle),
child: Text('Vehicle.No.', style: _headerStyle),
),
Expanded(
flex: 2,
child: Text('Company', style: _headerStyle),
child: Text('Insurer', style: _headerStyle),
),
Expanded(
flex: 2,
@ -579,7 +585,7 @@ class claimListState extends ConsumerState<claimList> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
//company
Text("Company", style: _cardheaderStyle),
Text("Insurer", style: _cardheaderStyle),
Text(
item['policy_end_date'] != null
? _formatDate(item['policy_end_date'])

View File

@ -43,8 +43,9 @@ class endosementState extends ConsumerState<endosement> {
final roleId = ref.read(userRoleProvider);
final userId = ref.read(userIdProvider);
print("F46 => r : $roleId | mId: $id | uId: $userId ");
if (userId != null) { getStaffList(userId, roleId); }
if (userId != null) {
getStaffList(userId, roleId);
}
});
}
@ -174,7 +175,7 @@ class endosementState extends ConsumerState<endosement> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 40,
height: 30,
width: MediaQuery.of(context).size.width,
child: GestureDetector(
onTap: () {
@ -187,8 +188,14 @@ class endosementState extends ConsumerState<endosement> {
Tooltip(
message: 'Back',
child: IconButton(
icon: const Icon(Icons.arrow_left_sharp,size: 25,color: Color(0xFF425B5B)),
onPressed: () { context.go(AppRoutes.dashboard); },
icon: const Icon(
Icons.arrow_left_sharp,
size: 25,
color: Color(0xFF425B5B),
),
onPressed: () {
context.go(AppRoutes.dashboard);
},
splashRadius: 18,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(4),
@ -208,7 +215,7 @@ class endosementState extends ConsumerState<endosement> {
),
),
SizedBox(height: 10),
SizedBox(height: 5),
Expanded(
child: Container(
@ -295,7 +302,7 @@ class endosementState extends ConsumerState<endosement> {
],
),
),
SizedBox(height: 10),
SizedBox(height: 5),
if (!ResponsiveLayout.isMobile(context))
Container(
decoration: BoxDecoration(
@ -314,11 +321,11 @@ class endosementState extends ConsumerState<endosement> {
),
Expanded(
flex: 2,
child: Text('Reg.No.', style: _headerStyle),
child: Text('Vehicle.No.', style: _headerStyle),
),
Expanded(
flex: 4,
child: Text('Company', style: _headerStyle),
child: Text('Insurer', style: _headerStyle),
),
Expanded(
flex: 2,
@ -548,7 +555,7 @@ class endosementState extends ConsumerState<endosement> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
//company
Text("Company", style: _cardheaderStyle),
Text("Insurer", style: _cardheaderStyle),
Text(
item['insurer_name'] ?? '-',
style: _cardBodyStyle,

View File

@ -43,9 +43,9 @@ class StaffListState extends ConsumerState<StaffList> {
Future.microtask(() {
final data1 = ref.read(managerIdProvider);
final data2 = ref.read(handlerIdProvider);
print("Edata1 => mId: $data1 -2 : $data2");
prefid = data2 ?? data1;
// final data2 = ref.read(handlerIdProvider);
print("Edata1 => mId: $data1 -2 :");
prefid = data1;
role = ref.read(userRoleProvider);
print("E43 => mId: $prefid");
if (prefid != null && role != null) {

View File

@ -11,13 +11,14 @@ import '../../layouts/main_layout.dart';
import '../../providers/manager_provider.dart';
import '../../providers/quotation_staff_proivder.dart';
import '../../providers/userRoleProvider.dart';
import '../staff/Enquiry/tabs/tab.dart';
import '../staff/assignStaff.dart';
final enquiriesProvider = Provider<List<Map<String, String>>>((ref) {
return List.generate(5, (i) {
return {
"reg": "rrTN64V4387",
"company": "rrNew India",
"Insurer": "rrNew India",
"date": "rr09/09/2025",
"time": "rr11:30 AM",
};
@ -86,24 +87,25 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
apiService = ApiService();
Future.microtask(() {
// final id = ref.read(managerIdProvider);
final prefid = ref.read(userIdProvider);
final prefmanagerid = ref.read(managerIdProvider);
final prefuserid = ref.read(userIdProvider);
final prefroleId = ref.read(userRoleProvider);
print("B81 => roleId: $prefroleId | userId: $prefid ");
if (prefid != null) {
getStaffList(prefid, prefroleId);
print("B81 => roleId: $prefroleId | userId: $prefuserid ");
if (prefuserid != null) {
getStaffList(prefmanagerid!, prefroleId, prefuserid);
}
});
}
void refresh() {
final prefid = ref.read(userIdProvider);
final prefmanagerid = ref.read(managerIdProvider);
final prefuserid = ref.read(userIdProvider);
final prefroleId = ref.read(userRoleProvider);
if (prefid != null) {
print("REFRESH- calling getStaffList with $prefid, $prefroleId");
getStaffList(prefid, prefroleId);
if (prefuserid != null) {
print("REFRESH- calling getStaffList with $prefmanagerid, $prefuserid");
getStaffList(prefmanagerid!, prefroleId, prefuserid);
}
}
@ -128,31 +130,56 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
}
Future<void> handleStaffEdit(String id, String? flag) async {
// Navigator.pop(context);
print('EDITStaff');
// Navigator.pop(context); ddd
dynamic val;
print('EDITStaff - $id');
final prefs = await SharedPreferences.getInstance();
await prefs.remove('enqStaffDataId');
// Save the new id
await prefs.setString('enqStaffDataId', id.toString());
ref.read(quotationStaffIdProvider.notifier).state = id;
if (flag == "Policies") {
context.go(AppRoutes.policy);
val = 'Policy';
} else {
context.go(AppRoutes.quotation);
val = '';
}
var enqId = id;
final prefs = await SharedPreferences.getInstance();
// Remove old value (if any)
await prefs.remove('enqStaffDataId');
// Save the new id
await prefs.setString('enqStaffDataId', enqId.toString());
await prefs.setString('navFromDashboard', 'Dashboard');
ref.read(quotationStaffIdProvider.notifier).state = enqId;
ref.read(navFromEnqStaffProvider.notifier).state = 'Dashboard';
// showDialog(
// context: context,
// builder: (context) => TabEnquiryStaffList(showKey: val),
// );
final result = await showDialog(
context: context,
barrierDismissible:
false, // optional - prevents closing by tapping outside
builder: (context) => TabEnquiryStaffList(showKey: val),
);
// Code here runs *after* the dialog is closed
print("Dialog closed");
print("Dialog result: $result");
refresh();
}
Future<void> getStaffList(int managerId, role) async {
Future<void> getStaffList(int managerId, role, userId) async {
print('B89 => Fns called => $managerId | $role');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchDashboard(managerId, role);
final response = await apiService.fetchDashboard(managerId, role, userId);
if (response['status'] == 'success') {
final data = response['data'];
@ -396,7 +423,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: buildTab("Awaiting Quotation", 0),
child: buildTab("Awaiting Proposal", 0),
),
const SizedBox(width: 10),
Padding(
@ -457,6 +484,12 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
),
color: Colors.white,
child: ListTile(
onTap: () {
dynamic id = item['id'].toString();
print("Tapped ID: ${item['id']}");
handleEdit(id);
},
title: Text(
item["reg_no"] ?? "-", // from API
style: GoogleFonts.inter(
@ -546,6 +579,8 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
0.69 //400
: (role == 'manager')
? MediaQuery.of(context).size.height * 0.5
: (role == 'staff')
? MediaQuery.of(context).size.height * 0.85
: MediaQuery.of(context).size.height *
0.5, // 350 adjust height as needed
child: (role == 'manager' || role == 'handler')
@ -556,7 +591,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
title:
"Staff Proposal Pending List (${staffQuotationsPendingList.length})",
data: staffQuotationsPendingList,
stringFlag: "Quotation",
stringFlag: "Proposal",
role: role!,
),
),
@ -568,7 +603,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
child: (role == 'agent')
? agentPendings(
title:
"Awaiting Quotation (${quotationsPendingList.length})",
"Awaiting Proposal (${quotationsPendingList.length})",
data: quotationsPendingList,
role: role!,
onEdit: (row) {
@ -584,7 +619,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
? SizedBox.shrink()
: agentPendings(
title:
"Awaiting Quotation (${quotationsPendingList.length})",
"Awaiting Proposal (${quotationsPendingList.length})",
data: quotationsPendingList,
role: role!,
onEdit: (row) {
@ -619,9 +654,9 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
? SizedBox.shrink()
// othersPendings(
// title:
// "Awaiting Quotation (${quotationsPendingList.length})",
// "Awaiting Proposal (${quotationsPendingList.length})",
// data: quotationsPendingList,
// stringFlag: "Quotation",
// stringFlag: "Proposal",
// )
: agentPendings(
title:
@ -660,9 +695,9 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
?
// ? othersPendings(
// title:
// "Awaiting Quotation (${quotationsPendingList.length})",
// "Awaiting Proposal (${quotationsPendingList.length})",
// data: quotationsPendingList,
// stringFlag: "Quotation",
// stringFlag: "Proposal",
// )
agentPendings(
title:
@ -972,7 +1007,7 @@ class agentPendings extends StatelessWidget {
// ),
// ),
Expanded(
flex: 1,
flex: 2,
child: Text(
"Date & Time",
textAlign: TextAlign.center,
@ -982,7 +1017,7 @@ class agentPendings extends StatelessWidget {
Expanded(
flex: 2,
child: Text(
"Registration number",
"Vehicle Number",
textAlign: TextAlign.center,
style: _headerStyle,
),
@ -991,7 +1026,7 @@ class agentPendings extends StatelessWidget {
Expanded(
flex: 2,
child: Text(
"Insurer Company",
"Insurer",
textAlign: TextAlign.center,
style: _headerStyle,
),
@ -1072,7 +1107,7 @@ class agentPendings extends StatelessWidget {
// ),
// Date & Time
Expanded(
flex: 1,
flex: 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -1691,7 +1726,7 @@ class UnassignedEnq extends StatelessWidget {
// ),
Expanded(
child: Text(
"Registration number",
"Vehicle Number",
textAlign: TextAlign.center,
style: _headerStyle,
),

View File

@ -38,6 +38,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
int itemsPerPage = 10;
late ApiService apiService;
dynamic userId;
dynamic managerId;
dynamic handlerId;
final _formKey = GlobalKey<FormState>();
// List<Map<String, dynamic>> dataVal = [];
@ -64,10 +66,13 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
final id = ref.read(managerIdProvider);
roleId = ref.read(userRoleProvider);
userId = ref.read(userIdProvider);
managerId = ref.read(managerIdProvider);
// handlerId = ref.read(handlerIdProvider);
print("C72 => r : $roleId | mId: $id | uId: $userId ");
if (userId != null) {
getStaffList(userId, roleId);
print('handlerIdENQ - $handlerId');
print("C72 => r : $roleId | mId: $id | uId: $userId !mID : $managerId ");
if (managerId != null) {
getStaffList(managerId, roleId);
}
});
}
@ -78,8 +83,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
final userId = ref.read(userIdProvider);
print("C82 => r : $roleId | mId: $id | uId: $userId ");
if (userId != null) {
getStaffList(userId, roleId);
if (managerId != null) {
getStaffList(managerId, roleId);
}
}
@ -128,47 +133,39 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
String fromDate = '',
String toDate = '',
}) async {
print('C89 => Fns called => $managerId | $role');
print('A72 => Fns called => $managerId | $role');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchPolicyList(
final response = await apiService.fetchEnquiryList(
managerId,
role,
fromDate: controllers['startDate']?.text ?? '',
toDate: controllers['endDate']?.text ?? '',
);
print('FromDate : $fromDate');
print('ToDate : $toDate');
if (response['status'] == 'success') {
final data = response['data'];
print('C99 => getStaffListData => ${response['data']}');
final fromDate = response['from_date'] ?? '';
final toDate = response['to_date'] ?? '';
print('FromDate : $fromDate');
print('ToDate : $toDate');
setState(() {
controllers['startDate']?.text = fromDate;
controllers['endDate']?.text = toDate;
if (data is List) {
// Already a list of maps
getStaffData = List<Map<String, dynamic>>.from(data);
} else if (data is Map) {
// Single object, wrap in a list
getStaffData = [Map<String, dynamic>.from(data)];
} else {
getStaffData = [];
}
// getStaffData = List<Map<String, dynamic>>.from(response['data']);
originalData = getStaffData;
filteredData = List.from(originalData);
// print('originalData - $getClaimPolicies');
});
} else {
getStaffData = [];
@ -183,17 +180,66 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
}
}
List<dynamic> get _paginatedData2 {
// Sort descending by id first
final sortedData = [...filteredData]
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
// final sortedData = [...filteredData];
final startIndex = (currentPage - 1) * itemsPerPage;
final endIndex = (currentPage * itemsPerPage).clamp(0, sortedData.length);
return sortedData.sublist(startIndex, endIndex);
}
// Future<void> getStaffList1(
// int managerId,
// role, {
// String fromDate = '',
// String toDate = '',
// }) async {
// print('C89 => Fns called => $managerId | $role');
// setState(() {
// isLoading = true;
// });
//
// try {
// final response = await apiService.fetchPolicyList(
// managerId,
// role,
// fromDate: controllers['startDate']?.text ?? '',
// toDate: controllers['endDate']?.text ?? '',
// );
//
// print('FromDate : $fromDate');
// print('ToDate : $toDate');
//
// if (response['status'] == 'success') {
// final data = response['data'];
// print('C99 => getStaffListData => ${response['data']}');
// final fromDate = response['from_date'] ?? '';
// final toDate = response['to_date'] ?? '';
//
// print('FromDate : $fromDate');
// print('ToDate : $toDate');
// setState(() {
// controllers['startDate']?.text = fromDate;
// controllers['endDate']?.text = toDate;
//
// if (data is List) {
// // Already a list of maps
// getStaffData = List<Map<String, dynamic>>.from(data);
// } else if (data is Map) {
// // Single object, wrap in a list
// getStaffData = [Map<String, dynamic>.from(data)];
// } else {
// getStaffData = [];
// }
// // getStaffData = List<Map<String, dynamic>>.from(response['data']);
// originalData = getStaffData;
// filteredData = List.from(originalData);
// // print('originalData - $getClaimPolicies');
// });
// } else {
// getStaffData = [];
// originalData = [];
// }
// } catch (e) {
// print('Exception occurred: $e');
// } finally {
// setState(() {
// isLoading = false;
// });
// }
// }
List<dynamic> get _paginatedData {
// Sort descending by id first
@ -266,149 +312,185 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
}
}
List<Widget> _buildPopupMenuActions(
Future<void> handleStaff(
BuildContext context,
dynamic data,
id,
regNum,
) {
return [
if (roleId == 'manager' && data['status'] == 'Awaiting Quotation') ...[
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.pop(context);
showDialog(
context: context,
builder: (ctx) => AssignStaffDialog(
enquiryPrimaryId: id,
regNum: regNum,
userId: 1,
onSubmit: (value) {
debugPrint("New assignY: $value");
refresh();
},
),
);
},
hoverColor: Color(0xFFE3F1F0),
splashColor: Color(0xFFE3F1F0),
borderRadius: BorderRadius.circular(6),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
child: Row(
// mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"assets/miscellaneous/image_3.png",
// height: 45,
// width: 15,
),
SizedBox(width: 10),
Text('Assign Staff'),
],
),
),
),
),
],
Material(
color: Colors.transparent,
child: InkWell(
onTap: () async {
Navigator.pop(context);
final prefs = await SharedPreferences.getInstance();
// Remove old value (if any)
await prefs.remove('enqStaffDataId');
// Save the new id
await prefs.setString('enqStaffDataId', id.toString());
// Read it back if needed
// final dynamic? enqStaffDataId = prefs.getString('enqStaffDataId');
// Update provider too
// ref.read(quotationStaffIdProvider.notifier).state = enqStaffDataId;
ref.read(quotationStaffIdProvider.notifier).state = id;
context.go(AppRoutes.quotation);
},
hoverColor: Color(0xFFE3F1F0),
splashColor: Color(0xFFE3F1F0),
borderRadius: BorderRadius.circular(6),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
child: Row(
// mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"assets/miscellaneous/image_1.png",
height: 15,
width: 15,
),
const SizedBox(width: 10),
((data['status'] == 'Policy Created') ||
(data['status'] == 'Quotation Accepted'))
? const Text('View Quotation')
: const Text('Create Quotation'),
],
),
),
),
) async {
showDialog(
context: context,
builder: (ctx) => AssignStaffDialog(
enquiryPrimaryId: id,
regNum: regNum,
userId: userId,
onSubmit: (value) {
debugPrint("New assignY: $value");
refresh();
},
),
if (data['status'] == 'Quotation Accepted' ||
data['status'] == 'Policy Created')
Material(
color: Colors.transparent,
child: InkWell(
onTap: () async {
Navigator.pop(context);
final prefs = await SharedPreferences.getInstance();
// Remove old value (if any)
await prefs.remove('enqStaffDataId');
// Save the new id
await prefs.setString('enqStaffDataId', id.toString());
// Update provider too
ref.read(quotationStaffIdProvider.notifier).state = id;
context.go(AppRoutes.policy);
},
hoverColor: Color(0xFFE3F1F0),
splashColor: Color(0xFFE3F1F0),
borderRadius: BorderRadius.circular(6),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
child: Row(
// mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"assets/miscellaneous/image_2.png",
height: 15,
width: 15,
),
const SizedBox(width: 10),
data['status'] == 'Policy Created'
? Text('View Policy')
: Text('Create Policy'),
],
),
),
),
),
];
);
}
Future<void> handleEdit(item) async {
// Navigator.pop(context);
print('EDITStaff - ${item['id']}');
final prefs = await SharedPreferences.getInstance();
await prefs.remove('enqAgentDataId');
final id = item['id'].toString();
// Save the new id
await prefs.setString('enqAgentDataId', id.toString());
ref.read(enquiryIdProvider.notifier).state = id;
context.go(AppRoutes.tabEnquiry);
}
// List<Widget> _buildPopupMenuActions(
// BuildContext context,
// dynamic data,
// id,
// regNum,
// ) {
// return [
// if (roleId == 'manager' && data['status'] == 'Awaiting Quotation') ...[
// Material(
// color: Colors.transparent,
// child: InkWell(
// onTap: () {
// Navigator.pop(context);
// showDialog(
// context: context,
// builder: (ctx) => AssignStaffDialog(
// enquiryPrimaryId: id,
// regNum: regNum,
// userId: 1,
// onSubmit: (value) {
// debugPrint("New assignY: $value");
// refresh();
// },
// ),
// );
// },
// hoverColor: Color(0xFFE3F1F0),
// splashColor: Color(0xFFE3F1F0),
// borderRadius: BorderRadius.circular(6),
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
// child: Row(
// // mainAxisSize: MainAxisSize.min,
// children: [
// Image.asset(
// "assets/miscellaneous/image_3.png",
// // height: 45,
// // width: 15,
// ),
//
// SizedBox(width: 10),
// Text('Assign Staff'),
// ],
// ),
// ),
// ),
// ),
// ],
//
// Material(
// color: Colors.transparent,
// child: InkWell(
// onTap: () async {
// Navigator.pop(context);
// final prefs = await SharedPreferences.getInstance();
//
// // Remove old value (if any)
// await prefs.remove('enqStaffDataId');
//
// // Save the new id
// await prefs.setString('enqStaffDataId', id.toString());
//
// // Read it back if needed
// // final dynamic? enqStaffDataId = prefs.getString('enqStaffDataId');
//
// // Update provider too
// // ref.read(quotationStaffIdProvider.notifier).state = enqStaffDataId;
// ref.read(quotationStaffIdProvider.notifier).state = id;
//
// context.go(AppRoutes.quotation);
// },
// hoverColor: Color(0xFFE3F1F0),
// splashColor: Color(0xFFE3F1F0),
// borderRadius: BorderRadius.circular(6),
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
// child: Row(
// // mainAxisSize: MainAxisSize.min,
// children: [
// Image.asset(
// "assets/miscellaneous/image_1.png",
// height: 15,
// width: 15,
// ),
//
// const SizedBox(width: 10),
// ((data['status'] == 'Policy Created') ||
// (data['status'] == 'Quotation Accepted'))
// ? const Text('View Quotation')
// : const Text('Create Quotation'),
// ],
// ),
// ),
// ),
// ),
//
// if (data['status'] == 'Quotation Accepted' ||
// data['status'] == 'Policy Created')
// Material(
// color: Colors.transparent,
// child: InkWell(
// onTap: () async {
// Navigator.pop(context);
//
// final prefs = await SharedPreferences.getInstance();
//
// // Remove old value (if any)
// await prefs.remove('enqStaffDataId');
//
// // Save the new id
// await prefs.setString('enqStaffDataId', id.toString());
//
// // Update provider too
//
// ref.read(quotationStaffIdProvider.notifier).state = id;
// context.go(AppRoutes.policy);
// },
// hoverColor: Color(0xFFE3F1F0),
// splashColor: Color(0xFFE3F1F0),
// borderRadius: BorderRadius.circular(6),
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
// child: Row(
// // mainAxisSize: MainAxisSize.min,
// children: [
// Image.asset(
// "assets/miscellaneous/image_2.png",
// height: 15,
// width: 15,
// ),
//
// const SizedBox(width: 10),
// data['status'] == 'Policy Created'
// ? Text('View Policy')
// : Text('Create Policy'),
// ],
// ),
// ),
// ),
// ),
// ];
// }
@override
Widget build(BuildContext context) {
return MainLayout(
@ -421,7 +503,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 40,
height: 30,
width: MediaQuery.of(context).size.width,
child: GestureDetector(
onTap: () {
@ -739,14 +821,17 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
child: const Row(
children: [
Expanded(
flex: 3,
flex: 2,
child: Text('Created Date', style: _headerStyle),
),
Expanded(
flex: 3,
flex: 2,
child: Text('Updated Date', style: _headerStyle),
),
Expanded(flex: 2, child: Text('Reg.No', style: _headerStyle)),
Expanded(
flex: 2,
child: Text('Vehicle.No', style: _headerStyle),
),
Expanded(flex: 2, child: Text('Partner', style: _headerStyle)),
Expanded(
flex: 2,
@ -754,7 +839,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
),
Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)),
Expanded(
flex: 3,
flex: 2,
child: Padding(
padding: EdgeInsets.only(left: 8.0),
child: Text('Insured Name', style: _headerStyle),
@ -770,7 +855,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
child: Text('Policy Number', style: _headerStyle),
),
Expanded(flex: 3, child: Text('Status', style: _headerStyle)),
Expanded(flex: 2, child: Text('Status', style: _headerStyle)),
Expanded(flex: 1, child: Text('Action', style: _headerStyle)),
],
),
@ -867,7 +952,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
child: Row(
children: [
Expanded(
flex: 3,
flex: 2,
child: Text(
_formatDate(item['created_on']) ?? '-',
style: _dataBold,
@ -876,7 +961,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
),
),
Expanded(
flex: 3,
flex: 2,
child: Text(
_formatDate(item['updated_on']) ?? '-',
style: _dataBold,
@ -890,10 +975,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
),
Expanded(
flex: 2,
child: Text(
_formatDate(item['agent_name']) ?? '-',
style: _dataBold,
),
child: Text(item['agent_name'] ?? '-', style: _dataBold),
),
Expanded(
flex: 2,
@ -909,14 +991,13 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
),
),
Expanded(
flex: 3,
child: Center(
child: Text(
item['insured_name'] ?? '-',
style: _dataBold,
softWrap: true,
maxLines: 3,
),
flex: 2,
child: Text(
item['insured_name'] ?? '-',
style: _dataBold,
softWrap: true,
maxLines: 3,
),
),
Expanded(
@ -948,7 +1029,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
),
Expanded(
flex: 3,
flex: 2,
child: Text(item['status'] ?? '-', style: _dataBold),
),
@ -956,36 +1037,37 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
flex: 1,
child: Row(
children: [
PopupMenuButton<int>(
color: Colors.white,
padding: EdgeInsets.zero,
offset: Offset(0, 30),
icon: Icon(
Icons.more_vert,
color: Color(0xFF475569),
size: 14,
),
itemBuilder: (context) => [
CustomPopupMenuEntry(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 8,
vertical: 8,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildPopupMenuActions(
context,
item,
item['id'],
item['reg_no'],
),
),
),
if (item['status'] == 'Awaiting Proposal')
Tooltip(
message: "Assign Staff",
child: IconButton(
icon: Icon(Icons.assignment_ind_outlined, size: 15),
onPressed: () {
handleStaff(context, item, item['id'], item['reg_no']);
},
splashRadius: 5,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(4),
constraints: const BoxConstraints(),
),
],
),
Tooltip(
message: 'Edit',
child: IconButton(
icon: Image.asset(
"assets/miscellaneous/Edit.png",
height: 12,
width: 12,
),
onPressed: () {
handleEdit(item);
},
splashRadius: 5,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(4),
constraints: const BoxConstraints(),
),
),
],
),
@ -1018,20 +1100,20 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
offset: Offset(0, 30),
icon: Icon(Icons.more_vert, color: Color(0xFF475569), size: 14),
itemBuilder: (context) => [
CustomPopupMenuEntry(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: _buildPopupMenuActions(
context,
item,
item['id'],
item['reg_no'],
),
),
),
),
// CustomPopupMenuEntry(
// child: Container(
// padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: _buildPopupMenuActions(
// context,
// item,
// item['id'],
// item['reg_no'],
// ),
// ),
// ),
// ),
],
),
],

View File

@ -174,18 +174,18 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
}
// Handler ID
final dynamic handlerIdRaw = data['manager_id'];
final int? handlerId = handlerIdRaw is int
? handlerIdRaw
: int.tryParse(handlerIdRaw.toString());
if (handlerId != null) {
ref.read(handlerIdProvider.notifier).state = handlerId;
print("✅ handlerId ID saved globally: $handlerId");
await prefs.setInt('handlerId', handlerId);
} else {
print("⚠️ handlerId ID is null or invalid");
}
// final dynamic handlerIdRaw = data['handler_id'];
// final int? handlerId = handlerIdRaw is int
// ? handlerIdRaw
// : int.tryParse(handlerIdRaw.toString());
//
// if (handlerId != null) {
// ref.read(handlerIdProvider.notifier).state = handlerId;
// print("✅ handlerId ID saved globally: $handlerId");
// await prefs.setInt('handlerId', handlerId);
// } else {
// print("⚠️ handlerId ID is null or invalid");
// }
// User ID
final dynamic userIdRaw = data['id'];

View File

@ -7,6 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/tab.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../core/config/env.dart';
@ -197,6 +198,21 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
}
}
Future<void> buildStatusActions(BuildContext context, status, id) async {
print("Actionsstatus - $status -$id");
dynamic val;
if (status == 'Awaiting Proposal' || status == 'Proposal Created') {
val = '';
} else {
val = 'Policy';
}
showDialog(
context: context,
builder: (context) => TabEnquiryStaffList(showKey: val),
);
}
List<dynamic> get _paginatedData2 {
// Sort descending by id first
final sortedData = [...filteredData]
@ -422,6 +438,27 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
];
}
List<Widget> _buildPopupDownload(
BuildContext context,
dynamic data,
id,
regNum,
) {
bool isMobile = ResponsiveLayout.isMobile(context);
return [
Row(
children: [
buildDocRC(context, isMobile, id),
Spacer(),
// SizedBox(width: 3),
buildDocIdProof(context, isMobile, id),
Spacer(),
buildDocPrevPolicy(context, isMobile, id),
],
),
];
}
@override
Widget build(BuildContext context) {
return MainLayout(
@ -723,37 +760,6 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
);
}
// Widget _buildDataTable(BuildContext context) {
// if (filteredData.isEmpty) {
// return const SizedBox(
// height: 50,
// child: Center(child: Text('No available data')),
// );
// }
//
// final sortedData = [..._paginatedData];
// return ListView.builder(
// itemCount: ResponsiveLayout.isMobile(context)
// ? sortedData
// .length // only cards for mobile
// : sortedData.length + 1, // +1 for header in desktop
// itemBuilder: (context, index) {
// if (!ResponsiveLayout.isMobile(context) && index == 0) {
// return _buildHeader();
// }
//
// final startIndex = (currentPage - 1) * itemsPerPage;
// final item =
// sortedData[index - (ResponsiveLayout.isMobile(context) ? 0 : 1)];
// final sno = startIndex + index;
//
// return !ResponsiveLayout.isMobile(context)
// ? _buildDataRow(item, sno)
// : _buildDataCard(item, sno);
// },
// );
// }
Widget _buildHeader() {
return SizedBox.shrink();
}
@ -803,18 +809,54 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
Expanded(
flex: 3,
child: InkWell(
hoverColor: Color(0xffD9EBE8),
focusColor: Color(0xffD9EBE8),
splashColor: Color(0xffD9EBE8),
highlightColor: Color(0xffD9EBE8),
onTap: () {
dynamic id = item['id'];
print("ENQID : $id ");
},
child: Text(item['reg_no'] ?? '-', style: _dataBold),
child: Builder(
builder: (buttonContext) => InkWell(
hoverColor: const Color(0xffD9EBE8),
focusColor: const Color(0xffD9EBE8),
splashColor: const Color(0xffD9EBE8),
highlightColor: const Color(0xffD9EBE8),
onTap: () async {
// Get overlay and button position RELATIVE to InkWell
final RenderBox button =
buttonContext.findRenderObject() as RenderBox;
final RenderBox overlay =
Overlay.of(buttonContext).context.findRenderObject()
as RenderBox;
final Offset position = button.localToGlobal(
Offset.zero,
ancestor: overlay,
);
await showMenu(
context: buttonContext,
position: RelativeRect.fromLTRB(
position.dx,
position.dy + button.size.height,
overlay.size.width - position.dx,
0,
),
items: [
PopupMenuItem(
child: Column(
mainAxisSize: MainAxisSize.min,
children: _buildPopupDownload(
buttonContext,
item,
item['id'],
item['reg_no'],
),
),
),
],
color: Colors.white,
);
},
child: Text(item['reg_no'] ?? '-', style: _dataBold),
),
),
),
Expanded(
flex: 3,
@ -837,79 +879,24 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
),
Expanded(
flex: 3,
child: Text(item['status'] ?? '-', style: _dataBold),
),
child: InkWell(
onTap: () async {
var status = item['status'];
var enqId = item['id'];
// Expanded(
// flex: 2,
// child: Text(item['assigned_to_name'] ?? '-', style: _dataBold),
// ),
//
// Expanded(
// flex: 2,
// child: Text(
// item['premium_amount'] ?? '-',
// style: _dataBold,
// softWrap: true,
// maxLines: 3,
// ),
// ),
// Expanded(
// flex: 2,
// child: Text(
// item['payment_mode'] ?? '-',
// style: _dataBold,
// softWrap: true,
// maxLines: 3,
// ),
// ),
// Expanded(
// flex: 2,
// child: Text(
// item['policy_number'] ?? '-',
// style: _dataBold,
// softWrap: true,
// maxLines: 3,
// ),
// ),
// Expanded(
// flex: 1,
// child: Row(
// children: [
// PopupMenuButton<int>(
// color: Colors.white,
// padding: EdgeInsets.zero,
// offset: Offset(0, 30),
// icon: Icon(
// Icons.more_vert,
// color: Color(0xFF475569),
// size: 14,
// ),
// itemBuilder: (context) => [
// CustomPopupMenuEntry(
// child: Container(
// padding: EdgeInsets.symmetric(
// horizontal: 8,
// vertical: 8,
// ),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: _buildPopupMenuActions(
// context,
// item,
// item['id'],
// item['reg_no'],
// ),
// ),
// ),
// ),
// ],
// ),
// ],
// ),
// ),
final prefs = await SharedPreferences.getInstance();
// Remove old value (if any)
await prefs.remove('enqStaffDataId');
// Save the new id
await prefs.setString('enqStaffDataId', enqId.toString());
ref.read(quotationStaffIdProvider.notifier).state = enqId;
buildStatusActions(context, status, enqId);
},
child: Text(item['status'] ?? '-', style: _dataBold),
),
),
],
),
);
@ -1101,6 +1088,129 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
);
}
Widget buildDocRC(BuildContext context, bool isMobile, selectedEnquiryId) {
return GestureDetector(
onTap: () {
// print("Upload $idget.id}{w");
final selectedId = selectedEnquiryId;
// final path =
// 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
final path =
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=rc';
apiService.getPdfDownload(path, selectedId);
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: const Color(0xFF425B5B),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"RC",
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
?isMobile ? null : SizedBox(width: 2),
// isMobile ? const Spacer() : const SizedBox(width: 15),
const Icon(
Icons.file_download_outlined,
size: 16,
color: Colors.white,
),
],
),
),
);
}
Widget buildDocIdProof(
BuildContext context,
bool isMobile,
selectedEnquiryId,
) {
return GestureDetector(
onTap: () {
print("Upload $selectedEnquiryId");
final selectedId = selectedEnquiryId;
// final path =
// 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
final path =
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=id_proof';
apiService.getPdfDownload(path, selectedId);
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: const Color(0xFF425B5B),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"ID Proof",
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
?isMobile ? null : SizedBox(width: 2),
// const SizedBox(width: 15),
Icon(Icons.file_download_outlined, size: 16, color: Colors.white),
],
),
),
);
}
Widget buildDocPrevPolicy(
BuildContext context,
bool isMobile,
selectedEnquiryId,
) {
return GestureDetector(
onTap: () {
print("QD597 Upload $selectedEnquiryId");
final selectedId = selectedEnquiryId;
// final path =
// 'api/agent/downloadAgentIncentiveFile?id=$selectedId';
final path =
'api/enquiry/downloadEnquiryFile?enquiry_id=$selectedId&file_type=previous_policy';
apiService.getPdfDownload(path, selectedId);
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: const Color(0xFF425B5B),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Previous Policy",
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
?isMobile ? null : SizedBox(width: 2),
// isMobile ? const Spacer() : const SizedBox(width: 15),
Icon(Icons.file_download_outlined, size: 16, color: Colors.white),
],
),
),
);
}
static final _dataBold = TextStyle(
fontSize: 14,

View File

@ -700,13 +700,16 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
children: [
Expanded(
flex: 3,
child: Text('Created Date', style: _headerStyle),
child: Text('Received Date & Time', style: _headerStyle),
),
Expanded(
flex: 3,
child: Text('Updated Date', style: _headerStyle),
),
Expanded(flex: 2, child: Text('Reg.No', style: _headerStyle)),
Expanded(
flex: 2,
child: Text('Vehicle.No', style: _headerStyle),
),
Expanded(flex: 2, child: Text('Partner', style: _headerStyle)),
Expanded(
flex: 2,
@ -1005,7 +1008,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Company", style: _cardheaderStyle),
const Text("Insurer", style: _cardheaderStyle),
Text(item['insurer_name'] ?? '-', style: _cardBodyStyle),
],
),

View File

@ -0,0 +1,769 @@
import 'dart:convert';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/data/utils/toastNotification.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../../core/config/env.dart';
import '../../../../../core/routing/routes.dart';
import '../../../../../core/services/api_service.dart';
import '../../../../../data/services/auth_service.dart';
import '../../../../../data/utils/validators.dart';
import '../../../../layouts/responsive_layout.dart';
import '../../../../providers/manager_provider.dart';
import '../../../../providers/quotation_staff_proivder.dart';
import '../../../../themes/indicators/customizd_file_upload.dart';
import '../../../../themes/indicators/input_field_decoration.dart';
import '../../../../themes/indicators/text_field_theme.dart';
class CreateQuotationForm extends ConsumerStatefulWidget {
final dynamic userId;
final dynamic managerId;
final dynamic selectedEnquiryId;
final dynamic selectedInsurdId;
final dynamic selectedQuotationFrmListdata;
final dynamic selectedQuotationFrmListId;
final void Function(String value) onSubmit;
const CreateQuotationForm({
super.key,
required this.userId,
required this.managerId,
required this.selectedEnquiryId,
required this.selectedInsurdId,
this.selectedQuotationFrmListdata,
this.selectedQuotationFrmListId,
required this.onSubmit,
});
@override
ConsumerState<CreateQuotationForm> createState() =>
CreateQuotationFormState();
// State<CreateQuotationForm> createState() => _CreateQuotationFormState();
}
class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
late ApiService apiService;
String? _token;
String? selectedFileNames;
List<Map<String, dynamic>> getInsurersData = [];
List<Map<String, dynamic>> filteredInsurersData = [];
String? selectedInsurer;
bool isLoading = false;
bool _autoValidate = false;
late TextEditingController controller;
Map<String, TextEditingController> controllers = {};
final _formKey = GlobalKey<FormState>();
String? docUploadedFileUrlFromApi;
String? selectedId;
PlatformFile? docUploadedFile;
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
dropDownKeyInsurer = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
List<String> tabHeader = ['idv', 'premium_Amount', 'insurer'];
List<Map<String, dynamic>> getInsuranceTypeData = [];
List<Map<String, dynamic>> filteredInsuranceData = [];
String? selectedInsPlanType;
String? selectedEndorsement;
Map<String, dynamic> dataDetails() {
final data = {
"enquiry_id": widget.selectedEnquiryId,
"insured_declared_value": controllers["idv"]?.text,
"insurer_id": widget.selectedInsurdId,
// "insurer_id": selectedInsurer,
"premium_amount": controllers["premium_Amount"]?.text,
"insurance_plan_type_id": selectedInsPlanType,
// "additional_uploaded_file_name": "extra_doc.pdf",
// "created_by": widget.userId,
"manager_id": widget.managerId,
};
return data;
}
@override
void initState() {
super.initState();
apiService = ApiService();
for (String field in tabHeader) {
controllers[field] = TextEditingController();
}
// 🔹 Init logic here (API calls, token fetch, etc.)
_initializeToken();
getInsuranceType();
// getInsurers();
updateData();
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
print("APISERTOKEN - $_token");
}
@override
void dispose() {
// Dispose all TextEditingControllers
for (var controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
void reset() {
_formKey.currentState?.reset();
// Clear all TextEditingControllers
for (var controller in controllers.values) {
controller.clear();
}
dropDownKey.currentState?.changeSelectedItem(null);
dropDownKeyInsurer.currentState?.changeSelectedItem(null);
// Reset dropdowns / selections
selectedInsurer = null;
selectedInsPlanType = null;
selectedEndorsement = null;
// Reset file selection
selectedFileNames = null;
docUploadedFile = null;
docUploadedFileUrlFromApi = null;
// Reset selected ID
selectedId = null;
// Trigger UI update
setState(() {});
}
void updateData() {
if (widget.selectedQuotationFrmListId != null &&
widget.selectedQuotationFrmListdata!.isNotEmpty) {
print('checkData -- ${widget.selectedQuotationFrmListdata}');
selectedId = widget.selectedQuotationFrmListId!;
// Pre-fill controllers
controllers["idv"]?.text =
widget.selectedQuotationFrmListdata!['insured_declared_value']
?.toString() ??
'';
controllers["premium_Amount"]?.text =
widget.selectedQuotationFrmListdata!['premium_amount']?.toString() ??
'';
selectedInsPlanType = widget
.selectedQuotationFrmListdata!['insurance_plan_type_id']
?.toString();
selectedInsurer = '1';
// controllers["insurer"]?.text = 'LIC';
// selectedInsurer =
// widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? '';
String? apiDocPath =
widget.selectedQuotationFrmListdata!["additional_uploaded_file_name"];
if (apiDocPath != null && apiDocPath.isNotEmpty) {
print('apiDocPath - $apiDocPath');
selectedFileNames = apiDocPath.split('/').last;
print('selectedFileNames - $selectedFileNames');
docUploadedFileUrlFromApi = apiDocPath;
print('passportFileUrlFromApi - $docUploadedFileUrlFromApi');
docUploadedFile = null;
} else {
selectedFileNames = null;
docUploadedFile = null;
docUploadedFileUrlFromApi = null;
}
}
}
Future<void> getInsurers() async {
print('Insurers called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchMasterDropDown('Insurers');
if (response['status'] == 200) {
print('getInsurers - ${response['data']}');
setState(() {
getInsurersData = List<Map<String, dynamic>>.from(response['data']);
print('API Data - $getInsurersData');
filteredInsurersData = List.from(getInsurersData);
print('originalData - $filteredInsurersData');
});
} else {
getInsurersData = [];
filteredInsurersData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
Future<void> getInsuranceType() async {
print('getClaimList called');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchMasterDropDown('InsuranceType');
if (response['status'] == 200) {
print('getInsuranceTypeData - ${response['data']}');
setState(() {
getInsuranceTypeData = List<Map<String, dynamic>>.from(
response['data'],
);
print('API Data - $getInsuranceTypeData');
filteredInsuranceData = List.from(getInsuranceTypeData);
print('originalData - $filteredInsuranceData');
});
} else {
getInsuranceTypeData = [];
filteredInsuranceData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
void handleDone() {
if (!_formKey.currentState!.validate()) return;
// setState(() {
// _autoValidate = true; // enable autovalidation after first save attempt
// });
setState(() {
if (_formKey.currentState!.validate()) {
dataDetails();
final dataSet = dataDetails();
print("dataSetAgent - $dataSet");
// print("managerId - $managerId ,userId - $userId ");
createUserData(dataSet);
} else {
// isDi sable = false;
}
});
}
Future<void> createUserData(Map<String, dynamic> userData) async {
// final bool isUpdating = widget.selectedQuotationFrmListId != null;
// final id = widget.selectedQuotationFrmListId!;
final bool isUpdating = widget.selectedQuotationFrmListId != null;
final id = widget.selectedQuotationFrmListId; // keep nullable
print('id - $id');
final uri = Uri.parse(
// isUpdating
// ? 'https://venbait.in/nhance/partner/dev/api/agent/updateAgent'
// : 'https://venbait.in/nhance/partner/dev/api/agent/createAgent',
isUpdating
? '${Env.apiUrl}quotation/updateQuotation'
: '${Env.apiUrl}quotation/createQuotation',
);
if (_token == null) {
throw Exception('Token not found. Please log in.');
}
// Use MultipartRequest (POST only)
final request = http.MultipartRequest('POST', uri);
request.headers['Authorization'] = 'Bearer $_token';
request.headers['app-signature'] =
'nhance-partner-2025-signature-35468846JRhH551HK';
// If updating, spoof the method Laravel-style
if (isUpdating) {
print('Updatrinf');
// request.fields['_method'] = 'PUT';
request.fields['id'] = id!;
request.fields['updated_by'] = widget.userId!.toString();
} else {
print('Not Updatrinf');
request.fields['created_by'] = widget.userId!.toString();
}
print("USerDAta - $userData");
// userData.forEach((key, value) {
// request.fields[key] = value.toString();
// print("✅ Encoded travel_details2: ${request.fields[key]}");
// });
userData.forEach((key, value) {
// if (key != 'certificate_file_name') {
request.fields[key] = value.toString();
print("✅ Encoded $key: ${request.fields[key]}");
// }
});
if (docUploadedFile != null) {
try {
if (docUploadedFile!.bytes != null) {
final multipartFile = http.MultipartFile.fromBytes(
'additional_uploaded_file_name',
docUploadedFile!.bytes!,
filename: docUploadedFile!.name,
);
request.files.add(multipartFile);
} else if (docUploadedFile!.path != null) {
final multipartFile = await http.MultipartFile.fromPath(
'additional_uploaded_file_name',
docUploadedFile!.path!,
filename: docUploadedFile!.name,
);
request.files.add(multipartFile);
}
print("📎 File attached: ${docUploadedFile!.name}");
} catch (e) {
print("❌ Failed to attach file: $e");
}
}
print(" Sending request with fields: ${request.fields}");
try {
final streamedResponse = await request.send();
final response = await http.Response.fromStream(streamedResponse);
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
if (response.statusCode == 200 || response.statusCode == 201) {
// dispose();
print("✅ Agent submitted successfully!");
print("Response: ${response.body}");
widget.onSubmit('Success');
reset();
// Navigator.of(context).pop();
} else {
final responseBody = jsonDecode(response.body);
dynamic msg = responseBody['data'];
print("❌ Submission failed. Status: ${response.statusCode}");
print("Body: ${response.body}");
ToastHelper.showErrorToast(context, 'Proposal Creation Failed');
}
} catch (e) {
print("🔥 Error submitting user: $e");
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Header row
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.selectedQuotationFrmListId != null
? 'Update Proposal'
: 'Create Proposal',
style: GoogleFonts.inter(
color: const Color(0xFF374141),
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(height: 8),
// 🔹 Switch content dynamically
buildFormFields(context),
],
);
}
Widget buildFormFields(BuildContext context) {
return Form(
key: _formKey,
// autovalidateMode: AutovalidateMode.onUserInteraction,
// autovalidateMode: _autoValidate
// ? AutovalidateMode.onUserInteraction
// : AutovalidateMode.disabled,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
buildIdv(context),
Spacer(),
// buildInsurer(context),
buildInsurancePlanType(context),
Spacer(),
buildPremiumAmnt(context),
Spacer(),
// buildDocuments(context),
GestureDetector(
onTap: () {
handleDone();
// widget.onSubmit(controller.text.trim());
// Navigator.of(context).pop();
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 25.0,
vertical: 15,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: const Color(0xFF425B5B),
),
child: const Text(
'Save',
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
),
),
// if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
// _buildResponsiveRow(
// context,
// buildAdditonalDocuments(context),
// buildRemarks(context),
// ),
],
),
);
}
// ------------------------- Claims Part -----------------------------------
Widget buildIdv(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('IDV *', style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
controller: controllers['idv']!,
validator: (value) => Validators.doubleNumber(value, "IDV"),
// validator: (value) => Validators.number(value, "IDV"),
backgroundColor: Color(0xFFEDF6F5),
// readOnly: true,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.15,
),
],
);
}
Widget buildInsurer2(BuildContext context) {
Map<String, dynamic>? selectedInsurerd = filteredInsurersData.firstWhere(
(item) => item['id'].toString() == selectedInsurer,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Insurer *', style: _textStyle),
SizedBox(height: 10),
Container(
decoration: BoxDecoration(
color: Colors.white,
// borderRadius: BorderRadius.circular(10.0),
),
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// height: 40,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyInsurer,
selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null,
items: (filter, infiniteScrollProps) {
return filteredInsurersData;
},
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;
},
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Insurer",
).copyWith(
filled: true,
fillColor: Color(
0xFFEDF6F5,
), // 👈 makes the dropdown input white
),
),
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 Insurer...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
print("Selected Insurer : ${val['name']}");
print("Id: ${val['id']}");
selectedInsurer = val['id'];
// controllers['agentId']?.text = val['agent_code'];
// agentId = agent['id'];
}
},
),
),
],
);
}
Widget buildPremiumAmnt(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Premium Amount *', style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
controller: controllers['premium_Amount']!,
backgroundColor: Color(0xFFEDF6F5),
validator: (value) => Validators.doubleNumber(value, "PremiumAmount"),
// validator: (value) => Validators.number(value, "PremiumAmount "),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.15,
),
],
);
}
Widget buildInsurancePlanType(context) {
Map<String, dynamic>? selectedVehicle = filteredInsuranceData.firstWhere(
(item) => item['id'].toString() == selectedInsPlanType,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Plan Type *", style: _textStyle),
SizedBox(height: 10),
Container(
color: Colors.white,
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.15,
// height: 40,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownKey,
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
items: (filter, infiniteScrollProps) {
return filteredInsuranceData;
},
itemAsString: (val) => val['insurance_plan_type'].toString(),
compareFn: (item, selectedItem) =>
item['id'] == selectedItem['id'], // compare by id
validator: (val) {
if (val == null) {
return "Required"; // error message
}
return null;
},
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Plan Type",
).copyWith(
filled: true,
fillColor: Color(
0xFFEDF6F5,
), // 👈 makes the dropdown input white
),
),
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 Plan Type...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
print("Selected ClaimsType : ${val['insurance_plan_type']}");
print("Id: ${val['id']}");
selectedInsPlanType = val['id'];
// controllers['agentId']?.text = val['agent_code'];
// agentId = agent['id'];
}
},
),
),
],
);
}
Widget buildDocuments(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Proposal Documents ', style: _textStyle),
const SizedBox(height: 10),
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
ThemedUploadField(
hintText: selectedFileNames ?? "Upload Document",
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
backgroundColor: Color(0xFFEDF6F5),
onFileSelected: (fileName, file) {
print("Picked file: $fileName (${file.size} bytes)");
setState(() {
docUploadedFile = file;
});
},
),
const SizedBox(height: 5),
if (docUploadedFileUrlFromApi != null)
Container(
// color: Colors.white,
child: Row(
children: [
GestureDetector(
onTap: () => apiService.downloadFile(
apiUrl:
'api/quotation/downloadAdditionalUploadedFile?id=$selectedId',
apiId: selectedId,
localFile: docUploadedFile,
fileName: selectedFileNames,
),
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Color(0xFF425B5B),
// color: Colors.green.shade300,
),
child: Row(
children: const [
Text(
"Download",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w200,
color: Colors.white,
),
),
SizedBox(width: 5),
Icon(Icons.download, size: 13, color: Colors.white),
],
),
),
),
],
),
),
],
),
],
);
}
// ------------------- STyle ---------------------------------
static final TextStyle _textStyle = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,723 @@
import 'dart:io' as html;
import 'package:dropdown_search/dropdown_search.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../../core/routing/routes.dart';
import '../../../../../core/services/api_service.dart';
import '../../../../../data/services/auth_service.dart';
import '../../../../../data/utils/validators.dart';
import '../../../../layouts/main_layout.dart';
import '../../../../layouts/responsive_layout.dart';
import '../../../../providers/manager_provider.dart';
import '../../../../providers/quotation_staff_proivder.dart';
import '../../../../themes/indicators/text_field_theme.dart';
import '../../quotations/createQuotationPopUp.dart';
import 'createQuotation.dart';
class QuotationStaffTab extends ConsumerStatefulWidget {
String? id;
List<Map<String, dynamic>>? data;
final Future<void> Function()? onRefresh;
QuotationStaffTab({super.key, this.data, this.id, this.onRefresh});
@override
ConsumerState<QuotationStaffTab> createState() => QuotationStaffTabState();
}
class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
int currentPage = 0;
int itemsPerPage = 10;
bool blockKey = false;
List<Map<String, dynamic>> dataVal = [];
final TextEditingController _searchController = TextEditingController();
late ApiService apiService;
final _formKey = GlobalKey<FormState>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
List<String> tabHeader = [
'regNum',
'insurer',
'mobile',
'code',
'address',
'regNo',
];
late String isActive = "1";
PlatformFile? docUploadedFile;
// PlatformFile? passportFile;
String? selectedFileNames;
String? selectedInsurdId;
String? passportFileUrlFromApi;
String? selectedId;
bool isLoading = false;
bool isquotation = false;
Map<String, TextEditingController> controllers = {};
String? _token;
dynamic userId;
dynamic selectedEnquiryId;
dynamic managerId;
dynamic enqQuotation;
dynamic selectedQuotationFrmListId;
Map<String, dynamic>? selectedQuotationFrmListData;
List<Map<String, dynamic>> getVehicleTypeData = [];
List<Map<String, dynamic>> filteredVechicleData = [];
List<Map<String, dynamic>> getInsurersData = [];
List<Map<String, dynamic>> filteredInsurersData = [];
Map<String, dynamic> dataDetails() {
final data = {
"regNum": controllers["regNum"]?.text,
// "insurer": controllers["insurer"]?.text,
"insurer": controllers["insurer"]?.text,
"mobile": controllers["mobile"]?.text,
"address": controllers["address"]?.text,
"agent_code": controllers["code"]?.text,
"is_active": isActive,
"manager_id": managerId,
};
return data;
}
List<Map<String, dynamic>> getQuotationData = [];
late Map<String, dynamic> enquiryData;
List<Map<String, dynamic>> originalData = [];
List<Map<String, dynamic>> filteredData = [];
// bool isLoading = false;
Future<void> _restoreManagerId(WidgetRef ref) async {
final prefs = await SharedPreferences.getInstance();
final String? savedId = prefs.getString(
'enqStaffDataId',
); // already a string
if (savedId != null) {
ref.read(quotationStaffIdProvider.notifier).state = savedId;
print("savedenqStaffDataId ID restored: $savedId");
_loadData(savedId);
}
}
@override
void initState() {
super.initState();
apiService = ApiService();
if (kIsWeb) {
Future.microtask(() => _restoreManagerId(ref));
}
for (String field in tabHeader) {
controllers[field] = TextEditingController();
}
_initializeToken();
Future.microtask(() {
managerId = ref.read(managerIdProvider); // use read
userId = ref.read(userIdProvider); // use read
print('QmanagerId - $managerId');
print('QuserId - $userId');
enqQuotation = ref.read(quotationStaffIdProvider); // use read
print('QenqQuotation - $enqQuotation');
if (enqQuotation != null) {
_loadData(enqQuotation);
}
});
}
@override
void dispose() {
// Dispose all TextEditingControllers
for (var controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
print("APISERTOKEN - $_token");
}
void updateEnquiryData(enquiryData) {
print('updateEnquiryData - $enquiryData');
setState(() {
selectedInsurdId = enquiryData['insurer_id'];
selectedEnquiryId = enquiryData['id'];
print('selectedEnquiryId- $selectedEnquiryId');
controllers["regNum"]?.text = enquiryData['reg_no'];
// controllers["insurer"]?.text = enquiryData['insurer_name'];
});
}
Future<void> _loadData(enqQuotation) async {
getQuotationList(enqQuotation);
}
void refresh() {
print("refresh--");
if (enqQuotation != null) {
_loadData(enqQuotation);
}
}
Future<void> getQuotationList(enqQuotation) async {
print('getClaimList called enqQuotation- $enqQuotation');
setState(() {
isLoading = true;
});
try {
final response = await apiService.findEnqQuotePolicyView(enqQuotation);
if (response['status'] == 'success') {
print('quoationListData - ${response['data']}');
setState(() {
enquiryData = Map<String, dynamic>.from(response['data']['enquiry']);
print('enquiryData - ${enquiryData}');
updateEnquiryData(enquiryData);
// getQuotationData = List<Map<String, dynamic>>.from(response['data']);
getQuotationData = List<Map<String, dynamic>>.from(
response['data']['quotations'],
);
originalData = getQuotationData;
filteredData = List.from(originalData);
blockKey = getQuotationData.any(
(item) => item['status'] == 'Accepted',
);
print('blockKey- $blockKey');
// print('originalData - $getClaimPolicies');
});
} else {
getQuotationData = [];
originalData = [];
}
} catch (e) {
print('Exception occurred: $e');
} finally {
setState(() {
isLoading = false;
});
}
}
Color _getStatusColor(String? status) {
switch (status) {
case 'Pending':
return Colors.yellow;
case 'Accepted':
return Colors.green;
case 'Rejected':
return Colors.red;
default:
return Colors.grey;
}
}
void handleEdit(id, data) {
print("sfd - $id");
print("sfdewe - $data");
setState(() {
selectedQuotationFrmListId = id;
selectedQuotationFrmListData = data;
// data = data;
});
}
@override
Widget build(BuildContext context) {
final isMobile = ResponsiveLayout.isMobile(context);
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
// child: SingleChildScrollView(
// scrollDirection: Axis.vertical,
child: Column(
children: [
if (!blockKey) ...[
CreateQuotationForm(
key: ValueKey(selectedQuotationFrmListId ?? "new"),
userId: userId,
selectedQuotationFrmListdata: selectedQuotationFrmListData,
selectedQuotationFrmListId: selectedQuotationFrmListId,
managerId: managerId,
selectedInsurdId: selectedInsurdId,
selectedEnquiryId: selectedEnquiryId,
onSubmit: (value) {
debugPrint("New Endorsement: $value");
if (value == 'Success') {
refresh();
}
},
),
SizedBox(height: 20),
],
//(TABLE)
Container(
// color: Colors.green,
decoration: BoxDecoration(
color: Color(0xFFEDF6F5),
borderRadius: BorderRadius.circular(10.0),
),
width: MediaQuery.of(context).size.width,
height: !blockKey
? MediaQuery.of(context).size.height * 0.44
: MediaQuery.of(context).size.height * 0.6,
padding: EdgeInsets.all(12.0),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
// Text('datta')
_buildDataTable(context),
],
),
),
),
],
),
// ),
);
}
Widget registerNumber(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Registration Number', style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
controller: controllers['regNum']!,
readOnly: true,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.2,
),
],
);
}
Widget insurer(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Insurer', style: _textStyle),
SizedBox(height: 10),
ThemedFormField(
controller: controllers['insurer']!,
readOnly: true,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.2,
),
],
);
}
Widget buildResponsiveField({required String label, required Widget field}) {
final isMobile = ResponsiveLayout.isMobile(context);
if (isMobile) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: _textStyle),
const SizedBox(height: 8),
field,
const SizedBox(height: 16),
],
);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: Text(label, style: _textStyle)),
const SizedBox(width: 10),
field,
],
);
}
}
Widget buildId(BuildContext context) {
return buildResponsiveField(
label: "Registration Number *",
field: ThemedFormField(
controller: controllers['regNo']!,
validator: (value) => Validators.requiredField(value, "regNo"),
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
),
);
}
Widget _buildDataTable(BuildContext context) {
if (filteredData.isEmpty) {
return const SizedBox(
height: 50,
child: Center(child: Text('No available data')),
);
}
final sortedData = [...filteredData]
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
return SingleChildScrollView(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: ResponsiveLayout.isMobile(context)
? sortedData
.length // only cards for mobile
: sortedData.length + 1, // +1 for header in desktop
itemBuilder: (context, index) {
if (!ResponsiveLayout.isMobile(context) && index == 0) {
return _buildHeader();
}
final startIndex = (currentPage - 1) * itemsPerPage;
final item =
sortedData[index -
(ResponsiveLayout.isMobile(context) ? 0 : 1)];
final sno = startIndex + index;
// return ResponsiveLayout.isMobile(context)
// ? _buildDataCard(item, sno)
return _buildDataRow(item, sno);
},
),
],
),
);
}
Widget _buildHeader() {
return Container(
decoration: BoxDecoration(
color: Color(0xFFEDF6F5),
borderRadius: BorderRadius.circular(6),
),
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 3),
child: Row(
children: [
// Expanded(flex: 3, child: Text(' ', style: _headerStyle)),
Expanded(
flex: 2,
child: Text('Registration Number', style: _headerStyle),
),
Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)),
Expanded(flex: 2, child: Text('IDV', style: _headerStyle)),
Expanded(flex: 2, child: Text('Plan Type', style: _headerStyle)),
Expanded(flex: 2, child: Text('Premium Amount', style: _headerStyle)),
Expanded(flex: 2, child: Text('Status', style: _headerStyle)),
Expanded(flex: 1, child: Text('', style: _headerStyle)),
],
),
);
}
Widget _buildDataRow(Map<String, dynamic> item, sno) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration(
color: Colors.white,
// color: Color(0xFFE0F7F9),
border: const Border(
bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1),
),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Expanded(
flex: 2,
child: Text(item['reg_no'] ?? '-', style: _dataBold),
),
Expanded(
flex: 3,
child: Text(item['insurer_name'] ?? '-', style: _dataBold),
),
Expanded(
flex: 2,
child: Text(
item['insured_declared_value'] ?? '-',
style: _dataBold,
),
),
Expanded(
flex: 2,
child: Text(item['insurance_plan_type'] ?? '-', style: _dataBold),
),
Expanded(
flex: 2,
child: Text(item['premium_amount'] ?? '-', style: _dataBold),
),
Expanded(
flex: 2,
child: Text(
item['status'] ?? '-',
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.w400,
color: _getStatusColor(item['status']),
),
),
),
Expanded(
flex: 1,
child: item['status'] == 'Pending'
? Tooltip(
message: 'Edit',
child: IconButton(
icon: Image.asset(
"assets/miscellaneous/Edit.png",
height: 15,
width: 15,
),
onPressed: () {
final id = item['id'];
print('RAV - $id');
handleEdit(id, item);
},
splashRadius: 20,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(8),
constraints: const BoxConstraints(),
),
)
: Image.asset(
"assets/miscellaneous/Edit_muted.png",
height: 15,
width: 15,
),
// child: GestureDetector(
// onTap: () {
// final id = item['id'];
// print('RAV - $id');
// handleEdit(id, item);
// },
// child: item['status'] == 'Pending'
// ? Image.asset(
// "assets/miscellaneous/Edit.png",
// height: 15,
// width: 15,
// )
// : Image.asset(
// "assets/miscellaneous/Edit_muted.png",
// height: 15,
// width: 15,
// ),
// ),
),
],
),
);
}
Widget _buildDataCard(Map<String, dynamic> item, int sno) {
return Container(
// margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFFFFFFF),
// color: const Color(0xFFF6FEFD),
borderRadius: BorderRadius.circular(8.0),
border: Border.all(color: const Color(0xffD9EBE8)),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
// "TN64V3456",
item['reg_no'] ?? '-',
style: _cardheaderStyle,
),
item['status'] == 'Pending'
// ? GestureDetector(
// onTap: () {
// final id = item['id'];
// print('RAV - $id');
// handleEdit(id, item);
// },
// child: Image.asset(
// "assets/miscellaneous/Edit.png",
// height: 15,
// width: 15,
// ),
// )
? Tooltip(
message: 'Edit',
child: IconButton(
icon: Image.asset(
"assets/miscellaneous/Edit.png",
height: 15,
width: 15,
),
onPressed: () {
final id = item['id'];
print('RAV - $id');
// handleEdit(id, item);
},
splashRadius: 28,
hoverColor: Colors.black12,
padding: const EdgeInsets.all(8),
constraints: const BoxConstraints(),
),
)
: Image.asset(
"assets/miscellaneous/Edit_muted.png",
height: 15,
width: 15,
),
],
),
Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
// flex: 2,
child: Text(
item['insurer_name'] ?? '-',
style: _cardRow1BodyStyle,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
item['insurance_plan_type'] ?? '-',
style: _cardRow1BodyStyle,
),
Text(
'IDV: ${item['insured_declared_value']}' ?? '-',
style: _cardRow2BodyStyle,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
RichText(
text: TextSpan(
children: [
TextSpan(
text: 'Status : ', // key
style: GoogleFonts.inter(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 11,
), // key color
),
TextSpan(
text: '${item['status'] ?? '-'}', // value
style: GoogleFonts.inter(
color: _getStatusColor(item['status']),
fontWeight: FontWeight.w600,
fontSize: 11,
), // value color
),
],
),
),
Text(
'${item['premium_amount']}' ?? '-',
style: _cardheaderStyle,
),
],
),
],
),
),
],
),
);
}
static final _dataBold = GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Color(0xFF000000),
);
static final _dataSub = GoogleFonts.inter(
fontSize: 10,
fontWeight: FontWeight.w300,
color: Color(0xFF585757),
);
static final _headerStyle = GoogleFonts.inter(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 13,
);
static final _textStyle = GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.w600,
);
static final _cardheaderStyle = GoogleFonts.inter(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 12,
);
static final _cardBodyStyle = GoogleFonts.inter(
color: Color(0xFF545454),
fontWeight: FontWeight.w400,
fontSize: 12,
);
static final _cardRow1BodyStyle = GoogleFonts.inter(
// color: Color(0xFF545454),
color: Colors.black,
fontWeight: FontWeight.w500,
fontSize: 12,
);
static final _cardRow2BodyStyle = GoogleFonts.inter(
color: const Color(0xFF545454),
// color: Colors.black,
fontWeight: FontWeight.w500,
fontSize: 12,
);
}

View File

@ -0,0 +1,214 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/policyTab.dart';
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../../core/routing/routes.dart';
import '../../../../../core/services/api_service.dart';
import '../../../../layouts/main_layout.dart';
import '../../../../providers/manager_provider.dart';
import '../../../../providers/quotation_staff_proivder.dart';
class TabEnquiryStaffList extends ConsumerStatefulWidget {
String? id;
String? showKey;
TabEnquiryStaffList({super.key, this.id, this.showKey});
@override
ConsumerState<TabEnquiryStaffList> createState() =>
TabEnquiryStaffListState();
}
class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
int? expandedIndex;
int selectedIndex = 0;
List<TabItem> tabs = [];
Map<String, dynamic>? enquiryData;
bool isLoading = true;
late ApiService apiService;
ScrollController _scrollController = ScrollController();
dynamic role;
@override
void initState() {
super.initState();
apiService = ApiService();
if (kIsWeb) {
Future.microtask(() => _restoreId(ref));
}
Future.microtask(() {
final id = ref.read(quotationStaffIdProvider);
role = ref.read(userRoleProvider);
print("IntialID - $id");
if (id != null) {
_loadData(id);
} else {
setState(() => isLoading = false);
tabs = [
TabItem("Proposal", QuotationStaffTab()),
// TabItem("Policy", PolicyStaffTab()),
];
}
});
// fetch immediately
}
Future<void> _restoreId(WidgetRef ref) async {
final prefs = await SharedPreferences.getInstance();
final String? savedId = prefs.getString(
'enqAgentDataId',
); // already a string
if (savedId != null) {
ref.read(enquiryIdProvider.notifier).state = savedId;
print("savedenqStaffDataId ID restored: $savedId");
_loadData(savedId);
}
}
Future<void> _loadData(id, {int? tabIndex}) async {
print('loadQuotationTab 2');
setState(() => isLoading = true);
// final response = await apiService.findEnqQuotePolicyView(id);
// print('loadQuotationTab 3 ');
setState(() {
print('loadQuotationTab 4');
// enquiryData = response["data"];
isLoading = false;
tabs = [
TabItem("Proposal", QuotationStaffTab()),
// TabItem("Policy", PolicyStaffTab()),
];
if (widget.showKey == "Policy") {
tabs.add(TabItem("Policy", PolicyStaffTab()));
}
// if (tabIndex != null) {
// selectedIndex = tabIndex;
// expandedIndex = tabIndex;
// }
// Auto-select tab based on showKey
if (widget.showKey == "Policy") {
selectedIndex = 1; // Policy tab index
} else if (tabIndex != null) {
selectedIndex = tabIndex;
} else {
selectedIndex = 0; // Default Quotation tab
}
expandedIndex = selectedIndex;
});
}
/// Public method to load data and select a tab
Future<void> loadQuotationTab(String id) async {
print('loadQuotationTab 1');
await _loadData(id, tabIndex: 2); // now _loadData will set the selected tab
}
@override
Widget build(BuildContext context) {
final bool isMobile = MediaQuery.of(context).size.width < 600;
// final id = ref.watch(enquiryIdProvider);
//
// print("TABUPDID- $id");
//
// print('ENQID: $id');
return AlertDialog(
backgroundColor: Colors.white,
content: Container(
width: MediaQuery.of(context).size.width * 0.55,
height: MediaQuery.of(context).size.height * 0.7,
child: isLoading
? const Center(child: CircularProgressIndicator())
: tabs.isEmpty
? const Center(
child: Text(
"No data available",
style: TextStyle(fontSize: 16, color: Colors.black54),
),
)
: _buildDesktopTabs(),
),
);
}
Widget _buildDesktopTabs() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: List.generate(tabs.length, (index) {
final isSelected = selectedIndex == index;
return Padding(
padding: const EdgeInsets.only(left: 10.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 2,
backgroundColor: isSelected
? const Color(0xFF425B5B)
: const Color(0xFFEDFFFC),
foregroundColor: isSelected
? Colors.white
: Colors.black87,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
onPressed: () {
setState(() => selectedIndex = index);
},
child: Text(tabs[index].title),
),
);
}),
),
GestureDetector(
onTap: () => Navigator.pop(context),
child: Container(
padding: const EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: const Color(0xFFF1F1F1),
borderRadius: BorderRadius.circular(5.0),
),
child: Tooltip(
message: 'Close',
child: const Icon(Icons.close, size: 18),
),
),
),
],
),
SizedBox(height: 10),
Expanded(child: tabs[selectedIndex].widget),
],
);
}
}
class TabItem {
final String title;
final Widget widget;
TabItem(this.title, this.widget);
}

View File

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
import 'package:toastification/toastification.dart';
@ -27,7 +28,6 @@ class AssignStaffDialog extends ConsumerStatefulWidget {
const AssignStaffDialog({
super.key,
required this.onSubmit,
required this.regNum,
required this.userId,
@ -42,7 +42,7 @@ class AssignStaffDialog extends ConsumerStatefulWidget {
class _AddDialogState extends ConsumerState<AssignStaffDialog> {
late ApiService apiService;
String? _token;
dynamic role;
bool isLoading = false;
bool showSuccess = false;
late TextEditingController controller;
@ -96,10 +96,13 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
getInsurers();
Future.microtask(() {
final managerId = ref.watch(managerIdProvider);
final handlerId = ref.watch(handlerIdProvider);
if (handlerId != null) {
final userID = ref.watch(userIdProvider);
// final handlerId = ref.watch(handlerIdProvider);
role = ref.watch(userRoleProvider);
print("managerId - $managerId");
if (userID != null) {
print('hansles');
getStaffDetails(handlerId);
getStaffDetails(userID);
}
});
}
@ -141,17 +144,15 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
}
Future<void> getStaffDetails(int id) async {
print('getStaffDetails called');
print('getStaffDetails called By handler');
setState(() {
isLoading = true;
});
try {
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
id,
);
final response = await apiService.fetchStaffUserList(id, role);
if (response['status'] == 200) {
if (response['status'] == 'success') {
print('getStaffDetails - ${response['data']}');
setState(() {
getStaffDetailsData = List<Map<String, dynamic>>.from(

View File

@ -1222,7 +1222,7 @@ class PolicyScreenState extends ConsumerState<PolicyScreen> {
date.year + 1,
date.month,
date.day,
).subtract(const Duration(days: 1)); // optional: subtract 1 day
); // optional: subtract 1 day
controllers['endDate']?.text = DateFormat(
'dd-MM-yyyy',
@ -1250,64 +1250,97 @@ class PolicyScreenState extends ConsumerState<PolicyScreen> {
txtheight: 50,
// backgroundColor: const Color(0xFFECECEC),
// validator: (value) => Validators.requiredField(value, "date"),
// validator: (value) {
// if (value == null || value.isEmpty) {
// return "Required";
// }
//
// final startDateControllerText = controllers['startDate']?.text;
// if (startDateControllerText == null ||
// startDateControllerText.isEmpty) {
// return "Select start date first";
// }
//
// final startDate = DateFormat(
// 'dd-MM-yyyy',
// ).parse(startDateControllerText);
// final endDate = DateFormat('dd-MM-yyyy').parse(value);
//
// if (endDate.isBefore(startDate)) {
// return "End date cannot be before start date";
// }
//
// // Minimum end date = start date + 1 year - 1 day (or just +1 year)
// final minEndDate = DateTime(
// startDate.year + 1,
// startDate.month,
// startDate.day,
// ).subtract(const Duration(days: 1));
//
// if (endDate.isBefore(minEndDate)) {
// return "End date must be at least 1 year from start date";
// }
//
// return null;
//
// // final startDateControllerText = controllers['startDate']?.text;
// // if (startDateControllerText == null ||
// // startDateControllerText.isEmpty) {
// // return "Select start date first";
// // }
// //
// // final startDate = DateFormat(
// // 'dd-MM-yyyy',
// // ).parse(startDateControllerText);
// // final endDate = DateFormat('dd-MM-yyyy').parse(value);
// //
// // if (endDate.isBefore(startDate)) {
// // return "End date cannot be before start date";
// // }
// //
// // final expectedEndDate = DateTime(
// // startDate.year + 1,
// // startDate.month,
// // startDate.day,
// // ).subtract(const Duration(days: 1));
// //
// // if (endDate != expectedEndDate) {
// // return "End date must be exactly 1 year from start date";
// // }
// //
// // return null; // valid
// },
validator: (value) {
if (value == null || value.isEmpty) {
return "Required";
}
final startDateControllerText = controllers['startDate']?.text;
if (startDateControllerText == null ||
startDateControllerText.isEmpty) {
final startText = controllers['startDate']?.text;
if (startText == null || startText.isEmpty) {
return "Select start date first";
}
final startDate = DateFormat('dd-MM-yyyy').parse(startDateControllerText);
final endDate = DateFormat('dd-MM-yyyy').parse(value);
final startDate = DateFormat('dd-MM-yyyy').parseStrict(startText);
final endDate = DateFormat('dd-MM-yyyy').parseStrict(value);
if (endDate.isBefore(startDate)) {
return "End date cannot be before start date";
}
// Minimum end date = start date + 1 year - 1 day (or just +1 year)
final minEndDate = DateTime(
startDate.year + 1,
startDate.month,
startDate.day,
).subtract(const Duration(days: 1));
// Add 365 days - 1 day to start date
final expectedEndDate = startDate
.add(const Duration(days: 365))
.subtract(const Duration(days: 1));
if (endDate.isBefore(minEndDate)) {
return "End date must be at least 1 year from start date";
if (endDate.day != expectedEndDate.day ||
endDate.month != expectedEndDate.month ||
endDate.year != expectedEndDate.year) {
return "End date must be exactly 1 year minus 1 day from start date";
}
return null;
// final startDateControllerText = controllers['startDate']?.text;
// if (startDateControllerText == null ||
// startDateControllerText.isEmpty) {
// return "Select start date first";
// }
//
// final startDate = DateFormat(
// 'dd-MM-yyyy',
// ).parse(startDateControllerText);
// final endDate = DateFormat('dd-MM-yyyy').parse(value);
//
// if (endDate.isBefore(startDate)) {
// return "End date cannot be before start date";
// }
//
// final expectedEndDate = DateTime(
// startDate.year + 1,
// startDate.month,
// startDate.day,
// ).subtract(const Duration(days: 1));
//
// if (endDate != expectedEndDate) {
// return "End date must be exactly 1 year from start date";
// }
//
// return null; // valid
},
controller: controllers['endDate']!,
onDateSelected: (date) {
print("Picked Date: $date");

View File

@ -244,48 +244,47 @@ class policylistState extends ConsumerState<policylist> {
regNum,
) {
return [
if (roleId == 'manager') ...[
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.pop(context);
showDialog(
context: context,
builder: (ctx) => AssignStaffDialog(
enquiryPrimaryId: id,
regNum: regNum,
userId: userId,
onSubmit: (value) {
debugPrint("New assignY: $value");
refresh();
},
),
);
},
hoverColor: Color(0xFFE3F1F0),
splashColor: Color(0xFFE3F1F0),
borderRadius: BorderRadius.circular(6),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
child: Row(
// mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"assets/miscellaneous/image_3.png",
// height: 45,
// width: 15,
),
SizedBox(width: 10),
Text('Assign Staff'),
],
),
),
),
),
],
// if (roleId == 'manager') ...[
// Material(
// color: Colors.transparent,
// child: InkWell(
// onTap: () {
// Navigator.pop(context);
// showDialog(
// context: context,
// builder: (ctx) => AssignStaffDialog(
// enquiryPrimaryId: id,
// regNum: regNum,
// userId: userId,
// onSubmit: (value) {
// debugPrint("New assignY: $value");
// refresh();
// },
// ),
// );
// },
// hoverColor: Color(0xFFE3F1F0),
// splashColor: Color(0xFFE3F1F0),
// borderRadius: BorderRadius.circular(6),
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
// child: Row(
// // mainAxisSize: MainAxisSize.min,
// children: [
// Image.asset(
// "assets/miscellaneous/image_3.png",
// // height: 45,
// // width: 15,
// ),
//
// SizedBox(width: 10),
// Text('Assign Staff'),
// ],
// ),
// ),
// ),
// ),
// ],
Material(
color: Colors.transparent,
child: InkWell(
@ -369,7 +368,7 @@ class policylistState extends ConsumerState<policylist> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 40,
height: 30,
width: MediaQuery.of(context).size.width,
child: GestureDetector(
onTap: () {
@ -409,7 +408,7 @@ class policylistState extends ConsumerState<policylist> {
),
),
SizedBox(height: 10),
SizedBox(height: 5),
ResponsiveLayout.isMobile(context)
? Container(
@ -617,7 +616,7 @@ class policylistState extends ConsumerState<policylist> {
],
),
),
SizedBox(height: 10),
SizedBox(height: 5),
if (!ResponsiveLayout.isMobile(context))
Container(
decoration: BoxDecoration(
@ -627,14 +626,22 @@ class policylistState extends ConsumerState<policylist> {
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: Row(
children: [
Expanded(flex: 4, child: Text('Date', style: _headerStyle)),
Expanded(flex: 3, child: Text('Reg.No', style: _headerStyle)),
Expanded(
flex: 4,
child: Text('Recieved Date/Time', style: _headerStyle),
),
Expanded(flex: 3, child: Text('Partner', style: _headerStyle)),
Expanded(
flex: 3,
child: Text('Assigned To', style: _headerStyle),
),
Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)),
Expanded(flex: 4, child: Text('Insurer', style: _headerStyle)),
Expanded(
flex: 3,
child: Text('Vehicle.No.', style: _headerStyle),
),
Expanded(
flex: 3,
child: Text('Insured Name', style: _headerStyle),
@ -758,10 +765,7 @@ class policylistState extends ConsumerState<policylist> {
maxLines: 3,
),
),
Expanded(
flex: 3,
child: Text(item['reg_no'] ?? '-', style: _dataBold),
),
Expanded(
flex: 3,
child: Text(
@ -774,7 +778,7 @@ class policylistState extends ConsumerState<policylist> {
child: Text(item['assigned_to_name'] ?? '-', style: _dataBold),
),
Expanded(
flex: 3,
flex: 4,
child: Text(
item['insurer_name'] ?? '-',
style: _dataBold,
@ -782,6 +786,10 @@ class policylistState extends ConsumerState<policylist> {
maxLines: 3,
),
),
Expanded(
flex: 3,
child: Text(item['reg_no'] ?? '-', style: _dataBold),
),
Expanded(
flex: 3,
child: Text(
@ -873,7 +881,7 @@ class policylistState extends ConsumerState<policylist> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Company", style: _cardheaderStyle),
Text("Insurer", style: _cardheaderStyle),
Text(item['insurer_name'] ?? '-', style: _cardBodyStyle),
],
),
@ -980,7 +988,7 @@ class policylistState extends ConsumerState<policylist> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Date", style: _cardheaderStyle),
Text("Recieved Date/Time", style: _cardheaderStyle),
Text(
_formatDate(item['updated_on']) ?? '-',
style: _cardBodyStyle,

View File

@ -78,7 +78,8 @@ class createQuotatDialogState extends State<createQuotatDialog> {
final data = {
"enquiry_id": widget.selectedEnquiryId,
"insured_declared_value": controllers["idv"]?.text,
"insurer_id": selectedInsurer,
"insurer_id": '1',
// "insurer_id": selectedInsurer,
"premium_amount": controllers["premium_Amount"]?.text,
"insurance_plan_type_id": selectedInsPlanType,
// "additional_uploaded_file_name": "extra_doc.pdf",
@ -135,6 +136,10 @@ class createQuotatDialogState extends State<createQuotatDialog> {
.selectedQuotationFrmListdata!['insurance_plan_type_id']
?.toString();
selectedInsurer = '1';
// controllers["insurer"]?.text = 'LIC';
// selectedInsurer =
// widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? '';
@ -426,7 +431,7 @@ class createQuotatDialogState extends State<createQuotatDialog> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildIdv(context),
buildInsurer(context),
// buildInsurer(context),
buildInsurancePlanType(context),
buildPremiumAmnt(context),
buildDocuments(context),
@ -464,7 +469,7 @@ class createQuotatDialogState extends State<createQuotatDialog> {
);
}
Widget buildInsurer(BuildContext context) {
Widget buildInsurer1(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -474,7 +479,7 @@ class createQuotatDialogState extends State<createQuotatDialog> {
controller: controllers['insurer']!,
validator: (value) => Validators.requiredField(value, "insurer"),
backgroundColor: Color(0xFFEDF6F5),
readOnly: true,
// readOnly: true,
txtwidth: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
@ -483,96 +488,96 @@ class createQuotatDialogState extends State<createQuotatDialog> {
);
}
// Widget buildInsurer(BuildContext context) {
// Map<String, dynamic>? selectedInsurerd = filteredInsurersData.firstWhere(
// (item) => item['id'].toString() == selectedInsurer,
// orElse: () => {},
// );
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text('Insurer *', style: _textStyle),
// SizedBox(height: 10),
// Container(
// decoration: BoxDecoration(
// color: Colors.white,
// // borderRadius: BorderRadius.circular(10.0),
// ),
// width: ResponsiveLayout.isMobile(context)
// ? null
// : MediaQuery.of(context).size.width * 0.26,
// // height: 40,
// child: DropdownSearch<Map<String, dynamic>>(
// key: dropDownKeyInsurer,
// selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null,
// items: (filter, infiniteScrollProps) {
// return filteredInsurersData;
// },
//
// 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;
// },
// decoratorProps: DropDownDecoratorProps(
// decoration:
// AppInputDecorations.dropdownDecoration(
// label: "Select Insurer",
// ).copyWith(
// filled: true,
// fillColor: Color(
// 0xFFEDF6F5,
// ), // 👈 makes the dropdown input white
// ),
// ),
//
// 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 Insurer...",
// enabledBorder: OutlineInputBorder(
// borderSide: BorderSide(
// color: Colors.white,
// ), // 👈 Normal border
// ),
// focusedBorder: OutlineInputBorder(
// borderSide: BorderSide(
// color: Colors.white,
// width: 1.5,
// ), // 👈 Focused border
// ),
// ),
// ),
// // constraints: BoxConstraints(),
// ),
//
// onChanged: (val) {
// if (val != null) {
// print("Selected Insurer : ${val['name']}");
// print("Id: ${val['id']}");
// selectedInsurer = val['id'];
// // controllers['agentId']?.text = val['agent_code'];
// // agentId = agent['id'];
// }
// },
// ),
// ),
// ],
// );
// }
Widget buildInsurer2(BuildContext context) {
Map<String, dynamic>? selectedInsurerd = filteredInsurersData.firstWhere(
(item) => item['id'].toString() == selectedInsurer,
orElse: () => {},
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Insurer *', style: _textStyle),
SizedBox(height: 10),
Container(
decoration: BoxDecoration(
color: Colors.white,
// borderRadius: BorderRadius.circular(10.0),
),
width: ResponsiveLayout.isMobile(context)
? null
: MediaQuery.of(context).size.width * 0.26,
// height: 40,
child: DropdownSearch<Map<String, dynamic>>(
key: dropDownKeyInsurer,
selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null,
items: (filter, infiniteScrollProps) {
return filteredInsurersData;
},
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;
},
decoratorProps: DropDownDecoratorProps(
decoration:
AppInputDecorations.dropdownDecoration(
label: "Select Insurer",
).copyWith(
filled: true,
fillColor: Color(
0xFFEDF6F5,
), // 👈 makes the dropdown input white
),
),
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 Insurer...",
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
), // 👈 Normal border
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.white,
width: 1.5,
), // 👈 Focused border
),
),
),
// constraints: BoxConstraints(),
),
onChanged: (val) {
if (val != null) {
print("Selected Insurer : ${val['name']}");
print("Id: ${val['id']}");
selectedInsurer = val['id'];
// controllers['agentId']?.text = val['agent_code'];
// agentId = agent['id'];
}
},
),
),
],
);
}
Widget buildPremiumAmnt(BuildContext context) {
return Column(

View File

@ -67,6 +67,7 @@ class ThemedFormField extends HookWidget {
),
);
final inputDecoration = InputDecoration(
// isDense: true,
errorStyle: TextStyle(color: const Color(0xFFD83731)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),