UI_Enq_Dashboard_Filter
This commit is contained in:
parent
3a0c29265b
commit
647f5ff05d
File diff suppressed because one or more lines are too long
@ -1,7 +1,18 @@
|
||||
class Env {
|
||||
static const String envName = String.fromEnvironment('ENV', defaultValue: 'dev');
|
||||
static const String apiUrl = String.fromEnvironment('API_URL', defaultValue: 'https://venbait.in/nhance/partner/dev/api/');
|
||||
static const String baseUrl = String.fromEnvironment('BASE_URL', defaultValue: '/nhance/partner/app');
|
||||
static const String App_Signature = String.fromEnvironment('App_Signature', defaultValue: 'nhance-partner-2025-signature-35468846JRhH551HK');
|
||||
static const String envName = String.fromEnvironment(
|
||||
'ENV',
|
||||
defaultValue: 'dev',
|
||||
);
|
||||
static const String apiUrl = String.fromEnvironment(
|
||||
'API_URL',
|
||||
defaultValue: 'https://venbait.in/nhance/partner/dev/api/',
|
||||
);
|
||||
static const String baseUrl = String.fromEnvironment(
|
||||
'BASE_URL',
|
||||
defaultValue: '/nhance/partner/app',
|
||||
);
|
||||
static const String App_Signature = String.fromEnvironment(
|
||||
'App_Signature',
|
||||
defaultValue: 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -27,7 +27,8 @@ import '../../presentation/screens/staff/policy/policy_list.dart';
|
||||
import '../../presentation/screens/staff/quotations/quotation.dart';
|
||||
|
||||
final GoRouter appRouter = GoRouter(
|
||||
initialLocation: AppRoutes.home,
|
||||
initialLocation: AppRoutes.login,
|
||||
// initialLocation: AppRoutes.home,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.splash,
|
||||
@ -37,10 +38,10 @@ final GoRouter appRouter = GoRouter(
|
||||
path: AppRoutes.login,
|
||||
builder: (context, state) => const LoginScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.home,
|
||||
builder: (context, state) => const HomeScreen(),
|
||||
),
|
||||
// GoRoute(
|
||||
// path: AppRoutes.home,
|
||||
// builder: (context, state) => const HomeScreen(),
|
||||
// ),
|
||||
GoRoute(
|
||||
path: AppRoutes.dashboard,
|
||||
builder: (context, state) => const DashboardScreen(),
|
||||
@ -193,7 +194,7 @@ final GoRouter appRouter = GoRouter(
|
||||
if (loggedIn && goingToLogin) {
|
||||
// Logged in but going to login → send to "next" if present
|
||||
final next = state.uri.queryParameters['next'];
|
||||
return next ?? AppRoutes.home;
|
||||
return next ?? AppRoutes.login;
|
||||
}
|
||||
|
||||
// if (!loggedIn && !goingToLogin) return AppRoutes.login;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:nhance_partner/data/services/auth_service.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@ -10,6 +11,8 @@ import '../config/env.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../routing/routes.dart';
|
||||
|
||||
class ApiService {
|
||||
late final BuildContext context;
|
||||
|
||||
@ -20,12 +23,14 @@ class ApiService {
|
||||
print("APISERTOKEN - $_token");
|
||||
}
|
||||
|
||||
Future<void> _clearLocalStorageAndRedirect() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.clear();
|
||||
Future<void> clearLocalStorageAndRedirect() async {
|
||||
// final prefs = await SharedPreferences.getInstance();
|
||||
// await prefs.clear();
|
||||
// Assuming you have access to the context
|
||||
ToastHelper.showErrorToast(context, 'Session Out');
|
||||
Navigator.pushNamed(context, 'login');
|
||||
// Navigator.pushNamed(context, 'login');
|
||||
AuthService.clearToken();
|
||||
context.go(AppRoutes.login);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _makeGetRequest(
|
||||
@ -46,7 +51,7 @@ class ApiService {
|
||||
// if (response.statusCode == 200) {
|
||||
// return jsonDecode(response.body);
|
||||
// } else if (response.statusCode == 401) {
|
||||
// await _clearLocalStorageAndRedirect();
|
||||
// await clearLocalStorageAndRedirect();
|
||||
// return {};
|
||||
// } else {
|
||||
// throw Exception('Failed to load data');
|
||||
@ -61,6 +66,9 @@ class ApiService {
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response; // return full http.Response, not Map
|
||||
} else if (response.statusCode == 403) {
|
||||
await clearLocalStorageAndRedirect();
|
||||
return http.Response('Forbidden', 403);
|
||||
} else {
|
||||
throw Exception('Failed request: ${response.statusCode}');
|
||||
}
|
||||
@ -83,8 +91,8 @@ class ApiService {
|
||||
Future<Map<String, dynamic>> _handleResponse(http.Response response) async {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else if (response.statusCode == 401) {
|
||||
await _clearLocalStorageAndRedirect();
|
||||
} else if (response.statusCode == 401 || response.statusCode == 403) {
|
||||
await clearLocalStorageAndRedirect();
|
||||
return {};
|
||||
} else {
|
||||
throw Exception('Failed to load data');
|
||||
@ -107,7 +115,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGethttpRequest(url, headers);
|
||||
|
||||
@ -200,7 +208,8 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
// 'App-Signature': Env.App_Signature,
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGethttpRequest(url, headers);
|
||||
@ -260,6 +269,8 @@ class ApiService {
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (response.statusCode == 403) {
|
||||
await clearLocalStorageAndRedirect();
|
||||
} else if (response.statusCode == 500) {
|
||||
ToastHelper.showInfoToast(context, 'No File Not Found');
|
||||
} else {
|
||||
@ -303,6 +314,7 @@ class ApiService {
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> updateStatus(id, status, role) async {
|
||||
print('updateStatusupdateStatus');
|
||||
final Map<String, dynamic> data = {
|
||||
"id": int.parse(id),
|
||||
"is_active": int.parse(status),
|
||||
@ -330,7 +342,8 @@ class ApiService {
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
// 'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
};
|
||||
|
||||
final response = await _makePostRequestJson(url, data, headers);
|
||||
@ -362,7 +375,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -386,7 +399,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -404,7 +417,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -423,7 +436,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -442,7 +455,7 @@ class ApiService {
|
||||
final url = Uri.parse('${Env.apiUrl}agent/findAgent?id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -461,7 +474,7 @@ class ApiService {
|
||||
final url = Uri.parse('${Env.apiUrl}agent/deleteAgentIncentiveFile?id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -490,7 +503,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -509,7 +522,7 @@ class ApiService {
|
||||
final url = Uri.parse('${Env.apiUrl}staff/findStaff?id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -543,7 +556,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -554,6 +567,8 @@ class ApiService {
|
||||
String role, {
|
||||
String? fromDate,
|
||||
String? toDate,
|
||||
String? selectedStatus,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
@ -573,13 +588,16 @@ class ApiService {
|
||||
query = 'agent_id=$id';
|
||||
}
|
||||
|
||||
// final url = Uri.parse(
|
||||
// '${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
// );
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}&status=$selectedStatus&staff_id=$selectedStaffId',
|
||||
);
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -588,6 +606,7 @@ class ApiService {
|
||||
|
||||
Future<Map<String, dynamic>> fetchAttndanceOFAllStaffList({
|
||||
required String month,
|
||||
required dynamic mangerId,
|
||||
}) async {
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
@ -600,12 +619,12 @@ class ApiService {
|
||||
// }
|
||||
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}staff/monthlyLoginCount?month=${month ?? ''}',
|
||||
'${Env.apiUrl}staff/monthlyLoginCount?month=${month ?? ''}&manager_id=$mangerId',
|
||||
);
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -628,7 +647,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -643,7 +662,7 @@ class ApiService {
|
||||
final url = Uri.parse('${Env.apiUrl}enquiry/enquiryList?enquiry_id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -661,7 +680,7 @@ class ApiService {
|
||||
);
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
print('findEnqQuotePolicyVie2w 3');
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -694,7 +713,7 @@ class ApiService {
|
||||
);
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -708,7 +727,7 @@ class ApiService {
|
||||
final url = Uri.parse('${Env.apiUrl}quotation/findQuotation?id=$id');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -721,17 +740,18 @@ class ApiService {
|
||||
role, {
|
||||
String? fromDate,
|
||||
String? toDate,
|
||||
String? selectedStatus,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
|
||||
final userId = '1';
|
||||
final url;
|
||||
|
||||
final String query;
|
||||
|
||||
final String val = 'Proposal Created';
|
||||
if (role == 'manager') {
|
||||
query = 'manager_id=$id';
|
||||
} else if (role == 'staff') {
|
||||
@ -740,8 +760,12 @@ class ApiService {
|
||||
query = 'agent_id=$id';
|
||||
}
|
||||
|
||||
// url = Uri.parse(
|
||||
// '${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
// );
|
||||
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}&status=$selectedStatus&staff_id=$selectedStaffId',
|
||||
);
|
||||
|
||||
// if (role == 'manager') {
|
||||
@ -757,7 +781,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -768,6 +792,7 @@ class ApiService {
|
||||
role, {
|
||||
String? fromDate,
|
||||
String? toDate,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
@ -787,7 +812,7 @@ class ApiService {
|
||||
}
|
||||
|
||||
final url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&only_policy_data=true&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||
'${Env.apiUrl}enquiry/enquiryList?$query&only_policy_data=true&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}&staff_id=$selectedStaffId',
|
||||
);
|
||||
|
||||
// if (role == 'manager') {
|
||||
@ -809,7 +834,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -840,7 +865,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -855,7 +880,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -888,7 +913,7 @@ class ApiService {
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -905,7 +930,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -941,7 +966,7 @@ class ApiService {
|
||||
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
@ -961,7 +986,7 @@ class ApiService {
|
||||
print('fetchHandlerNameDropDown 2');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
print('fetchHandlerNameDropDown 3');
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -985,7 +1010,7 @@ class ApiService {
|
||||
print('fetchHandlerNameDropDown 2');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
print('fetchHandlerNameDropDown 3');
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
@ -1007,7 +1032,7 @@ class ApiService {
|
||||
print('fetchAGENTNameDropDown 2');
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'App-Signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
print('fetchAGENTNameDropDown 3');
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
|
||||
@ -11,3 +11,7 @@ final staffIndiviualAttendanceIdProvider = StateProvider<String?>(
|
||||
final staffIndiviualAttendanceNameIdProvider = StateProvider<String?>(
|
||||
(ref) => null,
|
||||
);
|
||||
|
||||
final dashboardKeyProvider = StateProvider<int?>((ref) => null);
|
||||
final dashboardStatusProvider = StateProvider<String?>((ref) => null);
|
||||
final dashboardStaffIdProvider = StateProvider<String?>((ref) => null);
|
||||
|
||||
@ -468,8 +468,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -532,6 +531,8 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
}
|
||||
}
|
||||
setState(() => isSaving = false);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
@ -755,7 +756,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildName(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Full Name *",
|
||||
label: "Insured Name *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['name']!,
|
||||
|
||||
@ -773,6 +774,9 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
field: ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||
],
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -786,6 +790,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
field: ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[ 0-9]'))],
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -795,7 +800,7 @@ class EnquiryTabState extends ConsumerState<EnquiryTab> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number *",
|
||||
label: "Vehicle Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
inputFormatters: [
|
||||
|
||||
@ -216,55 +216,6 @@ class _AddDialogState extends State<AddDialog> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createUserData1(data, val) async {
|
||||
// final bool isUpdating = widget.id != null && widget.id != 'create';
|
||||
final String apiUrldata;
|
||||
|
||||
apiUrldata = (val == 'Claims')
|
||||
? '${Env.apiUrl}claim/createClaim'
|
||||
: '${Env.apiUrl}endorsement/createEndorsement';
|
||||
|
||||
// final token = await getToken(); // Fetch token
|
||||
|
||||
if (_token == null) {
|
||||
throw Exception('Token not found. Please log in.');
|
||||
}
|
||||
|
||||
print("data------- $data}");
|
||||
|
||||
try {
|
||||
final response = await http.post(
|
||||
Uri.parse(apiUrldata),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
},
|
||||
body: jsonEncode(data), // Convert map to JSON
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
print("Staff submitted successfully!");
|
||||
print("Response: ${response.body}");
|
||||
ToastHelper.showSuccessToast(context, 'Saved Successfully');
|
||||
Navigator.of(context).pop();
|
||||
|
||||
widget.onSubmit("success");
|
||||
// context.go(AppRoutes.staffLst);
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
|
||||
print("Failed to submit plan. Status: ${response.statusCode}");
|
||||
print("Error: ${response.body}");
|
||||
|
||||
ToastHelper.showErrorToast(context, 'Failed To Save');
|
||||
}
|
||||
} catch (e) {
|
||||
print(" Error submitting Staff: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createUserData(data, val) async {
|
||||
final Uri uri = (val == 'Claims')
|
||||
? Uri.parse('${Env.apiUrl}claim/createClaim')
|
||||
@ -277,8 +228,7 @@ class _AddDialogState extends State<AddDialog> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
print("USerDAta - $data");
|
||||
|
||||
@ -360,6 +310,8 @@ class _AddDialogState extends State<AddDialog> {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
widget.onSubmit("success");
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
|
||||
@ -712,9 +712,10 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
|
||||
Widget buildName(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number",
|
||||
label: "Vehicle Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.requiredField(value, "name"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -725,9 +726,10 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
|
||||
Widget buildInsusrer(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Insusrer",
|
||||
label: "Insurer",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['insurer']!,
|
||||
readOnly: true,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -740,7 +742,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
label: "IDV",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['idv']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -753,6 +756,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
label: "Insured Name",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['insurerName']!,
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -766,6 +770,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
label: "Policy Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['policyNo']!,
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -778,6 +783,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
return buildResponsiveField(
|
||||
label: "Payment Mode",
|
||||
field: ThemedFormField(
|
||||
readOnly: true,
|
||||
controller: controllers['paymentMode']!,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -791,7 +797,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
label: "Plan Type",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['planType']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -804,7 +811,8 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
label: "Premium Amount",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['premAmount']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
readOnly: true,
|
||||
// validator: (value) => Validators.phone(value, "phNumber"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:nhance_partner/presentation/providers/userRoleProvider.dart';
|
||||
@ -297,7 +298,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
headers: {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
},
|
||||
body: jsonEncode(data), // Convert map to JSON
|
||||
);
|
||||
@ -321,6 +322,8 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
// tabKey.currentState?.loadQuotationTab(widget.id ?? "");
|
||||
// });
|
||||
// context.go(AppRoutes.staffLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -349,8 +352,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
print("USerDAta - $userData");
|
||||
|
||||
@ -408,6 +410,8 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
await widget.onRefresh!();
|
||||
}
|
||||
// context.go(AppRoutes.agentLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -643,7 +647,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget buildName(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number",
|
||||
label: "Vehicle Number",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
readOnly: true,
|
||||
@ -657,7 +661,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget buildInsusrer(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Insusrer",
|
||||
label: "Insurer",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['insurer']!,
|
||||
readOnly: true,
|
||||
@ -674,6 +678,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
field: ThemedFormField(
|
||||
controller: controllers['idv']!,
|
||||
readOnly: true,
|
||||
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
@ -709,7 +714,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget buildDocuments(BuildContext context) {
|
||||
return buildResponsiveUploadField(
|
||||
label: 'Quotation Documents',
|
||||
label: 'Proposal Documents',
|
||||
hintText: selectedFileNames,
|
||||
onFileSelected: (fileName, file) {
|
||||
setState(() {
|
||||
@ -915,7 +920,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number *",
|
||||
label: "Vehicle Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
validator: (value) => Validators.requiredField(value, "regNo"),
|
||||
@ -936,10 +941,7 @@ class QuotationTabState extends ConsumerState<QuotationTab> {
|
||||
child: const Row(
|
||||
children: [
|
||||
Expanded(flex: 1, child: Text(' ', style: _headerStyle)),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text('Registration Number', style: _headerStyle),
|
||||
),
|
||||
Expanded(flex: 1, child: Text('Vehicle Number', style: _headerStyle)),
|
||||
Expanded(flex: 1, child: Text('Insurer', style: _headerStyle)),
|
||||
Expanded(flex: 1, child: Text('IDV', style: _headerStyle)),
|
||||
Expanded(flex: 1, child: Text('Plan Type', style: _headerStyle)),
|
||||
|
||||
@ -50,7 +50,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
setState(() => isLoading = false);
|
||||
tabs = [
|
||||
TabItem("Enquiry", EnquiryTab()),
|
||||
TabItem("Quotation", QuotationTab()),
|
||||
TabItem("Proposal", QuotationTab()),
|
||||
TabItem("Policy", PolicyTab()),
|
||||
];
|
||||
}
|
||||
@ -86,7 +86,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
EnquiryTab(data: enquiryData?["enquiry"], id: id ?? ""),
|
||||
),
|
||||
TabItem(
|
||||
"Quotation",
|
||||
"Proposal",
|
||||
QuotationTab(
|
||||
data:
|
||||
(enquiryData?["quotations"] as List<dynamic>?)
|
||||
@ -121,7 +121,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
// ),
|
||||
),
|
||||
|
||||
// TabItem("Quotation", QuotationTab(data: enquiryData?["quotations"])),
|
||||
// TabItem("Proposal", QuotationTab(data: enquiryData?["quotations"])),
|
||||
// TabItem("Policy", PolicyTab()),
|
||||
];
|
||||
});
|
||||
@ -141,7 +141,7 @@ class TabEnquiryListState extends ConsumerState<TabEnquiryList> {
|
||||
EnquiryTab(data: enquiryData?["enquiry"], id: id ?? ""),
|
||||
),
|
||||
TabItem(
|
||||
"Quotation",
|
||||
"Proposal",
|
||||
QuotationTab(
|
||||
data:
|
||||
(enquiryData?["quotations"] as List<dynamic>?)
|
||||
|
||||
@ -32,6 +32,9 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
late ApiService apiService;
|
||||
dynamic roleId;
|
||||
dynamic userId;
|
||||
dynamic SelectedStatus;
|
||||
dynamic SelectedStaffId;
|
||||
late final String? selectedStatusVal;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
// List<Map<String, dynamic>> dataVal = [];
|
||||
@ -82,26 +85,27 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
}
|
||||
|
||||
void filterDateRange() {
|
||||
// ✅ Validate the form first
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
// stop execution if validation fails
|
||||
return;
|
||||
}
|
||||
print('SelectedStatus - $SelectedStatus');
|
||||
// // ✅ Validate the form first
|
||||
// if (!_formKey.currentState!.validate()) {
|
||||
// // stop execution if validation fails
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// final fromDateText = controllers['startDate']?.text ?? '';
|
||||
// final toDateText = controllers['endDate']?.text ?? '';
|
||||
|
||||
final fromDateText = controllers['startDate']?.text ?? '';
|
||||
final toDateText = controllers['endDate']?.text ?? '';
|
||||
|
||||
// Optional: double-check End >= Start
|
||||
final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
// This is already caught by the validator, but extra safety
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
// // Optional: double-check End >= Start
|
||||
// final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
// final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
//
|
||||
// if (toDate.isBefore(fromDate)) {
|
||||
// // This is already caught by the validator, but extra safety
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// ✅ Call your API
|
||||
getStaffList(userId, roleId);
|
||||
@ -109,6 +113,8 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
|
||||
void refrshfilterDateRange() {
|
||||
setState(() {
|
||||
SelectedStatus = '';
|
||||
SelectedStaffId = null;
|
||||
controllers['startDate']!.clear();
|
||||
controllers['endDate']!.clear();
|
||||
|
||||
@ -184,6 +190,8 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
role,
|
||||
fromDate: controllers['startDate']?.text ?? '',
|
||||
toDate: controllers['endDate']?.text ?? '',
|
||||
selectedStatus: SelectedStatus != null ? SelectedStatus : '',
|
||||
selectedStaffId: SelectedStaffId ?? '',
|
||||
);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
@ -384,7 +392,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
),
|
||||
const SizedBox(width: 5), // spacing between icon and text
|
||||
Text(
|
||||
"Enquiries",
|
||||
"Enquiries ",
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: ResponsiveLayout.isMobile(context) ? 14 : 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -451,8 +459,20 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
padding: EdgeInsets.all(8.0),
|
||||
color: Color(0xffD9EBE8),
|
||||
child: DateFilterRow(
|
||||
key: ValueKey(SelectedStatus ?? ''),
|
||||
role: roleId,
|
||||
id: userId,
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
@ -476,8 +496,21 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context)) ...[
|
||||
DateFilterRow(
|
||||
role: roleId,
|
||||
id: userId,
|
||||
key: ValueKey(SelectedStatus ?? ''),
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
@ -500,7 +533,7 @@ class EnquiryListState extends ConsumerState<EnquiryList> {
|
||||
controller: _searchStaffController,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? MediaQuery.of(context).size.width * 0.6
|
||||
: MediaQuery.of(context).size.width * 0.2,
|
||||
: MediaQuery.of(context).size.width * 0.13,
|
||||
),
|
||||
ResponsiveLayout.isMobile(context)
|
||||
? Spacer()
|
||||
|
||||
@ -282,7 +282,13 @@ class ClaimsSubListState extends ConsumerState<ClaimsSubList> {
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(item['claim_status_value'] ?? '-', style: _dataBold),
|
||||
child: Text(
|
||||
item['claim_status_value'] != null
|
||||
? '${item['claim_status_value'][0].toUpperCase()}${item['claim_status_value'].substring(1).toLowerCase()}'
|
||||
: '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
// child: Text(item['claim_status_value'] ?? '-', style: _dataBold),
|
||||
),
|
||||
|
||||
// Expanded(
|
||||
|
||||
@ -144,6 +144,7 @@ class AttendanceAllDetailsState extends ConsumerState<AttendanceAllDetails> {
|
||||
try {
|
||||
final response = await apiService.fetchAttndanceOFAllStaffList(
|
||||
month: monthForApi,
|
||||
mangerId: managerId,
|
||||
// toDate: controllers['endDate']?.text ?? '',
|
||||
);
|
||||
|
||||
|
||||
@ -441,7 +441,7 @@ class IndividualAttendanceDetailsState
|
||||
Expanded(flex: 2, child: Text('Date', style: _headerStyle)),
|
||||
|
||||
Expanded(flex: 2, child: Text('Login', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('Login Time', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('Logout', style: _headerStyle)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Number Of Hours', style: _headerStyle),
|
||||
|
||||
@ -5,6 +5,7 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@ -151,8 +152,7 @@ class AgentState extends ConsumerState<Agent> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -248,6 +248,8 @@ class AgentState extends ConsumerState<Agent> {
|
||||
'Partner Created Successfully',
|
||||
);
|
||||
context.go(AppRoutes.agentLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -491,6 +493,9 @@ class AgentState extends ConsumerState<Agent> {
|
||||
ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||
],
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
),
|
||||
],
|
||||
@ -506,6 +511,9 @@ class AgentState extends ConsumerState<Agent> {
|
||||
ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[ 0-9]')),
|
||||
],
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
),
|
||||
],
|
||||
|
||||
@ -241,8 +241,7 @@ class UploadIncentiveModalState extends ConsumerState<UploadIncentiveModal> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
print("USerDAta - $dataSet");
|
||||
|
||||
@ -337,6 +336,8 @@ class UploadIncentiveModalState extends ConsumerState<UploadIncentiveModal> {
|
||||
}
|
||||
|
||||
// context.go(AppRoutes.agentLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("📨 Body: ${response.body}");
|
||||
|
||||
@ -209,7 +209,10 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
),
|
||||
Text(
|
||||
// profileData?['role'] ?? '-',
|
||||
role ?? '-',
|
||||
(role == 'agent')
|
||||
? 'partner'
|
||||
: role ?? '-',
|
||||
// role ?? '-',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -248,7 +251,8 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (profileData?['role_id'] != '1' &&
|
||||
profileData?['role_id'] != '2') ...[
|
||||
profileData?['role_id'] != '2' &&
|
||||
profileData?['role_id'] != '3') ...[
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
@ -272,7 +276,7 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
|
||||
if (profileData?['role_id'] != 2) ...[
|
||||
if (profileData?['role_id'] != 3) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
color: Color(0xffEDF6F5),
|
||||
@ -281,11 +285,12 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
print("Download - $latestId");
|
||||
dynamic path;
|
||||
|
||||
if (roleId == 1) {
|
||||
if (roleId == 1 &&
|
||||
roleId == 2 &&
|
||||
roleId == 3) {
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$latestId';
|
||||
} else if (roleId != 1 &&
|
||||
roleId != 2) {
|
||||
'api/staff/downloadManagerIncentiveFile?id=$latestId';
|
||||
} else {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$latestId';
|
||||
}
|
||||
@ -375,11 +380,12 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
|
||||
dynamic path;
|
||||
|
||||
if (roleId == 1) {
|
||||
if (roleId == 1 &&
|
||||
roleId == 2 &&
|
||||
roleId == 3) {
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$selectedId';
|
||||
} else if (roleId != 1 &&
|
||||
roleId != 2) {
|
||||
'api/staff/downloadManagerIncentiveFile?id=$selectedId';
|
||||
} else {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
}
|
||||
@ -508,7 +514,8 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (profileData?['role_id'] != '1' &&
|
||||
profileData?['role_id'] != '2') ...[
|
||||
profileData?['role_id'] != '2' &&
|
||||
profileData?['role_id'] != '3') ...[
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
@ -532,7 +539,7 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
|
||||
if (profileData?['role_id'] != 2) ...[
|
||||
if (profileData?['role_id'] != 3) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
color: Color(0xffEDF6F5),
|
||||
@ -541,11 +548,14 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
print("Download - $latestId");
|
||||
dynamic path;
|
||||
|
||||
if (roleId == 1) {
|
||||
if (roleId == 1 &&
|
||||
roleId == 2 &&
|
||||
roleId == 3) {
|
||||
print('teRole - $roleId');
|
||||
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$latestId';
|
||||
} else if (roleId != 1 &&
|
||||
roleId != 2) {
|
||||
'api/staff/downloadManagerIncentiveFile?id=$latestId';
|
||||
} else {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$latestId';
|
||||
}
|
||||
@ -635,11 +645,12 @@ class ProfileState extends ConsumerState<Profile> {
|
||||
|
||||
dynamic path;
|
||||
|
||||
if (roleId == 1) {
|
||||
if (roleId == 1 &&
|
||||
roleId == 2 &&
|
||||
roleId == 3) {
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$selectedId';
|
||||
} else if (roleId != 1 &&
|
||||
roleId != 2) {
|
||||
'api/staff/downloadManagerIncentiveFile?id=$selectedId';
|
||||
} else {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
||||
style: _headerStyle,
|
||||
),
|
||||
Text(
|
||||
role ?? '-',
|
||||
(role == 'agent') ? 'partner' : role ?? '-',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -300,7 +300,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
||||
|
||||
if (roleId == 1) {
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$latestId';
|
||||
'api/staff/downloadManagerIncentiveFile?id=$latestId';
|
||||
} else if (roleId != 1 && roleId != 2) {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$latestId';
|
||||
@ -383,7 +383,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
||||
|
||||
if (roleId == 1) {
|
||||
path =
|
||||
'api/agent/downloadManagerIncentiveFile?id=$selectedId';
|
||||
'api/staff/downloadManagerIncentiveFile?id=$selectedId';
|
||||
} else if (roleId != 1 && roleId != 2) {
|
||||
path =
|
||||
'api/agent/downloadAgentIncentiveFile?id=$selectedId';
|
||||
|
||||
@ -4,6 +4,7 @@ import 'dart:typed_data'; // Import for Uint8List
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@ -183,7 +184,7 @@ class StaffState extends ConsumerState<Staff> {
|
||||
headers: {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
},
|
||||
body: jsonEncode(data), // Convert map to JSON
|
||||
);
|
||||
@ -202,6 +203,8 @@ class StaffState extends ConsumerState<Staff> {
|
||||
'Staff Created Successfully',
|
||||
);
|
||||
context.go(AppRoutes.staffLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -475,6 +478,9 @@ class StaffState extends ConsumerState<Staff> {
|
||||
ThemedFormField(
|
||||
controller: controllers['email']!,
|
||||
validator: (value) => Validators.email(value, "email"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9_@.]')),
|
||||
],
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
),
|
||||
],
|
||||
@ -490,6 +496,9 @@ class StaffState extends ConsumerState<Staff> {
|
||||
ThemedFormField(
|
||||
controller: controllers['mobile']!,
|
||||
validator: (value) => Validators.phone(value, "phNumber"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[ 0-9]')),
|
||||
],
|
||||
txtwidth: MediaQuery.of(context).size.width * 0.26,
|
||||
),
|
||||
],
|
||||
|
||||
@ -1344,29 +1344,70 @@ class othersPendings extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
row['awaiting_quotation'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
print(
|
||||
'Awaiting Proposal : ${row['awaiting_quotation']}',
|
||||
);
|
||||
|
||||
handleDashboardNavigation(
|
||||
context,
|
||||
status: "Awaiting Proposal",
|
||||
staffId: row['staff_id'],
|
||||
role: role,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
row['awaiting_quotation'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
row['pending_quotation_approval'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
print(
|
||||
'Awaiting Approval : ${row['pending_quotation_approval']} - ${row['staff_id']}',
|
||||
);
|
||||
handleDashboardNavigation(
|
||||
context,
|
||||
status: "Proposal Created",
|
||||
staffId: row['staff_id'],
|
||||
role: role,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
row['pending_quotation_approval'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
row['awaiting_policy'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
print(
|
||||
'Awaiting Policy : ${row['awaiting_policy']}',
|
||||
);
|
||||
|
||||
handleDashboardNavigation(
|
||||
context,
|
||||
status: "Proposal Accepted",
|
||||
staffId: row['staff_id'],
|
||||
role: role,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
row['awaiting_policy'] ?? "",
|
||||
// row['total_approval_pending'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
@ -1884,6 +1925,34 @@ class UnassignedEnq extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleDashboardNavigation(
|
||||
BuildContext context, {
|
||||
required String status,
|
||||
required String staffId,
|
||||
required String role,
|
||||
}) async {
|
||||
print('Dashboard Tap => Status: $status | Staff: $staffId');
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
// ✅ Clear any old data
|
||||
await prefs.remove('dashboardKeyProvider');
|
||||
await prefs.remove('dashboardStatusProvider');
|
||||
await prefs.remove('dashboardStaffIdProvider');
|
||||
|
||||
// ✅ Save new values
|
||||
await prefs.setString('dashboardKeyProvider', 'fromDashboard');
|
||||
await prefs.setString('dashboardStatusProvider', status);
|
||||
await prefs.setString('dashboardStaffIdProvider', staffId);
|
||||
|
||||
// ✅ Navigate
|
||||
if (role == 'manager') {
|
||||
context.go(AppRoutes.enquiryForStaff);
|
||||
} else {
|
||||
context.go(AppRoutes.enquiryHandlerLst);
|
||||
}
|
||||
}
|
||||
|
||||
final _headerStyle = GoogleFonts.inter(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 14,
|
||||
|
||||
@ -39,6 +39,9 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
late ApiService apiService;
|
||||
dynamic userId;
|
||||
dynamic managerId;
|
||||
dynamic dashboardKey;
|
||||
dynamic SelectedStatus;
|
||||
dynamic SelectedStaffId;
|
||||
dynamic handlerId;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@ -62,16 +65,44 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
controllers[field] = TextEditingController();
|
||||
}
|
||||
|
||||
Future.microtask(() {
|
||||
Future.microtask(() async {
|
||||
final id = ref.read(managerIdProvider);
|
||||
roleId = ref.read(userRoleProvider);
|
||||
userId = ref.read(userIdProvider);
|
||||
managerId = ref.read(managerIdProvider);
|
||||
|
||||
// dashboardKey = ref.read(dashboardKeyProvider);
|
||||
// final dashboardStatus = ref.read(dashboardStatusProvider);
|
||||
// final dashboardStaffId = ref.read(dashboardStaffIdProvider);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
dashboardKey = prefs.getString('dashboardKeyProvider');
|
||||
final dashboardStatus = prefs.getString('dashboardStatusProvider');
|
||||
final dashboardStaffId = prefs.getString('dashboardStaffIdProvider');
|
||||
// handlerId = ref.read(handlerIdProvider);
|
||||
|
||||
print('handlerIdENQ - $handlerId');
|
||||
print("C72 => r : $roleId | mId: $id | uId: $userId !mID : $managerId ");
|
||||
if (managerId != null) {
|
||||
|
||||
print('dashboardKey - $dashboardKey');
|
||||
print('dashboardStatus - $dashboardStatus');
|
||||
print('dashboardStaffId - $dashboardStaffId');
|
||||
|
||||
if (managerId != null &&
|
||||
dashboardKey != null &&
|
||||
dashboardKey == 'fromDashboard' &&
|
||||
dashboardStatus != null &&
|
||||
dashboardStaffId != null) {
|
||||
print("DASHBOARD STATus-$dashboardStatus -- $dashboardStaffId -");
|
||||
SelectedStatus = dashboardStatus;
|
||||
SelectedStaffId = dashboardStaffId;
|
||||
getStaffList(
|
||||
managerId,
|
||||
roleId,
|
||||
SelectedStatus: dashboardStatus,
|
||||
SelectedStaffId: dashboardStaffId,
|
||||
);
|
||||
} else {
|
||||
print('ELSE');
|
||||
getStaffList(managerId, roleId);
|
||||
}
|
||||
});
|
||||
@ -89,26 +120,27 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
}
|
||||
|
||||
void filterDateRange() {
|
||||
// ✅ Validate the form first
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
// stop execution if validation fails
|
||||
return;
|
||||
}
|
||||
|
||||
final fromDateText = controllers['startDate']?.text ?? '';
|
||||
final toDateText = controllers['endDate']?.text ?? '';
|
||||
|
||||
// Optional: double-check End >= Start
|
||||
final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
// This is already caught by the validator, but extra safety
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
// print('SelectedStatus - $SelectedStatus');
|
||||
// // ✅ Validate the form first
|
||||
// if (!_formKey.currentState!.validate()) {
|
||||
// // stop execution if validation fails
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// final fromDateText = controllers['startDate']?.text ?? '';
|
||||
// final toDateText = controllers['endDate']?.text ?? '';
|
||||
//
|
||||
// // Optional: double-check End >= Start
|
||||
// final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
// final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
//
|
||||
// if (toDate.isBefore(fromDate)) {
|
||||
// // This is already caught by the validator, but extra safety
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// ✅ Call your API
|
||||
getStaffList(managerId, roleId);
|
||||
@ -116,6 +148,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
|
||||
void refrshfilterDateRange() {
|
||||
setState(() {
|
||||
SelectedStatus = '';
|
||||
SelectedStaffId = null;
|
||||
controllers['startDate']!.clear();
|
||||
controllers['endDate']!.clear();
|
||||
|
||||
@ -132,6 +166,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
role, {
|
||||
String fromDate = '',
|
||||
String toDate = '',
|
||||
String SelectedStatus = '',
|
||||
String SelectedStaffId = '',
|
||||
}) async {
|
||||
print('A72 => Fns called => $managerId | $role');
|
||||
setState(() {
|
||||
@ -144,6 +180,8 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
role,
|
||||
fromDate: controllers['startDate']?.text ?? '',
|
||||
toDate: controllers['endDate']?.text ?? '',
|
||||
selectedStatus: SelectedStatus != null ? SelectedStatus : '',
|
||||
selectedStaffId: SelectedStaffId ?? '',
|
||||
);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
@ -516,13 +554,17 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
Tooltip(
|
||||
message: 'Back',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.arrow_left_sharp),
|
||||
onPressed: () {
|
||||
icon: const Icon(Icons.arrow_left_sharp, size: 25),
|
||||
onPressed: () async {
|
||||
context.go(AppRoutes.dashboard);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('dashboardKeyProvider');
|
||||
await prefs.remove('dashboardStatusProvider');
|
||||
await prefs.remove('dashboardStaffIdProvider');
|
||||
},
|
||||
splashRadius: 28,
|
||||
splashRadius: 18,
|
||||
padding: const EdgeInsets.all(4),
|
||||
hoverColor: Colors.black12,
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
@ -538,7 +580,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
SizedBox(height: 5),
|
||||
ResponsiveLayout.isMobile(context)
|
||||
? Container(
|
||||
height: MediaQuery.of(context).size.height * 0.69,
|
||||
@ -604,10 +646,23 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
padding: EdgeInsets.all(8.0),
|
||||
color: Color(0xffD9EBE8),
|
||||
child: DateFilterRow(
|
||||
key: ValueKey(SelectedStatus ?? ''),
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
role: roleId,
|
||||
id: userId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
|
||||
onFilter: () {
|
||||
// call your filter logic
|
||||
filterDateRange();
|
||||
@ -624,13 +679,25 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
// height: 40,
|
||||
// color: Colors.pink,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context)) ...[
|
||||
DateFilterRow(
|
||||
key: ValueKey(SelectedStatus ?? ''),
|
||||
role: roleId,
|
||||
id: userId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
@ -653,7 +720,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryHandler> {
|
||||
controller: _searchStaffController,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? MediaQuery.of(context).size.width * 0.7
|
||||
: MediaQuery.of(context).size.width * 0.2,
|
||||
: MediaQuery.of(context).size.width * 0.13,
|
||||
),
|
||||
|
||||
ResponsiveLayout.isMobile(context)
|
||||
|
||||
@ -250,7 +250,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
body: json.encode(payload),
|
||||
headers: {
|
||||
HttpHeaders.contentTypeHeader: 'application/json',
|
||||
'App-Signature': Env.App_Signature,
|
||||
'app-signature': Env.App_Signature,
|
||||
},
|
||||
);
|
||||
|
||||
@ -311,7 +311,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
body: json.encode(payload),
|
||||
headers: {
|
||||
HttpHeaders.contentTypeHeader: 'application/json',
|
||||
'App-Signature': Env.App_Signature,
|
||||
'app-signature': Env.App_Signature,
|
||||
},
|
||||
);
|
||||
|
||||
@ -939,6 +939,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
Validators.email(value, "Email"),
|
||||
// imgPath: "MiscIconAssetPath.person",
|
||||
controller: _emailController,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r'[a-zA-Z0-9_@.]'),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (switcherStatus == 1)
|
||||
ThemedFormField(
|
||||
@ -948,6 +953,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
Validators.phone(value, "Phone"),
|
||||
// imgPath: "MiscIconAssetPath.person",
|
||||
controller: _PhoneNumberController,
|
||||
|
||||
// txtwidth: MediaQuery.of(context).size.width * 0.5,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 10,
|
||||
|
||||
@ -54,6 +54,8 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
late ApiService apiService;
|
||||
dynamic userId;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
dynamic SelectedStatus;
|
||||
dynamic SelectedStaffId;
|
||||
|
||||
// List<Map<String, dynamic>> dataVal = [];
|
||||
List<Map<String, dynamic>> getStaffData = [];
|
||||
@ -99,33 +101,64 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
}
|
||||
|
||||
void filterDateRange() {
|
||||
print('SelectedStatus - $SelectedStatus');
|
||||
print('SelectedStaffId - $SelectedStaffId');
|
||||
// ✅ Validate the form first
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
// stop execution if validation fails
|
||||
return;
|
||||
}
|
||||
// if (!_formKey.currentState!.validate()) {
|
||||
// // stop execution if validation fails
|
||||
// return;
|
||||
// }
|
||||
|
||||
final fromDateText = controllers['startDate']?.text ?? '';
|
||||
final toDateText = controllers['endDate']?.text ?? '';
|
||||
// final fromDateText = controllers['startDate']?.text ?? '';
|
||||
// final toDateText = controllers['endDate']?.text ?? '';
|
||||
//
|
||||
// print("fromDateText - $fromDateText");
|
||||
// print("toDateText - $toDateText");
|
||||
|
||||
// Optional: double-check End >= Start
|
||||
final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
// This is already caught by the validator, but extra safety
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
// final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
// final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
//
|
||||
// if (toDate.isBefore(fromDate)) {
|
||||
// // This is already caught by the validator, but extra safety
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// DateTime? fromDate;
|
||||
// DateTime? toDate;
|
||||
//
|
||||
// // ✅ Only parse if the date text is not empty
|
||||
// if (fromDateText.isNotEmpty) {
|
||||
// fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
// }
|
||||
// if (toDateText.isNotEmpty) {
|
||||
// toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
// }
|
||||
//
|
||||
// // ✅ Check if both dates are given before comparing
|
||||
// if (fromDate != null && toDate != null && toDate.isBefore(fromDate)) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(
|
||||
// content: Text("End Date cannot be earlier than Start Date"),
|
||||
// ),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
// ✅ Call your API
|
||||
getStaffList(userId, roleId);
|
||||
}
|
||||
|
||||
void refrshfilterDateRange() {
|
||||
print('refrshfilterDateRange--1');
|
||||
setState(() {
|
||||
SelectedStatus = '';
|
||||
SelectedStaffId = null;
|
||||
|
||||
print('refrshselectedStaff - $SelectedStaffId');
|
||||
print('refrshfilterDateRange--1 - $SelectedStatus');
|
||||
controllers['startDate']!.clear();
|
||||
controllers['endDate']!.clear();
|
||||
|
||||
@ -154,6 +187,8 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
role,
|
||||
fromDate: controllers['startDate']?.text ?? '',
|
||||
toDate: controllers['endDate']?.text ?? '',
|
||||
selectedStatus: SelectedStatus ?? '',
|
||||
selectedStaffId: SelectedStaffId ?? '',
|
||||
);
|
||||
|
||||
print('FromDate : $fromDate');
|
||||
@ -169,8 +204,9 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
print('ToDate : $toDate');
|
||||
setState(() {
|
||||
controllers['startDate']?.text = fromDate;
|
||||
print('1');
|
||||
controllers['endDate']?.text = toDate;
|
||||
|
||||
print('2');
|
||||
if (data is List) {
|
||||
// Already a list of maps
|
||||
getStaffData = List<Map<String, dynamic>>.from(data);
|
||||
@ -180,9 +216,12 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
} else {
|
||||
getStaffData = [];
|
||||
}
|
||||
print('3');
|
||||
// getStaffData = List<Map<String, dynamic>>.from(response['data']);
|
||||
originalData = getStaffData;
|
||||
print('4');
|
||||
filteredData = List.from(originalData);
|
||||
print('5');
|
||||
// print('originalData - $getClaimPolicies');
|
||||
});
|
||||
} else {
|
||||
@ -351,97 +390,97 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
// ✅ Remove old value (if any)
|
||||
await prefs.remove('enqStaffDataId');
|
||||
|
||||
// ✅ Save the new id
|
||||
await prefs.setString('enqStaffDataId', id.toString());
|
||||
|
||||
// Read it back if needed
|
||||
// final dynamic? enqStaffDataId = prefs.getString('enqStaffDataId');
|
||||
|
||||
// ✅ Update provider too
|
||||
// ref.read(quotationStaffIdProvider.notifier).state = enqStaffDataId;
|
||||
ref.read(quotationStaffIdProvider.notifier).state = id;
|
||||
|
||||
context.go(AppRoutes.quotation);
|
||||
},
|
||||
hoverColor: Color(0xFFE3F1F0),
|
||||
splashColor: Color(0xFFE3F1F0),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
child: Row(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/miscellaneous/image_1.png",
|
||||
height: 15,
|
||||
width: 15,
|
||||
),
|
||||
|
||||
const SizedBox(width: 10),
|
||||
((data['status'] == 'Policy Created') ||
|
||||
(data['status'] == 'Quotation Accepted'))
|
||||
? const Text('View Quotation')
|
||||
: const Text('Create Quotation'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (data['status'] == 'Quotation Accepted' ||
|
||||
data['status'] == 'Policy Created')
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
// ✅ Remove old value (if any)
|
||||
await prefs.remove('enqStaffDataId');
|
||||
|
||||
// ✅ Save the new id
|
||||
await prefs.setString('enqStaffDataId', id.toString());
|
||||
|
||||
// ✅ Update provider too
|
||||
|
||||
ref.read(quotationStaffIdProvider.notifier).state = id;
|
||||
context.go(AppRoutes.policy);
|
||||
},
|
||||
hoverColor: Color(0xFFE3F1F0),
|
||||
splashColor: Color(0xFFE3F1F0),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
child: Row(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/miscellaneous/image_2.png",
|
||||
height: 15,
|
||||
width: 15,
|
||||
),
|
||||
|
||||
const SizedBox(width: 10),
|
||||
data['status'] == 'Policy Created'
|
||||
? Text('View Policy')
|
||||
: Text('Create Policy'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Material(
|
||||
// color: Colors.transparent,
|
||||
// child: InkWell(
|
||||
// onTap: () async {
|
||||
// Navigator.pop(context);
|
||||
// final prefs = await SharedPreferences.getInstance();
|
||||
//
|
||||
// // ✅ Remove old value (if any)
|
||||
// await prefs.remove('enqStaffDataId');
|
||||
//
|
||||
// // ✅ Save the new id
|
||||
// await prefs.setString('enqStaffDataId', id.toString());
|
||||
//
|
||||
// // Read it back if needed
|
||||
// // final dynamic? enqStaffDataId = prefs.getString('enqStaffDataId');
|
||||
//
|
||||
// // ✅ Update provider too
|
||||
// // ref.read(quotationStaffIdProvider.notifier).state = enqStaffDataId;
|
||||
// ref.read(quotationStaffIdProvider.notifier).state = id;
|
||||
//
|
||||
// context.go(AppRoutes.quotation);
|
||||
// },
|
||||
// hoverColor: Color(0xFFE3F1F0),
|
||||
// splashColor: Color(0xFFE3F1F0),
|
||||
// borderRadius: BorderRadius.circular(6),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
// child: Row(
|
||||
// // mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// "assets/miscellaneous/image_1.png",
|
||||
// height: 15,
|
||||
// width: 15,
|
||||
// ),
|
||||
//
|
||||
// const SizedBox(width: 10),
|
||||
// ((data['status'] == 'Policy Created') ||
|
||||
// (data['status'] == 'Quotation Accepted'))
|
||||
// ? const Text('View Quotation')
|
||||
// : const Text('Create Quotation'),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
//
|
||||
// if (data['status'] == 'Quotation Accepted' ||
|
||||
// data['status'] == 'Policy Created')
|
||||
// Material(
|
||||
// color: Colors.transparent,
|
||||
// child: InkWell(
|
||||
// onTap: () async {
|
||||
// Navigator.pop(context);
|
||||
//
|
||||
// final prefs = await SharedPreferences.getInstance();
|
||||
//
|
||||
// // ✅ Remove old value (if any)
|
||||
// await prefs.remove('enqStaffDataId');
|
||||
//
|
||||
// // ✅ Save the new id
|
||||
// await prefs.setString('enqStaffDataId', id.toString());
|
||||
//
|
||||
// // ✅ Update provider too
|
||||
//
|
||||
// ref.read(quotationStaffIdProvider.notifier).state = id;
|
||||
// context.go(AppRoutes.policy);
|
||||
// },
|
||||
// hoverColor: Color(0xFFE3F1F0),
|
||||
// splashColor: Color(0xFFE3F1F0),
|
||||
// borderRadius: BorderRadius.circular(6),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
// child: Row(
|
||||
// // mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// "assets/miscellaneous/image_2.png",
|
||||
// height: 15,
|
||||
// width: 15,
|
||||
// ),
|
||||
//
|
||||
// const SizedBox(width: 10),
|
||||
// data['status'] == 'Policy Created'
|
||||
// ? Text('View Policy')
|
||||
// : Text('Create Policy'),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
];
|
||||
}
|
||||
|
||||
@ -491,13 +530,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
Tooltip(
|
||||
message: 'Back',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.arrow_left_sharp),
|
||||
icon: const Icon(Icons.arrow_left_sharp, size: 25),
|
||||
onPressed: () {
|
||||
context.go(AppRoutes.dashboard);
|
||||
},
|
||||
splashRadius: 28,
|
||||
splashRadius: 18,
|
||||
hoverColor: Colors.black12,
|
||||
padding: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(4),
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
),
|
||||
@ -579,8 +618,21 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
padding: EdgeInsets.all(8.0),
|
||||
color: Color(0xffD9EBE8),
|
||||
child: DateFilterRow(
|
||||
key: ValueKey((SelectedStatus ?? '') || (SelectedStaffId ?? '')),
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
role: roleId,
|
||||
id: userId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
@ -599,15 +651,27 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
// height: 40,
|
||||
// color: Colors.pink,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context)) ...[
|
||||
DateFilterRow(
|
||||
key: ValueKey(SelectedStatus ?? ''),
|
||||
role: roleId,
|
||||
id: userId,
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
selectedStatusVal: SelectedStatus,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
onFilter: () {
|
||||
// call your filter logic
|
||||
filterDateRange();
|
||||
@ -693,7 +757,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
],
|
||||
),
|
||||
),
|
||||
// SizedBox(height: 10),
|
||||
SizedBox(height: 8),
|
||||
if (!ResponsiveLayout.isMobile(context))
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
@ -859,7 +923,19 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
color: Colors.white,
|
||||
);
|
||||
},
|
||||
child: Text(item['reg_no'] ?? '-', style: _dataBold),
|
||||
child: Tooltip(
|
||||
message:
|
||||
'Click and Download Enquiry Files', // what appears on hover/long press
|
||||
waitDuration: const Duration(milliseconds: 500), // optional
|
||||
showDuration: const Duration(seconds: 2), // optional
|
||||
child: Text(
|
||||
item['reg_no'] ?? '-',
|
||||
style: _dataBold,
|
||||
overflow: TextOverflow
|
||||
.ellipsis, // optional, if text might overflow
|
||||
),
|
||||
),
|
||||
// child: Text(item['reg_no'] ?? '-', style: _dataBold),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -901,7 +977,17 @@ class EnquiryStaffState extends ConsumerState<EnquiryStaff> {
|
||||
ref.read(quotationStaffIdProvider.notifier).state = enqId;
|
||||
buildStatusActions(context, status, enqId);
|
||||
},
|
||||
child: Text(item['status'] ?? '-', style: _dataBold),
|
||||
child: Tooltip(
|
||||
message: 'Click to View or Process Enquiry', //
|
||||
waitDuration: const Duration(milliseconds: 500), // optional
|
||||
showDuration: const Duration(seconds: 2), // optional
|
||||
child: Text(
|
||||
item['status'] ?? '-',
|
||||
style: _dataBold,
|
||||
overflow: TextOverflow.ellipsis, //
|
||||
),
|
||||
),
|
||||
// child: Text(item['status'] ?? '-', style: _dataBold),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@ -130,6 +131,7 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
print('RESET');
|
||||
_formKey.currentState?.reset();
|
||||
// Clear all TextEditingControllers
|
||||
for (var controller in controllers.values) {
|
||||
@ -303,8 +305,7 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -370,6 +371,8 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
||||
widget.onSubmit('Success');
|
||||
reset();
|
||||
// Navigator.of(context).pop();
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -479,6 +482,9 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['idv']!,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||
],
|
||||
validator: (value) => Validators.doubleNumber(value, "IDV"),
|
||||
// validator: (value) => Validators.number(value, "IDV"),
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
@ -591,6 +597,9 @@ class CreateQuotationFormState extends ConsumerState<CreateQuotationForm> {
|
||||
ThemedFormField(
|
||||
controller: controllers['premium_Amount']!,
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||
],
|
||||
validator: (value) => Validators.doubleNumber(value, "PremiumAmount"),
|
||||
// validator: (value) => Validators.number(value, "PremiumAmount "),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
|
||||
@ -428,8 +428,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -482,6 +481,8 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
||||
ref.read(enquiryIdProvider.notifier).state = null;
|
||||
context.go(AppRoutes.enquiryForStaff);
|
||||
}
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
print("❌ Submission failed. Status: ${response.statusCode}");
|
||||
print("Body: ${response.body}");
|
||||
@ -879,7 +880,7 @@ class PolicyStaffTabState extends ConsumerState<PolicyStaffTab> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Registration Number*', style: _textStyle),
|
||||
Text('Vehicle Number*', style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
|
||||
@ -176,6 +176,11 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
||||
|
||||
void refresh() {
|
||||
print("refresh--");
|
||||
setState(() {
|
||||
selectedQuotationFrmListId = null;
|
||||
selectedQuotationFrmListData = null;
|
||||
});
|
||||
|
||||
if (enqQuotation != null) {
|
||||
_loadData(enqQuotation);
|
||||
}
|
||||
@ -307,7 +312,7 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Registration Number', style: _textStyle),
|
||||
Text('Vehicle Number', style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
@ -364,7 +369,7 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number *",
|
||||
label: "Vehicle Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
validator: (value) => Validators.requiredField(value, "regNo"),
|
||||
@ -426,10 +431,7 @@ class QuotationStaffTabState extends ConsumerState<QuotationStaffTab> {
|
||||
child: Row(
|
||||
children: [
|
||||
// Expanded(flex: 3, child: Text(' ', style: _headerStyle)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Registration Number', style: _headerStyle),
|
||||
),
|
||||
Expanded(flex: 2, child: Text('Vehicle Number', style: _headerStyle)),
|
||||
Expanded(flex: 3, child: Text('Insurer', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('IDV', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('Plan Type', style: _headerStyle)),
|
||||
|
||||
@ -211,7 +211,7 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
headers: {
|
||||
'Authorization': 'Bearer $_token',
|
||||
'Content-Type': 'application/json',
|
||||
'app-signature': 'nhance-partner-2025-signature-35468846JRhH551HK',
|
||||
'app-signature': Env.App_Signature,
|
||||
},
|
||||
body: jsonEncode(data), // Convert map to JSON
|
||||
);
|
||||
@ -229,6 +229,8 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
//
|
||||
widget.onSubmit("success");
|
||||
// context.go(AppRoutes.staffLst);
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
} else {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
dynamic msg = responseBody['data'];
|
||||
@ -387,7 +389,7 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Registration Number", style: _textStyle),
|
||||
Text("Vehicle Number", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
|
||||
@ -434,8 +434,7 @@ class PolicyScreenState extends ConsumerState<PolicyScreen> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -1011,7 +1010,7 @@ class PolicyScreenState extends ConsumerState<PolicyScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Registration Number*', style: _textStyle),
|
||||
Text('Vehicle Number*', style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
|
||||
@ -29,6 +29,8 @@ class policylistState extends ConsumerState<policylist> {
|
||||
int itemsPerPage = 10;
|
||||
late ApiService apiService;
|
||||
dynamic userId;
|
||||
dynamic SelectedStatus;
|
||||
dynamic SelectedStaffId;
|
||||
// List<Map<String, dynamic>> dataVal = [];
|
||||
List<Map<String, dynamic>> getStaffData = [];
|
||||
List<Map<String, dynamic>> originalData = [];
|
||||
@ -89,6 +91,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
role,
|
||||
fromDate: controllers['startDate']?.text ?? '',
|
||||
toDate: controllers['endDate']?.text ?? '',
|
||||
selectedStaffId: SelectedStaffId ?? '',
|
||||
);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
@ -149,25 +152,25 @@ class policylistState extends ConsumerState<policylist> {
|
||||
|
||||
void filterDateRange() {
|
||||
// ✅ Validate the form first
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
// stop execution if validation fails
|
||||
return;
|
||||
}
|
||||
|
||||
final fromDateText = controllers['startDate']?.text ?? '';
|
||||
final toDateText = controllers['endDate']?.text ?? '';
|
||||
|
||||
// Optional: double-check End >= Start
|
||||
final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
|
||||
if (toDate.isBefore(fromDate)) {
|
||||
// This is already caught by the validator, but extra safety
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
// if (!_formKey.currentState!.validate()) {
|
||||
// // stop execution if validation fails
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// final fromDateText = controllers['startDate']?.text ?? '';
|
||||
// final toDateText = controllers['endDate']?.text ?? '';
|
||||
//
|
||||
// // Optional: double-check End >= Start
|
||||
// final fromDate = DateFormat('dd-MM-yyyy').parse(fromDateText);
|
||||
// final toDate = DateFormat('dd-MM-yyyy').parse(toDateText);
|
||||
//
|
||||
// if (toDate.isBefore(fromDate)) {
|
||||
// // This is already caught by the validator, but extra safety
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(content: Text("End Date cannot be earlier than Start Date")),
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// ✅ Call your API
|
||||
getStaffList(userId, roleId);
|
||||
@ -175,6 +178,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
|
||||
void refrshfilterDateRange() {
|
||||
setState(() {
|
||||
SelectedStaffId = null;
|
||||
controllers['startDate']!.clear();
|
||||
controllers['endDate']!.clear();
|
||||
|
||||
@ -465,8 +469,19 @@ class policylistState extends ConsumerState<policylist> {
|
||||
padding: EdgeInsets.all(8.0),
|
||||
color: Color(0xffD9EBE8),
|
||||
child: DateFilterRow(
|
||||
dataFrom: 'Policy',
|
||||
role: roleId,
|
||||
id: userId,
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
@ -490,8 +505,19 @@ class policylistState extends ConsumerState<policylist> {
|
||||
children: [
|
||||
if (!ResponsiveLayout.isMobile(context)) ...[
|
||||
DateFilterRow(
|
||||
dataFrom: 'Policy',
|
||||
role: roleId,
|
||||
id: userId,
|
||||
onFilterStaff: (val) {
|
||||
print('Selected Filterd STAFF Id - $val');
|
||||
SelectedStaffId = val;
|
||||
},
|
||||
selectedStaffId: SelectedStaffId,
|
||||
startController: controllers['startDate']!,
|
||||
endController: controllers['endDate']!,
|
||||
onStatusChanged: (val) {
|
||||
SelectedStatus = val; // update parent
|
||||
},
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
|
||||
@ -3,6 +3,7 @@ import 'dart:convert';
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:toastification/toastification.dart';
|
||||
@ -262,8 +263,7 @@ class createQuotatDialogState extends State<createQuotatDialog> {
|
||||
// Use MultipartRequest (POST only)
|
||||
final request = http.MultipartRequest('POST', uri);
|
||||
request.headers['Authorization'] = 'Bearer $_token';
|
||||
request.headers['app-signature'] =
|
||||
'nhance-partner-2025-signature-35468846JRhH551HK';
|
||||
request.headers['app-signature'] = Env.App_Signature;
|
||||
|
||||
// If updating, spoof the method Laravel-style
|
||||
if (isUpdating) {
|
||||
@ -458,6 +458,9 @@ class createQuotatDialogState extends State<createQuotatDialog> {
|
||||
ThemedFormField(
|
||||
controller: controllers['idv']!,
|
||||
validator: (value) => Validators.doubleNumber(value, "IDV"),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||
],
|
||||
// validator: (value) => Validators.number(value, "IDV"),
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
// readOnly: true,
|
||||
|
||||
@ -653,7 +653,7 @@ class QuotationScreenState extends ConsumerState<QuotationScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Registration Number', style: _textStyle),
|
||||
Text('Vehicle Number', style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['regNum']!,
|
||||
@ -710,7 +710,7 @@ class QuotationScreenState extends ConsumerState<QuotationScreen> {
|
||||
|
||||
Widget buildId(BuildContext context) {
|
||||
return buildResponsiveField(
|
||||
label: "Registration Number *",
|
||||
label: "Vehicle Number *",
|
||||
field: ThemedFormField(
|
||||
controller: controllers['regNo']!,
|
||||
validator: (value) => Validators.requiredField(value, "regNo"),
|
||||
@ -773,10 +773,7 @@ class QuotationScreenState extends ConsumerState<QuotationScreen> {
|
||||
child: Row(
|
||||
children: [
|
||||
// Expanded(flex: 3, child: Text(' ', style: _headerStyle)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text('Registration Number', style: _headerStyle),
|
||||
),
|
||||
Expanded(flex: 2, child: Text('Vehicle Number', style: _headerStyle)),
|
||||
Expanded(flex: 4, child: Text('Insurer', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('IDV', style: _headerStyle)),
|
||||
Expanded(flex: 2, child: Text('Plan Type', style: _headerStyle)),
|
||||
|
||||
@ -143,7 +143,10 @@ class ThemedFormField extends HookWidget {
|
||||
readOnly: readOnly, // ✅ now supported
|
||||
keyboardType: keyboardType, // ✅ e.g. TextInputType.number
|
||||
maxLength: maxLength, // ✅ max length
|
||||
inputFormatters: inputFormatters,
|
||||
inputFormatters:
|
||||
inputFormatters ??
|
||||
[FilteringTextInputFormatter.allow(RegExp(r'[a-z A-Z]'))],
|
||||
|
||||
// ✅ allow multiline if user sets maxLines / minLines
|
||||
minLines: (keyboardType == TextInputType.multiline) ? 3 : 1,
|
||||
maxLines: (keyboardType == TextInputType.multiline) ? null : 1,
|
||||
|
||||
@ -1,15 +1,53 @@
|
||||
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 DateFilterRow extends StatelessWidget {
|
||||
// class DateFilterRow extends StatelessWidget {
|
||||
// final TextEditingController startController;
|
||||
// final String? selectedStatusVal;
|
||||
// final TextEditingController endController;
|
||||
// final ValueChanged<String?>? onStatusChanged;
|
||||
// final String? dataFrom;
|
||||
// final VoidCallback onFilter;
|
||||
// final VoidCallback onRefresh;
|
||||
// final GlobalKey<FormState> formKey;
|
||||
// final bool isMobile;
|
||||
//
|
||||
// DateFilterRow({
|
||||
// super.key,
|
||||
// required this.startController,
|
||||
// required this.endController,
|
||||
// required this.onFilter,
|
||||
// required this.onRefresh,
|
||||
// required this.onStatusChanged,
|
||||
// this.selectedStatusVal,
|
||||
// required this.formKey,
|
||||
// this.isMobile = false,
|
||||
// this.dataFrom,
|
||||
// });
|
||||
|
||||
class DateFilterRow extends ConsumerStatefulWidget {
|
||||
final TextEditingController startController;
|
||||
final String? selectedStatusVal;
|
||||
final String? selectedStaffId;
|
||||
final TextEditingController endController;
|
||||
final ValueChanged<String?>? onStatusChanged;
|
||||
final ValueChanged<String?>? onFilterStaff;
|
||||
final String? dataFrom;
|
||||
final VoidCallback onFilter;
|
||||
final VoidCallback onRefresh;
|
||||
final GlobalKey<FormState> formKey;
|
||||
final bool isMobile;
|
||||
final role;
|
||||
final id;
|
||||
|
||||
const DateFilterRow({
|
||||
super.key,
|
||||
@ -17,10 +55,93 @@ class DateFilterRow extends StatelessWidget {
|
||||
required this.endController,
|
||||
required this.onFilter,
|
||||
required this.onRefresh,
|
||||
required this.onStatusChanged,
|
||||
required this.onFilterStaff,
|
||||
required this.selectedStaffId,
|
||||
this.selectedStatusVal,
|
||||
required this.formKey,
|
||||
required this.role,
|
||||
required this.id,
|
||||
this.isMobile = false,
|
||||
this.dataFrom,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<DateFilterRow> createState() => _DateFilterRowState();
|
||||
}
|
||||
|
||||
class _DateFilterRowState extends ConsumerState<DateFilterRow> {
|
||||
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
|
||||
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
||||
late ApiService apiService;
|
||||
List<Map<String, dynamic>> getStaffDetailsData = [];
|
||||
List<Map<String, dynamic>> filteredStaffData = [];
|
||||
|
||||
String? selectedStaff;
|
||||
String? selectedStaffName;
|
||||
dynamic role;
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
apiService = ApiService();
|
||||
|
||||
Future.microtask(() {
|
||||
final managerId = ref.watch(managerIdProvider);
|
||||
final userID = ref.watch(userIdProvider);
|
||||
// final handlerId = ref.watch(handlerIdProvider);
|
||||
role = ref.watch(userRoleProvider);
|
||||
print("managerId - $managerId");
|
||||
if (userID != null && role != null) {
|
||||
print('hansles');
|
||||
getStaffDetails(userID);
|
||||
}
|
||||
});
|
||||
|
||||
// Future.microtask(() {
|
||||
// print("CUSTuserID - ${widget.id}, CUSTrole -${widget.role}");
|
||||
// if (widget.role != null && widget.id != null) {
|
||||
// print('hansles');
|
||||
// getStaffDetails(widget.id);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
Future<void> getStaffDetails(int id) async {
|
||||
print('getStaffDetails called By handler');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchStaffUserList(id, role);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
print('getStaffDetails - ${response['data']}');
|
||||
setState(() {
|
||||
getStaffDetailsData = List<Map<String, dynamic>>.from(
|
||||
response['data'],
|
||||
);
|
||||
print('API Data - $getStaffDetailsData');
|
||||
|
||||
filteredStaffData = List.from(getStaffDetailsData);
|
||||
print('originalData - $filteredStaffData');
|
||||
});
|
||||
} else {
|
||||
getStaffDetailsData = [];
|
||||
filteredStaffData = [];
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final spacing = 10.0;
|
||||
@ -51,6 +172,16 @@ class DateFilterRow extends StatelessWidget {
|
||||
SizedBox(width: spacing),
|
||||
buildEndDate(context),
|
||||
SizedBox(width: spacing),
|
||||
|
||||
if (widget.dataFrom == null && widget.dataFrom != 'Policy') ...[
|
||||
buildStatusSearch(context),
|
||||
SizedBox(width: spacing),
|
||||
],
|
||||
|
||||
if (widget.role == 'manager' || widget.role == 'handler') ...[
|
||||
buildSelectStaffMem(context),
|
||||
SizedBox(width: spacing),
|
||||
],
|
||||
];
|
||||
|
||||
final buttons = [
|
||||
@ -67,8 +198,8 @@ class DateFilterRow extends StatelessWidget {
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.filter_alt_outlined),
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
onFilter();
|
||||
if (widget.formKey.currentState!.validate()) {
|
||||
widget.onFilter();
|
||||
}
|
||||
},
|
||||
),
|
||||
@ -80,7 +211,7 @@ class DateFilterRow extends StatelessWidget {
|
||||
child: Tooltip(
|
||||
message: 'Refresh',
|
||||
child: IconButton(
|
||||
onPressed: onRefresh,
|
||||
onPressed: widget.onRefresh,
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
),
|
||||
@ -101,15 +232,15 @@ class DateFilterRow extends StatelessWidget {
|
||||
}
|
||||
|
||||
return Form(
|
||||
key: formKey,
|
||||
child: isMobile
|
||||
key: widget.formKey,
|
||||
child: widget.isMobile
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: getRowChildren(isMobile, spacing),
|
||||
children: getRowChildren(widget.isMobile, spacing),
|
||||
)
|
||||
: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: getRowChildren(isMobile, spacing),
|
||||
children: getRowChildren(widget.isMobile, spacing),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -124,15 +255,15 @@ class DateFilterRow extends StatelessWidget {
|
||||
hintText: "Select Date",
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.16,
|
||||
: MediaQuery.of(context).size.width * 0.1,
|
||||
// txtheight: 50,
|
||||
// backgroundColor: const Color(0xFFECECEC),
|
||||
// validator: (value) => Validators.requiredField(value, "date"),
|
||||
controller: startController,
|
||||
controller: widget.startController,
|
||||
onDateSelected: (date) {
|
||||
print("Picked Date: $date");
|
||||
|
||||
startController.text = DateFormat('dd-MM-yyyy').format(date);
|
||||
widget.startController.text = DateFormat('dd-MM-yyyy').format(date);
|
||||
// controllers['date']?.text = date as String;
|
||||
},
|
||||
),
|
||||
@ -150,17 +281,16 @@ class DateFilterRow extends StatelessWidget {
|
||||
hintText: "Select Date",
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.16,
|
||||
: MediaQuery.of(context).size.width * 0.1,
|
||||
// txtheight: 50,
|
||||
// backgroundColor: const Color(0xFFECECEC),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "End Date is required";
|
||||
}
|
||||
|
||||
final fromText = startController.text ?? '';
|
||||
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)) {
|
||||
@ -169,11 +299,11 @@ class DateFilterRow extends StatelessWidget {
|
||||
}
|
||||
return null; // ✅ no error
|
||||
},
|
||||
controller: endController,
|
||||
controller: widget.endController,
|
||||
lastDate: DateTime.now(),
|
||||
onDateSelected: (date) {
|
||||
print("Picked Date: $date");
|
||||
endController.text = DateFormat('dd-MM-yyyy').format(date);
|
||||
widget.endController.text = DateFormat('dd-MM-yyyy').format(date);
|
||||
// controllers['date']?.text = date as String;
|
||||
},
|
||||
),
|
||||
@ -181,6 +311,256 @@ class DateFilterRow extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildStatusSearch(BuildContext context) {
|
||||
final List<Map<String, dynamic>> statusOptions = [
|
||||
{'id': 1, 'status': 'Awaiting Proposal'},
|
||||
{'id': 2, 'status': 'Proposal Created'},
|
||||
{'id': 3, 'status': 'Proposal Accepted'},
|
||||
{'id': 4, 'status': 'Proposal Rejected'},
|
||||
{'id': 5, 'status': 'Policy Created'},
|
||||
];
|
||||
Map<String, dynamic>? selectedStatusMap = statusOptions
|
||||
.where((element) => element['status'] == widget.selectedStatusVal)
|
||||
.cast<Map<String, dynamic>>()
|
||||
.toList()
|
||||
.firstOrNull;
|
||||
Map<String, dynamic>? selectedItem = statusOptions
|
||||
.cast<Map<String, dynamic>>()
|
||||
.firstWhere(
|
||||
(e) => e['status'] == widget.selectedStatusVal,
|
||||
orElse: () => {}, // return empty map
|
||||
);
|
||||
|
||||
if (selectedItem.isEmpty) selectedItem = null;
|
||||
// Map<String, dynamic>? selectedStatus; // ✅ Default: no selection
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Status', style: _textStyle),
|
||||
SizedBox(height: 5),
|
||||
SizedBox(
|
||||
height: 40,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(color: Colors.grey.shade100),
|
||||
// color: Colors.black,
|
||||
),
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.14,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
// selectedItem: selectedStatus,
|
||||
selectedItem: selectedStatusMap,
|
||||
// selectedItem: statusOptions.firstWhere(
|
||||
// (element) => element['status'] == selectedStatusVal,
|
||||
// orElse: () => null, // ✅ return null if not found
|
||||
// ),
|
||||
items: (filter, infiniteScrollProps) => statusOptions,
|
||||
|
||||
itemAsString: (val) => val['status'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'],
|
||||
|
||||
// validator: (val) {
|
||||
// if (val == null) {
|
||||
// return "Please select a status";
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration: AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Status",
|
||||
).copyWith(filled: true, fillColor: Colors.white),
|
||||
),
|
||||
// popupProps: PopupProps.menu(
|
||||
// fit: FlexFit.loose,
|
||||
// constraints: BoxConstraints(maxHeight: 200),
|
||||
// menuProps: MenuProps(backgroundColor: Colors.white),
|
||||
// showSearchBox: false, // 👈 no search box since it's static
|
||||
//
|
||||
// ),
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: const BoxConstraints(maxHeight: 200),
|
||||
menuProps: const MenuProps(backgroundColor: Colors.white),
|
||||
showSearchBox: false,
|
||||
|
||||
itemBuilder: (context, item, isDisabled, isSelected) {
|
||||
// ✅ 4 parameters
|
||||
return Container(
|
||||
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
child: Text(
|
||||
item['status'].toString(),
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 13,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
print("Selected Status: ${val['status']}");
|
||||
if (widget.onStatusChanged != null)
|
||||
widget.onStatusChanged!(val['status']);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSelectStaffMem(BuildContext context) {
|
||||
// Map<String, dynamic>? selectedVehicle = filteredStaffData.firstWhere(
|
||||
// (item) => item['id'].toString() == selectedStaff,
|
||||
// orElse: () => {},
|
||||
// );
|
||||
|
||||
// Map<String, dynamic>? selectedVehicle;
|
||||
// try {
|
||||
// selectedVehicle = filteredStaffData.firstWhere(
|
||||
// (item) => item['id'].toString() == selectedStaff,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// selectedVehicle = null; // ✅ fallback
|
||||
// }
|
||||
|
||||
Map<String, dynamic>? selectedVehicle;
|
||||
if (widget.selectedStaffId == null) {
|
||||
selectedVehicle = null;
|
||||
} else if (widget.selectedStaffId != null) {
|
||||
selectedVehicle = filteredStaffData.firstWhere(
|
||||
(item) => item['id'] == widget.selectedStaffId,
|
||||
orElse: () => {}, // empty map
|
||||
);
|
||||
if (selectedVehicle.isEmpty) selectedVehicle = null;
|
||||
} else if (selectedStaff != null) {
|
||||
selectedVehicle = filteredStaffData.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),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
border: Border.all(color: Colors.grey.shade100),
|
||||
// color: Colors.black,
|
||||
),
|
||||
|
||||
width: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.13,
|
||||
height: 40,
|
||||
child: DropdownSearch<Map<String, dynamic>>(
|
||||
// key: dropDownKey,
|
||||
key: ValueKey(selectedStaff),
|
||||
// selectedItem: selectedVehicle.isNotEmpty ? selectedVehicle : null,
|
||||
selectedItem: selectedVehicle,
|
||||
|
||||
items: (filter, infiniteScrollProps) {
|
||||
return filteredStaffData;
|
||||
},
|
||||
|
||||
itemAsString: (val) => val['name'].toString(),
|
||||
compareFn: (item, selectedItem) =>
|
||||
item['id'] == selectedItem['id'], // ✅ compare by id
|
||||
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration:
|
||||
AppInputDecorations.dropdownDecoration(
|
||||
label: "Select Staff ",
|
||||
).copyWith(
|
||||
filled: true,
|
||||
fillColor:
|
||||
Colors.white, // 👈 makes the dropdown input white
|
||||
),
|
||||
),
|
||||
|
||||
popupProps: PopupProps.menu(
|
||||
fit: FlexFit.loose,
|
||||
constraints: BoxConstraints(maxHeight: 250),
|
||||
menuProps: MenuProps(
|
||||
backgroundColor:
|
||||
Colors.white, // 👈 sets dropdown background to white
|
||||
),
|
||||
showSearchBox: true,
|
||||
searchFieldProps: TextFieldProps(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
hintText: "Search 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) {
|
||||
// ✅ 4 parameters
|
||||
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'];
|
||||
|
||||
if (widget.onFilterStaff != null)
|
||||
widget.onFilterStaff!(val['id']);
|
||||
// controllers['agentId']?.text = val['agent_code'];
|
||||
// agentId = agent['id'];
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static const _textStyle = TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
@ -188,25 +568,27 @@ class DateFilterRow extends StatelessWidget {
|
||||
|
||||
Widget buildStartDate1() {
|
||||
return ThemedDateField(
|
||||
controller: startController,
|
||||
controller: widget.startController,
|
||||
hintText: 'Select Start Date',
|
||||
validator: (value) =>
|
||||
value == null || value.isEmpty ? "Start Date required" : null,
|
||||
onDateSelected: (date) =>
|
||||
startController.text = DateFormat('dd-MM-yyyy').format(date),
|
||||
widget.startController.text = DateFormat('dd-MM-yyyy').format(date),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildEndDate1() {
|
||||
return ThemedDateField(
|
||||
controller: endController,
|
||||
controller: widget.endController,
|
||||
hintText: 'Select End Date',
|
||||
lastDate: DateTime.now(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) return "End Date required";
|
||||
|
||||
if (startController.text.isNotEmpty) {
|
||||
final start = DateFormat('dd-MM-yyyy').parse(startController.text);
|
||||
if (widget.startController.text.isNotEmpty) {
|
||||
final start = DateFormat(
|
||||
'dd-MM-yyyy',
|
||||
).parse(widget.startController.text);
|
||||
final end = DateFormat('dd-MM-yyyy').parse(value);
|
||||
if (end.isBefore(start))
|
||||
return "End Date cannot be earlier than Start Date";
|
||||
@ -214,7 +596,7 @@ class DateFilterRow extends StatelessWidget {
|
||||
return null;
|
||||
},
|
||||
onDateSelected: (date) =>
|
||||
endController.text = DateFormat('dd-MM-yyyy').format(date),
|
||||
widget.endController.text = DateFormat('dd-MM-yyyy').format(date),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../core/routing/routes.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@ -112,8 +113,13 @@ class DrawerMenuState extends ConsumerState<DrawerMenu> {
|
||||
width: 25,
|
||||
),
|
||||
label: "Dashboard",
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
_hidePopup();
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('dashboardKeyProvider');
|
||||
await prefs.remove('dashboardStatusProvider');
|
||||
await prefs.remove('dashboardStaffIdProvider');
|
||||
context.go(AppRoutes.dashboard);
|
||||
},
|
||||
),
|
||||
@ -123,7 +129,11 @@ class DrawerMenuState extends ConsumerState<DrawerMenu> {
|
||||
context: context,
|
||||
icon: Icon(Icons.list_alt_rounded, size: 30, color: Colors.black),
|
||||
label: "Enquiry",
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('dashboardKeyProvider');
|
||||
await prefs.remove('dashboardStatusProvider');
|
||||
await prefs.remove('dashboardStaffIdProvider');
|
||||
_hidePopup();
|
||||
if (roleId == 'agent') {
|
||||
context.go(AppRoutes.enquiryLst);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user