pos policy_validation invoice
This commit is contained in:
parent
b9f2032d3b
commit
bd4465caa5
File diff suppressed because one or more lines are too long
@ -18,6 +18,7 @@ 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';
|
||||||
import '../../presentation/screens/UserManagement/Agent/agentList.dart';
|
import '../../presentation/screens/UserManagement/Agent/agentList.dart';
|
||||||
|
import '../../presentation/screens/UserManagement/POS/pos_list.dart';
|
||||||
import '../../presentation/screens/UserManagement/Profile/profile_mobile.dart';
|
import '../../presentation/screens/UserManagement/Profile/profile_mobile.dart';
|
||||||
import '../../presentation/screens/UserManagement/SalesExecutive/salesExecutive.dart';
|
import '../../presentation/screens/UserManagement/SalesExecutive/salesExecutive.dart';
|
||||||
import '../../presentation/screens/UserManagement/SalesExecutive/salesExecutiveList.dart';
|
import '../../presentation/screens/UserManagement/SalesExecutive/salesExecutiveList.dart';
|
||||||
@ -85,57 +86,61 @@ final GoRouter appRouter = GoRouter(
|
|||||||
builder: (context, state) => const AgentList(),
|
builder: (context, state) => const AgentList(),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
// GoRoute(
|
||||||
path: '/agent/:id',
|
// path: '/agent/:id',
|
||||||
builder: (context, state) {
|
// builder: (context, state) {
|
||||||
final id = state.pathParameters['id']!;
|
// final id = state.pathParameters['id']!;
|
||||||
|
//
|
||||||
// if "create", open empty form
|
// // if "create", open empty form
|
||||||
if (id == 'create') {
|
// if (id == 'create') {
|
||||||
return const Agent(); // create mode
|
// return const Agent(); // create mode
|
||||||
} else {
|
// } else {
|
||||||
return Agent(id: id); // update mode
|
// return Agent(id: id); // update mode
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: AppRoutes.staffLst,
|
path: AppRoutes.staffLst,
|
||||||
// builder: (context, state) => const Agent(),
|
// builder: (context, state) => const Agent(),
|
||||||
builder: (context, state) => const StaffList(),
|
builder: (context, state) => const StaffList(),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// GoRoute(
|
||||||
|
// path: '/staff/:id',
|
||||||
|
// builder: (context, state) {
|
||||||
|
// final id = state.pathParameters['id']!;
|
||||||
|
// // if "create", open empty form
|
||||||
|
// if (id == 'create') {
|
||||||
|
// return const Staff(); // create mode
|
||||||
|
// } else {
|
||||||
|
// return Staff(id: id); // update mode
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/staff/:id',
|
path: AppRoutes.posLst,
|
||||||
builder: (context, state) {
|
// builder: (context, state) => const Agent(),
|
||||||
final id = state.pathParameters['id']!;
|
builder: (context, state) => const PosList(),
|
||||||
// if "create", open empty form
|
|
||||||
if (id == 'create') {
|
|
||||||
return const Staff(); // create mode
|
|
||||||
} else {
|
|
||||||
return Staff(id: id); // update mode
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: AppRoutes.salesExecutiveLst,
|
path: AppRoutes.salesExecutiveLst,
|
||||||
// builder: (context, state) => const Agent(),
|
// builder: (context, state) => const Agent(),
|
||||||
builder: (context, state) => const SalesExecutiveList(),
|
builder: (context, state) => const SalesExecutiveList(),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
// GoRoute(
|
||||||
path: '/salesExecutive/:id',
|
// path: '/salesExecutive/:id',
|
||||||
builder: (context, state) {
|
// builder: (context, state) {
|
||||||
final id = state.pathParameters['id']!;
|
// final id = state.pathParameters['id']!;
|
||||||
// if "create", open empty form
|
// // if "create", open empty form
|
||||||
if (id == 'create') {
|
// if (id == 'create') {
|
||||||
return const SalesExecutive(); // create mode
|
// return const SalesExecutive(); // create mode
|
||||||
} else {
|
// } else {
|
||||||
return SalesExecutive(id: id); // update mode
|
// return SalesExecutive(id: id); // update mode
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: AppRoutes.enquiryLst,
|
path: AppRoutes.enquiryLst,
|
||||||
builder: (context, state) => const EnquiryList(),
|
builder: (context, state) => const EnquiryList(),
|
||||||
@ -194,8 +199,10 @@ final GoRouter appRouter = GoRouter(
|
|||||||
|
|
||||||
return CustomTransitionPage(
|
return CustomTransitionPage(
|
||||||
key: state.pageKey,
|
key: state.pageKey,
|
||||||
opaque: true, // ⭐ required for open animation
|
opaque: true, // ⭐ required for open animation
|
||||||
barrierColor: Colors.black.withOpacity(0.3), // optional dim background
|
barrierColor: Colors.black.withOpacity(
|
||||||
|
0.3,
|
||||||
|
), // optional dim background
|
||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
|
|
||||||
transitionDuration: const Duration(milliseconds: 1000),
|
transitionDuration: const Duration(milliseconds: 1000),
|
||||||
@ -210,7 +217,7 @@ final GoRouter appRouter = GoRouter(
|
|||||||
|
|
||||||
return SlideTransition(
|
return SlideTransition(
|
||||||
position: Tween<Offset>(
|
position: Tween<Offset>(
|
||||||
begin: const Offset(0, 1), // slide from bottom
|
begin: const Offset(0, 1), // slide from bottom
|
||||||
end: Offset.zero,
|
end: Offset.zero,
|
||||||
).animate(curved),
|
).animate(curved),
|
||||||
child: child,
|
child: child,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class AppRoutes {
|
|||||||
static const staff = '/staff/:id';
|
static const staff = '/staff/:id';
|
||||||
static const String salesExecutiveLst = '/salesExecutiveLst';
|
static const String salesExecutiveLst = '/salesExecutiveLst';
|
||||||
static const salesExecutive = '/salesExecutive/:id';
|
static const salesExecutive = '/salesExecutive/:id';
|
||||||
|
static const String posLst = '/posLst';
|
||||||
static const String enquiryLst = '/enquiryLst';
|
static const String enquiryLst = '/enquiryLst';
|
||||||
static const String enquiryForStaff = '/enquiryForStaff';
|
static const String enquiryForStaff = '/enquiryForStaff';
|
||||||
static const String tabEnquiry = '/tabEnquiry';
|
static const String tabEnquiry = '/tabEnquiry';
|
||||||
|
|||||||
@ -307,6 +307,8 @@ class ApiService {
|
|||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||||
|
// final url = Uri.parse('${Env.apiUrl}$path');
|
||||||
|
// final url = Uri.parse('${Env.apiUrl}$path');
|
||||||
print('getPdfDownload 2 - $url');
|
print('getPdfDownload 2 - $url');
|
||||||
await _initializeToken();
|
await _initializeToken();
|
||||||
|
|
||||||
@ -387,6 +389,183 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> generateChartExcel(
|
||||||
|
// BuildContext context,
|
||||||
|
String path,
|
||||||
|
String id,
|
||||||
|
String month,
|
||||||
|
dynamic managerId,
|
||||||
|
) async {
|
||||||
|
print('getPdfDownload 1 - $path');
|
||||||
|
|
||||||
|
dynamic pathVal;
|
||||||
|
if (path == 'Insurer') {
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadInsurerPoliciesExcel?manager_id=$managerId&month=$month&insurer_id=$id';
|
||||||
|
} else if (path == 'Broker') {
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadBrokerPoliciesExcel?manager_id=$managerId&month=$month&broker_id=$id';
|
||||||
|
} else if (path == 'Product') {
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadProductPoliciesExcel?manager_id=$managerId&month=$month&vehicle_type=$id';
|
||||||
|
} else if (path == 'PerformingTop50') {
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id';
|
||||||
|
} else if (path == 'NonPerformingBelow50K') {
|
||||||
|
pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId';
|
||||||
|
} else {
|
||||||
|
//NoBusiness
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadAgentsWithoutPoliciesExcel?manager_id=$managerId';
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse('${Env.apiUrl}$pathVal');
|
||||||
|
// final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||||
|
print('getPdfDownload 2 - $url');
|
||||||
|
await _initializeToken();
|
||||||
|
|
||||||
|
if (_token == null) throw Exception('Token not found. Please log in.');
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token',
|
||||||
|
// 'App-Signature': Env.App_Signature,
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await _makeGethttpRequest(url, headers);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final contentType = response.headers['content-type'] ?? '';
|
||||||
|
if (contentType.contains('application/json')) {
|
||||||
|
final jsonResponse = jsonDecode(response.body);
|
||||||
|
if (jsonResponse['code'] == 404 || jsonResponse['code'] == 500) {
|
||||||
|
ToastHelper.show('File Not Found', Colors.red);
|
||||||
|
} else {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
final blob = html.Blob([response.bodyBytes]);
|
||||||
|
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
|
||||||
|
print('getPdfDownload $blobUrl');
|
||||||
|
final contentDisp = response.headers['content-disposition'];
|
||||||
|
print('getPdfDownloadcontentDisp $contentDisp');
|
||||||
|
|
||||||
|
String fileName = extractFileName(contentDisp, path.split('/').last);
|
||||||
|
print('Resolved fileName: $fileName');
|
||||||
|
final anchor = html.AnchorElement(href: blobUrl)
|
||||||
|
..setAttribute('download', fileName)
|
||||||
|
..click();
|
||||||
|
|
||||||
|
html.Url.revokeObjectUrl(blobUrl);
|
||||||
|
}
|
||||||
|
} else if (response.statusCode == 404) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text('File not found.'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('OK'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
await clearLocalStorageAndRedirect();
|
||||||
|
} else if (response.statusCode == 500) {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
} else if (response.statusCode == 302) {
|
||||||
|
print('getPdfDownload 3-PP-302');
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
} else {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
throw Exception('Failed to download file');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> generatePerformanceDashboardExcel(
|
||||||
|
// BuildContext context,
|
||||||
|
String path,
|
||||||
|
String id,
|
||||||
|
String salesId,
|
||||||
|
String month,
|
||||||
|
dynamic managerId,
|
||||||
|
) async {
|
||||||
|
print('getPdfDownload 1 - $path');
|
||||||
|
|
||||||
|
dynamic pathVal;
|
||||||
|
|
||||||
|
pathVal =
|
||||||
|
'dashboard/downloadStaffAndProductPoliciesExcel?manager_id=$managerId&month=$month&sales_executive_id=$salesId&vehicle_type=$id';
|
||||||
|
|
||||||
|
final url = Uri.parse('${Env.apiUrl}$pathVal');
|
||||||
|
// final url = Uri.parse('https://venbait.in/nhance/partner/dev/$path');
|
||||||
|
print('getPdfDownload 2 - $url');
|
||||||
|
await _initializeToken();
|
||||||
|
|
||||||
|
if (_token == null) throw Exception('Token not found. Please log in.');
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token',
|
||||||
|
// 'App-Signature': Env.App_Signature,
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await _makeGethttpRequest(url, headers);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final contentType = response.headers['content-type'] ?? '';
|
||||||
|
if (contentType.contains('application/json')) {
|
||||||
|
final jsonResponse = jsonDecode(response.body);
|
||||||
|
if (jsonResponse['code'] == 404 || jsonResponse['code'] == 500) {
|
||||||
|
ToastHelper.show('File Not Found', Colors.red);
|
||||||
|
} else {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
final blob = html.Blob([response.bodyBytes]);
|
||||||
|
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
|
||||||
|
print('getPdfDownload $blobUrl');
|
||||||
|
final contentDisp = response.headers['content-disposition'];
|
||||||
|
print('getPdfDownloadcontentDisp $contentDisp');
|
||||||
|
|
||||||
|
String fileName = extractFileName(contentDisp, path.split('/').last);
|
||||||
|
print('Resolved fileName: $fileName');
|
||||||
|
final anchor = html.AnchorElement(href: blobUrl)
|
||||||
|
..setAttribute('download', fileName)
|
||||||
|
..click();
|
||||||
|
|
||||||
|
html.Url.revokeObjectUrl(blobUrl);
|
||||||
|
}
|
||||||
|
} else if (response.statusCode == 404) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text('File not found.'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('OK'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (response.statusCode == 403) {
|
||||||
|
await clearLocalStorageAndRedirect();
|
||||||
|
} else if (response.statusCode == 500) {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
} else if (response.statusCode == 302) {
|
||||||
|
print('getPdfDownload 3-PP-302');
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
} else {
|
||||||
|
ToastHelper.show('No File Found', Colors.red);
|
||||||
|
throw Exception('Failed to download file');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> downloadFile({
|
Future<void> downloadFile({
|
||||||
required String? apiUrl,
|
required String? apiUrl,
|
||||||
required PlatformFile? localFile,
|
required PlatformFile? localFile,
|
||||||
@ -754,7 +933,9 @@ class ApiService {
|
|||||||
} else if (role == 'Accounts') {
|
} else if (role == 'Accounts') {
|
||||||
print('manager');
|
print('manager');
|
||||||
// url = Uri.parse('${Env.apiUrl}staff/staffList');
|
// url = Uri.parse('${Env.apiUrl}staff/staffList');
|
||||||
url = Uri.parse('${Env.apiUrl}staff/staffList?manager_id=${managerId}');
|
url = Uri.parse(
|
||||||
|
'${Env.apiUrl}salesExecutive/executiveList?manager_id=${managerId}',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
print('handler');
|
print('handler');
|
||||||
url = Uri.parse(
|
url = Uri.parse(
|
||||||
@ -786,6 +967,36 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------- POS -------------------------------------------------
|
||||||
|
Future<Map<String, dynamic>> fetchPosList(int managerId, val) async {
|
||||||
|
// print(_token);
|
||||||
|
|
||||||
|
print('dropDown - $managerId');
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic url;
|
||||||
|
if (val == 'dropDown') {
|
||||||
|
print('dropDown');
|
||||||
|
url = Uri.parse(
|
||||||
|
'${Env.apiUrl}master/getAllPOS?is_active=1&manager_id=${managerId}',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print('List');
|
||||||
|
url = Uri.parse(
|
||||||
|
'${Env.apiUrl}master/getAllPOS?is_active=1&manager_id=${managerId}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- ENQUIRY -------------------------------------------------
|
// ----------------------------------- ENQUIRY -------------------------------------------------
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchEnquiryList(
|
Future<Map<String, dynamic>> fetchEnquiryList(
|
||||||
@ -1504,14 +1715,19 @@ class ApiService {
|
|||||||
|
|
||||||
// --------------------------------- PayOut Module----------------------------------------------
|
// --------------------------------- PayOut Module----------------------------------------------
|
||||||
Future<Map<String, dynamic>> getCommissionRateList(data) async {
|
Future<Map<String, dynamic>> getCommissionRateList(data) async {
|
||||||
|
print("getCommissionRateList------- $data}");
|
||||||
final url = Uri.parse('${Env.apiUrl}/invoice/commission-rate-list');
|
final url = Uri.parse('${Env.apiUrl}/invoice/commission-rate-list');
|
||||||
|
print("getCommissionRateList 1");
|
||||||
// final token = await getToken(); // Fetch token
|
// final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
if (_token == null) {
|
// if (_token == null) {
|
||||||
throw Exception('Token not found. Please log in.');
|
// throw Exception('Token not found. Please log in.');
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
print("getCommissionRateList 2");
|
||||||
print("data------- $data}");
|
print("data------- $data}");
|
||||||
|
|
||||||
final headers = {
|
final headers = {
|
||||||
@ -1526,7 +1742,7 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getCreateOrUpdate(data) async {
|
Future<Map<String, dynamic>> getCreateOrUpdate(data) async {
|
||||||
final url = Uri.parse('${Env.apiUrl}/invoice/create-or-update');
|
final url = Uri.parse('${Env.apiUrl}invoice/create-or-update');
|
||||||
|
|
||||||
// final token = await getToken(); // Fetch token
|
// final token = await getToken(); // Fetch token
|
||||||
|
|
||||||
@ -1666,4 +1882,50 @@ class ApiService {
|
|||||||
final response = await _makePostRequestJson(url, data, headers);
|
final response = await _makePostRequestJson(url, data, headers);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> calculateCommissionRequest(data) async {
|
||||||
|
final url = Uri.parse('${Env.apiUrl}policy/calculateCommissionRequest');
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchPolicyMasterDropDown(String val) async {
|
||||||
|
// print(_token);
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
print('VAl - $val');
|
||||||
|
|
||||||
|
dynamic url;
|
||||||
|
|
||||||
|
if (val == 'fuelType') {
|
||||||
|
url = Uri.parse('${Env.apiUrl}policy/fuelTypeMaster');
|
||||||
|
} else if (val == 'vehicleType') {
|
||||||
|
url = Uri.parse('${Env.apiUrl}policy/vehicleTypeMaster');
|
||||||
|
}
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,8 +67,8 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
} else if (currentRoute.contains('broker') ||
|
} else if (currentRoute.contains('broker') ||
|
||||||
currentRoute.contains('payment')) {
|
currentRoute.contains('payment')) {
|
||||||
_activeMenu = 'Masters';
|
_activeMenu = 'Masters';
|
||||||
} else if (currentRoute.contains('invoice')) {
|
} else if (currentRoute.contains('payout')) {
|
||||||
_activeMenu = 'Pay Out';
|
_activeMenu = 'Invoice';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -155,6 +155,15 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
context.go(AppRoutes.salesExecutiveLst);
|
context.go(AppRoutes.salesExecutiveLst);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
_buildPopupItem(
|
||||||
|
label: "POS",
|
||||||
|
onTap: () {
|
||||||
|
_hidePopup();
|
||||||
|
setState(() => _activeMenu = 'User');
|
||||||
|
context.go(AppRoutes.posLst);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
if (key == 'Reports') ...[
|
if (key == 'Reports') ...[
|
||||||
if (role == 'manager') ...[
|
if (role == 'manager') ...[
|
||||||
@ -330,12 +339,12 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
// Pay Out button for Accounts
|
// Pay Out button for Accounts
|
||||||
if (role == 'Accounts') ...[
|
if (role == 'Accounts') ...[
|
||||||
_buildMenuItem(
|
_buildMenuItem(
|
||||||
isActive: _activeMenu == 'Pay Out',
|
isActive: _activeMenu == 'Invoice',
|
||||||
icon: Icons.checklist_outlined,
|
icon: Icons.checklist_outlined,
|
||||||
label: "Pay Out",
|
label: "Invoice",
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
_hidePopup();
|
_hidePopup();
|
||||||
setState(() => _activeMenu = 'Pay Out');
|
setState(() => _activeMenu = 'Invoice');
|
||||||
await _clearDashboardFilters();
|
await _clearDashboardFilters();
|
||||||
context.go(AppRoutes.invoiceList);
|
context.go(AppRoutes.invoiceList);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import 'package:http/http.dart' as http;
|
|||||||
import 'package:nhance_partner/core/routing/routes.dart';
|
import 'package:nhance_partner/core/routing/routes.dart';
|
||||||
import 'package:nhance_partner/data/utils/toastNotification.dart';
|
import 'package:nhance_partner/data/utils/toastNotification.dart';
|
||||||
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart';
|
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart';
|
||||||
|
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme_inline_editor.dart';
|
||||||
|
|
||||||
import '../../../../core/config/env.dart';
|
import '../../../../core/config/env.dart';
|
||||||
import '../../../../core/services/api_service.dart';
|
import '../../../../core/services/api_service.dart';
|
||||||
@ -69,7 +70,11 @@ class BrokerState extends ConsumerState<Broker> {
|
|||||||
dynamic managerId;
|
dynamic managerId;
|
||||||
|
|
||||||
Map<String, dynamic> dataDetails() {
|
Map<String, dynamic> dataDetails() {
|
||||||
final data = {"name": controllers["name"]?.text, "is_active": isActive};
|
final data = {
|
||||||
|
"name": controllers["name"]?.text,
|
||||||
|
"short_name": controllers["code"]?.text,
|
||||||
|
"is_active": isActive,
|
||||||
|
};
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,12 +113,16 @@ class BrokerState extends ConsumerState<Broker> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedId = id;
|
selectedId = id;
|
||||||
controllers['name']?.text = data['name'] ?? '';
|
controllers['name']?.text = data['name'] ?? '';
|
||||||
|
controllers['code']?.text = data['short_name'] ?? '';
|
||||||
controllers["is_active"]?.text = data['is_active'].toString();
|
controllers["is_active"]?.text = data['is_active'].toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleSave() async {
|
Future<void> handleSave() async {
|
||||||
|
// if (controllers['name'] != null && controllers['name'] != '') {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
@ -185,17 +194,12 @@ class BrokerState extends ConsumerState<Broker> {
|
|||||||
print("Broker submitted successfully!");
|
print("Broker submitted successfully!");
|
||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
|
|
||||||
if(responseBody['status'] == 200){
|
if (responseBody['status'] == 200) {
|
||||||
refresh();
|
refresh();
|
||||||
isUpdating
|
isUpdating
|
||||||
? ToastHelper.showSuccessToast(
|
? ToastHelper.showSuccessToast(context, message)
|
||||||
context,message
|
: ToastHelper.showSuccessToast(context, message);
|
||||||
)
|
|
||||||
: ToastHelper.showSuccessToast(
|
|
||||||
context,message,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
print("Error: ${response.body}");
|
print("Error: ${response.body}");
|
||||||
|
|
||||||
@ -281,7 +285,9 @@ class BrokerState extends ConsumerState<Broker> {
|
|||||||
Widget buildFormFields() {
|
Widget buildFormFields() {
|
||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(children: [buildName()]),
|
child: Row(
|
||||||
|
children: [buildName(), SizedBox(width: 10), buildShortName()],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,13 +297,39 @@ class BrokerState extends ConsumerState<Broker> {
|
|||||||
children: [
|
children: [
|
||||||
Text("Broker *", style: _textStyle),
|
Text("Broker *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
ThemedFormField(
|
SizedBox(
|
||||||
controller: controllers['name']!,
|
child: ThemedFormInlineField(
|
||||||
validator: (value) => Validators.requiredField(value, "name"),
|
controller: controllers['name']!,
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
validator: (value) => Validators.requiredField(value, "name"),
|
||||||
borderColor: Color(0xFFE2E8F0),
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
highlightColor: Color(0xFF50A398),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
txtheight: 30,
|
highlightColor: Color(0xFF50A398),
|
||||||
|
// txtheight: 30,
|
||||||
|
isdense: true,
|
||||||
|
errFieldHgt: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildShortName() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Broker Code *", style: _textStyle),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
SizedBox(
|
||||||
|
child: ThemedFormInlineField(
|
||||||
|
controller: controllers['code']!,
|
||||||
|
validator: (value) => Validators.requiredField(value, "code"),
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
|
// txtheight: 30,
|
||||||
|
isdense: true,
|
||||||
|
errFieldHgt: 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -283,9 +283,13 @@ class BrokerListState extends ConsumerState<BrokerList> {
|
|||||||
child: Text('S.No.', style: _headerStyle),
|
child: Text('S.No.', style: _headerStyle),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 1,
|
||||||
child: Text('Broker', style: _headerStyle),
|
child: Text('Broker', style: _headerStyle),
|
||||||
),
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text('Broker Code', style: _headerStyle),
|
||||||
|
),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@ -383,7 +387,11 @@ class BrokerListState extends ConsumerState<BrokerList> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)),
|
Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)),
|
||||||
Expanded(flex: 2, child: Text(item['name'] ?? '-', style: _dataBold)),
|
Expanded(flex: 1, child: Text(item['name'] ?? '-', style: _dataBold)),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(item['short_name'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -466,17 +474,16 @@ class BrokerListState extends ConsumerState<BrokerList> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final _dataBold = GoogleFonts.inter(
|
|
||||||
fontSize: 11.5,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: Color(0xFF000000),
|
|
||||||
);
|
|
||||||
|
|
||||||
static final _dataSub = GoogleFonts.inter(
|
static final _dataSub = GoogleFonts.inter(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
color: Color(0xFF585757),
|
color: Color(0xFF585757),
|
||||||
);
|
);
|
||||||
|
static final _dataBold = GoogleFonts.inter(
|
||||||
|
fontSize: 11.5,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Color(0xFF000000),
|
||||||
|
);
|
||||||
|
|
||||||
static final _headerStyle = GoogleFonts.poppins(
|
static final _headerStyle = GoogleFonts.poppins(
|
||||||
fontSize: 11.2,
|
fontSize: 11.2,
|
||||||
|
|||||||
@ -114,6 +114,12 @@ class PaymentState extends ConsumerState<Payment> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleSave() async {
|
Future<void> handleSave() async {
|
||||||
|
if (controllers['value'] == null ||
|
||||||
|
controllers['value']!.text.trim().isEmpty) {
|
||||||
|
ToastHelper.showWarningToast(context, "Payment Mode is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
@ -194,38 +200,33 @@ class PaymentState extends ConsumerState<Payment> {
|
|||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
print(message);
|
print(message);
|
||||||
|
|
||||||
if(responseBody['status'] == 200){
|
if (responseBody['status'] == 200) {
|
||||||
refresh();
|
refresh();
|
||||||
isUpdating
|
isUpdating
|
||||||
? ToastHelper.showSuccessToast(
|
? ToastHelper.showSuccessToast(context, message)
|
||||||
context,message,
|
: ToastHelper.showSuccessToast(context, message);
|
||||||
)
|
} else {
|
||||||
: ToastHelper.showSuccessToast(
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||||
context,message,
|
print("Error: ${response.body}");
|
||||||
);
|
|
||||||
} else {
|
|
||||||
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(message),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
child: Text("OK"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("Payment Creation Failed"),
|
||||||
|
content: Text(message),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text("OK"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
await apiService.clearLocalStorageAndRedirect();
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
}
|
}
|
||||||
@ -302,11 +303,13 @@ class PaymentState extends ConsumerState<Payment> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['value']!,
|
controller: controllers['value']!,
|
||||||
validator: (value) => Validators.requiredField(value, "value"),
|
// validator: (value) => Validators.requiredField(value, "value"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
txtheight: 30,
|
txtheight: 30,
|
||||||
|
isdense: true,
|
||||||
|
errFieldFont: 0,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,7 +35,9 @@ import 'package:universal_html/html.dart' as html;
|
|||||||
|
|
||||||
class Agent extends ConsumerStatefulWidget {
|
class Agent extends ConsumerStatefulWidget {
|
||||||
final String? id;
|
final String? id;
|
||||||
const Agent({super.key, this.id});
|
final void Function(String value) onSubmit;
|
||||||
|
const Agent({super.key, this.id, required this.onSubmit});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<Agent> createState() => AgentState();
|
ConsumerState<Agent> createState() => AgentState();
|
||||||
}
|
}
|
||||||
@ -43,7 +45,14 @@ class Agent extends ConsumerStatefulWidget {
|
|||||||
class AgentState extends ConsumerState<Agent> {
|
class AgentState extends ConsumerState<Agent> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
List<String> tabHeader = ['name', 'email', 'mobile', 'code', 'address'];
|
List<String> tabHeader = [
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
'mobile',
|
||||||
|
'code',
|
||||||
|
'address',
|
||||||
|
'retenRate',
|
||||||
|
];
|
||||||
late String isActive = "1";
|
late String isActive = "1";
|
||||||
// html.File? docUploadedFile;
|
// html.File? docUploadedFile;
|
||||||
// PlatformFile? passportFile;
|
// PlatformFile? passportFile;
|
||||||
@ -73,6 +82,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
"mobile": controllers["mobile"]?.text,
|
"mobile": controllers["mobile"]?.text,
|
||||||
"address": controllers["address"]?.text,
|
"address": controllers["address"]?.text,
|
||||||
"agent_code": controllers["code"]?.text,
|
"agent_code": controllers["code"]?.text,
|
||||||
|
"retention_rate": controllers["retenRate"]?.text,
|
||||||
'sales_executive_id': selectedSalesExectv,
|
'sales_executive_id': selectedSalesExectv,
|
||||||
"is_active": isActive,
|
"is_active": isActive,
|
||||||
"manager_id": managerId,
|
"manager_id": managerId,
|
||||||
@ -85,6 +95,8 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
apiService = ApiService();
|
apiService = ApiService();
|
||||||
|
|
||||||
|
print('AGID - ${widget.id}');
|
||||||
|
|
||||||
for (String field in tabHeader) {
|
for (String field in tabHeader) {
|
||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
@ -156,8 +168,10 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
controllers['mobile']?.text = data['mobile'] ?? '';
|
controllers['mobile']?.text = data['mobile'] ?? '';
|
||||||
controllers['code']?.text = data['agent_code'] ?? '';
|
controllers['code']?.text = data['agent_code'] ?? '';
|
||||||
controllers['address']?.text = data['address'] ?? '';
|
controllers['address']?.text = data['address'] ?? '';
|
||||||
|
controllers['retenRate']?.text = data['retention_rate'] ?? '';
|
||||||
isActive = data["is_active"];
|
isActive = data["is_active"];
|
||||||
selectedSalesExectv = data['sales_executive_id'] ?? '';
|
selectedSalesExectv = data['sales_executive_id'] ?? '';
|
||||||
|
print('selectedSalesExectv - $selectedSalesExectv');
|
||||||
|
|
||||||
String? apiDocPath = data["certificate_file_name"];
|
String? apiDocPath = data["certificate_file_name"];
|
||||||
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
if (apiDocPath != null && apiDocPath.isNotEmpty) {
|
||||||
@ -182,7 +196,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
final email = controllers['email']!.text.trim();
|
final email = controllers['email']!.text.trim();
|
||||||
final phone = controllers['mobile']!.text.trim();
|
final phone = controllers['mobile']!.text.trim();
|
||||||
|
|
||||||
// 🔴 Conditional validation: at least one required
|
// Conditional validation: at least one required
|
||||||
if (email.isEmpty && phone.isEmpty) {
|
if (email.isEmpty && phone.isEmpty) {
|
||||||
ToastHelper.showSuccessToast(
|
ToastHelper.showSuccessToast(
|
||||||
context,
|
context,
|
||||||
@ -317,7 +331,11 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
context,
|
context,
|
||||||
'Partner Created Successfully',
|
'Partner Created Successfully',
|
||||||
);
|
);
|
||||||
context.go(AppRoutes.agentLst);
|
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
widget.onSubmit("success");
|
||||||
|
// context.go(AppRoutes.agentLst);
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
await apiService.clearLocalStorageAndRedirect();
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
} else {
|
} else {
|
||||||
@ -395,11 +413,12 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// managerId = ref.watch(managerIdProvider);
|
// managerId = ref.watch(managerIdProvider);
|
||||||
// userId = ref.watch(userProvider);
|
// userId = ref.watch(userProvider);
|
||||||
return MainLayout(
|
return AlertDialog(
|
||||||
title: "Partner",
|
backgroundColor: Colors.white,
|
||||||
body: Container(
|
content: Container(
|
||||||
// color: Colors.yellow.shade50,
|
// color: Colors.yellow.shade50,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width * 0.62,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.7,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -407,7 +426,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
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 * 0.8,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go(AppRoutes.agentLst);
|
context.go(AppRoutes.agentLst);
|
||||||
@ -416,24 +435,24 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Tooltip(
|
// Tooltip(
|
||||||
message: 'Back',
|
// message: 'Back',
|
||||||
child: IconButton(
|
// child: IconButton(
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.arrow_left_sharp,
|
// Icons.arrow_left_sharp,
|
||||||
size: 25,
|
// size: 25,
|
||||||
color: Color(0xFF425B5B),
|
// color: Color(0xFF425B5B),
|
||||||
),
|
// ),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
context.go(AppRoutes.agentLst);
|
// context.go(AppRoutes.agentLst);
|
||||||
},
|
// },
|
||||||
splashRadius: 18,
|
// splashRadius: 18,
|
||||||
hoverColor: Colors.black12,
|
// hoverColor: Colors.black12,
|
||||||
padding: const EdgeInsets.all(4),
|
// padding: const EdgeInsets.all(4),
|
||||||
constraints: const BoxConstraints(),
|
// constraints: const BoxConstraints(),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(width: 5), // spacing between icon and text
|
const SizedBox(width: 15), // spacing between icon and text
|
||||||
Text(
|
Text(
|
||||||
"Partner",
|
"Partner",
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
@ -441,16 +460,32 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFF1F1F1),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Close',
|
||||||
|
child: const Icon(Icons.close, size: 18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// const SizedBox(width: 15),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
// color: Colors.green,
|
// color: Colors.green,
|
||||||
width: MediaQuery.of(context).size.width,
|
// width: MediaQuery.of(context).size.width,
|
||||||
margin: EdgeInsets.all(8.0),
|
// margin: EdgeInsets.all(8.0),
|
||||||
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),
|
||||||
@ -459,7 +494,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(children: [Expanded(child: buildFormFields())]),
|
Row(children: [buildFormFields()]),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
@ -507,39 +542,42 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: buildName()),
|
buildName(),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
Expanded(child: buildEmail()),
|
buildEmail(),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
buildPhNumber(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: buildPhNumber()),
|
buildId(),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
Expanded(child: buildId()),
|
buildSalesExecutive(context),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
buildRetentionRate(context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: buildSalesExecutive(context)),
|
buildAddress(),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
Expanded(child: buildAddress()),
|
buildUploadDocument(),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
|
||||||
|
// Expanded(child: SizedBox.shrink()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
// Column(
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: buildUploadDocument()),
|
|
||||||
SizedBox(width: 25),
|
|
||||||
Expanded(child: SizedBox.shrink()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// Row(
|
|
||||||
// children: [
|
// children: [
|
||||||
// Expanded(child: buildIncentiveFile()),
|
// Expanded(child: buildIncentiveFile()),
|
||||||
// SizedBox(width: 25),
|
// SizedBox(width: 25),
|
||||||
@ -552,28 +590,29 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildName() {
|
Widget buildName() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("Full Name *", style: _textStyle),
|
Text("Full Name *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['name']!,
|
controller: controllers['name']!,
|
||||||
validator: (value) => Validators.requiredField(value, "name"),
|
validator: (value) => Validators.requiredField(value, "name"),
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEmail() {
|
Widget buildEmail() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Email *", style: _textStyle),
|
Text("Email *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['email']!,
|
controller: controllers['email']!,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
@ -591,18 +630,18 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPhNumber() {
|
Widget buildPhNumber() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Phone Number *", style: _textStyle),
|
Text("Phone Number *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['mobile']!,
|
controller: controllers['mobile']!,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
@ -621,18 +660,18 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildId() {
|
Widget buildId() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Partner Id *", style: _textStyle),
|
Text("Partner Id *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['code']!,
|
controller: controllers['code']!,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
@ -641,23 +680,55 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
validator: (value) => Validators.requiredField(value, "id"),
|
validator: (value) => Validators.requiredField(value, "id"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildRetentionRate(context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Retention Rate*", style: _textStyle),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
ThemedFormField(
|
||||||
|
controller: controllers['retenRate']!,
|
||||||
|
inputFormatters: [
|
||||||
|
TextInputFormatter.withFunction((oldValue, newValue) {
|
||||||
|
if (newValue.text.isEmpty) return newValue;
|
||||||
|
|
||||||
|
final value = double.tryParse(newValue.text);
|
||||||
|
if (value == null) return oldValue;
|
||||||
|
|
||||||
|
// Allow only values <= 10
|
||||||
|
if (value <= 10) {
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
return oldValue;
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
|
borderColor: Color(0xFFE2E8F0),
|
||||||
|
highlightColor: Color(0xFF50A398),
|
||||||
|
validator: (value) => Validators.requiredField(value, "id"),
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildAddress() {
|
Widget buildAddress() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Address", style: _textStyle),
|
Text("Address", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['address']!,
|
controller: controllers['address']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[ a-zA-Z0-9_#/.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[ a-zA-Z0-9_#/.]')),
|
||||||
],
|
],
|
||||||
@ -669,17 +740,20 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
Widget buildSalesExecutive(BuildContext context) {
|
Widget buildSalesExecutive(BuildContext context) {
|
||||||
Map<String, dynamic>? selectedroleVal = filteredSalesExecutiveData
|
Map<String, dynamic>? selectedroleVal = filteredSalesExecutiveData
|
||||||
.firstWhere(
|
.firstWhere(
|
||||||
(item) => item['id'].toString() == selectedSalesExectv,
|
(item) => item['id'] == selectedSalesExectv,
|
||||||
orElse: () => {},
|
orElse: () => {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final isReadOnly = widget.id != null;
|
print('selectedroleVal - $selectedroleVal');
|
||||||
|
|
||||||
return Row(
|
final isReadOnly = false;
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
// final isReadOnly = widget.id != null;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Sales Executive *", style: _textStyle),
|
Text("Sales Executive *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
@ -687,7 +761,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
),
|
),
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
// height: 40,
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: isReadOnly,
|
absorbing: isReadOnly,
|
||||||
@ -815,11 +889,11 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildUploadDocument() {
|
Widget buildUploadDocument() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Upload Certificate", style: _textStyle),
|
Text("Upload Certificate", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
@ -827,7 +901,8 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
children: [
|
children: [
|
||||||
ThemedUploadField(
|
ThemedUploadField(
|
||||||
hintText: selectedFileNames ?? "Upload Document",
|
hintText: selectedFileNames ?? "Upload Document",
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
|
txtheight: 45,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
// highlightColor: Color(0xFF50A398),
|
// highlightColor: Color(0xFF50A398),
|
||||||
onFileSelected: (fileName, file) {
|
onFileSelected: (fileName, file) {
|
||||||
@ -842,7 +917,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
if (docUploadedFile != null || passportFileUrlFromApi != null)
|
if (docUploadedFile != null || passportFileUrlFromApi != null)
|
||||||
Container(
|
Container(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
child: Row(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// IconButton(
|
// IconButton(
|
||||||
// onPressed: () {
|
// onPressed: () {
|
||||||
@ -873,7 +948,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
// color: Color(0xFF425B5B),
|
// color: Color(0xFF425B5B),
|
||||||
// color: Colors.green.shade300,
|
// color: Colors.green.shade300,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Column(
|
||||||
children: const [
|
children: const [
|
||||||
Text(
|
Text(
|
||||||
"Download",
|
"Download",
|
||||||
@ -901,7 +976,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
// children: [
|
// children: [
|
||||||
// ThemedUploadField(
|
// ThemedUploadField(
|
||||||
// hintText: selectedFileNames ?? "Upload Document",
|
// hintText: selectedFileNames ?? "Upload Document",
|
||||||
// txtwidth: MediaQuery.of(context).size.width * 0.26,
|
// txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
//
|
//
|
||||||
// onFileSelected: (fileName, file) {
|
// onFileSelected: (fileName, file) {
|
||||||
// // print("File picked: ${fileName}");
|
// // print("File picked: ${fileName}");
|
||||||
@ -920,7 +995,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
// // Centers the text
|
// // Centers the text
|
||||||
// Container(
|
// Container(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
// child: Row(
|
// child: Column(
|
||||||
// mainAxisAlignment: MainAxisAlignment.end,
|
// mainAxisAlignment: MainAxisAlignment.end,
|
||||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
// children: [
|
// children: [
|
||||||
@ -1009,7 +1084,7 @@ class AgentState extends ConsumerState<Agent> {
|
|||||||
// borderRadius: BorderRadius.circular(5),
|
// borderRadius: BorderRadius.circular(5),
|
||||||
// color: Colors.green.shade300,
|
// color: Colors.green.shade300,
|
||||||
// ),
|
// ),
|
||||||
// child: Row(
|
// child: Column(
|
||||||
// mainAxisAlignment: MainAxisAlignment.end,
|
// mainAxisAlignment: MainAxisAlignment.end,
|
||||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
// children: [
|
// children: [
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import '../../../themes/indicators/filter_btn.dart';
|
|||||||
import '../../../themes/indicators/search_field_theme.dart';
|
import '../../../themes/indicators/search_field_theme.dart';
|
||||||
import '../../../themes/indicators/text_field_theme.dart';
|
import '../../../themes/indicators/text_field_theme.dart';
|
||||||
import '../../../widgets/custom_action_popup.dart';
|
import '../../../widgets/custom_action_popup.dart';
|
||||||
|
import 'agent.dart';
|
||||||
import 'agentIncentiveFile.dart';
|
import 'agentIncentiveFile.dart';
|
||||||
|
|
||||||
class AgentList extends ConsumerStatefulWidget {
|
class AgentList extends ConsumerStatefulWidget {
|
||||||
@ -28,12 +29,14 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
int itemsPerPage = 10;
|
int itemsPerPage = 10;
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
dynamic managerId;
|
dynamic managerId;
|
||||||
|
dynamic selected_id;
|
||||||
// List<Map<String, dynamic>> dataVal = [];
|
// List<Map<String, dynamic>> dataVal = [];
|
||||||
List<Map<String, dynamic>> getAgentData = [];
|
List<Map<String, dynamic>> getAgentData = [];
|
||||||
List<Map<String, dynamic>> originalData = [];
|
List<Map<String, dynamic>> originalData = [];
|
||||||
List<Map<String, dynamic>> filteredData = [];
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
dynamic sortedData;
|
dynamic sortedData;
|
||||||
|
dynamic managerID;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -41,13 +44,19 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
// getAgentList();
|
// getAgentList();
|
||||||
|
|
||||||
Future.microtask(() {
|
Future.microtask(() {
|
||||||
final id = ref.read(managerIdProvider);
|
managerID = ref.read(managerIdProvider);
|
||||||
if (id != null) {
|
if (managerID != null) {
|
||||||
getAgentList(id);
|
getAgentList(managerID);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
if (managerID != null) {
|
||||||
|
getAgentList(managerID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
// void didChangeDependencies() {
|
// void didChangeDependencies() {
|
||||||
// super.didChangeDependencies();
|
// super.didChangeDependencies();
|
||||||
@ -162,6 +171,20 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showAgent({required String id}) {
|
||||||
|
print('showAgent : $id');
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => Agent(
|
||||||
|
id: id,
|
||||||
|
onSubmit: (value) {
|
||||||
|
debugPrint("New Claims: $value");
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
managerId = ref.watch(managerIdProvider);
|
managerId = ref.watch(managerIdProvider);
|
||||||
@ -301,6 +324,7 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
'Email',
|
'Email',
|
||||||
'Phone Number',
|
'Phone Number',
|
||||||
'Id',
|
'Id',
|
||||||
|
'Retention Rate',
|
||||||
'Address',
|
'Address',
|
||||||
'Status',
|
'Status',
|
||||||
],
|
],
|
||||||
@ -310,6 +334,7 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
"email",
|
"email",
|
||||||
"mobile",
|
"mobile",
|
||||||
"agent_code",
|
"agent_code",
|
||||||
|
"retention_rate",
|
||||||
"address",
|
"address",
|
||||||
"is_active",
|
"is_active",
|
||||||
],
|
],
|
||||||
@ -318,7 +343,8 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go('/agent/create');
|
// context.go('/agent/create');
|
||||||
|
showAgent(id: 'Create');
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(5.0),
|
padding: EdgeInsets.all(5.0),
|
||||||
@ -391,6 +417,13 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text('Id', style: _headerStyle),
|
child: Text('Id', style: _headerStyle),
|
||||||
),
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(
|
||||||
|
'Retention Rate ',
|
||||||
|
style: _headerStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text('Address', style: _headerStyle),
|
child: Text('Address', style: _headerStyle),
|
||||||
@ -511,6 +544,10 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(item['agent_code'] ?? '-', style: _dataBold),
|
child: Text(item['agent_code'] ?? '-', style: _dataBold),
|
||||||
),
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Text(item['retention_rate'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -567,8 +604,10 @@ class AgentListState extends ConsumerState<AgentList> {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
print('EDITStaff - ${item['id']}');
|
print('EDITStaff - ${item['id']}');
|
||||||
dynamic id = item['id'];
|
selected_id = item['id'];
|
||||||
context.go('/agent/$id');
|
|
||||||
|
showAgent(id: selected_id);
|
||||||
|
// context.go('/agent/$selected_id');
|
||||||
},
|
},
|
||||||
splashRadius: 28,
|
splashRadius: 28,
|
||||||
hoverColor: Colors.black12,
|
hoverColor: Colors.black12,
|
||||||
|
|||||||
569
lib/presentation/screens/UserManagement/POS/pos_list.dart
Normal file
569
lib/presentation/screens/UserManagement/POS/pos_list.dart
Normal file
@ -0,0 +1,569 @@
|
|||||||
|
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 '../../../../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 PosList extends ConsumerStatefulWidget {
|
||||||
|
const PosList({super.key});
|
||||||
|
@override
|
||||||
|
ConsumerState<PosList> createState() => PosListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PosListState extends ConsumerState<PosList> {
|
||||||
|
int currentPage = 1;
|
||||||
|
int itemsPerPage = 10;
|
||||||
|
late ApiService apiService;
|
||||||
|
dynamic managerId;
|
||||||
|
dynamic role;
|
||||||
|
dynamic prefid;
|
||||||
|
// List<Map<String, dynamic>> dataVal = [];
|
||||||
|
List<Map<String, dynamic>> getStaffData = [];
|
||||||
|
List<Map<String, dynamic>> originalData = [];
|
||||||
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
apiService = ApiService();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
final data1 = ref.read(managerIdProvider);
|
||||||
|
|
||||||
|
prefid = data1;
|
||||||
|
// role = ref.read(userRoleProvider);
|
||||||
|
// print("E43 => mId: $prefid");
|
||||||
|
// print("roleSTAFFLIST: $role");
|
||||||
|
if (prefid != null) {
|
||||||
|
getPosList(prefid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// getPosList();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// @override
|
||||||
|
// void didChangeDependencies() {
|
||||||
|
// super.didChangeDependencies();
|
||||||
|
// final id = ref.watch(managerIdProvider);
|
||||||
|
// if (id != null) {
|
||||||
|
// getPosList(id);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
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 filterData(String query) {
|
||||||
|
// print("FilterDAta - $query");
|
||||||
|
// setState(() {
|
||||||
|
// filteredData = getStaffData.where((item) {
|
||||||
|
// final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive";
|
||||||
|
//
|
||||||
|
// return (item['name'] ?? '-').toLowerCase().contains(
|
||||||
|
// query.toLowerCase(),
|
||||||
|
// ) ||
|
||||||
|
// (item['email'] ?? '-').toLowerCase().contains(
|
||||||
|
// query.toLowerCase(),
|
||||||
|
// ) ||
|
||||||
|
// (item['mobile'] ?? '-').toLowerCase().contains(
|
||||||
|
// query.toLowerCase(),
|
||||||
|
// ) ||
|
||||||
|
// (item['address'] ?? '-').toLowerCase().contains(
|
||||||
|
// query.toLowerCase(),
|
||||||
|
// ) ||
|
||||||
|
// (item['emp_id'] ?? item['agent_code'] ?? '-')
|
||||||
|
// .toLowerCase()
|
||||||
|
// .contains(query.toLowerCase()) ||
|
||||||
|
// isActiveStatus.contains(query.toLowerCase());
|
||||||
|
// }).toList();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
void filterData(String query) {
|
||||||
|
setState(() {
|
||||||
|
final q = query.toLowerCase();
|
||||||
|
|
||||||
|
if (q.isEmpty) {
|
||||||
|
filteredData = getStaffData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredData = getStaffData.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> getPosList(int id) async {
|
||||||
|
print('E104 => Fns called => $id');
|
||||||
|
|
||||||
|
final val = 'list';
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchPosList(id, val);
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('E113 => getStaffListData => ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getStaffData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
originalData = getStaffData;
|
||||||
|
filteredData = List.from(originalData);
|
||||||
|
// print('originalData - $getClaimPolicies');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getStaffData = [];
|
||||||
|
originalData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||||
|
return [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
print('EDITStaff - ${data['id']}');
|
||||||
|
dynamic id = data['id'];
|
||||||
|
context.go('/pos/$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: "Pos",
|
||||||
|
body: Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
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(8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
// height: 40,
|
||||||
|
// color: Colors.pink,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'POS',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
ThemedSearchField(
|
||||||
|
hintText: 'Search',
|
||||||
|
// backgroundColor: Color(0xFFF6F8F8),
|
||||||
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
|
txtHeight: 30,
|
||||||
|
onChanged: filterData,
|
||||||
|
controller: _searchStaffController,
|
||||||
|
txtwidth: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
|
ExportBtn(
|
||||||
|
sheetName: "POS",
|
||||||
|
fileName: "pos_list",
|
||||||
|
txt: !ResponsiveLayout.isMobile(context)
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
|
data: filteredData,
|
||||||
|
displayHeaders: [
|
||||||
|
'S.No.',
|
||||||
|
'Pos Name',
|
||||||
|
'Code',
|
||||||
|
'Email',
|
||||||
|
'Mobile',
|
||||||
|
'Bank',
|
||||||
|
'Aadhar',
|
||||||
|
'PAN',
|
||||||
|
],
|
||||||
|
keys: [
|
||||||
|
"sno", // handled internally as i + 1
|
||||||
|
"name",
|
||||||
|
"pos_code",
|
||||||
|
"email",
|
||||||
|
"mobile",
|
||||||
|
"bank_name",
|
||||||
|
"aadhar",
|
||||||
|
"pan",
|
||||||
|
// "is_active",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
// SizedBox(width: 10),
|
||||||
|
// InkWell(
|
||||||
|
// onTap: () {
|
||||||
|
// context.go('/pos/create');
|
||||||
|
// },
|
||||||
|
// child: Container(
|
||||||
|
// padding: EdgeInsets.all(4.8),
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: const Color(0xFF2E7D6E),
|
||||||
|
// borderRadius: BorderRadius.circular(8.0),
|
||||||
|
// ),
|
||||||
|
// child: Row(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
// Tooltip(
|
||||||
|
// message: 'Create Pos',
|
||||||
|
// child: Icon(
|
||||||
|
// Icons.add,
|
||||||
|
// color: Colors.white,
|
||||||
|
// size: 18,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
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('Name', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Code', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Email', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Mobile', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Bank', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('Aadhar', style: _headerStyle),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text('PAN', style: _headerStyle),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Expanded(
|
||||||
|
// flex: 1,
|
||||||
|
// child: Text('Status', 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: 10, 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: 2,
|
||||||
|
child: Text(item['pos_code'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(item['email'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(item['mobile'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(item['bank_name'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(item['aadhar'] ?? '-', style: _dataBold),
|
||||||
|
),
|
||||||
|
Expanded(flex: 2, child: Text(item['pan'] ?? '-', 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.updateStatus(
|
||||||
|
// item['id'],
|
||||||
|
// val ? "0" : "1",
|
||||||
|
// 'pos',
|
||||||
|
// );
|
||||||
|
// print("Response - $response");
|
||||||
|
// },
|
||||||
|
// activeColor: Color(0xFF2E7D6E), // thumb when active
|
||||||
|
// activeTrackColor: Color(0xFFDCFCE7), // track when active
|
||||||
|
// // activeColor: Color(0xFF425B5B), // thumb 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: [
|
||||||
|
// // GestureDetector(
|
||||||
|
// // onTap: () {
|
||||||
|
// // // Navigator.pop(context);
|
||||||
|
// // print('EDITStaff - ${item['id']}');
|
||||||
|
// // dynamic id = item['id'];
|
||||||
|
// // context.go('/pos/$id');
|
||||||
|
// // },
|
||||||
|
// // child: Image.asset(
|
||||||
|
// // "assets/miscellaneous/Edit.png",
|
||||||
|
// // height: 15,
|
||||||
|
// // width: 15,
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// Tooltip(
|
||||||
|
// message: 'Edit',
|
||||||
|
// child: IconButton(
|
||||||
|
// icon: Image.asset(
|
||||||
|
// "assets/miscellaneous/Edit.png",
|
||||||
|
// height: 12,
|
||||||
|
// width: 15,
|
||||||
|
// ),
|
||||||
|
// onPressed: () {
|
||||||
|
// print('EDITStaff - ${item['id']}');
|
||||||
|
// dynamic id = item['id'];
|
||||||
|
// context.go('/pos/$id');
|
||||||
|
// },
|
||||||
|
// splashRadius: 28,
|
||||||
|
// hoverColor: Colors.black12,
|
||||||
|
// padding: const EdgeInsets.all(8),
|
||||||
|
// constraints: const BoxConstraints(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
// : Row(
|
||||||
|
// children: [
|
||||||
|
// Image.asset(
|
||||||
|
// "assets/miscellaneous/Edit_muted.png",
|
||||||
|
// height: 12,
|
||||||
|
// width: 15,
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.poppins(
|
||||||
|
fontSize: 11.2,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -240,7 +240,10 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 26),
|
const SizedBox(height: 26),
|
||||||
if (profileData?['mobile'] != null ||
|
if (profileData?['mobile'] != null ||
|
||||||
profileData?['mobile'] != '') ...[
|
profileData!['mobile']
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.isNotEmpty) ...[
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
const Icon(
|
||||||
@ -258,7 +261,10 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
if (profileData?['email'] != null ||
|
if (profileData?['email'] != null ||
|
||||||
profileData?['email'] != '') ...[
|
profileData!['email']
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.isNotEmpty) ...[
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
const Icon(
|
||||||
@ -276,8 +282,11 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
|
||||||
if (profileData?['address'] != null ||
|
if (profileData?['address'] != null &&
|
||||||
profileData?['address'] != '') ...[
|
profileData!['address']
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.isNotEmpty) ...[
|
||||||
if ((roleId != 1) &&
|
if ((roleId != 1) &&
|
||||||
(roleId != 2) &&
|
(roleId != 2) &&
|
||||||
(roleId != 3)) ...[
|
(roleId != 3)) ...[
|
||||||
@ -304,9 +313,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
if ((roleId != 1) &&
|
if ((roleId == 5)) ...[
|
||||||
(roleId != 2) &&
|
|
||||||
(roleId != 3)) ...[
|
|
||||||
// Staff, Handler doesn't have this part Only Manager and agent have
|
// Staff, Handler doesn't have this part Only Manager and agent have
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(6),
|
padding: const EdgeInsets.all(6),
|
||||||
|
|||||||
@ -27,7 +27,8 @@ import '../../../themes/indicators/input_field_decoration.dart';
|
|||||||
|
|
||||||
class SalesExecutive extends ConsumerStatefulWidget {
|
class SalesExecutive extends ConsumerStatefulWidget {
|
||||||
final String? id;
|
final String? id;
|
||||||
const SalesExecutive({super.key, this.id});
|
final void Function(String value) onSubmit;
|
||||||
|
const SalesExecutive({super.key, this.id, required this.onSubmit});
|
||||||
@override
|
@override
|
||||||
ConsumerState<SalesExecutive> createState() => SalesExecutiveState();
|
ConsumerState<SalesExecutive> createState() => SalesExecutiveState();
|
||||||
}
|
}
|
||||||
@ -75,7 +76,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
// "emp_id": controllers["code"]?.text,
|
// "emp_id": controllers["code"]?.text,
|
||||||
"is_active": isActive,
|
"is_active": isActive,
|
||||||
// "handler_id": selectedHandler,
|
// "handler_id": selectedHandler,
|
||||||
"manager_id": userId,
|
"manager_id": managerId,
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -204,7 +205,9 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
context,
|
context,
|
||||||
'SalesExecutive Created Successfully',
|
'SalesExecutive Created Successfully',
|
||||||
);
|
);
|
||||||
context.go(AppRoutes.salesExecutiveLst);
|
Navigator.of(context).pop();
|
||||||
|
widget.onSubmit("success");
|
||||||
|
// context.go(AppRoutes.salesExecutiveLst);
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
await apiService.clearLocalStorageAndRedirect();
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
} else {
|
} else {
|
||||||
@ -310,11 +313,12 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MainLayout(
|
return AlertDialog(
|
||||||
title: "SalesExecutive",
|
backgroundColor: Colors.white,
|
||||||
body: Container(
|
content: Container(
|
||||||
// color: Colors.yellow.shade50,
|
// color: Colors.yellow.shade50,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width * 0.42,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.55,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -331,23 +335,23 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Tooltip(
|
// Tooltip(
|
||||||
message: 'Back',
|
// message: 'Back',
|
||||||
child: IconButton(
|
// child: IconButton(
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.arrow_left_sharp,
|
// Icons.arrow_left_sharp,
|
||||||
size: 25,
|
// size: 25,
|
||||||
color: Color(0xFF425B5B),
|
// color: Color(0xFF425B5B),
|
||||||
),
|
// ),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
context.go(AppRoutes.salesExecutiveLst);
|
// context.go(AppRoutes.salesExecutiveLst);
|
||||||
},
|
// },
|
||||||
splashRadius: 28,
|
// splashRadius: 28,
|
||||||
hoverColor: Colors.black12,
|
// hoverColor: Colors.black12,
|
||||||
padding: const EdgeInsets.all(8),
|
// padding: const EdgeInsets.all(8),
|
||||||
constraints: const BoxConstraints(),
|
// constraints: const BoxConstraints(),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(width: 5), // spacing between icon and text
|
const SizedBox(width: 5), // spacing between icon and text
|
||||||
Text(
|
Text(
|
||||||
"Sales Executive",
|
"Sales Executive",
|
||||||
@ -356,6 +360,21 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFF1F1F1),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Close',
|
||||||
|
child: const Icon(Icons.close, size: 18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -405,7 +424,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 30),
|
// SizedBox(height: 30),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -422,51 +441,40 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(children: [buildName(), SizedBox(width: 25), buildEmail()]),
|
||||||
children: [
|
|
||||||
Expanded(child: buildName()),
|
|
||||||
SizedBox(width: 25),
|
|
||||||
Expanded(child: buildEmail()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: buildPhNumber()),
|
|
||||||
SizedBox(width: 25),
|
|
||||||
Expanded(child: buildAddress()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
|
Row(children: [buildPhNumber(), SizedBox(width: 25), buildAddress()]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildName() {
|
Widget buildName() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Name *", style: _textStyle),
|
Text("Name *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
controller: controllers['name']!,
|
controller: controllers['name']!,
|
||||||
validator: (value) => Validators.requiredField(value, "name"),
|
validator: (value) => Validators.requiredField(value, "name"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEmail() {
|
Widget buildEmail() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Email *", style: _textStyle),
|
Text("Email *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['email']!,
|
controller: controllers['email']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
@ -485,18 +493,18 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPhNumber() {
|
Widget buildPhNumber() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Phone Number *", style: _textStyle),
|
Text("Phone Number *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['mobile']!,
|
controller: controllers['mobile']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
@ -516,18 +524,18 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildAddress() {
|
Widget buildAddress() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Address", style: _textStyle),
|
Text("Address", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['address']!,
|
controller: controllers['address']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
@ -535,15 +543,15 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[ a-zA-Z0-9_#/.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[ a-zA-Z0-9_#/.]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildId() {
|
Widget buildId() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("SalesExecutive Id ", style: _textStyle),
|
Text("SalesExecutive Id ", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
@ -552,7 +560,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
// validator: (value) => Validators.requiredField(value, "id"),
|
// validator: (value) => Validators.requiredField(value, "id"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -567,7 +575,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
// ThemedFormField(
|
// ThemedFormField(
|
||||||
// controller: controllers['address']!,
|
// controller: controllers['address']!,
|
||||||
//
|
//
|
||||||
// txtwidth: MediaQuery.of(context).size.width * 0.26,
|
// txtwidth: MediaQuery.of(context).size.width *0.18,
|
||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// );
|
// );
|
||||||
@ -590,8 +598,8 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
|
|
||||||
final isReadOnly = widget.id != null;
|
final isReadOnly = widget.id != null;
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Role *", style: _textStyle),
|
Text("Role *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
@ -602,7 +610,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
),
|
),
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
// height: 40,
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: isReadOnly,
|
absorbing: isReadOnly,
|
||||||
@ -727,8 +735,8 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
// final isReadOnly = widget.id != null;
|
// final isReadOnly = widget.id != null;
|
||||||
final isReadOnly = false;
|
final isReadOnly = false;
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Handler Name *", style: _textStyle),
|
Text("Handler Name *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
@ -739,7 +747,7 @@ class SalesExecutiveState extends ConsumerState<SalesExecutive> {
|
|||||||
),
|
),
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
// height: 40,
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: isReadOnly,
|
absorbing: isReadOnly,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
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/UserManagement/SalesExecutive/salesExecutive.dart';
|
||||||
|
|
||||||
import '../../../../core/routing/routes.dart';
|
import '../../../../core/routing/routes.dart';
|
||||||
import '../../../../core/services/api_service.dart';
|
import '../../../../core/services/api_service.dart';
|
||||||
@ -56,6 +57,12 @@ class SalesExecutiveListState extends ConsumerState<SalesExecutiveList> {
|
|||||||
// getSalesExecutiveList();
|
// getSalesExecutiveList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
if (prefid != null && role != null) {
|
||||||
|
getSalesExecutiveList(prefid, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<dynamic> get _paginatedData {
|
List<dynamic> get _paginatedData {
|
||||||
// Sort descending by id first
|
// Sort descending by id first
|
||||||
final sortedData = [...filteredData]
|
final sortedData = [...filteredData]
|
||||||
@ -131,6 +138,20 @@ class SalesExecutiveListState extends ConsumerState<SalesExecutiveList> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showSalesExecutive({required String id}) {
|
||||||
|
print('showSalesEXEC : $id');
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => SalesExecutive(
|
||||||
|
id: id,
|
||||||
|
onSubmit: (value) {
|
||||||
|
debugPrint("New onSubmit: $value");
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
managerId = ref.watch(managerIdProvider);
|
managerId = ref.watch(managerIdProvider);
|
||||||
@ -170,7 +191,7 @@ class SalesExecutiveListState extends ConsumerState<SalesExecutiveList> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Sales Executive List',
|
'Sales Executive',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -216,7 +237,8 @@ class SalesExecutiveListState extends ConsumerState<SalesExecutiveList> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go('/salesExecutive/create');
|
showSalesExecutive(id: 'create');
|
||||||
|
// context.go('/salesExecutive/create');
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(4.8),
|
padding: EdgeInsets.all(4.8),
|
||||||
@ -427,7 +449,9 @@ class SalesExecutiveListState extends ConsumerState<SalesExecutiveList> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
print('EDITStaff - ${item['id']}');
|
print('EDITStaff - ${item['id']}');
|
||||||
dynamic id = item['id'];
|
dynamic id = item['id'];
|
||||||
context.go('/salesExecutive/$id');
|
// context.go('/salesExecutive/$id');
|
||||||
|
|
||||||
|
showSalesExecutive(id: id);
|
||||||
},
|
},
|
||||||
splashRadius: 28,
|
splashRadius: 28,
|
||||||
hoverColor: Colors.black12,
|
hoverColor: Colors.black12,
|
||||||
|
|||||||
@ -27,7 +27,8 @@ import '../../../themes/indicators/input_field_decoration.dart';
|
|||||||
|
|
||||||
class Staff extends ConsumerStatefulWidget {
|
class Staff extends ConsumerStatefulWidget {
|
||||||
final String? id;
|
final String? id;
|
||||||
const Staff({super.key, this.id});
|
final void Function(String value) onSubmit;
|
||||||
|
const Staff({super.key, this.id, required this.onSubmit});
|
||||||
@override
|
@override
|
||||||
ConsumerState<Staff> createState() => StaffState();
|
ConsumerState<Staff> createState() => StaffState();
|
||||||
}
|
}
|
||||||
@ -56,8 +57,8 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
List<Map<String, dynamic>> filteredRolesData = [];
|
List<Map<String, dynamic>> filteredRolesData = [];
|
||||||
List<Map<String, dynamic>> getRolesData = [];
|
List<Map<String, dynamic>> getRolesData = [];
|
||||||
|
|
||||||
List<dynamic>? selectedHandlerIds = [];
|
|
||||||
String? selectedHandler;
|
String? selectedHandler;
|
||||||
|
List<dynamic>? selectedHandlerIds = [];
|
||||||
List<Map<String, dynamic>> filteredHandlersData = [];
|
List<Map<String, dynamic>> filteredHandlersData = [];
|
||||||
List<Map<String, dynamic>> getHandlersData = [];
|
List<Map<String, dynamic>> getHandlersData = [];
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateData() async {
|
void updateData() async {
|
||||||
if (widget.id != null && widget.id != 'create') {
|
if (widget.id != null && widget.id != 'Create') {
|
||||||
dynamic response = await apiService.findSingleStaffData(widget.id!);
|
dynamic response = await apiService.findSingleStaffData(widget.id!);
|
||||||
final data = response['data'];
|
final data = response['data'];
|
||||||
print("updateData - ${response['data']}");
|
print("updateData - ${response['data']}");
|
||||||
@ -184,7 +185,7 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createUserData(data) async {
|
Future<void> createUserData(data) async {
|
||||||
final bool isUpdating = widget.id != null && widget.id != 'create';
|
final bool isUpdating = widget.id != null && widget.id != 'Create';
|
||||||
final String? id = isUpdating ? widget.id : null;
|
final String? id = isUpdating ? widget.id : null;
|
||||||
final String apiUrldata;
|
final String apiUrldata;
|
||||||
// apiUrldata = isUpdating
|
// apiUrldata = isUpdating
|
||||||
@ -234,7 +235,10 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
context,
|
context,
|
||||||
'Staff Created Successfully',
|
'Staff Created Successfully',
|
||||||
);
|
);
|
||||||
context.go(AppRoutes.staffLst);
|
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
widget.onSubmit("success");
|
||||||
|
// context.go(AppRoutes.staffLst);
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
await apiService.clearLocalStorageAndRedirect();
|
await apiService.clearLocalStorageAndRedirect();
|
||||||
} else {
|
} else {
|
||||||
@ -340,11 +344,12 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MainLayout(
|
return AlertDialog(
|
||||||
title: "Staff",
|
backgroundColor: Colors.white,
|
||||||
body: Container(
|
content: Container(
|
||||||
// color: Colors.yellow.shade50,
|
// color: Colors.yellow.shade50,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width * 0.62,
|
||||||
|
height: MediaQuery.of(context).size.height * 0.65,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -361,23 +366,23 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Tooltip(
|
// Tooltip(
|
||||||
message: 'Back',
|
// message: 'Back',
|
||||||
child: IconButton(
|
// child: IconButton(
|
||||||
icon: const Icon(
|
// icon: const Icon(
|
||||||
Icons.arrow_left_sharp,
|
// Icons.arrow_left_sharp,
|
||||||
size: 25,
|
// size: 25,
|
||||||
color: Color(0xFF425B5B),
|
// color: Color(0xFF425B5B),
|
||||||
),
|
// ),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
context.go(AppRoutes.staffLst);
|
// context.go(AppRoutes.staffLst);
|
||||||
},
|
// },
|
||||||
splashRadius: 28,
|
// splashRadius: 28,
|
||||||
hoverColor: Colors.black12,
|
// hoverColor: Colors.black12,
|
||||||
padding: const EdgeInsets.all(8),
|
// padding: const EdgeInsets.all(8),
|
||||||
constraints: const BoxConstraints(),
|
// constraints: const BoxConstraints(),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(width: 5), // spacing between icon and text
|
const SizedBox(width: 5), // spacing between icon and text
|
||||||
Text(
|
Text(
|
||||||
"Staff",
|
"Staff",
|
||||||
@ -386,6 +391,21 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFF1F1F1),
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Close',
|
||||||
|
child: const Icon(Icons.close, size: 18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -455,30 +475,30 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: buildName()),
|
buildName(),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
Expanded(child: buildEmail()),
|
buildEmail(),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
buildPhNumber(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: buildPhNumber()),
|
buildRole(context),
|
||||||
SizedBox(width: 25),
|
SizedBox(width: 25),
|
||||||
Expanded(child: buildRole(context)),
|
if (showHandler) ...[
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
buildHandler(context),
|
||||||
|
SizedBox(width: 25),
|
||||||
|
SizedBox.shrink(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
|
||||||
|
|
||||||
if (showHandler) ...[
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: buildHandler(context)),
|
|
||||||
SizedBox(width: 25),
|
|
||||||
Expanded(child: SizedBox.shrink()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
// Row(
|
// Row(
|
||||||
// children: [
|
// children: [
|
||||||
// Expanded(child: buildAddress()),
|
// Expanded(child: buildAddress()),
|
||||||
@ -492,28 +512,28 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildName() {
|
Widget buildName() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Full Name *", style: _textStyle),
|
Text("Full Name *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
controller: controllers['name']!,
|
controller: controllers['name']!,
|
||||||
validator: (value) => Validators.requiredField(value, "name"),
|
validator: (value) => Validators.requiredField(value, "name"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEmail() {
|
Widget buildEmail() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Email *", style: _textStyle),
|
Text("Email *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['email']!,
|
controller: controllers['email']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
@ -532,18 +552,18 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPhNumber() {
|
Widget buildPhNumber() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Phone Number *", style: _textStyle),
|
Text("Phone Number *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['mobile']!,
|
controller: controllers['mobile']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
@ -563,24 +583,24 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||||
],
|
],
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildId() {
|
Widget buildId() {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Staff Id ", style: _textStyle),
|
Text("Staff Id ", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['code']!,
|
controller: controllers['code']!,
|
||||||
borderColor: Color(0xFFE2E8F0),
|
borderColor: Color(0xFFE2E8F0),
|
||||||
highlightColor: Color(0xFF50A398),
|
highlightColor: Color(0xFF50A398),
|
||||||
// validator: (value) => Validators.requiredField(value, "id"),
|
// validator: (value) => Validators.requiredField(value, "id"),
|
||||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -595,7 +615,7 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
// ThemedFormField(
|
// ThemedFormField(
|
||||||
// controller: controllers['address']!,
|
// controller: controllers['address']!,
|
||||||
//
|
//
|
||||||
// txtwidth: MediaQuery.of(context).size.width * 0.26,
|
// txtwidth: MediaQuery.of(context).size.width * 0.18,
|
||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// );
|
// );
|
||||||
@ -616,13 +636,13 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
showHandler = false;
|
showHandler = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isReadOnly = widget.id != null;
|
final isReadOnly = widget.id != null && widget.id != 'Create';
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Role *", style: _textStyle),
|
Text("Role *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
@ -630,7 +650,7 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
),
|
),
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
// height: 40,
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: isReadOnly,
|
absorbing: isReadOnly,
|
||||||
@ -719,13 +739,14 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
// constraints: BoxConstraints(),
|
// constraints: BoxConstraints(),
|
||||||
),
|
),
|
||||||
|
|
||||||
onChanged: widget.id != null
|
onChanged: widget.id != null && widget.id != 'Create'
|
||||||
? null
|
? null
|
||||||
: (val) {
|
: (val) {
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
print("Selected Role : ${val['role']}");
|
print("Selected Role : ${val['role']}");
|
||||||
print("Id: ${val['id']}");
|
print("Id: ${val['id']}");
|
||||||
selectedRole = val['id'];
|
selectedRole = val['id'];
|
||||||
|
print('selectedRole - ${val['role']}');
|
||||||
if (val['role'] == 'Staff') {
|
if (val['role'] == 'Staff') {
|
||||||
setState(() {
|
setState(() {
|
||||||
showHandler = true;
|
showHandler = true;
|
||||||
@ -736,6 +757,8 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print('showHandler - $showHandler');
|
||||||
|
|
||||||
// controllers['agentId']?.text = val['agent_code'];
|
// controllers['agentId']?.text = val['agent_code'];
|
||||||
// agentId = agent['id'];
|
// agentId = agent['id'];
|
||||||
}
|
}
|
||||||
@ -755,11 +778,11 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
// final isReadOnly = widget.id != null;
|
// final isReadOnly = widget.id != null;
|
||||||
final isReadOnly = false;
|
final isReadOnly = false;
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Handler Name *", style: _textStyle),
|
Text("Handler Name *", style: _textStyle),
|
||||||
SizedBox(width: 10),
|
SizedBox(height: 10),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: Colors.white,
|
// color: Colors.white,
|
||||||
@ -767,7 +790,7 @@ class StaffState extends ConsumerState<Staff> {
|
|||||||
),
|
),
|
||||||
width: ResponsiveLayout.isMobile(context)
|
width: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.18,
|
||||||
// height: 40,
|
// height: 40,
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: isReadOnly,
|
absorbing: isReadOnly,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
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/UserManagement/Staff/staff.dart';
|
||||||
|
|
||||||
import '../../../../core/routing/routes.dart';
|
import '../../../../core/routing/routes.dart';
|
||||||
import '../../../../core/services/api_service.dart';
|
import '../../../../core/services/api_service.dart';
|
||||||
@ -56,6 +57,13 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
});
|
});
|
||||||
// getStaffList();
|
// getStaffList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
if (prefid != null && role != null) {
|
||||||
|
getStaffList(prefid, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// @override
|
// @override
|
||||||
// void didChangeDependencies() {
|
// void didChangeDependencies() {
|
||||||
@ -167,6 +175,20 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showStaff({required String id}) {
|
||||||
|
print('showAgent : $id');
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => Staff(
|
||||||
|
id: id,
|
||||||
|
onSubmit: (value) {
|
||||||
|
debugPrint("New Claims: $value");
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
List<Widget> _buildPopupMenuActions(BuildContext context, dynamic data) {
|
||||||
return [
|
return [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -204,48 +226,6 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
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('Staff List', style: _headerStyle),
|
|
||||||
// // Icon(
|
|
||||||
// // Icons.arrow_left_sharp,
|
|
||||||
// // size: 35,
|
|
||||||
// // color: Color(0xFF425B5B),
|
|
||||||
// // ),
|
|
||||||
// // Tooltip(
|
|
||||||
// // message: 'Back',
|
|
||||||
// // child: IconButton(
|
|
||||||
// // icon: const Icon(
|
|
||||||
// // Icons.arrow_left_sharp,
|
|
||||||
// // size: 25,
|
|
||||||
// // color: Color(0xFF425B5B),
|
|
||||||
// // ),
|
|
||||||
// // onPressed: () {
|
|
||||||
// // context.go(AppRoutes.dashboard);
|
|
||||||
// // },
|
|
||||||
// // splashRadius: 18,
|
|
||||||
// // hoverColor: Colors.black12,
|
|
||||||
// // padding: const EdgeInsets.all(4),
|
|
||||||
// // constraints: const BoxConstraints(),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // const SizedBox(width: 15), // spacing between icon and text
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
//
|
|
||||||
// SizedBox(height: 5),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
// color: Colors.green,
|
// color: Colors.green,
|
||||||
@ -269,7 +249,7 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Staff List',
|
'Staff',
|
||||||
style: GoogleFonts.poppins(
|
style: GoogleFonts.poppins(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@ -315,7 +295,9 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.go('/staff/create');
|
// context.go('/staff/create');
|
||||||
|
|
||||||
|
showStaff(id: 'Create');
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(4.8),
|
padding: EdgeInsets.all(4.8),
|
||||||
@ -544,7 +526,9 @@ class StaffListState extends ConsumerState<StaffList> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
print('EDITStaff - ${item['id']}');
|
print('EDITStaff - ${item['id']}');
|
||||||
dynamic id = item['id'];
|
dynamic id = item['id'];
|
||||||
context.go('/staff/$id');
|
|
||||||
|
showStaff(id: id);
|
||||||
|
// context.go('/staff/$id');
|
||||||
},
|
},
|
||||||
splashRadius: 28,
|
splashRadius: 28,
|
||||||
hoverColor: Colors.black12,
|
hoverColor: Colors.black12,
|
||||||
|
|||||||
@ -243,6 +243,12 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> buildBrokerShortNames() {
|
||||||
|
return filteredBrokerWise.map<String>((item) {
|
||||||
|
return item['broker_short_name']?.toString() ?? '';
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
List<BarData> buildProductBarData() {
|
List<BarData> buildProductBarData() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
@ -291,8 +297,9 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
Spacer(),
|
||||||
Text('Hide and Show Charts : ', style: _styleSmall1),
|
Text('Hide and Show Charts : ', style: _styleSmall1),
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@ -355,19 +362,43 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Spacer(),
|
||||||
|
legendWidget(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
(showInsurer || showBroker)
|
||||||
Expanded(
|
? Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
showInsurer ? Expanded(child: insurerContainer()) : SizedBox(),
|
// if (showInsurer) Expanded(child: insurerContainer()),
|
||||||
showBroker ? Expanded(child: brokerContainer()) : SizedBox(),
|
// if (showBroker) Expanded(child: brokerContainer()),
|
||||||
showProduct ? Expanded(child: productContainer()) : SizedBox(),
|
showInsurer
|
||||||
],
|
? Expanded(child: insurerContainer())
|
||||||
|
: SizedBox(),
|
||||||
|
showBroker
|
||||||
|
? Expanded(child: brokerContainer())
|
||||||
|
: SizedBox(),
|
||||||
|
// showProduct ? Expanded(child: productContainer()) : SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: SizedBox(),
|
||||||
|
if (showProduct) ...[
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
showProduct
|
||||||
|
? Expanded(child: productContainer())
|
||||||
|
: SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
] else ...[
|
||||||
|
SizedBox.shrink(),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -381,31 +412,18 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(right: 10),
|
margin: const EdgeInsets.only(right: 10),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
elevation: 1, // card shadow
|
// color: Colors.amber.shade100,
|
||||||
|
elevation: 0.01, // card shadow
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: Text('Insurer-Wise', style: _chartHeader)),
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('Insurer Wise', style: _chartHeader),
|
|
||||||
Text(
|
|
||||||
'(Previous / Current Month)',
|
|
||||||
style: _chartHeader.copyWith(
|
|
||||||
color: Colors.black87,
|
|
||||||
fontSize: 8,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// buildInsurer(context),
|
// buildInsurer(context),
|
||||||
Text(
|
Text(
|
||||||
@ -425,6 +443,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
// color: Colors.amber.shade100,
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
// color: Colors.red.shade100,
|
// color: Colors.red.shade100,
|
||||||
child: CustomBarChart(
|
child: CustomBarChart(
|
||||||
@ -433,7 +452,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
legendWidget(),
|
// legendWidget(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -443,27 +462,23 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
Widget brokerContainer() {
|
Widget brokerContainer() {
|
||||||
final chartBrokerData = buildBrokerBarData();
|
final chartBrokerData = buildBrokerBarData();
|
||||||
final chartBrokerLabels = buildBrokerLabels();
|
final chartBrokerLabels = buildBrokerLabels();
|
||||||
|
final chartBrokerShortName = buildBrokerShortNames();
|
||||||
print('chartBrokerData - $chartBrokerData');
|
print('chartBrokerData - $chartBrokerData');
|
||||||
print('chartBrokerLabels - $chartBrokerLabels');
|
print('chartBrokerLabels - $chartBrokerLabels');
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(right: 10),
|
margin: const EdgeInsets.only(right: 10),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
elevation: 1, // card shadow
|
elevation: 0.01, // card shadow
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: Text('Broker-Wise', style: _chartHeader)),
|
||||||
child: Text(
|
|
||||||
'Broker Wise (Previous / Current Month)',
|
|
||||||
style: _chartHeader,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
isBrokerWisePolicy ? "Policies" : "Premium",
|
isBrokerWisePolicy ? "Policies" : "Premium",
|
||||||
@ -483,10 +498,14 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CustomBarChart(
|
child: CustomBarChart(
|
||||||
dataList: chartBrokerData,
|
dataList: chartBrokerData,
|
||||||
labels: chartBrokerLabels,
|
labels: chartBrokerShortName,
|
||||||
|
shortName: chartBrokerLabels,
|
||||||
|
|
||||||
|
// labels: chartBrokerLabels,
|
||||||
|
// shortName: chartBrokerShortName,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
legendWidget(),
|
// legendWidget(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -501,22 +520,17 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(right: 10),
|
margin: const EdgeInsets.only(right: 10),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
elevation: 1, // card shadow
|
elevation: 0.01, // card shadow
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(4.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: Text('Product-Wise', style: _chartHeader)),
|
||||||
child: Text(
|
|
||||||
'Product Wise (Previous / Current Month)',
|
|
||||||
style: _chartHeader,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
Text(
|
||||||
isProductWisePolicy ? "Policies" : "Premium",
|
isProductWisePolicy ? "Policies" : "Premium",
|
||||||
style: _styleSmall1,
|
style: _styleSmall1,
|
||||||
@ -538,7 +552,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
labels: chartProductLabels,
|
labels: chartProductLabels,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
legendWidget(),
|
// legendWidget(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -372,6 +372,8 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
: agentsPerformanceListPremium,
|
: agentsPerformanceListPremium,
|
||||||
isPerfomingAgntPolicy:
|
isPerfomingAgntPolicy:
|
||||||
isPerfomingAgntPolicy,
|
isPerfomingAgntPolicy,
|
||||||
|
apiService: apiService,
|
||||||
|
managerId: managerId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -437,6 +439,8 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
: nonAgentsPerformanceListPremium,
|
: nonAgentsPerformanceListPremium,
|
||||||
isPerfomingAgntPolicy:
|
isPerfomingAgntPolicy:
|
||||||
isNonPerfomingAgntPolicy,
|
isNonPerfomingAgntPolicy,
|
||||||
|
apiService: apiService,
|
||||||
|
managerId: managerId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -459,12 +463,16 @@ class Performance extends StatefulWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
final List<Map<String, dynamic>> data;
|
final List<Map<String, dynamic>> data;
|
||||||
final bool isPerfomingAgntPolicy;
|
final bool isPerfomingAgntPolicy;
|
||||||
|
late ApiService apiService;
|
||||||
|
dynamic managerId;
|
||||||
|
|
||||||
Performance({
|
Performance({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.data,
|
required this.data,
|
||||||
required this.isPerfomingAgntPolicy,
|
required this.isPerfomingAgntPolicy,
|
||||||
|
required this.apiService,
|
||||||
|
required this.managerId,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -504,7 +512,7 @@ class _PerformanceState extends State<Performance> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
"S.no.",
|
"S.No.",
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: _headerStyle,
|
style: _headerStyle,
|
||||||
),
|
),
|
||||||
@ -521,7 +529,7 @@ class _PerformanceState extends State<Performance> {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Partner Code",
|
"Partner Code",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.left,
|
||||||
style: _headerStyle,
|
style: _headerStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -610,34 +618,45 @@ class _PerformanceState extends State<Performance> {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
row['total_premium_amount'] ?? "",
|
row['total_premium_amount'] ?? "",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.right,
|
||||||
style: _tableDataStyle,
|
style: _tableDataStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
// (widget.title == 'Performing Partner')
|
SizedBox(width: 10),
|
||||||
// ? Expanded(
|
InkWell(
|
||||||
// flex: 1,
|
onTap: () async {
|
||||||
// child: Text(
|
final path1 = 'PerformingTop50';
|
||||||
// isPerfomingAgntPolicy
|
final path2 = widget.isPerfomingAgntPolicy
|
||||||
// ? (row['policy_count']?.toString() ?? "0")
|
? "NoBusiness"
|
||||||
// : (row['total_premium_amount']
|
: "NonPerformingBelow50K";
|
||||||
// ?.toString() ??
|
final path = (widget.title == 'Performing Partner')
|
||||||
// "0"),
|
? path1
|
||||||
// textAlign: TextAlign.center,
|
: path2;
|
||||||
// style: GoogleFonts.inter(
|
|
||||||
// fontSize: 11,
|
final id =
|
||||||
// fontWeight: FontWeight.w500,
|
((widget.title == 'Performing Partner') &&
|
||||||
// // color: isPerfomingAgntPolicy
|
(row['agent_id'] != null))
|
||||||
// // ? Colors.black
|
? row['agent_id']
|
||||||
// // : (row['status']?.toString().toLowerCase() ==
|
: '';
|
||||||
// // "active"
|
final month = 'current';
|
||||||
// // ? Colors.green
|
|
||||||
// // : Colors.red),
|
await widget.apiService.generateChartExcel(
|
||||||
// ),
|
path,
|
||||||
// ),
|
id,
|
||||||
// )
|
month,
|
||||||
// : SizedBox(),
|
widget.managerId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Click To Download Excel',
|
||||||
|
child: Icon(
|
||||||
|
Icons.download,
|
||||||
|
size: 14,
|
||||||
|
color: Colors.green.shade300,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -48,6 +48,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
[]; // 👈 Add this at the top with other state variables
|
[]; // 👈 Add this at the top with other state variables
|
||||||
Map<String, Color> vehicleColors = {};
|
Map<String, Color> vehicleColors = {};
|
||||||
List<String> staffLabels = [];
|
List<String> staffLabels = [];
|
||||||
|
List<String> staffLabelsId = [];
|
||||||
// List<List<List<dynamic>>> staffChartData = [];
|
// List<List<List<dynamic>>> staffChartData = [];
|
||||||
List<List<List<dynamic>>> staffChartData = [];
|
List<List<List<dynamic>>> staffChartData = [];
|
||||||
|
|
||||||
@ -170,6 +171,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
print('Dynamic Vehicle Colors: $dynamicVehicleColors');
|
print('Dynamic Vehicle Colors: $dynamicVehicleColors');
|
||||||
|
|
||||||
List<String> newLabels = [];
|
List<String> newLabels = [];
|
||||||
|
List<String> newLabelsId = [];
|
||||||
List<List<List<dynamic>>> newChartData = [];
|
List<List<List<dynamic>>> newChartData = [];
|
||||||
List<List<String>> vehicleNames = [];
|
List<List<String>> vehicleNames = [];
|
||||||
double newMax = 0.0;
|
double newMax = 0.0;
|
||||||
@ -188,6 +190,9 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
'';
|
'';
|
||||||
newLabels.add(name);
|
newLabels.add(name);
|
||||||
|
|
||||||
|
final id = (staff['sales_executive_id'])?.toString() ?? '';
|
||||||
|
newLabelsId.add(id);
|
||||||
|
|
||||||
final products = (staff['products_list'] ?? []) as List<dynamic>;
|
final products = (staff['products_list'] ?? []) as List<dynamic>;
|
||||||
|
|
||||||
List<List<dynamic>> currentRod = [];
|
List<List<dynamic>> currentRod = [];
|
||||||
@ -232,6 +237,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
filteredStaffWise = List<Map<String, dynamic>>.from(originalStaffWise);
|
filteredStaffWise = List<Map<String, dynamic>>.from(originalStaffWise);
|
||||||
|
|
||||||
staffLabels = newLabels;
|
staffLabels = newLabels;
|
||||||
|
staffLabelsId = newLabelsId;
|
||||||
staffChartData = newChartData;
|
staffChartData = newChartData;
|
||||||
staffVehicleTypeNames = vehicleNames;
|
staffVehicleTypeNames = vehicleNames;
|
||||||
vehicleColors = dynamicVehicleColors; // Save for legend
|
vehicleColors = dynamicVehicleColors; // Save for legend
|
||||||
@ -274,79 +280,6 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In insurerContainer() you are passing staffLabels (which we now populate).
|
|
||||||
// Also set the chart maxY to some headroom:
|
|
||||||
// CustomStackedBarChart(..., maxY: (maxPremium * 1.1).ceilToDouble(), ...)
|
|
||||||
|
|
||||||
List<BarData> buildStaffBarData() {
|
|
||||||
double parseDouble(dynamic value) {
|
|
||||||
if (value == null) return 0.0;
|
|
||||||
if (value is num) return value.toDouble();
|
|
||||||
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredStaffWise.map((item) {
|
|
||||||
print('policies_current - ${item['total_policies_current_month']}');
|
|
||||||
print('policies_PREV - ${item['total_policies_pre_month']}');
|
|
||||||
|
|
||||||
print('premium_current - ${item['total_premium_current_month']}');
|
|
||||||
print('premium_PREV - ${item['total_premium_pre_month']}');
|
|
||||||
return BarData(
|
|
||||||
Colors.blue,
|
|
||||||
isInsureWisePolicy
|
|
||||||
? parseDouble(item['total_policies_current_month'])
|
|
||||||
: parseDouble(item['total_premium_current_month']),
|
|
||||||
isInsureWisePolicy
|
|
||||||
? parseDouble(item['total_policies_pre_month'])
|
|
||||||
: parseDouble(item['total_premium_pre_month']),
|
|
||||||
item['vehicle_type'] != null ? item['vehicle_type'] : 0,
|
|
||||||
'Productivity',
|
|
||||||
5,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BarData> buildProductBarData() {
|
|
||||||
double parseDouble(dynamic value) {
|
|
||||||
if (value == null) return 0.0;
|
|
||||||
if (value is num) return value.toDouble();
|
|
||||||
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredProductWise.map((item) {
|
|
||||||
print('policies_current - ${item['total_policies_current_month']}');
|
|
||||||
print('policies_PREV - ${item['total_policies_pre_month']}');
|
|
||||||
|
|
||||||
print('premium_current - ${item['total_premium_current_month']}');
|
|
||||||
print('premium_PREV - ${item['total_premium_pre_month']}');
|
|
||||||
return BarData(
|
|
||||||
Colors.blue,
|
|
||||||
isProductWisePolicy
|
|
||||||
? parseDouble(item['total_policies_current_month'])
|
|
||||||
: parseDouble(item['total_premium_current_month']),
|
|
||||||
isProductWisePolicy
|
|
||||||
? parseDouble(item['total_policies_pre_month'])
|
|
||||||
: parseDouble(item['total_premium_pre_month']),
|
|
||||||
item['vehicle_type'],
|
|
||||||
'Productivity',
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> buildProductLabels() {
|
|
||||||
return filteredProductWise.map<String>((item) {
|
|
||||||
final name = item['vehicle_type'];
|
|
||||||
if (name != null && name.toString().trim().isNotEmpty) {
|
|
||||||
return name.toString();
|
|
||||||
} else {
|
|
||||||
return item['vehicle_type']?.toString() ?? '';
|
|
||||||
}
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -417,9 +350,6 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget insurerContainer() {
|
Widget insurerContainer() {
|
||||||
final chartStaffData = buildStaffBarData();
|
|
||||||
final chartStaffLabels = buildStaffLabels();
|
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(right: 10),
|
margin: const EdgeInsets.only(right: 10),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -447,6 +377,10 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
Transform.scale(
|
Transform.scale(
|
||||||
scale: 0.5,
|
scale: 0.5,
|
||||||
child: Switch(
|
child: Switch(
|
||||||
|
activeColor: Colors.teal,
|
||||||
|
activeTrackColor: Colors.grey.shade200,
|
||||||
|
inactiveThumbColor: Colors.orange,
|
||||||
|
inactiveTrackColor: Colors.white,
|
||||||
value: isInsureWisePolicy,
|
value: isInsureWisePolicy,
|
||||||
onChanged: (val) {
|
onChanged: (val) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -463,6 +397,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CustomStackedBarChart(
|
child: CustomStackedBarChart(
|
||||||
labels: staffLabels,
|
labels: staffLabels,
|
||||||
|
labelsId: staffLabelsId,
|
||||||
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
||||||
maxY: _getSmartMaxValue(),
|
maxY: _getSmartMaxValue(),
|
||||||
initialRotation: 1,
|
initialRotation: 1,
|
||||||
@ -479,55 +414,6 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widget productContainer() {
|
|
||||||
// final chartProductData = buildProductBarData();
|
|
||||||
// final chartProductLabels = buildProductLabels();
|
|
||||||
// print('chartProductData - $chartProductData');
|
|
||||||
// print('chartProductLabels - $chartProductLabels');
|
|
||||||
// return Container(
|
|
||||||
// padding: EdgeInsets.all(10),
|
|
||||||
// margin: EdgeInsets.only(right: 20),
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// color: Colors.white,
|
|
||||||
// borderRadius: BorderRadius.circular(10),
|
|
||||||
// ),
|
|
||||||
// child: Column(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
// children: [
|
|
||||||
// Row(
|
|
||||||
// children: [
|
|
||||||
// Expanded(
|
|
||||||
// child: Text(
|
|
||||||
// 'Sales Executive Product Wise (Previous / Current Month)',
|
|
||||||
// style: _chartHeader,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Text(
|
|
||||||
// isProductWisePolicy ? "Policies" : "Premium",
|
|
||||||
// style: _styleSmall1,
|
|
||||||
// ),
|
|
||||||
// Transform.scale(
|
|
||||||
// scale: 0.5,
|
|
||||||
// child: Switch(
|
|
||||||
// value: isProductWisePolicy,
|
|
||||||
// onChanged: (val) => setState(() => isProductWisePolicy = val),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// SizedBox(height: 10),
|
|
||||||
// Expanded(
|
|
||||||
// child: CustomBarChart(
|
|
||||||
// dataList: chartProductData,
|
|
||||||
// labels: chartProductLabels,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// legendWidget(),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
Widget legendWidget() {
|
Widget legendWidget() {
|
||||||
return Wrap(
|
return Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
|
|||||||
@ -344,7 +344,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
|||||||
if (userRole == 'staff') {
|
if (userRole == 'staff') {
|
||||||
context.go(AppRoutes.enquiryForStaff);
|
context.go(AppRoutes.enquiryForStaff);
|
||||||
} else if (userRole == 'Accounts') {
|
} else if (userRole == 'Accounts') {
|
||||||
context.go(AppRoutes.payout);
|
// context.go(AppRoutes.payout);
|
||||||
|
context.go(AppRoutes.invoiceList);
|
||||||
} else {
|
} else {
|
||||||
context.go(AppRoutes.dashboard);
|
context.go(AppRoutes.dashboard);
|
||||||
}
|
}
|
||||||
|
|||||||
806
lib/presentation/screens/payout/custom_dateRange.dart
Normal file
806
lib/presentation/screens/payout/custom_dateRange.dart
Normal file
@ -0,0 +1,806 @@
|
|||||||
|
import 'package:dropdown_search/dropdown_search.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import '../../../core/services/api_service.dart';
|
||||||
|
import '../../layouts/responsive_layout.dart';
|
||||||
|
import '../../providers/manager_provider.dart';
|
||||||
|
import '../../providers/userRoleProvider.dart';
|
||||||
|
import '../../themes/indicators/date_field_theme.dart';
|
||||||
|
import '../../themes/indicators/input_field_decoration.dart';
|
||||||
|
|
||||||
|
class DateFilterRowPayout extends ConsumerStatefulWidget {
|
||||||
|
final TextEditingController startController;
|
||||||
|
final String? selectedBroker;
|
||||||
|
final List<dynamic>? selectedParnter;
|
||||||
|
final String? selectedStaffId;
|
||||||
|
final TextEditingController endController;
|
||||||
|
final ValueChanged<String?>? onBrokerChanged;
|
||||||
|
final ValueChanged<List<String>>? onPartnerChanges;
|
||||||
|
final String? dataFrom;
|
||||||
|
final VoidCallback onFilter;
|
||||||
|
final VoidCallback onRefresh;
|
||||||
|
final GlobalKey<FormState> formKey;
|
||||||
|
final bool isMobile;
|
||||||
|
final role;
|
||||||
|
final id;
|
||||||
|
|
||||||
|
const DateFilterRowPayout({
|
||||||
|
super.key,
|
||||||
|
required this.startController,
|
||||||
|
required this.endController,
|
||||||
|
required this.onFilter,
|
||||||
|
required this.onRefresh,
|
||||||
|
this.onBrokerChanged,
|
||||||
|
this.onPartnerChanges,
|
||||||
|
required this.selectedStaffId,
|
||||||
|
required this.selectedParnter,
|
||||||
|
this.selectedBroker,
|
||||||
|
required this.formKey,
|
||||||
|
required this.role,
|
||||||
|
required this.id,
|
||||||
|
this.isMobile = false,
|
||||||
|
this.dataFrom,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<DateFilterRowPayout> createState() => _DateFilterRowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DateFilterRowState extends ConsumerState<DateFilterRowPayout> {
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKeyBroker =
|
||||||
|
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
||||||
|
dropDownKeyPartner = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||||
|
|
||||||
|
late ApiService apiService;
|
||||||
|
List<dynamic>? selectedPartnerIds = [];
|
||||||
|
List<Map<String, dynamic>> getPartnerData = [];
|
||||||
|
List<Map<String, dynamic>> filteredPartnerData = [];
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getBrokerData = [];
|
||||||
|
List<Map<String, dynamic>> filteredBrokerData = [];
|
||||||
|
|
||||||
|
String? selectedStaff;
|
||||||
|
String? selectedBroker;
|
||||||
|
String? selectedPartner;
|
||||||
|
String? selectedStaffName;
|
||||||
|
dynamic role;
|
||||||
|
dynamic managerId;
|
||||||
|
|
||||||
|
bool isLoading = false;
|
||||||
|
bool isLoadingBroker = false;
|
||||||
|
bool isLoadingAgentList = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
|
|
||||||
|
Future.microtask(() {
|
||||||
|
managerId = ref.watch(managerIdProvider);
|
||||||
|
final userID = ref.watch(userIdProvider);
|
||||||
|
role = ref.watch(userRoleProvider);
|
||||||
|
print("managerId - $managerId");
|
||||||
|
if (userID != null && role != null) {
|
||||||
|
print('hansles');
|
||||||
|
getPartnerDetails(userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (managerId != null) {
|
||||||
|
print('managerId - $managerId');
|
||||||
|
getAgentList(managerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getBroker();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getBroker() async {
|
||||||
|
print('getBroker called');
|
||||||
|
setState(() {
|
||||||
|
isLoadingBroker = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchMasterDropDown('Broker');
|
||||||
|
|
||||||
|
if (response['status'] == 200) {
|
||||||
|
print('getBroker - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getBrokerData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getBrokerData');
|
||||||
|
|
||||||
|
filteredBrokerData = List.from(getBrokerData);
|
||||||
|
print('originalData - $filteredBrokerData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getBrokerData = [];
|
||||||
|
filteredBrokerData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoadingBroker = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getAgentList(id) async {
|
||||||
|
print('getAgentListData called');
|
||||||
|
setState(() {
|
||||||
|
isLoadingAgentList = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchAgentNameDropDown(id);
|
||||||
|
print('getAgentListData called response');
|
||||||
|
print('get Agent- ${response['data']}');
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
print('get Agent- ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getPartnerData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getPartnerData');
|
||||||
|
|
||||||
|
filteredPartnerData = List.from(getPartnerData);
|
||||||
|
print('originalAgentData - $filteredPartnerData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getPartnerData = [];
|
||||||
|
filteredPartnerData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoadingAgentList = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getPartnerDetails(int id) async {
|
||||||
|
print('getPartnerDetails called By handler');
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// final response = await apiService.fetchStaffUserList(id, role);
|
||||||
|
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||||
|
managerId,
|
||||||
|
id,
|
||||||
|
role,
|
||||||
|
);
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
print('getStaffDetails - ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getPartnerData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
print('API Data - $getPartnerData');
|
||||||
|
|
||||||
|
filteredPartnerData = List.from(getPartnerData);
|
||||||
|
print('originalData - $filteredPartnerData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getPartnerData = [];
|
||||||
|
filteredPartnerData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final spacing = 5.0;
|
||||||
|
|
||||||
|
List<Widget> getRowChildren(bool isMobile, double spacing) {
|
||||||
|
final dateFields = [
|
||||||
|
buildStartDate(context),
|
||||||
|
SizedBox(width: spacing),
|
||||||
|
buildEndDate(context),
|
||||||
|
SizedBox(width: spacing),
|
||||||
|
buildBroker(context),
|
||||||
|
SizedBox(width: spacing),
|
||||||
|
buildPartner(context),
|
||||||
|
SizedBox(width: spacing),
|
||||||
|
];
|
||||||
|
|
||||||
|
final buttons = [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 0.0),
|
||||||
|
// child: GestureDetector(
|
||||||
|
// onTap: () {
|
||||||
|
// if (formKey.currentState!.validate()) onFilter();
|
||||||
|
// },
|
||||||
|
// child: Icon(Icons.filter_alt_outlined),
|
||||||
|
// ),
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Filter',
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.search_rounded,
|
||||||
|
size: 18,
|
||||||
|
color: const Color(0xFF94A3B8),
|
||||||
|
),
|
||||||
|
|
||||||
|
onPressed: () {
|
||||||
|
if (widget.formKey.currentState!.validate()) {
|
||||||
|
widget.onFilter();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(0.0),
|
||||||
|
// child: GestureDetector(onTap: onRefresh, child: Icon(Icons.refresh)),
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Refresh',
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: widget.onRefresh,
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
size: 18,
|
||||||
|
color: const Color(0xFF94A3B8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
|
// For mobile: buttons below fields
|
||||||
|
return [
|
||||||
|
...dateFields,
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Row(mainAxisAlignment: MainAxisAlignment.end, children: buttons),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// For desktop: buttons inline with fields
|
||||||
|
return [...dateFields, Spacer(), ...buttons];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
key: widget.formKey,
|
||||||
|
child: widget.isMobile
|
||||||
|
? Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|
||||||
|
children: getRowChildren(widget.isMobile, spacing),
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
|
||||||
|
children: getRowChildren(widget.isMobile, spacing),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildStartDate(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Start Date', style: _textStyle),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
child: ThemedDateField(
|
||||||
|
hintText: "Select Date",
|
||||||
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
// txtheight: 50,
|
||||||
|
// backgroundColor: const Color(0xFFECECEC),
|
||||||
|
// validator: (value) => Validators.requiredField(value, "date"),
|
||||||
|
controller: widget.startController,
|
||||||
|
onDateSelected: (date) {
|
||||||
|
print("Picked Date: $date");
|
||||||
|
widget.startController.text = DateFormat(
|
||||||
|
'dd-MM-yyyy',
|
||||||
|
).format(date);
|
||||||
|
// controllers['date']?.text = date as String;
|
||||||
|
Future.microtask(() => widget.onFilter());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildEndDate(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('End Date', style: _textStyle),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
child: ThemedDateField(
|
||||||
|
hintText: "Select Date",
|
||||||
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
// txtheight: 50,
|
||||||
|
// backgroundColor: const Color(0xFFECECEC),
|
||||||
|
validator: (value) {
|
||||||
|
final fromText = widget.startController.text ?? '';
|
||||||
|
if (fromText.isNotEmpty) {
|
||||||
|
final startDate = DateFormat('dd-MM-yyyy').parse(fromText);
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return "End Date is required";
|
||||||
|
}
|
||||||
|
final endDate = DateFormat('dd-MM-yyyy').parse(value);
|
||||||
|
|
||||||
|
if (endDate.isBefore(startDate)) {
|
||||||
|
return "End Date cannot be earlier than Start Date";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; // ✅ no error
|
||||||
|
},
|
||||||
|
controller: widget.endController,
|
||||||
|
lastDate: DateTime.now(),
|
||||||
|
onDateSelected: (date) {
|
||||||
|
print("Picked Date: $date");
|
||||||
|
widget.endController.text = DateFormat('dd-MM-yyyy').format(date);
|
||||||
|
Future.microtask(() => widget.onFilter());
|
||||||
|
// controllers['date']?.text = date as String;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildBroker(BuildContext context) {
|
||||||
|
Map<String, dynamic>? selectedBrokers = filteredBrokerData.firstWhere(
|
||||||
|
(item) => item['id'].toString() == widget.selectedBroker,
|
||||||
|
orElse: () => {},
|
||||||
|
);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Broker', style: _textStyle),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.15,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
key: dropDownKeyBroker,
|
||||||
|
selectedItem: selectedBrokers.isNotEmpty ? selectedBrokers : null,
|
||||||
|
items: (filter, infiniteScrollProps) {
|
||||||
|
return filteredBrokerData;
|
||||||
|
},
|
||||||
|
|
||||||
|
itemAsString: (val) => val['name'].toString(), // what to show
|
||||||
|
compareFn: (item, selectedItem) =>
|
||||||
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
|
// validator: (val) {
|
||||||
|
// if (val == null) {
|
||||||
|
// return "Required"; // ✅ error message
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// },
|
||||||
|
suffixProps: DropdownSuffixProps(
|
||||||
|
// make sure the dropdown button is visible
|
||||||
|
dropdownButtonProps: DropdownButtonProps(
|
||||||
|
isVisible: true,
|
||||||
|
padding: EdgeInsets.zero, // remove default padding
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
// shrink icon tap area
|
||||||
|
minWidth: 12,
|
||||||
|
minHeight: 12,
|
||||||
|
),
|
||||||
|
iconSize: 15, // smaller icon
|
||||||
|
// icon: const Icon(Icons.arrow_drop_down),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownBuilder: (context, selectedItem) => Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem != null ? selectedItem['name'].toString() : "",
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.black,
|
||||||
|
// color: Color(0XFF6366F1),
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
decoratorProps: DropDownDecoratorProps(
|
||||||
|
decoration:
|
||||||
|
AppInputDecorations.dropdownDecoration(
|
||||||
|
label: "Broker",
|
||||||
|
).copyWith(
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
|
isDense: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
menuProps: MenuProps(
|
||||||
|
backgroundColor:
|
||||||
|
Colors.white, // 👈 sets dropdown background to white
|
||||||
|
),
|
||||||
|
showSearchBox: true,
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(1),
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search Broker...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
), // 👈 Normal border
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
width: 1.5,
|
||||||
|
), // 👈 Focused border
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['name'].toString(),
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// constraints: BoxConstraints(),
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val != null) {
|
||||||
|
print("Selected Broker : ${val['name']}");
|
||||||
|
print("Id: ${val['id']}");
|
||||||
|
// selectedBroker = val['id'];
|
||||||
|
widget.onBrokerChanged?.call(val['id'].toString());
|
||||||
|
// widget.onBrokerChanged?.call(val['id']);
|
||||||
|
// controllers['agentId']?.text = val['agent_code'];
|
||||||
|
// agentId = agent['id'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildPartner(BuildContext context) {
|
||||||
|
final isReadOnly = false;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Referer", style: _textStyle),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
width: MediaQuery.of(context).size.width * 0.42,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>.multiSelection(
|
||||||
|
key: dropDownKeyPartner,
|
||||||
|
|
||||||
|
// selectedItem: selectedHandlered.isNotEmpty
|
||||||
|
// ? selectedHandlered
|
||||||
|
// : null,
|
||||||
|
selectedItems: filteredPartnerData
|
||||||
|
.where(
|
||||||
|
(item) => (selectedPartnerIds ?? []).contains(item['id']),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
items: (filter, infiniteScrollProps) {
|
||||||
|
return filteredPartnerData;
|
||||||
|
},
|
||||||
|
|
||||||
|
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;
|
||||||
|
// },
|
||||||
|
validator: (val) {
|
||||||
|
if (val == null || val.isEmpty) {
|
||||||
|
return "Required";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
decoratorProps: DropDownDecoratorProps(
|
||||||
|
decoration:
|
||||||
|
AppInputDecorations.dropdownDecoration(
|
||||||
|
label: "Select Partner",
|
||||||
|
).copyWith(
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
// color: Colors.white,
|
||||||
|
), // 👈 Normal border
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xFFE2E8F0),
|
||||||
|
// color: Colors.white,
|
||||||
|
width: 1.5,
|
||||||
|
), // 👈 Focused border
|
||||||
|
),
|
||||||
|
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
popupProps: PopupPropsMultiSelection.menu(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
showSearchBox: true,
|
||||||
|
menuProps: MenuProps(backgroundColor: Colors.white),
|
||||||
|
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
autofocus: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search Partner...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
// color: Colors.blue,
|
||||||
|
color: Color(0xFFEDF6F5),
|
||||||
|
width: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['name'].toString(),
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (List<Map<String, dynamic>> selectedVals) {
|
||||||
|
// selectedPartnerIds = selectedVals
|
||||||
|
// .map((v) => v['id'].toString())
|
||||||
|
// .toList();
|
||||||
|
final ids = selectedVals.map((v) => v['id'].toString()).toList();
|
||||||
|
print("Selected PArnter IDs: $selectedPartnerIds");
|
||||||
|
widget.onPartnerChanges?.call(ids);
|
||||||
|
// widget.onPartnerChanges!(v['id']);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildSelectStaffMem(BuildContext context) {
|
||||||
|
Map<String, dynamic>? selectedVehicle;
|
||||||
|
if (widget.selectedStaffId == null) {
|
||||||
|
selectedVehicle = null;
|
||||||
|
} else if (widget.selectedStaffId != null) {
|
||||||
|
selectedVehicle = filteredPartnerData.firstWhere(
|
||||||
|
(item) => item['id'] == widget.selectedStaffId,
|
||||||
|
orElse: () => {}, // empty map
|
||||||
|
);
|
||||||
|
if (selectedVehicle.isEmpty) selectedVehicle = null;
|
||||||
|
} else if (selectedStaff != null) {
|
||||||
|
selectedVehicle = filteredPartnerData.firstWhere(
|
||||||
|
(item) => item['id'] == selectedStaff,
|
||||||
|
orElse: () => {}, // empty map
|
||||||
|
);
|
||||||
|
if (selectedVehicle.isEmpty) selectedVehicle = null;
|
||||||
|
} else {
|
||||||
|
selectedVehicle = null;
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Text("Staff Name", style: _textStyle),
|
||||||
|
// SizedBox(height: 10),
|
||||||
|
SizedBox(
|
||||||
|
height: 35,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
border: Border.all(color: Color(0xFFE2E8F0)),
|
||||||
|
// color: Colors.black,
|
||||||
|
),
|
||||||
|
|
||||||
|
width: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.13,
|
||||||
|
// height: 45,
|
||||||
|
child: DropdownSearch<Map<String, dynamic>>(
|
||||||
|
// key: dropDownKey,
|
||||||
|
key: ValueKey(selectedStaff),
|
||||||
|
// selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||||
|
selectedItem: selectedVehicle,
|
||||||
|
|
||||||
|
items: (filter, infiniteScrollProps) {
|
||||||
|
return filteredPartnerData;
|
||||||
|
},
|
||||||
|
|
||||||
|
itemAsString: (val) => val['name'].toString(),
|
||||||
|
compareFn: (item, selectedItem) =>
|
||||||
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
|
dropdownBuilder: (context, selectedItem) => Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
selectedItem != null ? selectedItem['name'].toString() : "",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11, color: Colors.black),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
decoratorProps: DropDownDecoratorProps(
|
||||||
|
decoration:
|
||||||
|
AppInputDecorations.dropdownDecoration(
|
||||||
|
label: "Select Staff ",
|
||||||
|
).copyWith(
|
||||||
|
filled: true,
|
||||||
|
fillColor:
|
||||||
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 6,
|
||||||
|
vertical: 1, // 👈 adjust this to make the field shorter
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
popupProps: PopupProps.menu(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
constraints: BoxConstraints(maxHeight: 250),
|
||||||
|
menuProps: MenuProps(
|
||||||
|
backgroundColor:
|
||||||
|
Colors.white, // 👈 sets dropdown background to white
|
||||||
|
),
|
||||||
|
showSearchBox: true,
|
||||||
|
searchFieldProps: TextFieldProps(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
hintText: "Search Staff ...",
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
), // 👈 Normal border
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Colors.white,
|
||||||
|
width: 1.5,
|
||||||
|
), // 👈 Focused border
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||||
|
return Container(
|
||||||
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 3,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
item['name'].toString(),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
// constraints: BoxConstraints(),
|
||||||
|
),
|
||||||
|
|
||||||
|
onChanged: (val) {
|
||||||
|
if (val != null) {
|
||||||
|
print("Selected Staff : ${val['name']}");
|
||||||
|
print("Id: ${val['id']}");
|
||||||
|
// selectedStaffName = val['name'];
|
||||||
|
// selectedStaff = val['id'];
|
||||||
|
widget.onBrokerChanged!(val['id']);
|
||||||
|
// if (widget.onFilterStaff != null)
|
||||||
|
// widget.onFilterStaff!(val['id']);
|
||||||
|
|
||||||
|
// Future.microtask(() => widget.onFilter());
|
||||||
|
// controllers['agentId']?.text = val['agent_code'];
|
||||||
|
// agentId = agent['id'];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final _textStyle = GoogleFonts.poppins(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -177,13 +177,16 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
(item['invoice_no'] ?? '-').toLowerCase().contains(
|
(item['invoice_no'] ?? '-').toLowerCase().contains(
|
||||||
query.toLowerCase(),
|
query.toLowerCase(),
|
||||||
) ||
|
) ||
|
||||||
(item['invoice_amount'] ?? '-').toLowerCase().contains(
|
(item['invoice_amount_indian_format'] ?? '-')
|
||||||
query.toLowerCase(),
|
.toLowerCase()
|
||||||
) ||
|
.contains(query.toLowerCase()) ||
|
||||||
(item['broker_name'] ?? '-').toLowerCase().contains(
|
(item['broker_name'] ?? '-').toLowerCase().contains(
|
||||||
query.toLowerCase(),
|
query.toLowerCase(),
|
||||||
) ||
|
) ||
|
||||||
(item['agent_name'] ?? '-').toLowerCase().contains(
|
(item['pos_name'] ?? '-').toLowerCase().contains(
|
||||||
|
query.toLowerCase(),
|
||||||
|
) ||
|
||||||
|
(item['payout_status'] ?? '-').toLowerCase().contains(
|
||||||
query.toLowerCase(),
|
query.toLowerCase(),
|
||||||
)
|
)
|
||||||
// ||
|
// ||
|
||||||
@ -195,7 +198,7 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
|
|
||||||
final TextEditingController _searchStaffController = TextEditingController();
|
final TextEditingController _searchStaffController = TextEditingController();
|
||||||
|
|
||||||
String _formatDate(String rawDate) {
|
String _formatDateTime(String rawDate) {
|
||||||
try {
|
try {
|
||||||
final dateTime = DateTime.parse(rawDate);
|
final dateTime = DateTime.parse(rawDate);
|
||||||
return DateFormat('dd-MM-yyyy HH:mm').format(dateTime); // 24-hour format
|
return DateFormat('dd-MM-yyyy HH:mm').format(dateTime); // 24-hour format
|
||||||
@ -204,61 +207,69 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _formatDate(String rawDate) {
|
||||||
|
try {
|
||||||
|
final dateTime = DateTime.parse(rawDate);
|
||||||
|
return DateFormat('dd-MM-yyyy').format(dateTime); // 24-hour format
|
||||||
|
} catch (e) {
|
||||||
|
return rawDate; // fallback if parsing fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MainLayout(
|
return MainLayout(
|
||||||
title: "Pay Out",
|
title: "Pay Out",
|
||||||
body: Container(
|
body: Container(
|
||||||
height: 30,
|
// height: 30,
|
||||||
// color: Colors.yellow.shade50,
|
// color: Colors.yellow.shade50,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
// Container(
|
||||||
height: 30,
|
// height: 30,
|
||||||
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: [
|
||||||
// Tooltip(
|
// // Tooltip(
|
||||||
// message: 'Back',
|
// // message: 'Back',
|
||||||
// child: IconButton(
|
// // child: IconButton(
|
||||||
// icon: const Icon(
|
// // icon: const Icon(
|
||||||
// Icons.arrow_left_sharp,
|
// // Icons.arrow_left_sharp,
|
||||||
// size: 25,
|
// // size: 25,
|
||||||
// color: Color(0xFF425B5B),
|
// // color: Color(0xFF425B5B),
|
||||||
// ),
|
// // ),
|
||||||
// onPressed: () {
|
// // onPressed: () {
|
||||||
// context.go(AppRoutes.dashboard);
|
// // context.go(AppRoutes.dashboard);
|
||||||
// },
|
// // },
|
||||||
// splashRadius: 18,
|
// // splashRadius: 18,
|
||||||
// hoverColor: Colors.black12,
|
// // hoverColor: Colors.black12,
|
||||||
// padding: const EdgeInsets.all(4),
|
// // padding: const EdgeInsets.all(4),
|
||||||
// constraints: const BoxConstraints(),
|
// // constraints: const BoxConstraints(),
|
||||||
// ),
|
// // ),
|
||||||
// ),
|
// // ),
|
||||||
// const SizedBox(width: 5), // spacing between icon and text
|
// // const SizedBox(width: 5), // spacing between icon and text
|
||||||
Text(
|
// Text(
|
||||||
"Invoice",
|
// "Invoice",
|
||||||
style: GoogleFonts.inter(
|
// style: GoogleFonts.inter(
|
||||||
fontSize: 14,
|
// fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
// fontWeight: FontWeight.w500,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
|
//
|
||||||
SizedBox(height: 5),
|
// SizedBox(height: 5),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
@ -306,71 +317,15 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
// if (!ResponsiveLayout.isMobile(context)) ...[
|
Text(
|
||||||
// DateFilterRow(
|
"Invoice",
|
||||||
// dataFrom: 'Policy',
|
style: GoogleFonts.poppins(
|
||||||
// role: roleId,
|
fontSize: 14,
|
||||||
// id: userId,
|
fontWeight: FontWeight.w400,
|
||||||
// onFilterStaff: (val) {
|
),
|
||||||
// print('Selected Filterd STAFF Id - $val');
|
),
|
||||||
// SelectedStaffId = val;
|
|
||||||
// },
|
Spacer(),
|
||||||
// selectedStaffId: SelectedStaffId,
|
|
||||||
// startController: controllers['startDate']!,
|
|
||||||
// endController: controllers['endDate']!,
|
|
||||||
// onStatusChanged: (val) {
|
|
||||||
// SelectedStatus = val; // update parent
|
|
||||||
// },
|
|
||||||
// formKey: _formKey,
|
|
||||||
// isMobile: ResponsiveLayout.isMobile(context),
|
|
||||||
// onFilter: () {
|
|
||||||
// // call your filter logic
|
|
||||||
// filterDateRange();
|
|
||||||
// },
|
|
||||||
// onRefresh: () {
|
|
||||||
// // call your refresh logic
|
|
||||||
// refrshfilterDateRange();
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
//
|
|
||||||
// // Form(
|
|
||||||
// // key: _formKey,
|
|
||||||
// // child: Row(
|
|
||||||
// // mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
// // crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
// // children: [
|
|
||||||
// // buildStartDate(context),
|
|
||||||
// // SizedBox(width: 10),
|
|
||||||
// // buildEndDate(context),
|
|
||||||
// // SizedBox(width: 10),
|
|
||||||
// //
|
|
||||||
// // Padding(
|
|
||||||
// // padding: const EdgeInsets.symmetric(
|
|
||||||
// // vertical: 8.0,
|
|
||||||
// // ),
|
|
||||||
// // child: GestureDetector(
|
|
||||||
// // // onTap: filterDateRange,
|
|
||||||
// // onTap: () {
|
|
||||||
// // if (_formKey.currentState!.validate()) {
|
|
||||||
// // filterDateRange(); // only runs if valid
|
|
||||||
// // }
|
|
||||||
// // },
|
|
||||||
// // child: Icon(Icons.filter_alt_outlined),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// //
|
|
||||||
// // Padding(
|
|
||||||
// // padding: const EdgeInsets.all(8.0),
|
|
||||||
// // child: GestureDetector(
|
|
||||||
// // onTap: refrshfilterDateRange,
|
|
||||||
// // child: Icon(Icons.refresh),
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// // ],
|
|
||||||
// // ),
|
|
||||||
// // ),
|
|
||||||
// Spacer(),
|
|
||||||
// ],
|
|
||||||
ThemedSearchField(
|
ThemedSearchField(
|
||||||
hintText: 'Search',
|
hintText: 'Search',
|
||||||
// backgroundColor: Color(0xFFF6F8F8),
|
// backgroundColor: Color(0xFFF6F8F8),
|
||||||
@ -383,24 +338,13 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'Export File',
|
message: 'Raise Invoice',
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
context.go(AppRoutes.payout);
|
context.go(AppRoutes.payout);
|
||||||
},
|
},
|
||||||
// onTap: () {
|
|
||||||
// print('TAV ExcelExporter');
|
|
||||||
//
|
|
||||||
// ExcelExporter.exportToExcel(
|
|
||||||
// sheetName: sheetName,
|
|
||||||
// data: data,
|
|
||||||
// headers: headers,
|
|
||||||
// fileName: fileName,
|
|
||||||
// keys: keys!,
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(4.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF2E7D6E),
|
color: const Color(0xFF2E7D6E),
|
||||||
// color: const Color(0xFF425B5B),
|
// color: const Color(0xFF425B5B),
|
||||||
@ -414,7 +358,7 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
// height: 25,
|
// height: 25,
|
||||||
// width: 25,
|
// width: 25,
|
||||||
// ),
|
// ),
|
||||||
Icon(Icons.add, color: Colors.white, size: 25),
|
Icon(Icons.add, color: Colors.white, size: 18),
|
||||||
// Image.asset("assets/miscellaneous/export", height: 15, width: 15),
|
// Image.asset("assets/miscellaneous/export", height: 15, width: 15),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -428,20 +372,22 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
data: filteredData,
|
data: filteredData,
|
||||||
txt: true,
|
txt: true,
|
||||||
displayHeaders: [
|
displayHeaders: [
|
||||||
"Updated Date",
|
|
||||||
"Invoice Date",
|
|
||||||
"Invoice No",
|
"Invoice No",
|
||||||
|
"Invoice Date",
|
||||||
"Invoice Amount",
|
"Invoice Amount",
|
||||||
"Broker Name",
|
"Broker ",
|
||||||
"Partner Name",
|
"POS ",
|
||||||
|
"Status ",
|
||||||
|
"Updated Date",
|
||||||
],
|
],
|
||||||
keys: [
|
keys: [
|
||||||
"updated_at",
|
|
||||||
"invoice_date",
|
"invoice_date",
|
||||||
"invoice_no",
|
"invoice_no",
|
||||||
"invoice_amount",
|
"invoice_amount_indian_format",
|
||||||
"broker_name",
|
"broker_name",
|
||||||
"agent_name",
|
"pos_name",
|
||||||
|
"payout_status",
|
||||||
|
"updated_at",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -450,34 +396,32 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFFEDF6F5),
|
color: Color(0xFFF1F5F9),
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(flex: 3, child: Text('Invoice No', style: _headerStyle)),
|
Expanded(flex: 3, child: Text('Invoice No', style: _headerStyle)),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text('Invoice Date', style: _headerStyle),
|
child: Text('Invoice Date', style: _headerStyle),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text('Invoice Amount', style: _headerStyle),
|
child: Text('Invoice Amount', style: _headerStyle),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text('Broker Name', style: _headerStyle),
|
child: Text('Broker Name', style: _headerStyle),
|
||||||
),
|
),
|
||||||
|
Expanded(flex: 2, child: Text('POS Name', style: _headerStyle)),
|
||||||
|
Expanded(flex: 2, child: Text('Status', style: _headerStyle)),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text('Partner Name', style: _headerStyle),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: Text('Updated Date', style: _headerStyle),
|
child: Text('Updated Date', style: _headerStyle),
|
||||||
),
|
),
|
||||||
Expanded(flex: 3, child: Text('Action', style: _headerStyle)),
|
Expanded(flex: 2, child: Text('Action', style: _headerStyle)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -516,7 +460,7 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
|
|
||||||
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
Widget _buildDataRow(Map<String, dynamic> item, sno) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 16),
|
||||||
// margin: const EdgeInsets.only(top: 10),
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -533,40 +477,62 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
child: Text(item['invoice_no'] ?? '-', style: _dataBold),
|
child: Text(item['invoice_no'] ?? '-', style: _dataBold),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text(item['invoice_date'] ?? '-', style: _dataBold),
|
child: Text(
|
||||||
|
item['invoice_date'] != null
|
||||||
|
? _formatDate(item['invoice_date'])
|
||||||
|
: '-',
|
||||||
|
style: _dataBold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
item['invoice_amount'] ?? '-',
|
item['invoice_amount_indian_format'] ?? '-',
|
||||||
style: _dataBold,
|
style: _dataBold,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
item['broker_name'] ?? '-',
|
item['broker_name'] != null ? item['broker_name'] : '-',
|
||||||
style: _dataBold,
|
style: _dataBold,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
item['agent_name'] ?? '-',
|
item['pos_name'] != null ? item['pos_name'] : '-',
|
||||||
style: _dataBold,
|
style: _dataBold,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 2,
|
||||||
child: Text(
|
child: Text(
|
||||||
_formatDate(item['updated_at']) ?? '-',
|
// item['payout_status'] != null ? item['payout_status'] : '-',
|
||||||
|
item['payout_status'] == '1'
|
||||||
|
? 'Pending'
|
||||||
|
: item['payout_status'] != null
|
||||||
|
? 'Completed'
|
||||||
|
: '-',
|
||||||
|
style: _dataBold,
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Text(
|
||||||
|
item['updated_at'] != null
|
||||||
|
? _formatDateTime(item['updated_at'])
|
||||||
|
: '-',
|
||||||
style: _dataBold,
|
style: _dataBold,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
@ -577,27 +543,38 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// EDIT ICON
|
// EDIT ICON
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.edit, color: Colors.blue, size: 20),
|
icon: const Icon(
|
||||||
|
Icons.remove_red_eye_outlined,
|
||||||
|
color: Colors.blue,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: handle edit
|
// TODO: handle edit
|
||||||
context.go(AppRoutes.payout, extra: item);
|
context.go(AppRoutes.payout, extra: item);
|
||||||
print("Edit clicked for ${item['invoice_no']}");
|
print("Edit clicked for ${item['invoice_no']}");
|
||||||
},
|
},
|
||||||
|
splashRadius: 18,
|
||||||
|
hoverColor: Colors.black12,
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
|
||||||
|
|
||||||
// DELETE ICON
|
// DELETE ICON
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.delete, color: Colors.red, size: 20),
|
icon: const Icon(Icons.delete, color: Colors.red, size: 18),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: handle delete
|
// TODO: handle delete
|
||||||
deleteInvoice(item['id']);
|
deleteInvoice(item['id']);
|
||||||
print("Delete clicked for ${item['invoice_no']}");
|
print("Delete clicked for ${item['invoice_no']}");
|
||||||
},
|
},
|
||||||
|
splashRadius: 18,
|
||||||
|
hoverColor: Colors.black12,
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -608,14 +585,14 @@ class _InvoiceListState extends ConsumerState<InvoiceList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final _dataBold = GoogleFonts.inter(
|
static final _dataBold = GoogleFonts.inter(
|
||||||
fontSize: 14,
|
fontSize: 11.5,
|
||||||
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: Color(0xFF000000),
|
color: Color(0xFF000000),
|
||||||
);
|
);
|
||||||
|
|
||||||
static final _headerStyle = GoogleFonts.inter(
|
static final _headerStyle = GoogleFonts.poppins(
|
||||||
color: Colors.black,
|
fontSize: 11.2,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
1070
lib/presentation/screens/payout/payout_old.dart
Normal file
1070
lib/presentation/screens/payout/payout_old.dart
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -371,46 +371,62 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Wrap(
|
return Form(
|
||||||
spacing: 12,
|
key: _formKey,
|
||||||
runSpacing: 12,
|
child: Wrap(
|
||||||
children: [
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
buildSelectStaffMem(context),
|
spacing: 12,
|
||||||
buildAgentName(context, fromHeader: false),
|
runSpacing: 12,
|
||||||
buildInsurer(context),
|
children: [
|
||||||
buildBroker(context),
|
buildSelectStaffMem(context),
|
||||||
buildInsuredName(context),
|
buildAgentName(context, fromHeader: false),
|
||||||
buildVehicleNumber(context),
|
buildInsurer(context),
|
||||||
buildEmail(context),
|
buildBroker(context),
|
||||||
buildPhNumber(context),
|
buildInsuredName(context),
|
||||||
buildRemarks(context),
|
buildVehicleNumber(context),
|
||||||
|
buildEmail(context),
|
||||||
|
buildPhNumber(context),
|
||||||
|
buildRemarks(context),
|
||||||
|
|
||||||
IconButton(
|
Row(
|
||||||
tooltip: 'Save',
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: EdgeInsets.zero,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
constraints: const BoxConstraints(minWidth: 24, minHeight: 24),
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
icon: const Icon(
|
|
||||||
Icons.check,
|
|
||||||
color: Colors.green,
|
|
||||||
size: 28, // smaller icon
|
|
||||||
),
|
|
||||||
splashRadius: 14, //
|
|
||||||
onPressed: () => widget.onSave(widget.selectId),
|
|
||||||
),
|
|
||||||
|
|
||||||
IconButton(
|
children: [
|
||||||
tooltip: 'Close',
|
IconButton(
|
||||||
padding: EdgeInsets.zero,
|
tooltip: 'Save',
|
||||||
constraints: const BoxConstraints(minWidth: 24, minHeight: 24),
|
padding: EdgeInsets.zero,
|
||||||
icon: const Icon(
|
constraints: const BoxConstraints(minWidth: 14, minHeight: 24),
|
||||||
Icons.close,
|
icon: const Icon(
|
||||||
color: Colors.indigo,
|
Icons.check,
|
||||||
size: 28, // smaller icon
|
color: Colors.green,
|
||||||
|
size: 20, // smaller icon
|
||||||
|
),
|
||||||
|
splashRadius: 14, //
|
||||||
|
onPressed: () {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
|
||||||
|
widget.onSave(widget.selectId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Close',
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
constraints: const BoxConstraints(minWidth: 14, minHeight: 24),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
color: Colors.indigo,
|
||||||
|
size: 20, // smaller icon
|
||||||
|
),
|
||||||
|
splashRadius: 14, //
|
||||||
|
onPressed: widget.onClose,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
splashRadius: 14, //
|
],
|
||||||
onPressed: widget.onClose,
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,12 +462,12 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
itemAsString: (val) => val['name'].toString(), // what to show
|
itemAsString: (val) => val['name'].toString(), // what to show
|
||||||
compareFn: (item, selectedItem) =>
|
compareFn: (item, selectedItem) =>
|
||||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
validator: (val) {
|
// validator: (val) {
|
||||||
if (val == null) {
|
// if (val == null) {
|
||||||
return "Required"; // ✅ error message
|
// return "Required"; // ✅ error message
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
},
|
// },
|
||||||
suffixProps: DropdownSuffixProps(
|
suffixProps: DropdownSuffixProps(
|
||||||
// make sure the dropdown button is visible
|
// make sure the dropdown button is visible
|
||||||
dropdownButtonProps: DropdownButtonProps(
|
dropdownButtonProps: DropdownButtonProps(
|
||||||
@ -608,6 +624,10 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
hintText: 'Vehicle Number',
|
hintText: 'Vehicle Number',
|
||||||
borderColor: Color(0XFF6366F1),
|
borderColor: Color(0XFF6366F1),
|
||||||
textColr: Color(0XFF6366F1),
|
textColr: Color(0XFF6366F1),
|
||||||
|
enableBorderWidth: 0.5,
|
||||||
|
bordedRad: 5,
|
||||||
|
errFieldHgt: 10,
|
||||||
|
errFieldFont: 0,
|
||||||
isdense: true,
|
isdense: true,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
UpperCaseTextFormatter(), // 👈 custom formatter for uppercase
|
UpperCaseTextFormatter(), // 👈 custom formatter for uppercase
|
||||||
@ -662,7 +682,7 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
// errorText: fieldErrors['name'],
|
// errorText: fieldErrors['name'],
|
||||||
borderColor: Color(0XFF6366F1),
|
borderColor: Color(0XFF6366F1),
|
||||||
isdense: true,
|
isdense: true,
|
||||||
validator: (value) => Validators.requiredField(value, "name"),
|
// validator: (value) => Validators.requiredField(value, "name"),
|
||||||
widthNone: true,
|
widthNone: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -678,11 +698,15 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width * 0.1,
|
width: MediaQuery.of(context).size.width * 0.1,
|
||||||
child: ThemedFormInlineField(
|
child: ThemedFormField(
|
||||||
controller: widget.controllers['email']!,
|
controller: widget.controllers['email']!,
|
||||||
borderColor: Color(0XFF6366F1),
|
borderColor: Color(0XFF6366F1),
|
||||||
textColr: Color(0XFF6366F1),
|
textColr: Color(0XFF6366F1),
|
||||||
hintText: 'Email',
|
hintText: 'Email',
|
||||||
|
bordedRad: 5,
|
||||||
|
enableBorderWidth: 0.5,
|
||||||
|
// errFieldHgt: 10,
|
||||||
|
// errFieldFont: 0,
|
||||||
isdense: true,
|
isdense: true,
|
||||||
validator: (value) => Validators.nonReqemail(value, "email"),
|
validator: (value) => Validators.nonReqemail(value, "email"),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
@ -705,15 +729,17 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
SizedBox(height: 5),
|
SizedBox(height: 5),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width * 0.1,
|
width: MediaQuery.of(context).size.width * 0.1,
|
||||||
child: ThemedFormInlineField(
|
child: ThemedFormField(
|
||||||
controller: widget.controllers['mobile']!,
|
controller: widget.controllers['mobile']!,
|
||||||
borderColor: Color(0XFF6366F1),
|
borderColor: Color(0XFF6366F1),
|
||||||
textColr: Color(0XFF6366F1),
|
textColr: Color(0XFF6366F1),
|
||||||
hintText: 'Mobile',
|
hintText: 'Mobile',
|
||||||
|
enableBorderWidth: 0.5,
|
||||||
|
bordedRad: 5,
|
||||||
isdense: true,
|
isdense: true,
|
||||||
validator: (value) => Validators.nonReqphone(value, "phone"),
|
validator: (value) => Validators.nonReqphone(value, "phone"),
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(r'[ 0-9]')),
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||||
],
|
],
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
@ -737,6 +763,7 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
controller: widget.controllers['remarks']!,
|
controller: widget.controllers['remarks']!,
|
||||||
borderColor: Color(0XFF6366F1),
|
borderColor: Color(0XFF6366F1),
|
||||||
textColr: Color(0XFF6366F1),
|
textColr: Color(0XFF6366F1),
|
||||||
|
bordedRad: 5,
|
||||||
verticalPad: 10,
|
verticalPad: 10,
|
||||||
horizonalPad: 10,
|
horizonalPad: 10,
|
||||||
isdense: true,
|
isdense: true,
|
||||||
@ -785,12 +812,12 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
itemAsString: (val) => val['name'].toString(),
|
itemAsString: (val) => val['name'].toString(),
|
||||||
compareFn: (item, selectedItem) =>
|
compareFn: (item, selectedItem) =>
|
||||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
validator: (val) {
|
// validator: (val) {
|
||||||
if (val == null) {
|
// if (val == null) {
|
||||||
return "Required"; // ✅ error message
|
// return "Required"; // ✅ error message
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
},
|
// },
|
||||||
suffixProps: DropdownSuffixProps(
|
suffixProps: DropdownSuffixProps(
|
||||||
// make sure the dropdown button is visible
|
// make sure the dropdown button is visible
|
||||||
dropdownButtonProps: DropdownButtonProps(
|
dropdownButtonProps: DropdownButtonProps(
|
||||||
@ -963,12 +990,12 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
itemAsString: (val) => val['short_name'].toString(), // what to show
|
itemAsString: (val) => val['short_name'].toString(), // what to show
|
||||||
compareFn: (item, selectedItem) =>
|
compareFn: (item, selectedItem) =>
|
||||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
validator: (val) {
|
// validator: (val) {
|
||||||
if (val == null) {
|
// if (val == null) {
|
||||||
return "Required"; // ✅ error message
|
// return "Required"; // ✅ error message
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
},
|
// },
|
||||||
suffixProps: DropdownSuffixProps(
|
suffixProps: DropdownSuffixProps(
|
||||||
// make sure the dropdown button is visible
|
// make sure the dropdown button is visible
|
||||||
dropdownButtonProps: DropdownButtonProps(
|
dropdownButtonProps: DropdownButtonProps(
|
||||||
@ -1117,12 +1144,12 @@ class _SubRowWidgetState extends ConsumerState<SubRowWidget> {
|
|||||||
itemAsString: (val) => val['name'].toString(), // what to show
|
itemAsString: (val) => val['name'].toString(), // what to show
|
||||||
compareFn: (item, selectedItem) =>
|
compareFn: (item, selectedItem) =>
|
||||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||||
validator: (val) {
|
// validator: (val) {
|
||||||
if (val == null) {
|
// if (val == null) {
|
||||||
return "Required"; // ✅ error message
|
// return "Required"; // ✅ error message
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
},
|
// },
|
||||||
suffixProps: DropdownSuffixProps(
|
suffixProps: DropdownSuffixProps(
|
||||||
// make sure the dropdown button is visible
|
// make sure the dropdown button is visible
|
||||||
dropdownButtonProps: DropdownButtonProps(
|
dropdownButtonProps: DropdownButtonProps(
|
||||||
|
|||||||
@ -52,12 +52,14 @@ class EnquiryListStaffInline extends ConsumerStatefulWidget {
|
|||||||
class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
int itemsPerPage = 10;
|
int itemsPerPage = 10;
|
||||||
|
// int itemsPerPage = 5;
|
||||||
|
|
||||||
int completedCurrentPage = 1;
|
int completedCurrentPage = 1;
|
||||||
|
// int completedItemsPerPage = 5;
|
||||||
int completedItemsPerPage = 50;
|
int completedItemsPerPage = 50;
|
||||||
int totalCompletedPages = 1;
|
int totalCompletedPages = 1;
|
||||||
List<int> itemsPerPageOptions = [25, 50, 100, 200];
|
List<int> itemsPerPageOptions = [25, 50, 100, 200];
|
||||||
|
Timer? _debounce;
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
dynamic userId;
|
dynamic userId;
|
||||||
dynamic idPrimary;
|
dynamic idPrimary;
|
||||||
@ -389,21 +391,80 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add this getter method to calculate paginated completed data
|
// Add this getter method to calculate paginated completed data
|
||||||
|
// List<Map<String, dynamic>> get paginatedCompletedData {
|
||||||
|
// if (completedData.isEmpty) return [];
|
||||||
|
//
|
||||||
|
// // Calculate total pages
|
||||||
|
// totalCompletedPages = (completedData.length / completedItemsPerPage).ceil();
|
||||||
|
//
|
||||||
|
// // Calculate start and end indices
|
||||||
|
// final startIndex = (completedCurrentPage - 1) * completedItemsPerPage;
|
||||||
|
// final endIndex = (startIndex + completedItemsPerPage).clamp(
|
||||||
|
// 0,
|
||||||
|
// completedData.length,
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// // Return paginated subset
|
||||||
|
// return completedData.sublist(startIndex, endIndex);
|
||||||
|
// }
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> get paginatedCompletedData1 {
|
||||||
|
// If search is active (filteredData is different from completedData), use filteredData
|
||||||
|
// Otherwise use completedData
|
||||||
|
final dataToUse = filteredData;
|
||||||
|
|
||||||
|
print("paginatedCompletedData - $dataToUse");
|
||||||
|
|
||||||
|
if (dataToUse.isEmpty) return [];
|
||||||
|
|
||||||
|
// For completed tab only
|
||||||
|
if (selectedIndex == 1) {
|
||||||
|
// Calculate total pages based on current data
|
||||||
|
totalCompletedPages = (dataToUse.length / completedItemsPerPage).ceil();
|
||||||
|
if (totalCompletedPages == 0) totalCompletedPages = 1;
|
||||||
|
|
||||||
|
// Calculate start and end indices
|
||||||
|
final startIndex = (completedCurrentPage - 1) * completedItemsPerPage;
|
||||||
|
final endIndex = (startIndex + completedItemsPerPage).clamp(
|
||||||
|
0,
|
||||||
|
dataToUse.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return paginated subset
|
||||||
|
return dataToUse.sublist(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataToUse;
|
||||||
|
}
|
||||||
|
|
||||||
List<Map<String, dynamic>> get paginatedCompletedData {
|
List<Map<String, dynamic>> get paginatedCompletedData {
|
||||||
if (completedData.isEmpty) return [];
|
final dataToUse = filteredData;
|
||||||
|
|
||||||
// Calculate total pages
|
if (dataToUse.isEmpty) return [];
|
||||||
totalCompletedPages = (completedData.length / completedItemsPerPage).ceil();
|
|
||||||
|
|
||||||
// Calculate start and end indices
|
if (selectedIndex == 1) {
|
||||||
final startIndex = (completedCurrentPage - 1) * completedItemsPerPage;
|
totalCompletedPages = (dataToUse.length / completedItemsPerPage)
|
||||||
final endIndex = (startIndex + completedItemsPerPage).clamp(
|
.ceil()
|
||||||
0,
|
.clamp(1, double.infinity)
|
||||||
completedData.length,
|
.toInt();
|
||||||
);
|
|
||||||
|
|
||||||
// Return paginated subset
|
final startIndex = (completedCurrentPage - 1) * completedItemsPerPage;
|
||||||
return completedData.sublist(startIndex, endIndex);
|
|
||||||
|
// 🚨 Guard: page out of range after search
|
||||||
|
if (startIndex >= dataToUse.length) {
|
||||||
|
completedCurrentPage = 1;
|
||||||
|
return dataToUse.take(completedItemsPerPage).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final endIndex = (startIndex + completedItemsPerPage).clamp(
|
||||||
|
0,
|
||||||
|
dataToUse.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
return dataToUse.sublist(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> autoRefrshfilterDateRange() async {
|
Future<void> autoRefrshfilterDateRange() async {
|
||||||
@ -647,6 +708,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
? List.from(inProgressData)
|
? List.from(inProgressData)
|
||||||
: List.from(completedData);
|
: List.from(completedData);
|
||||||
|
|
||||||
|
if (SelectedStatus == 'Completed') {
|
||||||
|
selectedIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
print('filteredData count: ${filteredData.length}');
|
print('filteredData count: ${filteredData.length}');
|
||||||
print('inProgressData count: ${inProgressData.length}');
|
print('inProgressData count: ${inProgressData.length}');
|
||||||
print('completedData count: ${completedData.length}');
|
print('completedData count: ${completedData.length}');
|
||||||
@ -671,7 +736,180 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String safeString(dynamic value) {
|
||||||
|
if (value == null) return '';
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
void filterData(String query) {
|
void filterData(String query) {
|
||||||
|
_debounce?.cancel();
|
||||||
|
_debounce = Timer(const Duration(milliseconds: 300), () {
|
||||||
|
_applyFilter(query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _applyFilter(String query) {
|
||||||
|
print("FilterData - $query");
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
final sourceList = (selectedIndex == 0) ? inProgressData : completedData;
|
||||||
|
|
||||||
|
final q = query.trim().toLowerCase();
|
||||||
|
|
||||||
|
completedCurrentPage = 1;
|
||||||
|
|
||||||
|
if (q.length < 2) {
|
||||||
|
filteredData = List.from(sourceList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredData = sourceList.where((item) {
|
||||||
|
return safeString(item['agent_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['agent_code']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['reg_no']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['insured_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['policy_number']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['broker_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['insurer_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['insurer_short_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['enquiry_status']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['assigned_to_name']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['status']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['payment_mode']).toLowerCase().contains(q) ||
|
||||||
|
safeString(item['premium_amount']).toLowerCase().contains(q) ||
|
||||||
|
safeString(
|
||||||
|
_formatDate(item['created_on']),
|
||||||
|
).toLowerCase().contains(q) ||
|
||||||
|
safeString(
|
||||||
|
_formatDate(item['updated_on']),
|
||||||
|
).toLowerCase().contains(q);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
print("FilterData2 - ${filteredData.length}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// void _applyFilter(String query) {
|
||||||
|
// print("FilterData - $query");
|
||||||
|
// setState(() {
|
||||||
|
// // ALWAYS search from the FULL source list, not current filtered results
|
||||||
|
// final sourceList = (selectedIndex == 0) ? inProgressData : completedData;
|
||||||
|
//
|
||||||
|
// final q = query.trim().toLowerCase();
|
||||||
|
//
|
||||||
|
// if (q.length < 2) {
|
||||||
|
// filteredData = List.from(sourceList);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (query.isEmpty) {
|
||||||
|
// // If search is empty, show all data for current tab
|
||||||
|
// filteredData = List.from(sourceList);
|
||||||
|
//
|
||||||
|
// print("FilterData1 - $filteredData");
|
||||||
|
// } else {
|
||||||
|
// // Search within ALL data from the current tab's source
|
||||||
|
// filteredData = sourceList.where((item) {
|
||||||
|
// final searchLower = query.toLowerCase();
|
||||||
|
//
|
||||||
|
// return safeString(
|
||||||
|
// item['agent_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['agent_code'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(item['reg_no']).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['insurer_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['enquiry_status'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['assigned_to_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['insured_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['insurer_short_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['premium_amount']?.toString(),
|
||||||
|
// ).contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['payment_mode'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// item['broker_name'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(
|
||||||
|
// _formatDate(item['created_on']),
|
||||||
|
// ).toLowerCase().contains(q) ||
|
||||||
|
// safeString(
|
||||||
|
// _formatDate(item['updated_on']),
|
||||||
|
// ).toLowerCase().contains(q) ||
|
||||||
|
// safeString(
|
||||||
|
// item['policy_number'],
|
||||||
|
// ).toLowerCase().contains(searchLower) ||
|
||||||
|
// safeString(item['status']).toLowerCase().contains(searchLower);
|
||||||
|
//
|
||||||
|
// // return safeString(
|
||||||
|
// // item['agent_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['agent_code'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['reg_no'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['insurer_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['enquiry_status'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['assigned_to_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['insured_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['insurer_short_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['premium_amount'] ?? '-',
|
||||||
|
// // ).toString().toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['payment_mode'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['broker_name'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // _formatDate(item['created_on']),
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // _formatDate(item['updated_on']),
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['policy_number'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower) ||
|
||||||
|
// // safeString(
|
||||||
|
// // item['status'] ?? '-',
|
||||||
|
// // ).toLowerCase().contains(searchLower);
|
||||||
|
// }).toList();
|
||||||
|
// print("FilterData2 - $filteredData");
|
||||||
|
// // Reset to page 1 when searching in completed tab
|
||||||
|
// if (selectedIndex == 1) {
|
||||||
|
// completedCurrentPage = 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
void filterData1(String query) {
|
||||||
print("FilterData - $query");
|
print("FilterData - $query");
|
||||||
setState(() {
|
setState(() {
|
||||||
// Get the correct source list based on selected tab
|
// Get the correct source list based on selected tab
|
||||||
@ -730,6 +968,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectedIndex == 1) {
|
||||||
|
completedCurrentPage = 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1537,6 +1779,17 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
|
onEnter: (_) {
|
||||||
|
setState(() {
|
||||||
|
isActionable = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onExit: (_) {
|
||||||
|
setState(() {
|
||||||
|
// isActionable = false;
|
||||||
|
isActionable = _searchStaffController.text.isNotEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
child: ThemedSearchField(
|
child: ThemedSearchField(
|
||||||
hintText: 'Search',
|
hintText: 'Search',
|
||||||
backgroundColor: Color(0xFFFFFFFF),
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
@ -1614,49 +1867,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
'Assigned': 'Assigned',
|
'Assigned': 'Assigned',
|
||||||
'In progress': 'In Progress',
|
'In progress': 'In Progress',
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Map<String, dynamic>> get filteredDataByTab1 {
|
|
||||||
if (selectedIndex == 0) {
|
|
||||||
// Progress enquiries
|
|
||||||
final sortedData = [...inProgressData]
|
|
||||||
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
|
||||||
|
|
||||||
// final sortedData = [...filteredData]
|
|
||||||
// ..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
|
||||||
|
|
||||||
if (sortedData.isEmpty) return [];
|
|
||||||
return sortedData.where((e) {
|
|
||||||
return [
|
|
||||||
"To be assigned",
|
|
||||||
"Assigned",
|
|
||||||
"In progress",
|
|
||||||
].contains(e['enquiry_status']);
|
|
||||||
}).toList();
|
|
||||||
} else {
|
|
||||||
// final sortedData = [...filteredData]
|
|
||||||
// ..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
|
||||||
|
|
||||||
final sortedData = [...completedData]
|
|
||||||
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
|
||||||
|
|
||||||
if (sortedData.isEmpty) return [];
|
|
||||||
// Completed enquiries
|
|
||||||
return paginatedCompletedData;
|
|
||||||
// return sortedData.where((e) {
|
|
||||||
// return e['enquiry_status'] == "Completed";
|
|
||||||
// }).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<String, dynamic>> get filteredDataByTab {
|
List<Map<String, dynamic>> get filteredDataByTab {
|
||||||
// Use filteredData instead of the raw source lists
|
|
||||||
final sortedData = [...filteredData]
|
final sortedData = [...filteredData]
|
||||||
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
..sort((a, b) => int.parse(b['id']) - int.parse(a['id']));
|
||||||
|
|
||||||
if (sortedData.isEmpty) return [];
|
if (sortedData.isEmpty) return [];
|
||||||
|
|
||||||
if (selectedIndex == 0) {
|
if (selectedIndex == 0) {
|
||||||
// Progress enquiries - return filtered in-progress items
|
|
||||||
return sortedData.where((e) {
|
return sortedData.where((e) {
|
||||||
return [
|
return [
|
||||||
"To be assigned",
|
"To be assigned",
|
||||||
@ -1664,26 +1881,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
"In progress",
|
"In progress",
|
||||||
].contains(e['enquiry_status']);
|
].contains(e['enquiry_status']);
|
||||||
}).toList();
|
}).toList();
|
||||||
} else {
|
|
||||||
// Completed enquiries - apply pagination to filtered completed items
|
|
||||||
final completedFiltered = sortedData.where((e) {
|
|
||||||
return e['enquiry_status'] == "Completed";
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
// Update total pages based on filtered results
|
|
||||||
totalCompletedPages = (completedFiltered.length / completedItemsPerPage)
|
|
||||||
.ceil();
|
|
||||||
if (totalCompletedPages == 0) totalCompletedPages = 1;
|
|
||||||
|
|
||||||
// Apply pagination
|
|
||||||
final startIndex = (completedCurrentPage - 1) * completedItemsPerPage;
|
|
||||||
final endIndex = (startIndex + completedItemsPerPage).clamp(
|
|
||||||
0,
|
|
||||||
completedFiltered.length,
|
|
||||||
);
|
|
||||||
|
|
||||||
return completedFiltered.sublist(startIndex, endIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Completed tab → ALWAYS paginate
|
||||||
|
return paginatedCompletedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add group enquiries by status
|
// Add group enquiries by status
|
||||||
@ -2647,7 +2848,12 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
: '-',
|
: '-',
|
||||||
style: _dataBold,
|
style: _dataBold,
|
||||||
),
|
),
|
||||||
Text(_formatDate(item['updated_on']), style: _dataBoldthm4),
|
Text(
|
||||||
|
item['updated_on'] != null
|
||||||
|
? _formatDate(item['updated_on'])
|
||||||
|
: '-',
|
||||||
|
style: _dataBoldthm4,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -2828,10 +3034,15 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
print('TAPPED TAB');
|
print('TAPPED TAB');
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
|
|
||||||
filteredData = (index == 0) ? inProgressData : completedData;
|
filteredData = (index == 0) ? inProgressData : completedData;
|
||||||
if (index == 1) {
|
if (index == 1) {
|
||||||
completedCurrentPage = 1;
|
completedCurrentPage = 1;
|
||||||
|
// final newValue = false;
|
||||||
|
// isActionable = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_searchStaffController.clear();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
@ -3079,6 +3290,129 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
if (selectedIndex != 1 || completedData.length <= 25) {
|
if (selectedIndex != 1 || completedData.length <= 25) {
|
||||||
return SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
// if (selectedIndex != 1 || completedData.length <= 25) {
|
||||||
|
// return SizedBox.shrink();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Calculate display values based on filteredData
|
||||||
|
final totalItems = filteredData.length;
|
||||||
|
final startItem = ((completedCurrentPage - 1) * completedItemsPerPage) + 1;
|
||||||
|
final endItem = (completedCurrentPage * completedItemsPerPage).clamp(
|
||||||
|
0,
|
||||||
|
totalItems,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border(top: BorderSide(color: Color(0xFFE2E8F0))),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Showing $startItem-$endItem of $totalItems', // ← Changed this
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Color(0xFF64748B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
// Items per page dropdown
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: Color(0xFFE2E8F0)),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: DropdownButton<int>(
|
||||||
|
value: completedItemsPerPage,
|
||||||
|
underline: SizedBox(),
|
||||||
|
isDense: true,
|
||||||
|
items: itemsPerPageOptions.map((int value) {
|
||||||
|
return DropdownMenuItem<int>(
|
||||||
|
value: value,
|
||||||
|
child: Text(
|
||||||
|
'$value / page',
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Color(0xFF334155),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (int? newValue) {
|
||||||
|
if (newValue != null) {
|
||||||
|
setState(() {
|
||||||
|
completedItemsPerPage = newValue;
|
||||||
|
completedCurrentPage = 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// Pagination buttons remain the same
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.first_page, size: 18),
|
||||||
|
onPressed: completedCurrentPage > 1
|
||||||
|
? () => setState(() => completedCurrentPage = 1)
|
||||||
|
: null,
|
||||||
|
color: completedCurrentPage > 1
|
||||||
|
? Color(0xFF2E7D6E)
|
||||||
|
: Colors.grey,
|
||||||
|
tooltip: 'First page',
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_left, size: 18),
|
||||||
|
onPressed: completedCurrentPage > 1
|
||||||
|
? () => setState(() => completedCurrentPage--)
|
||||||
|
: null,
|
||||||
|
color: completedCurrentPage > 1
|
||||||
|
? Color(0xFF2E7D6E)
|
||||||
|
: Colors.grey,
|
||||||
|
tooltip: 'Previous page',
|
||||||
|
),
|
||||||
|
..._buildPageNumbers(),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_right, size: 18),
|
||||||
|
onPressed: completedCurrentPage < totalCompletedPages
|
||||||
|
? () => setState(() => completedCurrentPage++)
|
||||||
|
: null,
|
||||||
|
color: completedCurrentPage < totalCompletedPages
|
||||||
|
? Color(0xFF2E7D6E)
|
||||||
|
: Colors.grey,
|
||||||
|
tooltip: 'Next page',
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.last_page, size: 18),
|
||||||
|
onPressed: completedCurrentPage < totalCompletedPages
|
||||||
|
? () => setState(
|
||||||
|
() => completedCurrentPage = totalCompletedPages,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
color: completedCurrentPage < totalCompletedPages
|
||||||
|
? Color(0xFF2E7D6E)
|
||||||
|
: Colors.grey,
|
||||||
|
tooltip: 'Last page',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPaginationControls1() {
|
||||||
|
if (selectedIndex != 1 || completedData.length <= 25) {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 16),
|
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 16),
|
||||||
@ -3093,7 +3427,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Showing ${((completedCurrentPage - 1) * completedItemsPerPage) + 1}-${(completedCurrentPage * completedItemsPerPage).clamp(0, completedData.length)} of ${completedData.length}',
|
'Showing ${((completedCurrentPage - 1) * completedItemsPerPage) + 1}-${(completedCurrentPage * completedItemsPerPage).clamp(0, filteredData.length)} of ${filteredData.length}',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Color(0xFF64748B),
|
color: Color(0xFF64748B),
|
||||||
|
|||||||
@ -423,6 +423,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
buildVehicleNumber(context),
|
buildVehicleNumber(context),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
buildRefresh(context),
|
buildRefresh(context),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
|
|||||||
@ -775,7 +775,7 @@ class policylistState extends ConsumerState<policylist> {
|
|||||||
context.push(AppRoutes.policyValidation, extra: item);
|
context.push(AppRoutes.policyValidation, extra: item);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 110, // ⭐ FIXED WIDTH → Equal in both states
|
width: 80, // ⭐ FIXED WIDTH → Equal in both states
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 8,
|
horizontal: 8,
|
||||||
vertical: 4,
|
vertical: 4,
|
||||||
@ -787,8 +787,9 @@ class policylistState extends ConsumerState<policylist> {
|
|||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.center, // ⭐ Center content
|
MainAxisAlignment.spaceEvenly, // ⭐ Center content
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
item['is_data_accuracy_checked'] == '1'
|
item['is_data_accuracy_checked'] == '1'
|
||||||
@ -797,12 +798,12 @@ class policylistState extends ConsumerState<policylist> {
|
|||||||
size: 12,
|
size: 12,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 1),
|
||||||
Text(
|
Text(
|
||||||
item['is_data_accuracy_checked'] == '1'
|
item['is_data_accuracy_checked'] == '1'
|
||||||
? 'Verified'
|
? 'Verified'
|
||||||
: 'Click to Verify',
|
: 'To Verify',
|
||||||
style: const TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1355
lib/presentation/screens/staff/policy/policy_validation_old.dart
Normal file
1355
lib/presentation/screens/staff/policy/policy_validation_old.dart
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,18 @@
|
|||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import '../../../core/services/api_service.dart';
|
||||||
import '../../../data/models/bar_data.dart';
|
import '../../../data/models/bar_data.dart';
|
||||||
|
import '../../providers/manager_provider.dart';
|
||||||
import 'appChartColors.dart';
|
import 'appChartColors.dart';
|
||||||
|
|
||||||
class CustomBarChart extends StatefulWidget {
|
class CustomBarChart extends ConsumerStatefulWidget {
|
||||||
final List<BarData> dataList;
|
final List<BarData> dataList;
|
||||||
final List<String> labels;
|
final List<String> labels;
|
||||||
|
final List<String>? shortName;
|
||||||
final String title;
|
final String title;
|
||||||
final String? btnName;
|
final String? btnName;
|
||||||
final double maxY;
|
final double maxY;
|
||||||
@ -17,6 +22,7 @@ class CustomBarChart extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.dataList,
|
required this.dataList,
|
||||||
required this.labels,
|
required this.labels,
|
||||||
|
this.shortName,
|
||||||
this.btnName,
|
this.btnName,
|
||||||
this.title = "Horizontal Bar Chart",
|
this.title = "Horizontal Bar Chart",
|
||||||
this.maxY = 20,
|
this.maxY = 20,
|
||||||
@ -26,23 +32,27 @@ class CustomBarChart extends StatefulWidget {
|
|||||||
final shadowColor = const Color(0xFFCCCCCC);
|
final shadowColor = const Color(0xFFCCCCCC);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CustomBarChart> createState() => _CustomBarChartState();
|
// State<CustomBarChart> createState() => _CustomBarChartState();
|
||||||
|
ConsumerState<CustomBarChart> createState() => _CustomBarChartState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomBarChartState extends State<CustomBarChart> {
|
class _CustomBarChartState extends ConsumerState<CustomBarChart> {
|
||||||
int touchedGroupIndex = -1;
|
int touchedGroupIndex = -1;
|
||||||
late int rotationTurns;
|
late int rotationTurns;
|
||||||
dynamic managerId;
|
dynamic managerId;
|
||||||
|
late ApiService apiService;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
rotationTurns = widget.initialRotation;
|
rotationTurns = widget.initialRotation;
|
||||||
// Future.microtask(() {
|
Future.microtask(() {
|
||||||
// managerId = ref.read(managerIdProvider);
|
managerId = ref.read(managerIdProvider);
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final indianFormatter = NumberFormat('#,##,##0', 'en_IN');
|
||||||
BarChartGroupData generateBarGroup(
|
BarChartGroupData generateBarGroup(
|
||||||
int x,
|
int x,
|
||||||
Color color,
|
Color color,
|
||||||
@ -53,180 +63,267 @@ class _CustomBarChartState extends State<CustomBarChart> {
|
|||||||
return BarChartGroupData(
|
return BarChartGroupData(
|
||||||
x: x,
|
x: x,
|
||||||
groupVertically: false,
|
groupVertically: false,
|
||||||
|
|
||||||
// showingTooltipIndicators: [0],
|
// showingTooltipIndicators: [0],
|
||||||
// barsSpace: 30,
|
// barsSpace: 30,
|
||||||
barRods: [
|
barRods: [
|
||||||
BarChartRodData(toY: value1, color: Colors.cyan.shade300, width: 4),
|
BarChartRodData(toY: 0, color: Colors.transparent, width: 10),
|
||||||
|
BarChartRodData(
|
||||||
|
toY: value1,
|
||||||
|
color: Colors.cyan.shade300,
|
||||||
|
width: 20,
|
||||||
|
borderRadius: BorderRadius.circular(0),
|
||||||
|
),
|
||||||
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
||||||
BarChartRodData(toY: value2, color: Colors.orange.shade300, width: 4),
|
BarChartRodData(
|
||||||
|
toY: value2,
|
||||||
|
color: Colors.orange.shade300,
|
||||||
|
width: 20,
|
||||||
|
borderRadius: BorderRadius.circular(0),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
showingTooltipIndicators: touchedGroupIndex == x ? [0] : [],
|
showingTooltipIndicators: touchedGroupIndex == x ? [0] : [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// return AspectRatio(
|
||||||
|
// aspectRatio: 1.4,
|
||||||
|
//
|
||||||
|
// );
|
||||||
|
// }
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AspectRatio(
|
return LayoutBuilder(
|
||||||
aspectRatio: 1.4,
|
builder: (context, constraints) {
|
||||||
child: BarChart(
|
return SizedBox(
|
||||||
BarChartData(
|
width: constraints.maxWidth,
|
||||||
alignment: BarChartAlignment.spaceBetween,
|
height: constraints.maxHeight,
|
||||||
// verticalAxis: Axis.horizontal,
|
child: BarChart(
|
||||||
rotationQuarterTurns: rotationTurns,
|
BarChartData(
|
||||||
|
// alignment: BarChartAlignment.spaceBetween,
|
||||||
|
alignment: BarChartAlignment.start,
|
||||||
|
// verticalAxis: Axis.horizontal,
|
||||||
|
// rotationQuarterTurns: rotationTurns,
|
||||||
|
barTouchData: BarTouchData(
|
||||||
|
enabled: true,
|
||||||
|
handleBuiltInTouches: true,
|
||||||
|
touchTooltipData: BarTouchTooltipData(
|
||||||
|
tooltipMargin: 6,
|
||||||
|
tooltipRoundedRadius: 6,
|
||||||
|
tooltipPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 6,
|
||||||
|
),
|
||||||
|
// ask fl_chart to fit tooltip inside available space
|
||||||
|
fitInsideVertically:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
fitInsideHorizontally:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
getTooltipItem:
|
||||||
|
(
|
||||||
|
BarChartGroupData group,
|
||||||
|
int groupIndex,
|
||||||
|
BarChartRodData rod,
|
||||||
|
int rodIndex,
|
||||||
|
) {
|
||||||
|
final textColor = rodIndex == 1
|
||||||
|
? Colors.cyan.shade300
|
||||||
|
: Colors.orange.shade300;
|
||||||
|
final textStyle = TextStyle(
|
||||||
|
color: textColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
|
||||||
barTouchData: BarTouchData(
|
final formattedValue = indianFormatter.format(
|
||||||
enabled: true,
|
rod.toY.round(),
|
||||||
handleBuiltInTouches: true,
|
);
|
||||||
touchTooltipData: BarTouchTooltipData(
|
|
||||||
tooltipMargin: 6,
|
return BarTooltipItem(formattedValue, textStyle);
|
||||||
tooltipRoundedRadius: 6,
|
// return BarTooltipItem('${rod.toY.round()}', textStyle);
|
||||||
tooltipPadding: const EdgeInsets.symmetric(
|
},
|
||||||
horizontal: 10,
|
),
|
||||||
vertical: 6,
|
|
||||||
),
|
touchCallback: (FlTouchEvent e, BarTouchResponse? r) async {
|
||||||
// ask fl_chart to fit tooltip inside available space
|
// optional: change state to highlight tapped group
|
||||||
fitInsideVertically: true, // if your fl_chart version supports it
|
if (r == null || r.spot == null) {
|
||||||
fitInsideHorizontally:
|
setState(() => touchedGroupIndex = -1);
|
||||||
true, // if your fl_chart version supports it
|
return;
|
||||||
getTooltipItem:
|
}
|
||||||
(
|
setState(
|
||||||
BarChartGroupData group,
|
() => touchedGroupIndex = r.spot!.touchedBarGroupIndex,
|
||||||
int groupIndex,
|
);
|
||||||
BarChartRodData rod,
|
|
||||||
int rodIndex,
|
final spot = r.spot!;
|
||||||
) {
|
final groupIndex = spot.touchedBarGroupIndex;
|
||||||
final textColor = rodIndex == 0
|
final rodIndex = spot.touchedRodDataIndex;
|
||||||
? Colors.cyan.shade300
|
|
||||||
: Colors.orange.shade300;
|
final barData = widget.dataList[groupIndex];
|
||||||
final textStyle = TextStyle(
|
|
||||||
color: textColor,
|
final name = barData.chartName;
|
||||||
fontSize: 12,
|
final val = barData.id;
|
||||||
fontWeight: FontWeight.w600,
|
final month = rodIndex == 1 ? 'current' : 'previous';
|
||||||
|
print('name - $name');
|
||||||
|
print('val - $val');
|
||||||
|
print('month - $month');
|
||||||
|
print('managerId - $managerId');
|
||||||
|
if (e is FlTapUpEvent) {
|
||||||
|
debugPrint(
|
||||||
|
'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
||||||
|
' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}',
|
||||||
);
|
);
|
||||||
return BarTooltipItem('${rod.toY.round()}', textStyle);
|
if (managerId != null) {
|
||||||
},
|
print('managerId - $managerId');
|
||||||
),
|
await apiService.generateChartExcel(
|
||||||
|
name,
|
||||||
touchCallback: (FlTouchEvent e, BarTouchResponse? r) {
|
val,
|
||||||
// optional: change state to highlight tapped group
|
month,
|
||||||
if (r == null || r.spot == null) {
|
managerId,
|
||||||
setState(() => touchedGroupIndex = -1);
|
);
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
setState(() => touchedGroupIndex = r.spot!.touchedBarGroupIndex);
|
|
||||||
|
|
||||||
final spot = r.spot!;
|
|
||||||
final groupIndex = spot.touchedBarGroupIndex;
|
|
||||||
final rodIndex = spot.touchedRodDataIndex;
|
|
||||||
|
|
||||||
final barData = widget.dataList[groupIndex];
|
|
||||||
|
|
||||||
if (e is FlTapUpEvent) {
|
|
||||||
debugPrint(
|
|
||||||
'Tapped value → ${rodIndex == 0 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
|
||||||
' ${rodIndex == 0 ? 'current' : 'previous'} -> ${barData.chartName}',
|
|
||||||
);
|
|
||||||
// await apiService.generateExcel()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
borderData: FlBorderData(
|
|
||||||
show: true,
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: AppColors.contentColorBlack,
|
|
||||||
width: 0.1,
|
|
||||||
),
|
|
||||||
right: BorderSide(color: AppColors.contentColorBlack, width: 0.1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
gridData: FlGridData(
|
|
||||||
show: true,
|
|
||||||
// drawVerticalLine: true,
|
|
||||||
drawVerticalLine: false,
|
|
||||||
getDrawingHorizontalLine: (value) => FlLine(
|
|
||||||
// color: AppColors.gridLinesColor.withValues(alpha: 0.2),
|
|
||||||
color: Colors.blueGrey.shade100,
|
|
||||||
// color: Colors.black,
|
|
||||||
// color: AppColors.borderColor,
|
|
||||||
strokeWidth: 0.3,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
titlesData: FlTitlesData(
|
|
||||||
bottomTitles: AxisTitles(
|
|
||||||
axisNameWidget: widget.btnName != null
|
|
||||||
? Text(widget.btnName!)
|
|
||||||
: Text(''),
|
|
||||||
axisNameSize: 10,
|
|
||||||
sideTitles: SideTitles(
|
|
||||||
reservedSize: 60,
|
|
||||||
showTitles: true,
|
|
||||||
getTitlesWidget: (value, meta) {
|
|
||||||
final i = value.toInt();
|
|
||||||
if (i >= widget.labels.length) return const SizedBox();
|
|
||||||
return SideTitleWidget(
|
|
||||||
meta: meta,
|
|
||||||
child: Text(
|
|
||||||
widget.labels[i],
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 9.5,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
rightTitles: AxisTitles(
|
borderData: FlBorderData(
|
||||||
sideTitles: SideTitles(
|
show: true,
|
||||||
showTitles: true,
|
border: Border(
|
||||||
getTitlesWidget: (value, meta) {
|
bottom: BorderSide(
|
||||||
return Transform.rotate(
|
color: AppColors.contentColorBlack,
|
||||||
angle: -3,
|
width: 0.1,
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.only(right: 3.0),
|
left: BorderSide(
|
||||||
child: Text(
|
color: AppColors.contentColorBlack,
|
||||||
value.toInt().toString(),
|
width: 0.1,
|
||||||
textAlign: TextAlign.end,
|
),
|
||||||
style: GoogleFonts.inter(
|
),
|
||||||
fontSize: 9,
|
),
|
||||||
fontWeight: FontWeight.w400,
|
gridData: FlGridData(
|
||||||
|
show: true,
|
||||||
|
// drawVerticalLine: true,
|
||||||
|
drawVerticalLine: false,
|
||||||
|
getDrawingHorizontalLine: (value) => FlLine(
|
||||||
|
// color: AppColors.gridLinesColor.withValues(alpha: 0.2),
|
||||||
|
color: Colors.blueGrey.shade100,
|
||||||
|
// color: Colors.black,
|
||||||
|
// color: AppColors.borderColor,
|
||||||
|
strokeWidth: 0.3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
axisNameWidget: widget.btnName != null
|
||||||
|
? Text(widget.btnName!)
|
||||||
|
: Text(''),
|
||||||
|
axisNameSize: 10,
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
reservedSize: 30,
|
||||||
|
showTitles: true,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
final i = value.toInt();
|
||||||
|
if (i >= widget.labels.length) return const SizedBox();
|
||||||
|
final hasShortName =
|
||||||
|
widget.shortName != null &&
|
||||||
|
widget.shortName!.length > i &&
|
||||||
|
widget.shortName![i].trim().isNotEmpty;
|
||||||
|
|
||||||
|
return SideTitleWidget(
|
||||||
|
meta: meta,
|
||||||
|
child: hasShortName
|
||||||
|
? Tooltip(
|
||||||
|
message: widget.shortName![i],
|
||||||
|
child: Text(
|
||||||
|
widget.labels[i],
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9.5,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
widget.labels[i],
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9.5,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
leftTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
// interval: 10,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
// print("valuevalue - $value");
|
||||||
|
|
||||||
|
final text = value.toInt().toString();
|
||||||
|
|
||||||
|
final bool isLast = value == meta.max;
|
||||||
|
// if (isLast) {
|
||||||
|
// return const SizedBox.shrink(); // 👈 hide last label
|
||||||
|
// }
|
||||||
|
// print('value: $value');
|
||||||
|
// print('text: $text');
|
||||||
|
// print('length: ${text.length}');
|
||||||
|
// print('isLast: $isLast');
|
||||||
|
return Transform.rotate(
|
||||||
|
// angle: -3,
|
||||||
|
angle: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 3.0),
|
||||||
|
child: Text(
|
||||||
|
isLast ? '0' : value.toInt().toString(),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 9,
|
||||||
|
color: isLast ? Colors.white : Colors.black,
|
||||||
|
fontWeight: isLast
|
||||||
|
? FontWeight.w100
|
||||||
|
: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
);
|
reservedSize: 45,
|
||||||
},
|
),
|
||||||
reservedSize: 45,
|
),
|
||||||
|
rightTitles: const AxisTitles(),
|
||||||
|
topTitles: const AxisTitles(),
|
||||||
),
|
),
|
||||||
),
|
barGroups: widget.dataList.asMap().entries.map((e) {
|
||||||
leftTitles: const AxisTitles(),
|
final index = e.key;
|
||||||
topTitles: const AxisTitles(),
|
final data = e.value;
|
||||||
),
|
print('generateBarGroupBAR - $data');
|
||||||
barGroups: widget.dataList.asMap().entries.map((e) {
|
return generateBarGroup(
|
||||||
final index = e.key;
|
index,
|
||||||
final data = e.value;
|
data.color,
|
||||||
print('generateBarGroupBAR - $data');
|
data.value1,
|
||||||
return generateBarGroup(
|
data.value2,
|
||||||
index,
|
data.shadowValue,
|
||||||
data.color,
|
);
|
||||||
data.value1,
|
}).toList(),
|
||||||
data.value2,
|
|
||||||
data.shadowValue,
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
|
|
||||||
// maxY: widget.maxY,
|
// maxY: widget.maxY,
|
||||||
maxY: (widget.dataList != null && widget.dataList!.isNotEmpty)
|
maxY: (widget.dataList != null && widget.dataList!.isNotEmpty)
|
||||||
? widget.dataList!
|
? widget.dataList!
|
||||||
.map((e) => e.value1 > e.value2 ? e.value1 : e.value2)
|
.map(
|
||||||
.reduce((a, b) => a > b ? a : b) +
|
(e) => e.value1 > e.value2 ? e.value1 : e.value2,
|
||||||
15
|
)
|
||||||
: 20,
|
.reduce((a, b) => a > b ? a : b) +
|
||||||
),
|
15
|
||||||
),
|
: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
// custom_stacked_bar_chart.dart
|
// custom_stacked_bar_chart.dart
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../../core/services/api_service.dart';
|
||||||
import '../../../data/models/bar_data.dart';
|
import '../../../data/models/bar_data.dart';
|
||||||
|
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
@ -13,10 +15,12 @@ import 'package:fl_chart/fl_chart.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../providers/manager_provider.dart';
|
||||||
import 'appChartColors.dart';
|
import 'appChartColors.dart';
|
||||||
|
|
||||||
class CustomStackedBarChart extends StatefulWidget {
|
class CustomStackedBarChart extends ConsumerStatefulWidget {
|
||||||
final List<String> labels;
|
final List<String> labels;
|
||||||
|
final List<String> labelsId;
|
||||||
final List<dynamic> dataList;
|
final List<dynamic> dataList;
|
||||||
final double maxY;
|
final double maxY;
|
||||||
final int initialRotation;
|
final int initialRotation;
|
||||||
@ -27,6 +31,7 @@ class CustomStackedBarChart extends StatefulWidget {
|
|||||||
const CustomStackedBarChart({
|
const CustomStackedBarChart({
|
||||||
super.key,
|
super.key,
|
||||||
required this.labels,
|
required this.labels,
|
||||||
|
required this.labelsId,
|
||||||
required this.dataList,
|
required this.dataList,
|
||||||
this.maxY = 100.0,
|
this.maxY = 100.0,
|
||||||
this.initialRotation = 1,
|
this.initialRotation = 1,
|
||||||
@ -36,16 +41,23 @@ class CustomStackedBarChart extends StatefulWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CustomStackedBarChart> createState() => _CustomStackedBarChartState();
|
ConsumerState<CustomStackedBarChart> createState() =>
|
||||||
|
_CustomStackedBarChartState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
class _CustomStackedBarChartState extends ConsumerState<CustomStackedBarChart> {
|
||||||
late int rotationTurns;
|
late int rotationTurns;
|
||||||
|
dynamic managerId;
|
||||||
|
late ApiService apiService;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
rotationTurns = widget.initialRotation;
|
rotationTurns = widget.initialRotation;
|
||||||
|
Future.microtask(() {
|
||||||
|
managerId = ref.read(managerIdProvider);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -191,6 +203,37 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
touchCallback: (event, response) async {
|
||||||
|
if (response == null || response.spot == null) return;
|
||||||
|
|
||||||
|
// ✅ ONLY handle clicks
|
||||||
|
if (event is! FlTapUpEvent) return;
|
||||||
|
|
||||||
|
final spot = response.spot!;
|
||||||
|
final int groupIndex = spot.touchedBarGroupIndex;
|
||||||
|
final int rodIndex = spot.touchedRodDataIndex;
|
||||||
|
final int stackIndex = spot.touchedStackItemIndex!;
|
||||||
|
|
||||||
|
final label =
|
||||||
|
widget.vehicleTypeNames?[groupIndex][stackIndex] ?? 'Unknown';
|
||||||
|
final isCurrentMonth = rodIndex == 0;
|
||||||
|
final monthLabel = isCurrentMonth ? 'Current' : 'Previous';
|
||||||
|
final categoryLabel = widget.labels[groupIndex];
|
||||||
|
final categoryLabelID = widget.labelsId[groupIndex];
|
||||||
|
|
||||||
|
debugPrint(
|
||||||
|
'Clicked stack → $label -> $monthLabel ->$managerId ->$categoryLabel->$categoryLabelID',
|
||||||
|
);
|
||||||
|
|
||||||
|
await apiService.generatePerformanceDashboardExcel(
|
||||||
|
'StaffProduct',
|
||||||
|
label,
|
||||||
|
categoryLabelID,
|
||||||
|
monthLabel,
|
||||||
|
managerId,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
barGroups: widget.productsList.asMap().entries.map((entry) {
|
barGroups: widget.productsList.asMap().entries.map((entry) {
|
||||||
|
|||||||
@ -34,6 +34,9 @@ class ThemedFormField extends HookWidget {
|
|||||||
this.horizonalPad,
|
this.horizonalPad,
|
||||||
this.enableBorderWidth,
|
this.enableBorderWidth,
|
||||||
this.textColr,
|
this.textColr,
|
||||||
|
|
||||||
|
this.errFieldFont,
|
||||||
|
this.errFieldHgt,
|
||||||
});
|
});
|
||||||
|
|
||||||
final double? verticalPad;
|
final double? verticalPad;
|
||||||
@ -53,6 +56,8 @@ class ThemedFormField extends HookWidget {
|
|||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final Color? errorBorderColor;
|
final Color? errorBorderColor;
|
||||||
final Color? errorTextColor;
|
final Color? errorTextColor;
|
||||||
|
final double? errFieldFont;
|
||||||
|
final double? errFieldHgt;
|
||||||
final double? txtwidth;
|
final double? txtwidth;
|
||||||
final bool readOnly;
|
final bool readOnly;
|
||||||
final bool isdense;
|
final bool isdense;
|
||||||
@ -91,7 +96,13 @@ class ThemedFormField extends HookWidget {
|
|||||||
);
|
);
|
||||||
final inputDecoration = InputDecoration(
|
final inputDecoration = InputDecoration(
|
||||||
isDense: isdense,
|
isDense: isdense,
|
||||||
errorStyle: TextStyle(color: Color(0xFFD83731)),
|
|
||||||
|
// errorStyle: TextStyle(color: Color(0xFFD83731)),
|
||||||
|
// errorStyle: TextStyle(
|
||||||
|
// color: Color(0xFFD83731),
|
||||||
|
// fontSize: errFieldFont ?? 12,
|
||||||
|
// height: errFieldHgt ?? 10,
|
||||||
|
// ),
|
||||||
errorBorder: OutlineInputBorder(
|
errorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
@ -140,7 +151,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
borderSide: BorderSide(color: borderColor ?? Color(0xFFFFFFFF)),
|
borderSide: BorderSide(color: borderColor ?? Color(0xFFFFFFFF)),
|
||||||
)
|
)
|
||||||
: OutlineInputBorder(
|
: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(bordedRad ?? 10),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: highlightColor ?? borderColor ?? Color(0xFF50A398),
|
color: highlightColor ?? borderColor ?? Color(0xFF50A398),
|
||||||
width: 2,
|
width: 2,
|
||||||
|
|||||||
@ -182,6 +182,7 @@ class ThemedFormInlineField extends HookWidget {
|
|||||||
suffixIcon: isObscurable ? obscureBtn : null,
|
suffixIcon: isObscurable ? obscureBtn : null,
|
||||||
);
|
);
|
||||||
return Container(
|
return Container(
|
||||||
|
width: txtwidth ?? MediaQuery.of(context).size.width,
|
||||||
height: txtheight ?? null,
|
height: txtheight ?? null,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: boxDecoration,
|
decoration: boxDecoration,
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import '../../core/routing/routes.dart';
|
|||||||
import '../layouts/responsive_layout.dart';
|
import '../layouts/responsive_layout.dart';
|
||||||
import '../providers/manager_provider.dart';
|
import '../providers/manager_provider.dart';
|
||||||
import '../providers/userRoleProvider.dart';
|
import '../providers/userRoleProvider.dart';
|
||||||
|
import '../screens/staff/Enquiry/Proposal_QuickCreation/Proposal_QuickCreation.dart';
|
||||||
|
import '../themes/indicators/side_Drawer_Panel.dart';
|
||||||
|
|
||||||
class TopBar extends ConsumerStatefulWidget implements PreferredSizeWidget {
|
class TopBar extends ConsumerStatefulWidget implements PreferredSizeWidget {
|
||||||
final String title;
|
final String title;
|
||||||
@ -141,6 +143,32 @@ class _TopBarState extends ConsumerState<TopBar> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
|
if (role != 'Accounts') ...[
|
||||||
|
// Proposal button
|
||||||
|
Container(
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: Colors.grey.shade200, width: 1),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
icon: const Icon(Icons.quora, color: Colors.black87, size: 20),
|
||||||
|
onPressed: () {
|
||||||
|
SideDrawerPanel.show(
|
||||||
|
context: context,
|
||||||
|
title: 'Quote Creation',
|
||||||
|
child: CreateProposal_Quick(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
tooltip: 'Quick Quote',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
],
|
||||||
Container(
|
Container(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|||||||
20
pubspec.lock
20
pubspec.lock
@ -700,26 +700,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.0.2"
|
version: "10.0.9"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.10"
|
version: "3.0.9"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.1"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1297,10 +1297,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.6"
|
version: "0.7.4"
|
||||||
toastification:
|
toastification:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1417,10 +1417,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.1.4"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user