pay out module
This commit is contained in:
commit
12daf54cb7
File diff suppressed because one or more lines are too long
@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:nhance_partner/core/routing/routes.dart';
|
import 'package:nhance_partner/core/routing/routes.dart';
|
||||||
import 'package:nhance_partner/presentation/screens/Enquiry/enquiryList.dart';
|
import 'package:nhance_partner/presentation/screens/Enquiry/enquiryList.dart';
|
||||||
|
import 'package:nhance_partner/presentation/screens/Masters/PaymentMode/paymentList.dart';
|
||||||
import 'package:nhance_partner/presentation/screens/UserManagement/Profile/profile_web.dart';
|
import 'package:nhance_partner/presentation/screens/UserManagement/Profile/profile_web.dart';
|
||||||
import 'package:nhance_partner/presentation/screens/dashboard/dashboard.dart';
|
import 'package:nhance_partner/presentation/screens/dashboard/dashboard.dart';
|
||||||
import 'package:nhance_partner/presentation/screens/payout/invoice_list.dart';
|
import 'package:nhance_partner/presentation/screens/payout/invoice_list.dart';
|
||||||
@ -12,6 +13,7 @@ import '../../presentation/providers/manager_provider.dart';
|
|||||||
import '../../presentation/screens/Enquiry/enquiry/tabs.dart';
|
import '../../presentation/screens/Enquiry/enquiry/tabs.dart';
|
||||||
import '../../presentation/screens/Enquiry/policy_claims_endros/claims.dart';
|
import '../../presentation/screens/Enquiry/policy_claims_endros/claims.dart';
|
||||||
import '../../presentation/screens/Enquiry/policy_claims_endros/endrosment.dart';
|
import '../../presentation/screens/Enquiry/policy_claims_endros/endrosment.dart';
|
||||||
|
import '../../presentation/screens/Masters/Brokers/brokerList.dart';
|
||||||
import '../../presentation/screens/StaffAttendance/attendanceAllDetails.dart';
|
import '../../presentation/screens/StaffAttendance/attendanceAllDetails.dart';
|
||||||
import '../../presentation/screens/StaffAttendance/individual_Attendance.dart';
|
import '../../presentation/screens/StaffAttendance/individual_Attendance.dart';
|
||||||
import '../../presentation/screens/UserManagement/Agent/agent.dart';
|
import '../../presentation/screens/UserManagement/Agent/agent.dart';
|
||||||
@ -192,6 +194,16 @@ final GoRouter appRouter = GoRouter(
|
|||||||
path: AppRoutes.individualAttendance,
|
path: AppRoutes.individualAttendance,
|
||||||
builder: (context, state) => const IndividualAttendanceDetails(),
|
builder: (context, state) => const IndividualAttendanceDetails(),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.brokerLst,
|
||||||
|
builder: (context, state) => const BrokerList(),
|
||||||
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.paymentModeLst,
|
||||||
|
builder: (context, state) => const PaymentLsit(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
redirect: (context, state) async {
|
redirect: (context, state) async {
|
||||||
final loggedIn = await AuthService.isLoggedIn();
|
final loggedIn = await AuthService.isLoggedIn();
|
||||||
|
|||||||
@ -24,4 +24,6 @@ class AppRoutes {
|
|||||||
|
|
||||||
static const String payout = '/payout';
|
static const String payout = '/payout';
|
||||||
static const String invoiceList = '/invoiceList';
|
static const String invoiceList = '/invoiceList';
|
||||||
|
static const String brokerLst = '/brokerLst';
|
||||||
|
static const String paymentModeLst = '/paymentMode';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -342,14 +342,8 @@ class ApiService {
|
|||||||
final url;
|
final url;
|
||||||
|
|
||||||
if (role == 'staff') {
|
if (role == 'staff') {
|
||||||
// url = Uri.parse(
|
|
||||||
// 'https://venbait.in/nhance/partner/dev/api/staff/changeStaffStatus',
|
|
||||||
// );
|
|
||||||
url = Uri.parse('${Env.apiUrl}staff/changeStaffStatus');
|
url = Uri.parse('${Env.apiUrl}staff/changeStaffStatus');
|
||||||
} else {
|
} else {
|
||||||
// url = Uri.parse(
|
|
||||||
// 'https://venbait.in/nhance/partner/dev/api/agent/changeAgentStatus',
|
|
||||||
// );
|
|
||||||
url = Uri.parse('${Env.apiUrl}/api/agent/changeAgentStatus');
|
url = Uri.parse('${Env.apiUrl}/api/agent/changeAgentStatus');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,6 +366,44 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> updateStatusMasters(
|
||||||
|
id,
|
||||||
|
status,
|
||||||
|
masterName,
|
||||||
|
userId,
|
||||||
|
) async {
|
||||||
|
print('updateStatusMaster $id $status $masterName $userId');
|
||||||
|
final Map<String, dynamic> data = {
|
||||||
|
"is_active": int.parse(status),
|
||||||
|
"updated_by": userId,
|
||||||
|
};
|
||||||
|
final url;
|
||||||
|
|
||||||
|
if (masterName == 'Broker') {
|
||||||
|
url = Uri.parse('${Env.apiUrl}master/updateBrokerStatus/$id');
|
||||||
|
} else {
|
||||||
|
url = Uri.parse('${Env.apiUrl}master/updatePaymentModeStatus/$id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
print("data------- $data}");
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
// 'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await _makePostRequestJson(url, data, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Dashboard -------------------------------------------------
|
// ----------------------------------- Dashboard -------------------------------------------------
|
||||||
Future<Map<String, dynamic>> fetchDashboard(int id, role, userId) async {
|
Future<Map<String, dynamic>> fetchDashboard(int id, role, userId) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
@ -1005,6 +1037,8 @@ class ApiService {
|
|||||||
url = Uri.parse('${Env.apiUrl}master/getEndorsementMaster');
|
url = Uri.parse('${Env.apiUrl}master/getEndorsementMaster');
|
||||||
} else if (val == 'Broker') {
|
} else if (val == 'Broker') {
|
||||||
url = Uri.parse('${Env.apiUrl}master/getAllBrokers');
|
url = Uri.parse('${Env.apiUrl}master/getAllBrokers');
|
||||||
|
} else if (val == 'PaymentMode') {
|
||||||
|
url = Uri.parse('${Env.apiUrl}master/getAllPaymentModelist');
|
||||||
}
|
}
|
||||||
|
|
||||||
final headers = {
|
final headers = {
|
||||||
|
|||||||
@ -146,6 +146,26 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
if (key == 'Masters') ...[
|
||||||
|
if (role == 'manager') ...[
|
||||||
|
_buildPopupItem(
|
||||||
|
label: "Broker",
|
||||||
|
onTap: () {
|
||||||
|
_hidePopup();
|
||||||
|
context.go(AppRoutes.brokerLst);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
SizedBox(height: 2),
|
||||||
|
_buildPopupItem(
|
||||||
|
label: "Payment Mode",
|
||||||
|
onTap: () {
|
||||||
|
_hidePopup();
|
||||||
|
context.go(AppRoutes.paymentModeLst);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -227,6 +247,16 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// User (Manager Only) - with hover popup
|
||||||
|
if (roleId == 'manager') ...[
|
||||||
|
_buildHoverMenuItem(
|
||||||
|
icon: Icons.settings_suggest_outlined,
|
||||||
|
label: "Masters",
|
||||||
|
popupKey: 'Masters',
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
|
||||||
// Reports (Not Staff) - with hover popup
|
// Reports (Not Staff) - with hover popup
|
||||||
if (roleId != 'staff') ...[
|
if (roleId != 'staff') ...[
|
||||||
_buildHoverMenuItem(
|
_buildHoverMenuItem(
|
||||||
|
|||||||
310
lib/presentation/screens/Masters/Brokers/broker.dart
Normal file
310
lib/presentation/screens/Masters/Brokers/broker.dart
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
// import 'dart:io' as html;
|
||||||
|
import 'dart:typed_data'; // Import for Uint8List
|
||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.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/core/routing/routes.dart';
|
||||||
|
import 'package:nhance_partner/data/utils/toastNotification.dart';
|
||||||
|
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart';
|
||||||
|
|
||||||
|
import '../../../../core/config/env.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 'package:universal_html/html.dart' as html;
|
||||||
|
|
||||||
|
import '../../../themes/indicators/input_field_decoration.dart';
|
||||||
|
|
||||||
|
class Broker extends ConsumerStatefulWidget {
|
||||||
|
final String? id;
|
||||||
|
final Map<String, dynamic>? data;
|
||||||
|
final VoidCallback onSubmit;
|
||||||
|
const Broker({super.key, this.id, this.data, required this.onSubmit});
|
||||||
|
@override
|
||||||
|
ConsumerState<Broker> createState() => BrokerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrokerState extends ConsumerState<Broker> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
late ApiService apiService;
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||||
|
dropDownKeyHandler = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
List<String> tabHeader = ['name', 'email', 'mobile', 'code'];
|
||||||
|
late String isActive = "1";
|
||||||
|
html.File? passportFile;
|
||||||
|
String? selectedFileNames;
|
||||||
|
String? passportFileUrlFromApi;
|
||||||
|
dynamic selectedId;
|
||||||
|
String? _token;
|
||||||
|
bool isLoading = false;
|
||||||
|
bool showHandler = false;
|
||||||
|
|
||||||
|
String? selectedRole;
|
||||||
|
List<Map<String, dynamic>> filteredRolesData = [];
|
||||||
|
List<Map<String, dynamic>> getRolesData = [];
|
||||||
|
|
||||||
|
List<dynamic>? selectedHandlerIds = [];
|
||||||
|
String? selectedHandler;
|
||||||
|
List<Map<String, dynamic>> filteredHandlersData = [];
|
||||||
|
List<Map<String, dynamic>> getHandlersData = [];
|
||||||
|
|
||||||
|
Map<String, TextEditingController> controllers = {};
|
||||||
|
|
||||||
|
dynamic userId;
|
||||||
|
dynamic managerId;
|
||||||
|
|
||||||
|
Map<String, dynamic> dataDetails() {
|
||||||
|
final data = {"name": controllers["name"]?.text, "is_active": isActive};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
|
for (String field in tabHeader) {
|
||||||
|
controllers[field] = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
_initializeToken();
|
||||||
|
updateData();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
managerId = ref.watch(managerIdProvider);
|
||||||
|
userId = ref.watch(userIdProvider);
|
||||||
|
if (managerId != null) {
|
||||||
|
print('hansles');
|
||||||
|
// getHandlers(managerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initializeToken() async {
|
||||||
|
_token = await AuthService.getToken();
|
||||||
|
print("APISERTOKEN - $_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateData() async {
|
||||||
|
if (widget.data != null) {
|
||||||
|
dynamic id = widget.data?['id'];
|
||||||
|
final data = widget.data;
|
||||||
|
|
||||||
|
if (data == null) return;
|
||||||
|
setState(() {
|
||||||
|
selectedId = id;
|
||||||
|
controllers['name']?.text = data['name'] ?? '';
|
||||||
|
controllers["is_active"]?.text = data['is_active'].toString();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleSave() async {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
setState(() {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
dataDetails();
|
||||||
|
final dataSet = dataDetails();
|
||||||
|
print("dataSetAgent - $dataSet");
|
||||||
|
|
||||||
|
print("TYPE of is_active → ${dataSet['is_active'].runtimeType}");
|
||||||
|
print("TYPE of name → ${dataSet['name'].runtimeType}");
|
||||||
|
createUserData(dataSet);
|
||||||
|
} else {
|
||||||
|
// isDisable = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
print('REfresj');
|
||||||
|
widget.onSubmit();
|
||||||
|
setState(() {
|
||||||
|
// clear all text controllers
|
||||||
|
for (var controller in controllers.values) {
|
||||||
|
controller.clear();
|
||||||
|
} // 👈 clear selected agent
|
||||||
|
controllers['name']?.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createUserData(data) async {
|
||||||
|
final bool isUpdating = selectedId != null;
|
||||||
|
final dynamic id = isUpdating ? int.tryParse(selectedId.toString()) : 0;
|
||||||
|
final String apiUrldata;
|
||||||
|
|
||||||
|
print("TYPE of id → $id - ${id.runtimeType}");
|
||||||
|
print("TYPE of id → $userId - ${userId.runtimeType}");
|
||||||
|
|
||||||
|
apiUrldata = isUpdating
|
||||||
|
? '${Env.apiUrl}/master/updateBroker/$selectedId'
|
||||||
|
: '${Env.apiUrl}/master/createBroker';
|
||||||
|
|
||||||
|
// final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUpdating) {
|
||||||
|
data['updated_by'] = userId.toString();
|
||||||
|
} else {
|
||||||
|
data['created_by'] = userId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
print("data------- $data}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $_token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
},
|
||||||
|
body: jsonEncode(data), // Convert map to JSON
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
print("Broker submitted successfully!");
|
||||||
|
print("Response: ${response.body}");
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
isUpdating
|
||||||
|
? ToastHelper.showSuccessToast(
|
||||||
|
context,
|
||||||
|
'Broker Updated Successfully',
|
||||||
|
)
|
||||||
|
: ToastHelper.showSuccessToast(
|
||||||
|
context,
|
||||||
|
'Broker Created Successfully',
|
||||||
|
);
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
|
} else {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
dynamic msg = responseBody['data'];
|
||||||
|
|
||||||
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
|
print("Error: ${response.body}");
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("Broker Creation Failed"),
|
||||||
|
content: Text(msg),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text("OK"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(" Error submitting Staff: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
for (var controller in controllers.values) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
buildFormFields(),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
handleSave();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6),
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
color: Color(0xFF2E7D6E),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Save',
|
||||||
|
style: GoogleFonts.inter(color: Colors.white, fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(6.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF2E7D6E),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Icon(Icons.refresh, size: 13, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildFormFields() {
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(children: [buildName()]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildName() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Broker *", style: _textStyle),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
ThemedFormField(
|
||||||
|
controller: controllers['name']!,
|
||||||
|
validator: (value) => Validators.requiredField(value, "name"),
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
|
txtheight: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final _textStyle = GoogleFonts.inter(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
475
lib/presentation/screens/Masters/Brokers/brokerList.dart
Normal file
475
lib/presentation/screens/Masters/Brokers/brokerList.dart
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
import 'package:flutter/cupertino.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/Masters/Brokers/broker.dart';
|
||||||
|
|
||||||
|
import '../../../../core/routing/routes.dart';
|
||||||
|
import '../../../../core/services/api_service.dart';
|
||||||
|
import '../../../../data/utils/Pagination.dart';
|
||||||
|
import '../../../layouts/main_layout.dart';
|
||||||
|
import '../../../layouts/responsive_layout.dart';
|
||||||
|
import '../../../providers/manager_provider.dart';
|
||||||
|
import '../../../themes/indicators/export_btn.dart';
|
||||||
|
import '../../../themes/indicators/filter_btn.dart';
|
||||||
|
import '../../../themes/indicators/search_field_theme.dart';
|
||||||
|
import '../../../themes/indicators/text_field_theme.dart';
|
||||||
|
import '../../../widgets/custom_action_popup.dart';
|
||||||
|
|
||||||
|
class BrokerList extends ConsumerStatefulWidget {
|
||||||
|
const BrokerList({super.key});
|
||||||
|
@override
|
||||||
|
ConsumerState<BrokerList> createState() => BrokerListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrokerListState extends ConsumerState<BrokerList> {
|
||||||
|
int currentPage = 1;
|
||||||
|
int itemsPerPage = 10;
|
||||||
|
late ApiService apiService;
|
||||||
|
dynamic managerId;
|
||||||
|
dynamic role;
|
||||||
|
dynamic prefid;
|
||||||
|
dynamic userId;
|
||||||
|
// List<Map<String, dynamic>> dataVal = [];
|
||||||
|
List<Map<String, dynamic>> getBrokerData = [];
|
||||||
|
List<Map<String, dynamic>> originalData = [];
|
||||||
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
Map<String, dynamic>? selectedBroker;
|
||||||
|
dynamic selectedId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
apiService = ApiService();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
final data1 = ref.read(managerIdProvider);
|
||||||
|
userId = ref.watch(userIdProvider);
|
||||||
|
// 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) {
|
||||||
|
getBroker();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// getBrokerList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> get _paginatedData {
|
||||||
|
// Sort descending by id first
|
||||||
|
final sortedData = [...filteredData]
|
||||||
|
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
||||||
|
|
||||||
|
if (sortedData.isEmpty) return [];
|
||||||
|
|
||||||
|
// Ensure currentPage is valid
|
||||||
|
final maxPage = (sortedData.length / itemsPerPage).ceil();
|
||||||
|
final safePage = currentPage.clamp(1, maxPage);
|
||||||
|
|
||||||
|
final startIndex = (safePage - 1) * itemsPerPage;
|
||||||
|
final endIndex = (startIndex + itemsPerPage).clamp(0, sortedData.length);
|
||||||
|
|
||||||
|
return sortedData.sublist(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEdit(Map<String, dynamic> item) {
|
||||||
|
setState(() {
|
||||||
|
selectedId = item['id'];
|
||||||
|
selectedBroker = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void filterData(String query) {
|
||||||
|
setState(() {
|
||||||
|
final q = query.toLowerCase();
|
||||||
|
|
||||||
|
if (q.isEmpty) {
|
||||||
|
filteredData = getBrokerData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredData = getBrokerData.where((item) {
|
||||||
|
final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
|
||||||
|
return (item['name'] ?? '').toString().toLowerCase().contains(q) ||
|
||||||
|
(item['email'] ?? '').toString().toLowerCase().contains(q) ||
|
||||||
|
(item['mobile'] ?? '').toString().toLowerCase().contains(q) ||
|
||||||
|
(item['address'] ?? '').toString().toLowerCase().contains(q) ||
|
||||||
|
(item['emp_id'] ?? item['agent_code'] ?? '')
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(q) ||
|
||||||
|
isActiveStatus.contains(q);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final TextEditingController _searchStaffController = TextEditingController();
|
||||||
|
|
||||||
|
Future<void> getBroker() async {
|
||||||
|
print('getBroker called');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchMasterDropDown('Broker');
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('getBroker - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getBrokerData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getBrokerData');
|
||||||
|
|
||||||
|
filteredData = List.from(getBrokerData);
|
||||||
|
print('originalData - $filteredData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getBrokerData = [];
|
||||||
|
filteredData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||||
|
return [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
print('EDITStaff - ${data['id']}');
|
||||||
|
dynamic id = data['id'];
|
||||||
|
context.go('/staff/$id');
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
Text('Edit'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
managerId = ref.watch(managerIdProvider);
|
||||||
|
|
||||||
|
return MainLayout(
|
||||||
|
title: "Broker",
|
||||||
|
body: Container(
|
||||||
|
// padding: EdgeInsets.all(8.0),
|
||||||
|
// margin: EdgeInsets.all(10.0),
|
||||||
|
|
||||||
|
// color: Colors.yellow.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// height: 30,
|
||||||
|
// color: Colors.red.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.go(AppRoutes.dashboard);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [Text('Broker List', style: _headerStyle)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
// color: Colors.green,
|
||||||
|
// color: Colors.green.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
// margin: EdgeInsets.all(10.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
|
||||||
|
padding: EdgeInsets.all(15.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// height: 40,
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Broker(
|
||||||
|
key: ValueKey(selectedId),
|
||||||
|
data: selectedBroker,
|
||||||
|
id: selectedId,
|
||||||
|
onSubmit: () {
|
||||||
|
getBroker();
|
||||||
|
setState(() {
|
||||||
|
selectedBroker = null;
|
||||||
|
selectedId = null;
|
||||||
|
}); // reset after save
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
ThemedSearchField(
|
||||||
|
hintText: 'Search',
|
||||||
|
// backgroundColor: Color(0xFFF6F8F8),
|
||||||
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
|
txtHeight: 30,
|
||||||
|
onChanged: filterData,
|
||||||
|
controller: _searchStaffController,
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.2,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
|
ExportBtn(
|
||||||
|
sheetName: "Broker",
|
||||||
|
fileName: "broker_list",
|
||||||
|
txt: !ResponsiveLayout.isMobile(context)
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
|
data: filteredData,
|
||||||
|
displayHeaders: ['S.No.', 'Broker', 'Status'],
|
||||||
|
keys: ["sno", "name", "is_active"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(0xFFF1F5F9),
|
||||||
|
|
||||||
|
// color: Color(0xFFEDF6F5),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('S.No.', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Broker', style: _headerStyle),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('Status', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('Action', style: _headerStyle),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(child: _buildDataTable(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
// height: 20,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
// color: Colors.green.shade50,
|
||||||
|
child: PaginationControls(
|
||||||
|
currentPage: currentPage,
|
||||||
|
itemsPerPage: itemsPerPage,
|
||||||
|
// totalItems: dataVal.length,
|
||||||
|
totalItems: filteredData.length,
|
||||||
|
// activeColor: layoutColor, // your theme color
|
||||||
|
onPageChanged: (page) {
|
||||||
|
setState(() {
|
||||||
|
currentPage = page;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onItemsPerPageChanged: (items) {
|
||||||
|
setState(() {
|
||||||
|
itemsPerPage = items;
|
||||||
|
currentPage = 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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: filteredData.length + 1, // +1 for header, +1 for pagination
|
||||||
|
itemCount: sortedData.length + 1, // +1 for header, +1 for pagination
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == 0) return _buildHeader();
|
||||||
|
// if (index == dataVal.length + 1)
|
||||||
|
// return _buildPagination(context);
|
||||||
|
final startIndex = ((currentPage - 1) * itemsPerPage);
|
||||||
|
// final item = filteredData[index - 1];
|
||||||
|
final item = sortedData[index - 1];
|
||||||
|
final sno = startIndex + index;
|
||||||
|
return _buildDataRow(item, sno);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader() {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16),
|
||||||
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
// color: Color(0xFFE0F7F9),
|
||||||
|
border: const Border(
|
||||||
|
bottom: BorderSide(color: Colors.blueGrey, width: 0.15),
|
||||||
|
),
|
||||||
|
// borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)),
|
||||||
|
Expanded(flex: 2, child: Text(item['name'] ?? '-', style: _dataBold)),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// color: Colors.yellow.shade50,
|
||||||
|
child: Transform.scale(
|
||||||
|
scale: 0.4, // reduce size (0.7–0.9 works well)
|
||||||
|
child: Switch(
|
||||||
|
value: item['is_active'] == "1",
|
||||||
|
onChanged: (val) {
|
||||||
|
setState(() {
|
||||||
|
item['is_active'] = val ? "1" : "0";
|
||||||
|
});
|
||||||
|
final response = apiService.updateStatusMasters(
|
||||||
|
item['id'],
|
||||||
|
val ? "0" : "1",
|
||||||
|
'Broker',
|
||||||
|
userId,
|
||||||
|
);
|
||||||
|
print("Response - $response");
|
||||||
|
},
|
||||||
|
activeColor: Color(0xFF2E7D6E), // thumb when active
|
||||||
|
// activeColor: Color(0xFF425B5B), // thumb when active
|
||||||
|
activeTrackColor: Color(0xFFDCFCE7), // track when active
|
||||||
|
// activeTrackColor: Color(0xFFB2D8D3), // track when active
|
||||||
|
inactiveThumbColor:
|
||||||
|
Colors.grey.shade400, // thumb when inactive
|
||||||
|
inactiveTrackColor:
|
||||||
|
Colors.grey.shade300, // track when inactive
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: item['is_active'] == "1"
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Tooltip(
|
||||||
|
message: 'Edit',
|
||||||
|
child: IconButton(
|
||||||
|
icon: Image.asset(
|
||||||
|
"assets/miscellaneous/Edit.png",
|
||||||
|
height: 12,
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
print('EDITBrokwer - ${item['id']}');
|
||||||
|
print('EDITBrokwer - ${item}');
|
||||||
|
dynamic id = item['id'];
|
||||||
|
|
||||||
|
handleEdit(item);
|
||||||
|
|
||||||
|
print(item);
|
||||||
|
},
|
||||||
|
splashRadius: 28,
|
||||||
|
hoverColor: Colors.black12,
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
"assets/miscellaneous/Edit_muted.png",
|
||||||
|
height: 15,
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final _dataBold = GoogleFonts.inter(
|
||||||
|
fontSize: 11.5,
|
||||||
|
|
||||||
|
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: Color(0XFF1e293b),
|
||||||
|
fontSize: 12,
|
||||||
|
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
318
lib/presentation/screens/Masters/PaymentMode/payment.dart
Normal file
318
lib/presentation/screens/Masters/PaymentMode/payment.dart
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
// import 'dart:io' as html;
|
||||||
|
import 'dart:typed_data'; // Import for Uint8List
|
||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.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/core/routing/routes.dart';
|
||||||
|
import 'package:nhance_partner/data/utils/toastNotification.dart';
|
||||||
|
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart';
|
||||||
|
|
||||||
|
import '../../../../core/config/env.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 'package:universal_html/html.dart' as html;
|
||||||
|
|
||||||
|
import '../../../themes/indicators/input_field_decoration.dart';
|
||||||
|
|
||||||
|
class Payment extends ConsumerStatefulWidget {
|
||||||
|
final String? id;
|
||||||
|
final Map<String, dynamic>? data;
|
||||||
|
final VoidCallback onSubmit;
|
||||||
|
const Payment({super.key, this.id, this.data, required this.onSubmit});
|
||||||
|
@override
|
||||||
|
ConsumerState<Payment> createState() => PaymentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaymentState extends ConsumerState<Payment> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
late ApiService apiService;
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||||
|
dropDownKeyHandler = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
List<String> tabHeader = ['value', 'email', 'mobile', 'code'];
|
||||||
|
late String isActive = "1";
|
||||||
|
html.File? passportFile;
|
||||||
|
String? selectedFileNames;
|
||||||
|
String? passportFileUrlFromApi;
|
||||||
|
dynamic selectedId;
|
||||||
|
String? _token;
|
||||||
|
bool isLoading = false;
|
||||||
|
bool showHandler = false;
|
||||||
|
|
||||||
|
String? selectedRole;
|
||||||
|
List<Map<String, dynamic>> filteredRolesData = [];
|
||||||
|
List<Map<String, dynamic>> getRolesData = [];
|
||||||
|
|
||||||
|
List<dynamic>? selectedHandlerIds = [];
|
||||||
|
String? selectedHandler;
|
||||||
|
List<Map<String, dynamic>> filteredHandlersData = [];
|
||||||
|
List<Map<String, dynamic>> getHandlersData = [];
|
||||||
|
|
||||||
|
Map<String, TextEditingController> controllers = {};
|
||||||
|
|
||||||
|
dynamic userId;
|
||||||
|
dynamic managerId;
|
||||||
|
|
||||||
|
Map<String, dynamic> dataDetails() {
|
||||||
|
final data = {"value": controllers["value"]?.text, "is_active": isActive};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
|
for (String field in tabHeader) {
|
||||||
|
controllers[field] = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
_initializeToken();
|
||||||
|
updateData();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
managerId = ref.watch(managerIdProvider);
|
||||||
|
userId = ref.watch(userIdProvider);
|
||||||
|
if (managerId != null) {
|
||||||
|
print('hansles');
|
||||||
|
// getHandlers(managerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initializeToken() async {
|
||||||
|
_token = await AuthService.getToken();
|
||||||
|
print("APISERTOKEN - $_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateData() async {
|
||||||
|
if (widget.data != null) {
|
||||||
|
dynamic id = widget.data?['id'];
|
||||||
|
final data = widget.data;
|
||||||
|
|
||||||
|
if (data == null) return;
|
||||||
|
setState(() {
|
||||||
|
selectedId = id;
|
||||||
|
controllers['value']?.text = data['value'] ?? '';
|
||||||
|
controllers["is_active"]?.text = data['is_active'].toString();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleSave() async {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
setState(() {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
dataDetails();
|
||||||
|
final dataSet = dataDetails();
|
||||||
|
print("dataSetAgent - $dataSet");
|
||||||
|
|
||||||
|
print("TYPE of is_active → ${dataSet['is_active'].runtimeType}");
|
||||||
|
print("TYPE of value → ${dataSet['value'].runtimeType}");
|
||||||
|
createUserData(dataSet);
|
||||||
|
} else {
|
||||||
|
// isDisable = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
print('REfresj');
|
||||||
|
widget.onSubmit();
|
||||||
|
setState(() {
|
||||||
|
// clear all text controllers
|
||||||
|
for (var controller in controllers.values) {
|
||||||
|
controller.clear();
|
||||||
|
} // 👈 clear selected agent
|
||||||
|
controllers['value']?.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createUserData(data) async {
|
||||||
|
final bool isUpdating = selectedId != null;
|
||||||
|
final dynamic id = isUpdating ? int.tryParse(selectedId.toString()) : 0;
|
||||||
|
final String apiUrldata;
|
||||||
|
|
||||||
|
print("TYPE of id → $id - ${id.runtimeType}");
|
||||||
|
print("TYPE of id → $userId - ${userId.runtimeType}");
|
||||||
|
|
||||||
|
apiUrldata = isUpdating
|
||||||
|
? '${Env.apiUrl}/master/updatePaymentMode/$selectedId'
|
||||||
|
: '${Env.apiUrl}/master/createPaymentMode';
|
||||||
|
|
||||||
|
print('apiUrldata - $apiUrldata');
|
||||||
|
// final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUpdating) {
|
||||||
|
data['updated_by'] = userId.toString();
|
||||||
|
} else {
|
||||||
|
data['created_by'] = userId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (isUpdating) {
|
||||||
|
// data['updated_by'] = userId;
|
||||||
|
// // data.remove('id');
|
||||||
|
// } else {
|
||||||
|
// data['created_by'] = userId;
|
||||||
|
// }
|
||||||
|
|
||||||
|
print("data------- $data}");
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse(apiUrldata),
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $_token',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
},
|
||||||
|
body: jsonEncode(data), // Convert map to JSON
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
print("Payment submitted successfully!");
|
||||||
|
print("Response: ${response.body}");
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
isUpdating
|
||||||
|
? ToastHelper.showSuccessToast(
|
||||||
|
context,
|
||||||
|
'Payment Updated Successfully',
|
||||||
|
)
|
||||||
|
: ToastHelper.showSuccessToast(
|
||||||
|
context,
|
||||||
|
'Payment Created Successfully',
|
||||||
|
);
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
|
} else {
|
||||||
|
final responseBody = jsonDecode(response.body);
|
||||||
|
dynamic msg = responseBody['data'];
|
||||||
|
|
||||||
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
|
print("Error: ${response.body}");
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("Payment Creation Failed"),
|
||||||
|
content: Text(msg),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text("OK"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(" Error submitting Staff: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
for (var controller in controllers.values) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
buildFormFields(),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
handleSave();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6),
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
color: Color(0xFF2E7D6E),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Save',
|
||||||
|
style: GoogleFonts.inter(color: Colors.white, fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(6.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF2E7D6E),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Icon(Icons.refresh, size: 13, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildFormFields() {
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(children: [buildName()]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildName() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Payment Mode *", style: _textStyle),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
ThemedFormField(
|
||||||
|
controller: controllers['value']!,
|
||||||
|
validator: (value) => Validators.requiredField(value, "value"),
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
|
txtheight: 30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final _textStyle = GoogleFonts.inter(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
471
lib/presentation/screens/Masters/PaymentMode/paymentList.dart
Normal file
471
lib/presentation/screens/Masters/PaymentMode/paymentList.dart
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
import 'package:flutter/cupertino.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/Masters/PaymentMode/payment.dart';
|
||||||
|
|
||||||
|
import '../../../../core/routing/routes.dart';
|
||||||
|
import '../../../../core/services/api_service.dart';
|
||||||
|
import '../../../../data/utils/Pagination.dart';
|
||||||
|
import '../../../layouts/main_layout.dart';
|
||||||
|
import '../../../layouts/responsive_layout.dart';
|
||||||
|
import '../../../providers/manager_provider.dart';
|
||||||
|
import '../../../themes/indicators/export_btn.dart';
|
||||||
|
import '../../../themes/indicators/filter_btn.dart';
|
||||||
|
import '../../../themes/indicators/search_field_theme.dart';
|
||||||
|
import '../../../themes/indicators/text_field_theme.dart';
|
||||||
|
import '../../../widgets/custom_action_popup.dart';
|
||||||
|
|
||||||
|
class PaymentLsit extends ConsumerStatefulWidget {
|
||||||
|
const PaymentLsit({super.key});
|
||||||
|
@override
|
||||||
|
ConsumerState<PaymentLsit> createState() => PaymentLsitState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaymentLsitState extends ConsumerState<PaymentLsit> {
|
||||||
|
int currentPage = 1;
|
||||||
|
int itemsPerPage = 10;
|
||||||
|
late ApiService apiService;
|
||||||
|
dynamic managerId;
|
||||||
|
dynamic role;
|
||||||
|
dynamic prefid;
|
||||||
|
dynamic userId;
|
||||||
|
// List<Map<String, dynamic>> dataVal = [];
|
||||||
|
List<Map<String, dynamic>> getPaymentData = [];
|
||||||
|
List<Map<String, dynamic>> originalData = [];
|
||||||
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
Map<String, dynamic>? selectedPayment;
|
||||||
|
dynamic selectedId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
apiService = ApiService();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
final data1 = ref.read(managerIdProvider);
|
||||||
|
// final data2 = ref.read(handlerIdProvider);
|
||||||
|
print("Edata1 => mId: $data1 -2 :");
|
||||||
|
prefid = data1;
|
||||||
|
role = ref.read(userRoleProvider);
|
||||||
|
userId = ref.watch(userIdProvider);
|
||||||
|
print("E43 => mId: $prefid");
|
||||||
|
if (prefid != null && role != null) {
|
||||||
|
getPayment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// getPaymentList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> get _paginatedData {
|
||||||
|
// Sort descending by id first
|
||||||
|
final sortedData = [...filteredData]
|
||||||
|
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
||||||
|
|
||||||
|
if (sortedData.isEmpty) return [];
|
||||||
|
|
||||||
|
// Ensure currentPage is valid
|
||||||
|
final maxPage = (sortedData.length / itemsPerPage).ceil();
|
||||||
|
final safePage = currentPage.clamp(1, maxPage);
|
||||||
|
|
||||||
|
final startIndex = (safePage - 1) * itemsPerPage;
|
||||||
|
final endIndex = (startIndex + itemsPerPage).clamp(0, sortedData.length);
|
||||||
|
|
||||||
|
return sortedData.sublist(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEdit(Map<String, dynamic> item) {
|
||||||
|
setState(() {
|
||||||
|
selectedId = item['id'];
|
||||||
|
selectedPayment = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void filterData(String query) {
|
||||||
|
setState(() {
|
||||||
|
final q = query.toLowerCase();
|
||||||
|
|
||||||
|
if (q.isEmpty) {
|
||||||
|
filteredData = getPaymentData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredData = getPaymentData.where((item) {
|
||||||
|
final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
|
||||||
|
return (item['value'] ?? '').toString().toLowerCase().contains(q) ||
|
||||||
|
isActiveStatus.contains(q);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final TextEditingController _searchStaffController = TextEditingController();
|
||||||
|
|
||||||
|
Future<void> getPayment() async {
|
||||||
|
print('getPayment called');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchMasterDropDown('PaymentMode');
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('getPayment - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getPaymentData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getPaymentData');
|
||||||
|
|
||||||
|
filteredData = List.from(getPaymentData);
|
||||||
|
print('originalData - $filteredData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getPaymentData = [];
|
||||||
|
filteredData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||||
|
return [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
print('EDITStaff - ${data['id']}');
|
||||||
|
dynamic id = data['id'];
|
||||||
|
context.go('/staff/$id');
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
Text('Edit'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
managerId = ref.watch(managerIdProvider);
|
||||||
|
|
||||||
|
return MainLayout(
|
||||||
|
title: "Staff",
|
||||||
|
body: Container(
|
||||||
|
// padding: EdgeInsets.all(8.0),
|
||||||
|
// margin: EdgeInsets.all(10.0),
|
||||||
|
|
||||||
|
// color: Colors.yellow.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// height: 30,
|
||||||
|
// color: Colors.red.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.go(AppRoutes.dashboard);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [Text('Payment List', style: _headerStyle)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
// color: Colors.green,
|
||||||
|
// color: Colors.green.shade50,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
// margin: EdgeInsets.all(10.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
|
||||||
|
padding: EdgeInsets.all(15.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// height: 40,
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Payment(
|
||||||
|
key: ValueKey(selectedId),
|
||||||
|
data: selectedPayment,
|
||||||
|
id: selectedId,
|
||||||
|
onSubmit: () {
|
||||||
|
getPayment();
|
||||||
|
setState(() {
|
||||||
|
selectedPayment = null;
|
||||||
|
selectedId = null;
|
||||||
|
}); // reset after save
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
ThemedSearchField(
|
||||||
|
hintText: 'Search',
|
||||||
|
// backgroundColor: Color(0xFFF6F8F8),
|
||||||
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
|
txtHeight: 30,
|
||||||
|
onChanged: filterData,
|
||||||
|
controller: _searchStaffController,
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.2,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
|
ExportBtn(
|
||||||
|
sheetName: "Payment",
|
||||||
|
fileName: "Payment_list",
|
||||||
|
txt: !ResponsiveLayout.isMobile(context)
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
|
data: filteredData,
|
||||||
|
displayHeaders: ['S.No.', 'Payment', 'Status'],
|
||||||
|
keys: ["sno", "value", "is_active"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(0xFFF1F5F9),
|
||||||
|
|
||||||
|
// color: Color(0xFFEDF6F5),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('S.No.', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Payment', style: _headerStyle),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('Status', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('Action', style: _headerStyle),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(child: _buildDataTable(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
// height: 20,
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
// color: Colors.green.shade50,
|
||||||
|
child: PaginationControls(
|
||||||
|
currentPage: currentPage,
|
||||||
|
itemsPerPage: itemsPerPage,
|
||||||
|
// totalItems: dataVal.length,
|
||||||
|
totalItems: filteredData.length,
|
||||||
|
// activeColor: layoutColor, // your theme color
|
||||||
|
onPageChanged: (page) {
|
||||||
|
setState(() {
|
||||||
|
currentPage = page;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onItemsPerPageChanged: (items) {
|
||||||
|
setState(() {
|
||||||
|
itemsPerPage = items;
|
||||||
|
currentPage = 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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: filteredData.length + 1, // +1 for header, +1 for pagination
|
||||||
|
itemCount: sortedData.length + 1, // +1 for header, +1 for pagination
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == 0) return _buildHeader();
|
||||||
|
// if (index == dataVal.length + 1)
|
||||||
|
// return _buildPagination(context);
|
||||||
|
final startIndex = ((currentPage - 1) * itemsPerPage);
|
||||||
|
// final item = filteredData[index - 1];
|
||||||
|
final item = sortedData[index - 1];
|
||||||
|
final sno = startIndex + index;
|
||||||
|
return _buildDataRow(item, sno);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader() {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16),
|
||||||
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
// color: Color(0xFFE0F7F9),
|
||||||
|
border: const Border(
|
||||||
|
bottom: BorderSide(color: Colors.blueGrey, width: 0.15),
|
||||||
|
),
|
||||||
|
// borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(item['value'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// color: Colors.yellow.shade50,
|
||||||
|
child: Transform.scale(
|
||||||
|
scale: 0.4, // reduce size (0.7–0.9 works well)
|
||||||
|
child: Switch(
|
||||||
|
value: item['is_active'] == "1",
|
||||||
|
onChanged: (val) {
|
||||||
|
setState(() {
|
||||||
|
item['is_active'] = val ? "1" : "0";
|
||||||
|
});
|
||||||
|
final response = apiService.updateStatusMasters(
|
||||||
|
item['id'],
|
||||||
|
val ? "0" : "1",
|
||||||
|
'PaymentMode',
|
||||||
|
userId,
|
||||||
|
);
|
||||||
|
print("Response - $response");
|
||||||
|
},
|
||||||
|
activeColor: Color(0xFF2E7D6E), // thumb when active
|
||||||
|
// activeColor: Color(0xFF425B5B), // thumb when active
|
||||||
|
activeTrackColor: Color(0xFFDCFCE7), // track when active
|
||||||
|
// activeTrackColor: Color(0xFFB2D8D3), // track when active
|
||||||
|
inactiveThumbColor:
|
||||||
|
Colors.grey.shade400, // thumb when inactive
|
||||||
|
inactiveTrackColor:
|
||||||
|
Colors.grey.shade300, // track when inactive
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: item['is_active'] == "1"
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Tooltip(
|
||||||
|
message: 'Edit',
|
||||||
|
child: IconButton(
|
||||||
|
icon: Image.asset(
|
||||||
|
"assets/miscellaneous/Edit.png",
|
||||||
|
height: 12,
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
print('EDITBrokwer - ${item['id']}');
|
||||||
|
print('EDITBrokwer - ${item}');
|
||||||
|
dynamic id = item['id'];
|
||||||
|
|
||||||
|
handleEdit(item);
|
||||||
|
|
||||||
|
print(item);
|
||||||
|
},
|
||||||
|
splashRadius: 28,
|
||||||
|
hoverColor: Colors.black12,
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
"assets/miscellaneous/Edit_muted.png",
|
||||||
|
height: 15,
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final _dataBold = GoogleFonts.inter(
|
||||||
|
fontSize: 11.5,
|
||||||
|
|
||||||
|
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: Color(0XFF1e293b),
|
||||||
|
fontSize: 12,
|
||||||
|
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -385,8 +385,8 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 14.0, vertical: 20.0),
|
padding: EdgeInsets.symmetric(horizontal: 14.0, vertical: 20.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
// color: Color(0xFFEDF6F5),
|
color: Color(0xFFEDF6F5),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -203,55 +203,60 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Container(
|
Container(
|
||||||
// // height: 30,
|
// height: 30,
|
||||||
// // color: Colors.red.shade50,
|
// color: Colors.red.shade50,
|
||||||
// width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
// child: GestureDetector(
|
child: GestureDetector(
|
||||||
// onTap: () {
|
onTap: () {
|
||||||
// context.go(AppRoutes.dashboard);
|
context.go(AppRoutes.dashboard);
|
||||||
// },
|
},
|
||||||
// child: Row(
|
child: Row(
|
||||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
// mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
// children: [
|
children: [
|
||||||
// // Icon(
|
Text('Staff List', style: _headerStyle),
|
||||||
// // Icons.arrow_left_sharp,
|
// Icon(
|
||||||
// // size: 35,
|
// Icons.arrow_left_sharp,
|
||||||
// // color: Color(0xFF425B5B),
|
// size: 35,
|
||||||
// // ),
|
// color: Color(0xFF425B5B),
|
||||||
// // Tooltip(
|
// ),
|
||||||
// // message: 'Back',
|
// Tooltip(
|
||||||
// // child: IconButton(
|
// message: 'Back',
|
||||||
// // icon: const Icon(
|
// child: IconButton(
|
||||||
// // Icons.arrow_left_sharp,
|
// icon: const Icon(
|
||||||
// // size: 25,
|
// Icons.arrow_left_sharp,
|
||||||
// // color: Color(0xFF425B5B),
|
// size: 25,
|
||||||
// // ),
|
// color: Color(0xFF425B5B),
|
||||||
// // onPressed: () {
|
// ),
|
||||||
// // context.go(AppRoutes.dashboard);
|
// onPressed: () {
|
||||||
// // },
|
// context.go(AppRoutes.dashboard);
|
||||||
// // splashRadius: 18,
|
// },
|
||||||
// // hoverColor: Colors.black12,
|
// splashRadius: 18,
|
||||||
// // padding: const EdgeInsets.all(4),
|
// hoverColor: Colors.black12,
|
||||||
// // constraints: const BoxConstraints(),
|
// padding: const EdgeInsets.all(4),
|
||||||
// // ),
|
// constraints: const BoxConstraints(),
|
||||||
// // ),
|
// ),
|
||||||
// // const SizedBox(width: 15), // spacing between icon and text
|
// ),
|
||||||
//
|
// const SizedBox(width: 15), // spacing between icon and text
|
||||||
// ],
|
],
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
//
|
|
||||||
// SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
// color: Colors.green,
|
// color: Colors.green,
|
||||||
// color: Colors.green.shade50,
|
// color: Colors.green.shade50,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
|
// margin: EdgeInsets.all(10.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
|
||||||
// padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(15.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
@ -261,14 +266,6 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
|
||||||
"Staff",
|
|
||||||
style: GoogleFonts.inter(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
ThemedSearchField(
|
ThemedSearchField(
|
||||||
hintText: 'Search',
|
hintText: 'Search',
|
||||||
// backgroundColor: Color(0xFFF6F8F8),
|
// backgroundColor: Color(0xFFF6F8F8),
|
||||||
@ -279,8 +276,7 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
txtwidth: MediaQuery.of(context).size.width * 0.2,
|
txtwidth: MediaQuery.of(context).size.width * 0.2,
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 10),
|
||||||
|
|
||||||
ExportBtn(
|
ExportBtn(
|
||||||
sheetName: "Staff",
|
sheetName: "Staff",
|
||||||
fileName: "staff_list",
|
fileName: "staff_list",
|
||||||
@ -306,7 +302,7 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(width: 10),
|
Spacer(),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go('/staff/create');
|
context.go('/staff/create');
|
||||||
@ -320,15 +316,6 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// Text(
|
|
||||||
// 'Create New Staff',
|
|
||||||
// style: GoogleFonts.inter(
|
|
||||||
// color: Colors.white,
|
|
||||||
// fontWeight: FontWeight.w500,
|
|
||||||
// fontSize: 11,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// SizedBox(width: 10),
|
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'Create Staff',
|
message: 'Create Staff',
|
||||||
child: Icon(
|
child: Icon(
|
||||||
@ -457,15 +444,15 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
|
|
||||||
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16),
|
||||||
// margin: const EdgeInsets.only(top: 10),
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
// color: Color(0xFFE0F7F9),
|
// color: Color(0xFFE0F7F9),
|
||||||
border: const Border(
|
border: const Border(
|
||||||
bottom: BorderSide(color: Color(0xFFEAEAEA), width: 1),
|
bottom: BorderSide(color: Colors.blueGrey, width: 0.15),
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(8),
|
// borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@ -607,7 +594,7 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final _dataBold = GoogleFonts.inter(
|
static final _dataBold = GoogleFonts.inter(
|
||||||
fontSize: 12,
|
fontSize: 11.5,
|
||||||
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Color(0xFF000000),
|
color: Color(0xFF000000),
|
||||||
|
|||||||
@ -713,8 +713,19 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
key: dropDownSelectStaffKey,
|
key: dropDownSelectStaffKey,
|
||||||
// selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
// selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||||
selectedItem: selectedVehicle,
|
selectedItem: selectedVehicle,
|
||||||
items: (filter, infiniteScrollProps) {
|
|
||||||
return filteredStaffDataEnqAsgn;
|
// items: (filter, infiniteScrollProps) {
|
||||||
|
// return filteredStaffDataEnqAsgn;
|
||||||
|
// },
|
||||||
|
items: (filter, infiniteScrollProps) async {
|
||||||
|
if (filter.isEmpty) {
|
||||||
|
return filteredStaffDataEnqAsgn;
|
||||||
|
}
|
||||||
|
return filteredStaffDataEnqAsgn.where((item) {
|
||||||
|
return item['name'].toString().toLowerCase().contains(
|
||||||
|
filter.toLowerCase(),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
},
|
},
|
||||||
|
|
||||||
itemAsString: (val) => val['name'].toString(),
|
itemAsString: (val) => val['name'].toString(),
|
||||||
@ -791,7 +802,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
),
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Staff ...",
|
hintText: "Search Staff ...",
|
||||||
@ -951,8 +965,11 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
),
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
|
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Insurer...",
|
hintText: "Search Insurer...",
|
||||||
@ -1084,7 +1101,9 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
),
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Broker...",
|
hintText: "Search Broker...",
|
||||||
@ -1331,14 +1350,18 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
|
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Partner Name",
|
hintText: "Partner Name",
|
||||||
hintStyle: GoogleFonts.inter(
|
hintStyle: GoogleFonts.inter(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.grey,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
|
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -1538,8 +1561,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
),
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
padding: const EdgeInsets.all(1.0),
|
padding: const EdgeInsets.all(1.0),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Vehicle Type...",
|
hintText: "Search Vehicle Type...",
|
||||||
@ -1549,10 +1574,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
borderSide: BorderSide(color: Colors.white), // 👈 Normal border
|
borderSide: BorderSide(color: Colors.white), // 👈 Normal border
|
||||||
),
|
),
|
||||||
isDense: true, // reduces height
|
isDense: true, // reduces height
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
// contentPadding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8,
|
// horizontal: 8,
|
||||||
vertical: 8, // reduce this value for smaller height
|
// vertical: 8, // reduce this value for smaller height
|
||||||
),
|
// ),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -3340,33 +3365,34 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
|
|
||||||
// Premium
|
// Premium
|
||||||
DataCell(
|
DataCell(
|
||||||
(item['status'] == 'Proposal Created' ||
|
// (item['status'] == 'Proposal Created' ||
|
||||||
item['status'] == 'Proposal Rejected')
|
// item['status'] == 'Proposal Rejected')
|
||||||
? SizedBox(
|
// ? SizedBox(
|
||||||
width: 80,
|
// width: 80,
|
||||||
child: InkWell(
|
// child: InkWell(
|
||||||
onTap: () {
|
// onTap: () {
|
||||||
// handle approval logic
|
// // handle approval logic
|
||||||
|
//
|
||||||
handleProposalAccept(context, item['id']);
|
// handleProposalAccept(context, item['id']);
|
||||||
},
|
// },
|
||||||
child: Text(
|
// child: Text(
|
||||||
'Click To\nApprove',
|
// 'Click To\nApprove',
|
||||||
style: GoogleFonts.inter(
|
// style: GoogleFonts.inter(
|
||||||
color: Colors.green,
|
// color: Colors.green,
|
||||||
fontSize: 11,
|
// fontSize: 11,
|
||||||
fontWeight: FontWeight.w700,
|
// fontWeight: FontWeight.w700,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
: SizedBox(
|
// :
|
||||||
width: 80,
|
SizedBox(
|
||||||
child: Text(
|
width: 80,
|
||||||
item['premium_amount']?.toString() ?? '-',
|
child: Text(
|
||||||
style: _dataBold,
|
item['premium_amount']?.toString() ?? '-',
|
||||||
),
|
style: _dataBold,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Payment Mode
|
// Payment Mode
|
||||||
@ -3430,7 +3456,8 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
item['status'] ?? '-',
|
item['status'] ?? '-',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: statusTextColors[status] ?? Colors.black,
|
color: Color(0XFF1e293b),
|
||||||
|
// color: statusTextColors[status] ?? Colors.black,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
// overflow: TextOverflow.clip, //
|
// overflow: TextOverflow.clip, //
|
||||||
|
|||||||
@ -355,8 +355,13 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
buildInsuredName(context, fromHeader: true),
|
buildInsuredName(context, fromHeader: true),
|
||||||
|
|
||||||
buildVehicleNumber(context),
|
buildVehicleNumber(context),
|
||||||
|
Row(
|
||||||
buildSave(context),
|
children: [
|
||||||
|
buildRefresh(context),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
buildSave(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -474,6 +479,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Partner Name",
|
hintText: "Partner Name",
|
||||||
@ -673,6 +679,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Insurer...",
|
hintText: "Search Insurer...",
|
||||||
@ -864,6 +871,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Staff ...",
|
hintText: "Search Staff ...",
|
||||||
@ -927,7 +935,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
resetFields();
|
resetFields();
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(5.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF2E7D6E),
|
color: const Color(0xFF2E7D6E),
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
@ -937,6 +945,22 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildRefresh(context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
resetFields();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(6.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF2E7D6E),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Icon(Icons.refresh, size: 18, color: Colors.white),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void resetFields() {
|
void resetFields() {
|
||||||
print('Field ReSET');
|
print('Field ReSET');
|
||||||
// 1. Reset all text controllers
|
// 1. Reset all text controllers
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import '../../../../themes/indicators/customizd_file_upload.dart';
|
|||||||
import '../../../../themes/indicators/input_field_decoration.dart';
|
import '../../../../themes/indicators/input_field_decoration.dart';
|
||||||
import '../../../../themes/indicators/text_field_theme.dart';
|
import '../../../../themes/indicators/text_field_theme.dart';
|
||||||
|
|
||||||
class CreateQuotationForm extends ConsumerStatefulWidget {
|
class CreateProposalForm extends ConsumerStatefulWidget {
|
||||||
final dynamic userId;
|
final dynamic userId;
|
||||||
final dynamic managerId;
|
final dynamic managerId;
|
||||||
final dynamic selectedEnquiryId;
|
final dynamic selectedEnquiryId;
|
||||||
@ -34,7 +34,7 @@ class CreateQuotationForm extends ConsumerStatefulWidget {
|
|||||||
final dynamic selectedQuotationFrmListId;
|
final dynamic selectedQuotationFrmListId;
|
||||||
final void Function(String value) onSubmit;
|
final void Function(String value) onSubmit;
|
||||||
|
|
||||||
const CreateQuotationForm({
|
const CreateProposalForm({
|
||||||
super.key,
|
super.key,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.managerId,
|
required this.managerId,
|
||||||
@ -46,12 +46,11 @@ class CreateQuotationForm extends ConsumerStatefulWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<CreateQuotationForm> createState() =>
|
ConsumerState<CreateProposalForm> createState() => CreateProposalFormState();
|
||||||
CreateQuotationFormState();
|
// State<CreateProposalForm> createState() => _CreateProposalFormState();
|
||||||
// State<CreateQuotationForm> createState() => _CreateQuotationFormState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
class CreateProposalFormState extends ConsumerState<CreateProposalForm> {
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
String? _token;
|
String? _token;
|
||||||
|
|
||||||
@ -75,16 +74,31 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyBroker =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||||
dropDownKeyInsurer = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
dropDownKeyInsurer = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||||
|
dropDownSelectPaymentModeKey =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
List<String> tabHeader = ['idv', 'premium_Amount', 'insurer'];
|
List<String> tabHeader = ['idv', 'premium_Amount', 'insurer'];
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getBrokerData = [];
|
||||||
|
List<Map<String, dynamic>> filteredBrokerData = [];
|
||||||
|
String? selectedBroker;
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getPaymentModeData = [];
|
||||||
|
List<Map<String, dynamic>> filteredPaymentModeData = [];
|
||||||
|
|
||||||
List<Map<String, dynamic>> getInsuranceTypeData = [];
|
List<Map<String, dynamic>> getInsuranceTypeData = [];
|
||||||
List<Map<String, dynamic>> filteredInsuranceData = [];
|
List<Map<String, dynamic>> filteredInsuranceData = [];
|
||||||
|
|
||||||
String? selectedInsPlanType;
|
String? selectedInsPlanType;
|
||||||
String? selectedEndorsement;
|
String? selectedEndorsement;
|
||||||
|
String? selectedPaymentMode;
|
||||||
|
|
||||||
Map<String, dynamic> dataDetails() {
|
Map<String, dynamic> dataDetails() {
|
||||||
final data = {
|
final data = {
|
||||||
@ -94,6 +108,8 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// "insurer_id": selectedInsurer,
|
// "insurer_id": selectedInsurer,
|
||||||
"premium_amount": controllers["premium_Amount"]?.text,
|
"premium_amount": controllers["premium_Amount"]?.text,
|
||||||
"insurance_plan_type_id": selectedInsPlanType,
|
"insurance_plan_type_id": selectedInsPlanType,
|
||||||
|
"payment_mode_id": selectedPaymentMode,
|
||||||
|
"broker_id": selectedBroker,
|
||||||
// "additional_uploaded_file_name": "extra_doc.pdf",
|
// "additional_uploaded_file_name": "extra_doc.pdf",
|
||||||
// "created_by": widget.userId,
|
// "created_by": widget.userId,
|
||||||
"manager_id": widget.managerId,
|
"manager_id": widget.managerId,
|
||||||
@ -112,8 +128,10 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// 🔹 Init logic here (API calls, token fetch, etc.)
|
// 🔹 Init logic here (API calls, token fetch, etc.)
|
||||||
_initializeToken();
|
_initializeToken();
|
||||||
getInsuranceType();
|
getInsuranceType();
|
||||||
|
getPaymentMode();
|
||||||
// getInsurers();
|
// getInsurers();
|
||||||
updateData();
|
updateData();
|
||||||
|
getBroker();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initializeToken() async {
|
Future<void> _initializeToken() async {
|
||||||
@ -157,6 +175,37 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getBroker() async {
|
||||||
|
print('getBroker called');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchMasterDropDown('Broker');
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('getBroker - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getBrokerData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getBrokerData');
|
||||||
|
|
||||||
|
filteredBrokerData = List.from(getBrokerData);
|
||||||
|
print('originalData - $filteredBrokerData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getBrokerData = [];
|
||||||
|
filteredBrokerData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateData() {
|
void updateData() {
|
||||||
if (widget.selectedQuotationFrmListId != null &&
|
if (widget.selectedQuotationFrmListId != null &&
|
||||||
widget.selectedQuotationFrmListdata!.isNotEmpty) {
|
widget.selectedQuotationFrmListdata!.isNotEmpty) {
|
||||||
@ -174,8 +223,11 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
selectedInsPlanType = widget
|
selectedInsPlanType = widget
|
||||||
.selectedQuotationFrmListdata!['insurance_plan_type_id']
|
.selectedQuotationFrmListdata!['insurance_plan_type_id']
|
||||||
?.toString();
|
?.toString();
|
||||||
|
selectedBroker = widget.selectedQuotationFrmListdata!['broker_id']
|
||||||
|
?.toString();
|
||||||
|
|
||||||
selectedInsurer = '1';
|
selectedPaymentMode = widget.selectedQuotationFrmListdata!['broker_id']
|
||||||
|
?.toString();
|
||||||
|
|
||||||
// controllers["insurer"]?.text = 'LIC';
|
// controllers["insurer"]?.text = 'LIC';
|
||||||
|
|
||||||
@ -183,7 +235,7 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? '';
|
// widget.selectedQuotationFrmListdata!['insurer_id']?.toString() ?? '';
|
||||||
|
|
||||||
String? apiDocPath =
|
String? apiDocPath =
|
||||||
widget.selectedQuotationFrmListdata!["additional_uploaded_file_name"];
|
widget.selectedQuotationFrmListdata!["policy_pdf_file_name"];
|
||||||
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
||||||
print('apiDocPath - $apiDocPath');
|
print('apiDocPath - $apiDocPath');
|
||||||
selectedFileNames = apiDocPath.split('/').last;
|
selectedFileNames = apiDocPath.split('/').last;
|
||||||
@ -263,6 +315,39 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getPaymentMode() async {
|
||||||
|
print('getPaymentMode called');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchMasterDropDown('PaymentMode');
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('getPaymentModeData - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getPaymentModeData = List<Map<String, dynamic>>.from(
|
||||||
|
response['data'],
|
||||||
|
);
|
||||||
|
print('API Data - $getPaymentModeData');
|
||||||
|
|
||||||
|
filteredPaymentModeData = List.from(getPaymentModeData);
|
||||||
|
print('originalData - $filteredPaymentModeData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getPaymentModeData = [];
|
||||||
|
filteredPaymentModeData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleDone() {
|
void handleDone() {
|
||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
|
||||||
@ -292,11 +377,9 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
print('id - $id');
|
print('id - $id');
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse(
|
||||||
// isUpdating
|
// isUpdating
|
||||||
// ? 'https://venbait.in/nhance/partner/dev/api/agent/updateAgent'
|
// ? '${Env.apiUrl}quotation/updateQuotation'
|
||||||
// : 'https://venbait.in/nhance/partner/dev/api/agent/createAgent',
|
// : '${Env.apiUrl}quotation/createQuotation',
|
||||||
isUpdating
|
'${Env.apiUrl}quotation/proceedQuotation',
|
||||||
? '${Env.apiUrl}quotation/updateQuotation'
|
|
||||||
: '${Env.apiUrl}quotation/createQuotation',
|
|
||||||
);
|
);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
throw Exception('Token not found. Please log in.');
|
throw Exception('Token not found. Please log in.');
|
||||||
@ -336,14 +419,14 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
try {
|
try {
|
||||||
if (docUploadedFile!.bytes != null) {
|
if (docUploadedFile!.bytes != null) {
|
||||||
final multipartFile = http.MultipartFile.fromBytes(
|
final multipartFile = http.MultipartFile.fromBytes(
|
||||||
'additional_uploaded_file_name',
|
'policy_pdf_file_name',
|
||||||
docUploadedFile!.bytes!,
|
docUploadedFile!.bytes!,
|
||||||
filename: docUploadedFile!.name,
|
filename: docUploadedFile!.name,
|
||||||
);
|
);
|
||||||
request.files.add(multipartFile);
|
request.files.add(multipartFile);
|
||||||
} else if (docUploadedFile!.path != null) {
|
} else if (docUploadedFile!.path != null) {
|
||||||
final multipartFile = await http.MultipartFile.fromPath(
|
final multipartFile = await http.MultipartFile.fromPath(
|
||||||
'additional_uploaded_file_name',
|
'policy_pdf_file_name',
|
||||||
docUploadedFile!.path!,
|
docUploadedFile!.path!,
|
||||||
filename: docUploadedFile!.name,
|
filename: docUploadedFile!.name,
|
||||||
);
|
);
|
||||||
@ -369,8 +452,9 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
|
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
widget.onSubmit('Success');
|
widget.onSubmit('Success');
|
||||||
|
// ToastHelper.showErrorToast(context, 'Proposal Created');
|
||||||
reset();
|
reset();
|
||||||
// Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
await apiService.clearLocalStorageAndRedirect();
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
} else {
|
} else {
|
||||||
@ -411,7 +495,43 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// const SizedBox(height: 8),
|
// const SizedBox(height: 8),
|
||||||
|
|
||||||
// 🔹 Switch content dynamically
|
// 🔹 Switch content dynamically
|
||||||
buildFormFields(context),
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.525,
|
||||||
|
child: buildFormFields(context),
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
handleDone();
|
||||||
|
// widget.onSubmit(controller.text.trim());
|
||||||
|
// Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 25.0,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
color: const Color(0xFF425B5B),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Save',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -419,54 +539,43 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
Widget buildFormFields(BuildContext context) {
|
Widget buildFormFields(BuildContext context) {
|
||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
// autovalidateMode: AutovalidateMode.onUserInteraction,
|
child: Column(
|
||||||
// autovalidateMode: _autoValidate
|
|
||||||
// ? AutovalidateMode.onUserInteraction
|
|
||||||
// : AutovalidateMode.disabled,
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
|
|
||||||
children: [
|
children: [
|
||||||
buildIdv(context),
|
Row(
|
||||||
Spacer(),
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
// 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),
|
children: [
|
||||||
// _buildResponsiveRow(
|
buildIdv(context),
|
||||||
// context,
|
Spacer(),
|
||||||
// buildAdditonalDocuments(context),
|
// buildInsurer(context),
|
||||||
// buildRemarks(context),
|
buildInsurancePlanType(context),
|
||||||
// ),
|
Spacer(),
|
||||||
|
buildPremiumAmnt(context),
|
||||||
|
Spacer(),
|
||||||
|
// buildDocuments(context),
|
||||||
|
|
||||||
|
// if (!ResponsiveLayout.isMobile(context)) const SizedBox(height: 10),
|
||||||
|
// _buildResponsiveRow(
|
||||||
|
// context,
|
||||||
|
// buildAdditonalDocuments(context),
|
||||||
|
// buildRemarks(context),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
|
||||||
|
children: [
|
||||||
|
buildPaymentMode(context),
|
||||||
|
Spacer(),
|
||||||
|
// buildInsurer(context),
|
||||||
|
buildBroker(context),
|
||||||
|
Spacer(),
|
||||||
|
buildDocuments(context), Spacer(),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -486,103 +595,15 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||||
],
|
],
|
||||||
validator: (value) => Validators.doubleNumber(value, "IDV"),
|
validator: (value) => Validators.doubleNumber(value, "IDV"),
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
// validator: (value) => Validators.number(value, "IDV"),
|
// validator: (value) => Validators.number(value, "IDV"),
|
||||||
backgroundColor: Color(0xFFEDF6F5),
|
// backgroundColor: Color(0xFFEDF6F5),
|
||||||
// readOnly: true,
|
// readOnly: true,
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.15,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
txtheight: 35,
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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'];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -596,7 +617,9 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['premium_Amount']!,
|
controller: controllers['premium_Amount']!,
|
||||||
backgroundColor: Color(0xFFEDF6F5),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
|
// backgroundColor: Color(0xFFEDF6F5),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||||
],
|
],
|
||||||
@ -604,7 +627,8 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// validator: (value) => Validators.number(value, "PremiumAmount "),
|
// validator: (value) => Validators.number(value, "PremiumAmount "),
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.15,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
|
txtheight: 35,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -625,15 +649,24 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.15,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
height: 35,
|
||||||
child: DropdownSearch<Map<String, dynamic>>(
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
key: dropDownKey,
|
key: dropDownKey,
|
||||||
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||||
items: (filter, infiniteScrollProps) {
|
// items: (filter, infiniteScrollProps) {
|
||||||
return filteredInsuranceData;
|
// return filteredInsuranceData;
|
||||||
|
// },
|
||||||
|
items: (filter, infiniteScrollProps) async {
|
||||||
|
if (filter.isEmpty) {
|
||||||
|
return filteredInsuranceData;
|
||||||
|
}
|
||||||
|
return filteredInsuranceData.where((item) {
|
||||||
|
return item['name'].toString().toLowerCase().contains(
|
||||||
|
filter.toLowerCase(),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
},
|
},
|
||||||
|
|
||||||
itemAsString: (val) => val['insurance_plan_type'].toString(),
|
itemAsString: (val) => val['insurance_plan_type'].toString(),
|
||||||
compareFn: (item, selectedItem) =>
|
compareFn: (item, selectedItem) =>
|
||||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
@ -643,18 +676,36 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
decoratorProps: DropDownDecoratorProps(
|
decoratorProps: DropDownDecoratorProps(
|
||||||
decoration:
|
decoration:
|
||||||
AppInputDecorations.dropdownDecoration(
|
AppInputDecorations.dropdownDecoration(
|
||||||
label: "Select Plan Type",
|
label: "Select Staff Member",
|
||||||
).copyWith(
|
).copyWith(
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Color(
|
fillColor:
|
||||||
0xFFEDF6F5,
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
), // 👈 makes the dropdown input white
|
isDense: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
popupProps: PopupProps.menu(
|
popupProps: PopupProps.menu(
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
constraints: BoxConstraints(maxHeight: 250),
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
@ -664,10 +715,16 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
),
|
),
|
||||||
showSearchBox: true,
|
showSearchBox: true,
|
||||||
searchFieldProps: TextFieldProps(
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: Colors.white,
|
fillColor: Colors.white,
|
||||||
hintText: "Search Plan Type...",
|
hintText: "Search Plan Type ...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -681,6 +738,38 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['insurance_plan_type'].toString(),
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 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(),
|
// constraints: BoxConstraints(),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -699,22 +788,291 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildPaymentMode(context) {
|
||||||
|
Map<String, dynamic>? selectedVehicle = filteredPaymentModeData.firstWhere(
|
||||||
|
(item) => item['id'].toString() == selectedPaymentMode,
|
||||||
|
orElse: () => {},
|
||||||
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Payment Mode", style: _textStyle),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
|
height: 35,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
key: dropDownSelectPaymentModeKey,
|
||||||
|
selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||||
|
// items: (filter, infiniteScrollProps) {
|
||||||
|
// return filteredInsuranceData;
|
||||||
|
// },
|
||||||
|
items: (filter, infiniteScrollProps) async {
|
||||||
|
if (filter.isEmpty) {
|
||||||
|
return filteredPaymentModeData;
|
||||||
|
}
|
||||||
|
return filteredPaymentModeData.where((item) {
|
||||||
|
return item['name'].toString().toLowerCase().contains(
|
||||||
|
filter.toLowerCase(),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
itemAsString: (val) => val['value'].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 Payment Mode",
|
||||||
|
).copyWith(
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
|
isDense: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
menuProps: MenuProps(
|
||||||
|
backgroundColor:
|
||||||
|
Colors.white, // 👈 sets dropdown background to white
|
||||||
|
),
|
||||||
|
showSearchBox: true,
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search Payment Mode ...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
), // 👈 Normal border
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
width: 1.5,
|
||||||
|
), // 👈 Focused border
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['value'].toString(),
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val != null) {
|
||||||
|
print("Selected value : ${val['value']}");
|
||||||
|
print("Id: ${val['id']}");
|
||||||
|
selectedPaymentMode = val['id'];
|
||||||
|
// controllers['agentId']?.text = val['agent_code'];
|
||||||
|
// agentId = agent['id'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildBroker(context) {
|
||||||
|
Map<String, dynamic>? selectedBrokers = filteredBrokerData.firstWhere(
|
||||||
|
(item) => item['id'].toString() == selectedBroker,
|
||||||
|
orElse: () => {},
|
||||||
|
);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Broker", style: _textStyle),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
|
height: 35,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
key: dropDownKeyBroker,
|
||||||
|
selectedItem: selectedBrokers.isNotEmpty ? selectedBrokers : null,
|
||||||
|
// items: (filter, infiniteScrollProps) {
|
||||||
|
// return filteredInsuranceData;
|
||||||
|
// },
|
||||||
|
items: (filter, infiniteScrollProps) async {
|
||||||
|
if (filter.isEmpty) {
|
||||||
|
return filteredBrokerData;
|
||||||
|
}
|
||||||
|
return filteredBrokerData.where((item) {
|
||||||
|
return item['name'].toString().toLowerCase().contains(
|
||||||
|
filter.toLowerCase(),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
itemAsString: (val) => val['name'].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 Broker",
|
||||||
|
).copyWith(
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
|
isDense: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
menuProps: MenuProps(
|
||||||
|
backgroundColor:
|
||||||
|
Colors.white, // 👈 sets dropdown background to white
|
||||||
|
),
|
||||||
|
showSearchBox: true,
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search Broker...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
), // 👈 Normal border
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
width: 1.5,
|
||||||
|
), // 👈 Focused border
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['name'].toString(),
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val != null) {
|
||||||
|
print("Selected ClaimsType : ${val['id']}");
|
||||||
|
print("Id: ${val['id']}");
|
||||||
|
selectedBroker = val['id'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildDocuments(BuildContext context) {
|
Widget buildDocuments(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('Proposal Documents ', style: _textStyle),
|
Text('Upload Policy PDF', style: _textStyle),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Column(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
children: [
|
||||||
ThemedUploadField(
|
ThemedUploadField(
|
||||||
hintText: selectedFileNames ?? "Upload Document",
|
hintText: selectedFileNames ?? "Upload Document",
|
||||||
|
txtheight: 40,
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
backgroundColor: Color(0xFFEDF6F5),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
// highlightColor: Color(0xFF50A398),
|
||||||
|
// backgroundColor: Color(0xFFEDF6F5),
|
||||||
onFileSelected: (fileName, file) {
|
onFileSelected: (fileName, file) {
|
||||||
print("Picked file: $fileName (${file.size} bytes)");
|
print("Picked file: $fileName (${file.size} bytes)");
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -722,47 +1080,40 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5),
|
// const SizedBox(height: 5),
|
||||||
|
//
|
||||||
if (docUploadedFileUrlFromApi != null)
|
// if (docUploadedFileUrlFromApi != null)
|
||||||
Container(
|
// Container(
|
||||||
// color: Colors.white,
|
// // color: Colors.white,
|
||||||
child: Row(
|
// child: Row(
|
||||||
children: [
|
// children: [
|
||||||
GestureDetector(
|
// GestureDetector(
|
||||||
onTap: () => apiService.downloadFile(
|
// onTap: () => apiService.downloadFile(
|
||||||
apiUrl:
|
// // apiUrl:
|
||||||
'api/quotation/downloadAdditionalUploadedFile?id=$selectedId',
|
// // 'api/quotation/downloadAdditionalUploadedFile?id=$selectedId',
|
||||||
apiId: selectedId,
|
// apiUrl:
|
||||||
localFile: docUploadedFile,
|
// 'api/policy/downloadPolicyFile?policy_id=$selectedId&file_type=policy_pdf',
|
||||||
fileName: selectedFileNames,
|
// apiId: selectedId,
|
||||||
),
|
// localFile: docUploadedFile,
|
||||||
child: Container(
|
// fileName: selectedFileNames,
|
||||||
padding: const EdgeInsets.all(5),
|
// ),
|
||||||
decoration: BoxDecoration(
|
// child: Container(
|
||||||
borderRadius: BorderRadius.circular(5),
|
// padding: const EdgeInsets.all(5),
|
||||||
color: Color(0xFF425B5B),
|
// decoration: BoxDecoration(
|
||||||
// color: Colors.green.shade300,
|
// borderRadius: BorderRadius.circular(5),
|
||||||
),
|
// color: Color(0xFF425B5B),
|
||||||
child: Row(
|
// // color: Colors.green.shade300,
|
||||||
children: const [
|
// ),
|
||||||
Text(
|
// child: Row(
|
||||||
"Download",
|
// children: const [
|
||||||
style: TextStyle(
|
// Icon(Icons.download, size: 13, color: Colors.white),
|
||||||
fontSize: 12,
|
// ],
|
||||||
fontWeight: FontWeight.w200,
|
// ),
|
||||||
color: Colors.white,
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ],
|
||||||
SizedBox(width: 5),
|
// ),
|
||||||
Icon(Icons.download, size: 13, color: Colors.white),
|
// ),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -772,7 +1123,8 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
|||||||
// ------------------- STyle ---------------------------------
|
// ------------------- STyle ---------------------------------
|
||||||
|
|
||||||
static final TextStyle _textStyle = TextStyle(
|
static final TextStyle _textStyle = TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.w600,
|
color: Color(0XFF334155),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,778 @@
|
|||||||
|
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/services.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() {
|
||||||
|
print('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'] = Env.App_Signature;
|
||||||
|
|
||||||
|
// 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 if (response.statusCode == 403) {
|
||||||
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
|
} 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']!,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||||
|
],
|
||||||
|
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),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||||
|
],
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -160,7 +160,6 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
"sgst": controllers["sgst"]?.text,
|
"sgst": controllers["sgst"]?.text,
|
||||||
"igst": controllers["igst"]?.text,
|
"igst": controllers["igst"]?.text,
|
||||||
"premium_amount": controllers["premiumTOT"]?.text,
|
"premium_amount": controllers["premiumTOT"]?.text,
|
||||||
|
|
||||||
"manager_id": managerId,
|
"manager_id": managerId,
|
||||||
// "policy_pdf_file_name": "policy_doc.pdf",
|
// "policy_pdf_file_name": "policy_doc.pdf",
|
||||||
// "policy_payment_receipt_file_name": "receipt_doc.pdf",
|
// "policy_payment_receipt_file_name": "receipt_doc.pdf",
|
||||||
@ -378,10 +377,11 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
quotationAcceptedData = acceptedItem;
|
quotationAcceptedData = acceptedItem;
|
||||||
print('AcceptedData - $quotationAcceptedData');
|
print('AcceptedData YYY - $quotationAcceptedData');
|
||||||
|
|
||||||
if (quotationAcceptedData != null) {
|
if (quotationAcceptedData != null) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
print('AcceptedData YYY2');
|
||||||
setState(() {
|
setState(() {
|
||||||
controllers["insurer"]?.text = quotationAcceptedData?['insurer_name'];
|
controllers["insurer"]?.text = quotationAcceptedData?['insurer_name'];
|
||||||
acceptedQuotationId = quotationAcceptedData?['id']?.toString() ?? '';
|
acceptedQuotationId = quotationAcceptedData?['id']?.toString() ?? '';
|
||||||
@ -392,6 +392,10 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
quotationAcceptedData?['premium_amount']?.toString() ?? '';
|
quotationAcceptedData?['premium_amount']?.toString() ?? '';
|
||||||
controllers["planType"]?.text =
|
controllers["planType"]?.text =
|
||||||
quotationAcceptedData?['insurance_plan_type']?.toString() ?? '';
|
quotationAcceptedData?['insurance_plan_type']?.toString() ?? '';
|
||||||
|
controllers["policyPaymentMode"]?.text =
|
||||||
|
quotationAcceptedData?['payment_mode_value']?.toString() ?? '';
|
||||||
|
selectedBroker = quotationAcceptedData?['broker_id'] ?? '';
|
||||||
|
selectedBrokerName = quotationAcceptedData?['broker_name'] ?? '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -435,6 +439,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
policyData['premium_amount']?.toString() ?? '';
|
policyData['premium_amount']?.toString() ?? '';
|
||||||
|
|
||||||
selectedBroker = policyData['broker_id'] ?? '';
|
selectedBroker = policyData['broker_id'] ?? '';
|
||||||
|
selectedBrokerName = policyData['broker_name'] ?? '';
|
||||||
// RC FILE
|
// RC FILE
|
||||||
String? rcPath = policyData["policy_pdf_file_name"];
|
String? rcPath = policyData["policy_pdf_file_name"];
|
||||||
if (rcPath != null && rcPath.isNotEmpty) {
|
if (rcPath != null && rcPath.isNotEmpty) {
|
||||||
@ -485,6 +490,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
policyData['policy_number']?.toString() ?? '';
|
policyData['policy_number']?.toString() ?? '';
|
||||||
controllers["policyPaymentMode"]?.text =
|
controllers["policyPaymentMode"]?.text =
|
||||||
policyData['payment_mode']?.toString() ?? '';
|
policyData['payment_mode']?.toString() ?? '';
|
||||||
|
|
||||||
controllers["issueDate"]?.text =
|
controllers["issueDate"]?.text =
|
||||||
_formatDate(policyData['issued_date']!.toString()) ?? '';
|
_formatDate(policyData['issued_date']!.toString()) ?? '';
|
||||||
controllers["startDate"]?.text =
|
controllers["startDate"]?.text =
|
||||||
@ -531,15 +537,16 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
|
|
||||||
final bool isUpdating = choosedPolcyId != null;
|
final bool isUpdating = choosedPolcyId != null;
|
||||||
|
|
||||||
if (!isUpdating && selectedBrokerName == 'Nhance') {
|
// if (!isUpdating && selectedBrokerName == 'Nhance') {
|
||||||
// if (!isUpdating && enqBrokerName == 'Nhance') {
|
// // if (!isUpdating && enqBrokerName == 'Nhance') {
|
||||||
ToastHelper.showErrorToast(context, "Policy PDF is required");
|
// ToastHelper.showErrorToast(context, "Policy PDF is required");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
// (enqBrokerName != 'Nhance')
|
// (enqBrokerName != 'Nhance')
|
||||||
// File validations
|
// File validations
|
||||||
if ((selectedBrokerName != 'Nhance') &&
|
if (
|
||||||
(docPDFUploadedFile == null || docPDFUploadedFile?.bytes == null) &&
|
// (selectedBrokerName != 'Nhance') &&
|
||||||
|
(docPDFUploadedFile == null || docPDFUploadedFile?.bytes == null) &&
|
||||||
(docUploadedPDFFileUrlFromApi == null ||
|
(docUploadedPDFFileUrlFromApi == null ||
|
||||||
docUploadedPDFFileUrlFromApi!.isEmpty)) {
|
docUploadedPDFFileUrlFromApi!.isEmpty)) {
|
||||||
ToastHelper.showErrorToast(context, "Policy PDF is required");
|
ToastHelper.showErrorToast(context, "Policy PDF is required");
|
||||||
@ -849,8 +856,11 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
// color: Colors.green,
|
// color: Colors.green,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: Colors.orange.shade50,
|
// color: Colors.orange.shade50,
|
||||||
color: Color(0xffEDF6F5),
|
// color: Color(0xffEDF6F5),
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
border: Border(
|
||||||
|
top: BorderSide(color: Colors.blueGrey.shade200, width: 0.2),
|
||||||
|
),
|
||||||
|
// borderRadius: BorderRadius.circular(10.0),
|
||||||
),
|
),
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: MediaQuery.of(context).size.height * 0.58,
|
height: MediaQuery.of(context).size.height * 0.58,
|
||||||
@ -1064,13 +1074,14 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
Paymentmode(context),
|
||||||
|
SizedBox(width: 20),
|
||||||
buildBroker(context),
|
buildBroker(context),
|
||||||
if (selectedBrokerName != null) ...[
|
if (selectedBrokerName != null) ...[
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
buildUploadPolicyPdf(context),
|
buildUploadPolicyPdf(context),
|
||||||
SizedBox(width: 20),
|
|
||||||
|
|
||||||
Paymentmode(context),
|
// SizedBox(width: 20),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -1386,6 +1397,8 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['policyNumber']!,
|
controller: controllers['policyNumber']!,
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
validator: (value) => Validators.requiredField(value, "policyNumber"),
|
validator: (value) => Validators.requiredField(value, "policyNumber"),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z 0-9]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z 0-9]')),
|
||||||
@ -1406,7 +1419,14 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text('Broker *', style: _textStyle),
|
Text('Broker *', style: _textStyle),
|
||||||
SizedBox(width: 15),
|
SizedBox(width: 10),
|
||||||
|
// SizedBox(
|
||||||
|
// width: MediaQuery.of(context).size.width * 0.095,
|
||||||
|
// child: Text(
|
||||||
|
// '$selectedBrokerName',
|
||||||
|
// style: GoogleFonts.inter(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 30,
|
height: 30,
|
||||||
width: MediaQuery.of(context).size.width * 0.1,
|
width: MediaQuery.of(context).size.width * 0.1,
|
||||||
@ -1456,20 +1476,21 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
label: "Select Broker",
|
label: "Select Broker",
|
||||||
).copyWith(
|
).copyWith(
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor:
|
fillColor: Color(0xffEDF6F5),
|
||||||
Colors.white, // 👈 makes the dropdown input white
|
// fillColor:
|
||||||
|
// Colors.white, // 👈 makes the dropdown input white
|
||||||
isDense: true,
|
isDense: true,
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
borderSide: const BorderSide(
|
borderSide: const BorderSide(
|
||||||
color: Colors.black,
|
color: Color(0xffEDF6F5),
|
||||||
width: 0.1,
|
width: 0.1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
borderSide: const BorderSide(
|
borderSide: const BorderSide(
|
||||||
color: Colors.black,
|
color: Color(0xffEDF6F5),
|
||||||
width: 0.1,
|
width: 0.1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1548,23 +1569,34 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
|
|
||||||
Widget Paymentmode(BuildContext context) {
|
Widget Paymentmode(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text('Payment Mode *', style: _textStyle),
|
Text('Payment Mode *', style: _textStyle),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 15),
|
||||||
ThemedFormField(
|
SizedBox(
|
||||||
controller: controllers['policyPaymentMode']!,
|
width: MediaQuery.of(context).size.width * 0.075,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
child: Text(
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
controllers['policyPaymentMode']?.text ?? 'Online',
|
||||||
hintText: 'Online / Cash',
|
style: GoogleFonts.inter(fontSize: 12),
|
||||||
// borderColor: Color(0xffEDF6F5),
|
),
|
||||||
validator: (value) =>
|
|
||||||
Validators.requiredField(value, "policyPaymentMode"),
|
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
|
||||||
? null
|
|
||||||
: MediaQuery.of(context).size.width * 0.07,
|
|
||||||
),
|
),
|
||||||
|
// ThemedFormField(
|
||||||
|
// controller: controllers['policyPaymentMode']!,
|
||||||
|
// // borderColor: Color(0xFFE2E8F0),
|
||||||
|
// borderColor: Colors.white,
|
||||||
|
// highlightColor: Colors.white,
|
||||||
|
// // highlightColor: Color(0xFF50A398),
|
||||||
|
// errorBorderColor: Color(0xffEDF6F5),
|
||||||
|
// hintText: 'Online / Cash',
|
||||||
|
// // borderColor: Color(0xffEDF6F5),
|
||||||
|
// readOnly: true,
|
||||||
|
// validator: (value) =>
|
||||||
|
// Validators.requiredField(value, "policyPaymentMode"),
|
||||||
|
// txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
|
// ? null
|
||||||
|
// : MediaQuery.of(context).size.width * 0.07,
|
||||||
|
// ),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1733,7 +1765,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width * 0.12,
|
width: MediaQuery.of(context).size.width * 0.15,
|
||||||
child: Text('Upload Policy PDF * ', style: _textStyle),
|
child: Text('Upload Policy PDF * ', style: _textStyle),
|
||||||
),
|
),
|
||||||
// const SizedBox(height: 10),
|
// const SizedBox(height: 10),
|
||||||
@ -1745,13 +1777,17 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
ThemedUploadField(
|
ThemedUploadField(
|
||||||
hintText: selectedPDFFileNames ?? "Upload Document",
|
hintText: selectedPDFFileNames ?? "Upload Document",
|
||||||
allowedExtensions: ['pdf'],
|
allowedExtensions: ['pdf'],
|
||||||
|
// backgroundColor: Colors.white,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
backgroundColor: Color(0xffEDF6F5),
|
||||||
|
txtheight: 35,
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: (docUploadedPDFFileUrlFromApi != null)
|
: (docUploadedPDFFileUrlFromApi != null)
|
||||||
? MediaQuery.of(context).size.width * 0.135
|
? MediaQuery.of(context).size.width * 0.117
|
||||||
|
// ? MediaQuery.of(context).size.width * 0.135
|
||||||
// ? MediaQuery.of(context).size.width * 0.12
|
// ? MediaQuery.of(context).size.width * 0.12
|
||||||
: MediaQuery.of(context).size.width * 0.15,
|
: MediaQuery.of(context).size.width * 0.14,
|
||||||
|
// : MediaQuery.of(context).size.width * 0.15,
|
||||||
// backgroundColor: Color(0xFFEDF6F5),
|
// backgroundColor: Color(0xFFEDF6F5),
|
||||||
onFileSelected: (fileName, file) async {
|
onFileSelected: (fileName, file) async {
|
||||||
print("Picked file: $fileName (${file.size} bytes)");
|
print("Picked file: $fileName (${file.size} bytes)");
|
||||||
@ -1775,9 +1811,9 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
docPDFUploadedFile = file;
|
docPDFUploadedFile = file;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selectedBrokerName == 'Nhance') {
|
// if (selectedBrokerName == 'Nhance') {
|
||||||
handleUploadPolicy();
|
// handleUploadPolicy();
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -1962,7 +1998,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['tp']!,
|
controller: controllers['tp']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
validator: (value) => Validators.requiredField(value, "Third Party"),
|
validator: (value) => Validators.requiredField(value, "Third Party"),
|
||||||
@ -1994,7 +2030,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['od']!,
|
controller: controllers['od']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
validator: (value) => Validators.requiredField(value, "OwnDamage"),
|
validator: (value) => Validators.requiredField(value, "OwnDamage"),
|
||||||
@ -2022,7 +2058,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['pa']!,
|
controller: controllers['pa']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
onChanged: (value) => calculateAmount(),
|
onChanged: (value) => calculateAmount(),
|
||||||
@ -2051,7 +2087,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['cgst']!,
|
controller: controllers['cgst']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
validator: (value) => Validators.requiredField(value, "CGST"),
|
validator: (value) => Validators.requiredField(value, "CGST"),
|
||||||
@ -2078,7 +2114,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['sgst']!,
|
controller: controllers['sgst']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
@ -2105,7 +2141,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['igst']!,
|
controller: controllers['igst']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
validator: (value) => Validators.requiredField(value, "IGST"),
|
validator: (value) => Validators.requiredField(value, "IGST"),
|
||||||
@ -2132,7 +2168,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['premiumTOT']!,
|
controller: controllers['premiumTOT']!,
|
||||||
backgroundColor: Color(0xffEDF6F5),
|
// backgroundColor: Color(0xffEDF6F5),
|
||||||
errorBorderColor: Color(0xffEDF6F5),
|
errorBorderColor: Color(0xffEDF6F5),
|
||||||
hintText: '0',
|
hintText: '0',
|
||||||
validator: (value) => Validators.requiredField(value, "premium"),
|
validator: (value) => Validators.requiredField(value, "premium"),
|
||||||
@ -2381,9 +2417,10 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const _textStyle = TextStyle(
|
static final _textStyle = GoogleFonts.inter(
|
||||||
fontSize: 12,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.w600,
|
color: Color(0XFF334155),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
);
|
);
|
||||||
static const _textStrongStyle = TextStyle(
|
static const _textStrongStyle = TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|||||||
@ -215,11 +215,32 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
|||||||
originalData = getQuotationData;
|
originalData = getQuotationData;
|
||||||
filteredData = List.from(originalData);
|
filteredData = List.from(originalData);
|
||||||
|
|
||||||
blockKey = getQuotationData.any(
|
// dynamic data = getQuotationData
|
||||||
(item) => item['status'] == 'Accepted',
|
// .where((item) => item['status'] == 'Accepted')
|
||||||
);
|
// .toList();
|
||||||
|
// blockKey = getQuotationData.any(
|
||||||
|
// (item) => item['status'] == 'Accepted',
|
||||||
|
// );
|
||||||
|
|
||||||
|
final acceptedList = getQuotationData
|
||||||
|
.where((item) => item['status'] == 'Accepted')
|
||||||
|
.toList();
|
||||||
|
|
||||||
print('blockKey- $blockKey');
|
print('blockKey- $blockKey');
|
||||||
// print('originalData - $getClaimPolicies');
|
print('originalDataData - $acceptedList');
|
||||||
|
|
||||||
|
final data = acceptedList.isNotEmpty ? acceptedList.first : null;
|
||||||
|
|
||||||
|
final id = selectedQuotationFrmListData?['id'];
|
||||||
|
|
||||||
|
handleEdit(id, data);
|
||||||
|
|
||||||
|
// selectedQuotationFrmListData = data;
|
||||||
|
|
||||||
|
print('originalDatasdata- $data');
|
||||||
|
print(
|
||||||
|
'originalDataselectedQuotationFrmListData - $selectedQuotationFrmListData',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
getQuotationData = [];
|
getQuotationData = [];
|
||||||
@ -265,51 +286,35 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
|||||||
return Container(
|
return Container(
|
||||||
height: MediaQuery.of(context).size.height,
|
height: MediaQuery.of(context).size.height,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(color: Colors.blueGrey.shade200, width: 0.2),
|
||||||
|
),
|
||||||
|
),
|
||||||
// child: SingleChildScrollView(
|
// child: SingleChildScrollView(
|
||||||
// scrollDirection: Axis.vertical,
|
// scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (!blockKey) ...[
|
// if (!blockKey) ...[
|
||||||
// if (!blockKey && roleId != 'manager') ...[
|
// if (!blockKey && roleId != 'manager') ...[
|
||||||
CreateQuotationForm(
|
CreateProposalForm(
|
||||||
key: ValueKey(selectedQuotationFrmListId ?? "new"),
|
key: ValueKey(selectedQuotationFrmListId ?? "new"),
|
||||||
userId: userId,
|
userId: userId,
|
||||||
selectedQuotationFrmListdata: selectedQuotationFrmListData,
|
selectedQuotationFrmListdata: selectedQuotationFrmListData,
|
||||||
selectedQuotationFrmListId: selectedQuotationFrmListId,
|
selectedQuotationFrmListId: selectedQuotationFrmListId,
|
||||||
managerId: managerId,
|
managerId: managerId,
|
||||||
selectedInsurdId: selectedInsurdId,
|
selectedInsurdId: selectedInsurdId,
|
||||||
selectedEnquiryId: selectedEnquiryId,
|
selectedEnquiryId: selectedEnquiryId,
|
||||||
onSubmit: (value) {
|
onSubmit: (value) {
|
||||||
debugPrint("New Endorsement: $value");
|
debugPrint("New Endorsement: $value");
|
||||||
if (value == 'Success') {
|
if (value == 'Success') {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
],
|
|
||||||
|
|
||||||
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.4
|
|
||||||
: MediaQuery.of(context).size.height * 0.55,
|
|
||||||
padding: EdgeInsets.all(12.0),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// Text('datta')
|
|
||||||
_buildDataTable(context),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
// ],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// ),
|
// ),
|
||||||
@ -388,299 +393,6 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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('Vehicle 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(
|
static final _dataBold = GoogleFonts.inter(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,733 @@
|
|||||||
|
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:nhance_partner/presentation/providers/userRoleProvider.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';
|
||||||
|
import 'createQuotationOld.dart';
|
||||||
|
|
||||||
|
class PropoalStaffTab extends ConsumerStatefulWidget {
|
||||||
|
String? id;
|
||||||
|
List<Map<String, dynamic>>? data;
|
||||||
|
final Future<void> Function()? onRefresh;
|
||||||
|
|
||||||
|
PropoalStaffTab({super.key, this.data, this.id, this.onRefresh});
|
||||||
|
@override
|
||||||
|
ConsumerState<PropoalStaffTab> createState() => PropoalStaffTabState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PropoalStaffTabState extends ConsumerState<PropoalStaffTab> {
|
||||||
|
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 roleId;
|
||||||
|
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
|
||||||
|
roleId = ref.read(userRoleProvider); // ✅ use read
|
||||||
|
|
||||||
|
print('QmanagerId - $managerId');
|
||||||
|
print('QuserId - $userId');
|
||||||
|
print('QroleId - $roleId');
|
||||||
|
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');
|
||||||
|
if (!mounted) return;
|
||||||
|
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--");
|
||||||
|
setState(() {
|
||||||
|
selectedQuotationFrmListId = null;
|
||||||
|
selectedQuotationFrmListData = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (enqQuotation != null) {
|
||||||
|
_loadData(enqQuotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getQuotationList(enqQuotation) async {
|
||||||
|
print('getClaimList called enqQuotation- $enqQuotation');
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.findEnqQuotePolicyView(enqQuotation);
|
||||||
|
if (!mounted) return;
|
||||||
|
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 {
|
||||||
|
if (!mounted) return;
|
||||||
|
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) ...[
|
||||||
|
// if (!blockKey && roleId != 'manager') ...[
|
||||||
|
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),
|
||||||
|
],
|
||||||
|
|
||||||
|
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.4
|
||||||
|
: MediaQuery.of(context).size.height * 0.55,
|
||||||
|
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('Vehicle 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: "Vehicle 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('Vehicle 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:nhance_partner/presentation/providers/userRoleProvider.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/policyTab.dart';
|
||||||
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab.dart';
|
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab.dart';
|
||||||
|
import 'package:nhance_partner/presentation/screens/staff/Enquiry/tabs/quotationTab_old.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import '../../../../../core/routing/routes.dart';
|
import '../../../../../core/routing/routes.dart';
|
||||||
@ -62,8 +63,9 @@ class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
|
|||||||
} else {
|
} else {
|
||||||
setState(() => isLoading = false);
|
setState(() => isLoading = false);
|
||||||
tabs = [
|
tabs = [
|
||||||
|
// TabItem("Proposal", PropoalStaffTab()),
|
||||||
TabItem("Proposal", QuotationStaffTab()),
|
TabItem("Proposal", QuotationStaffTab()),
|
||||||
// TabItem("Policy", PolicyStaffTab()),
|
TabItem("Policy", PolicyStaffTab()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -103,19 +105,20 @@ class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
|
|||||||
selectedVehicleType = data['enquiry']?['vehicle_type'];
|
selectedVehicleType = data['enquiry']?['vehicle_type'];
|
||||||
selectedBrokerName = data['enquiry']?['broker_name'];
|
selectedBrokerName = data['enquiry']?['broker_name'];
|
||||||
selectedAgentName = data['enquiry']?['agent_name'];
|
selectedAgentName = data['enquiry']?['agent_name'];
|
||||||
selectedInsurer = data['enquiry']?['insurer_short_name'];
|
selectedInsurer = data['enquiry']?['short_name'];
|
||||||
print(
|
print(
|
||||||
'loadQuotationTab 4s -$selectedBrokerName $selectedInsuredName - $selectedVehicleNum - $selectedVehicleType',
|
'loadQuotationTab 4s -$selectedBrokerName $selectedInsuredName - $selectedVehicleNum - $selectedVehicleType',
|
||||||
);
|
);
|
||||||
|
|
||||||
tabs = [
|
tabs = [
|
||||||
|
// TabItem("Proposal", PropoalStaffTab()),
|
||||||
TabItem("Proposal", QuotationStaffTab()),
|
TabItem("Proposal", QuotationStaffTab()),
|
||||||
// TabItem("Policy", PolicyStaffTab()),
|
TabItem("Policy", PolicyStaffTab()),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (widget.showKey == "Policy") {
|
// if (widget.showKey == "Policy") {
|
||||||
tabs.add(TabItem("Policy", PolicyStaffTab()));
|
// tabs.add(TabItem("Policy", PolicyStaffTab()));
|
||||||
}
|
// }
|
||||||
|
|
||||||
// if (tabIndex != null) {
|
// if (tabIndex != null) {
|
||||||
// selectedIndex = tabIndex;
|
// selectedIndex = tabIndex;
|
||||||
@ -246,12 +249,13 @@ class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
children: List.generate(tabs.length, (index) {
|
children: List.generate(tabs.length, (index) {
|
||||||
final isSelected = selectedIndex == index;
|
final isSelected = selectedIndex == index;
|
||||||
|
|
||||||
return Padding(
|
return Container(
|
||||||
|
// decoration: BoxDecoration(border: Border(bottom: BorderSide())),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 1.0),
|
padding: const EdgeInsets.symmetric(horizontal: 1.0),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => setState(() => selectedIndex = index),
|
onTap: () => setState(() => selectedIndex = index),
|
||||||
@ -259,18 +263,21 @@ class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// ---- TEXT ----
|
// ---- TEXT ----
|
||||||
Text(
|
SizedBox(
|
||||||
tabs[index].title,
|
width: 80,
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
fontSize: 12,
|
tabs[index].title,
|
||||||
fontWeight: isSelected
|
style: GoogleFonts.poppins(
|
||||||
? FontWeight.w600
|
fontSize: 13,
|
||||||
: FontWeight.w400,
|
fontWeight: isSelected
|
||||||
color: isSelected
|
? FontWeight.w600
|
||||||
? const Color(
|
: FontWeight.w600,
|
||||||
0xFF2E7D6E,
|
color: isSelected
|
||||||
) // Purple-ish like screenshot
|
? const Color(
|
||||||
: Colors.black87,
|
0xFF2E7D6E,
|
||||||
|
) // Purple-ish like screenshot
|
||||||
|
: Colors.black87,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -295,6 +302,7 @@ class TabEnquiryStaffListState extends ConsumerState<TabEnquiryStaffList> {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
||||||
Expanded(child: tabs[selectedIndex].widget),
|
Expanded(child: tabs[selectedIndex].widget),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -18,6 +18,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
this.isObscurable = false,
|
this.isObscurable = false,
|
||||||
this.hintColor,
|
this.hintColor,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
|
this.highlightColor,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.errorBorderColor,
|
this.errorBorderColor,
|
||||||
this.errorTextColor,
|
this.errorTextColor,
|
||||||
@ -39,6 +40,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
final double? enableBorderWidth;
|
final double? enableBorderWidth;
|
||||||
final String? hintText;
|
final String? hintText;
|
||||||
final Color? textColr;
|
final Color? textColr;
|
||||||
|
final Color? highlightColor;
|
||||||
|
|
||||||
final String? imgPath;
|
final String? imgPath;
|
||||||
final String? Function(String? text)? validator;
|
final String? Function(String? text)? validator;
|
||||||
@ -133,7 +135,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
: OutlineInputBorder(
|
: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? Color(0xFF50A398),
|
color: highlightColor ?? borderColor ?? Color(0xFF50A398),
|
||||||
width: 2,
|
width: 2,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -169,7 +171,6 @@ class ThemedFormField extends HookWidget {
|
|||||||
);
|
);
|
||||||
return Container(
|
return Container(
|
||||||
width: txtwidth ?? MediaQuery.of(context).size.width,
|
width: txtwidth ?? MediaQuery.of(context).size.width,
|
||||||
|
|
||||||
height: txtheight ?? null,
|
height: txtheight ?? null,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: boxDecoration,
|
decoration: boxDecoration,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user