approvals screen done
This commit is contained in:
parent
b8bd8952ed
commit
7ce3e95b17
@ -54,6 +54,8 @@ class Environment {
|
|||||||
return "$base - Dashboard";
|
return "$base - Dashboard";
|
||||||
case 'policies':
|
case 'policies':
|
||||||
return "$base - Policies";
|
return "$base - Policies";
|
||||||
|
case 'pendingDependentApproval':
|
||||||
|
return "$base - Approvals";
|
||||||
case 'CdPoliciesList':
|
case 'CdPoliciesList':
|
||||||
return "$base - CD Details";
|
return "$base - CD Details";
|
||||||
case 'ClaimsPolicies':
|
case 'ClaimsPolicies':
|
||||||
|
|||||||
@ -89,6 +89,12 @@ class _NhanceSideBarState extends State<NhanceSideBar> {
|
|||||||
'label': 'Policies',
|
'label': 'Policies',
|
||||||
'icon': 'policies',
|
'icon': 'policies',
|
||||||
});
|
});
|
||||||
|
items.add({
|
||||||
|
'route': 'pendingDependentApproval',
|
||||||
|
'label': 'Approvals',
|
||||||
|
'icon': 'pending_approve',
|
||||||
|
'useMaterialIcon': true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// CD
|
// CD
|
||||||
@ -363,10 +369,17 @@ class _NhanceSideBarState extends State<NhanceSideBar> {
|
|||||||
final showClaimsSubMenu = isClaims && _hasMultipleClaimsSubMenus;
|
final showClaimsSubMenu = isClaims && _hasMultipleClaimsSubMenus;
|
||||||
final claimsDirectRoute =
|
final claimsDirectRoute =
|
||||||
isClaims ? (_singleClaimsRoute ?? 'ClaimsPolicies') : null;
|
isClaims ? (_singleClaimsRoute ?? 'ClaimsPolicies') : null;
|
||||||
|
final useMaterialIcon = item['useMaterialIcon'] == true;
|
||||||
|
|
||||||
return _SideItem(
|
return _SideItem(
|
||||||
key: itemKey,
|
key: itemKey,
|
||||||
icon: SvgPicture.string(
|
icon: useMaterialIcon
|
||||||
|
? const Icon(
|
||||||
|
Icons.how_to_reg_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 30,
|
||||||
|
)
|
||||||
|
: SvgPicture.string(
|
||||||
SvgService.getSvg(item['icon']),
|
SvgService.getSvg(item['icon']),
|
||||||
width: 35,
|
width: 35,
|
||||||
height: 35,
|
height: 35,
|
||||||
@ -730,10 +743,14 @@ class _SideItem extends StatelessWidget {
|
|||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 11,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
|
height: 1.15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import 'package:nhancepolicy/presentation/postFileUpload.dart';
|
|||||||
import 'package:nhancepolicy/presentation/cdList.dart';
|
import 'package:nhancepolicy/presentation/cdList.dart';
|
||||||
import 'package:nhancepolicy/presentation/claims.dart';
|
import 'package:nhancepolicy/presentation/claims.dart';
|
||||||
import 'package:nhancepolicy/presentation/nonEBClaimsList.dart';
|
import 'package:nhancepolicy/presentation/nonEBClaimsList.dart';
|
||||||
|
import 'package:nhancepolicy/presentation/pendingDependentApproval.dart';
|
||||||
import 'package:nhancepolicy/presentation/policies.dart';
|
import 'package:nhancepolicy/presentation/policies.dart';
|
||||||
import 'package:nhancepolicy/service/session/session_service.dart';
|
import 'package:nhancepolicy/service/session/session_service.dart';
|
||||||
import 'package:nhancepolicy/service/token_storage_service.dart';
|
import 'package:nhancepolicy/service/token_storage_service.dart';
|
||||||
@ -187,6 +188,7 @@ const Set<String> _authProtectedRoutes = {
|
|||||||
'hrHome',
|
'hrHome',
|
||||||
'hrDashboard',
|
'hrDashboard',
|
||||||
'policies',
|
'policies',
|
||||||
|
'pendingDependentApproval',
|
||||||
'claimsOverviewDashboard',
|
'claimsOverviewDashboard',
|
||||||
'ClaimsPolicies',
|
'ClaimsPolicies',
|
||||||
'nonEBClaimsList',
|
'nonEBClaimsList',
|
||||||
@ -378,6 +380,9 @@ final Map<String, WidgetBuilder> appRoutes = {
|
|||||||
'policies': (context) => AuthWrapper(
|
'policies': (context) => AuthWrapper(
|
||||||
builder: (_) => const policies(),
|
builder: (_) => const policies(),
|
||||||
),
|
),
|
||||||
|
'pendingDependentApproval': (context) => AuthWrapper(
|
||||||
|
builder: (_) => const PendingDependentApproval(),
|
||||||
|
),
|
||||||
'CdPoliciesList': (context) => AuthWrapper(
|
'CdPoliciesList': (context) => AuthWrapper(
|
||||||
builder: (_) => CdPoliciesList(),
|
builder: (_) => CdPoliciesList(),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1947,13 +1947,13 @@ class _HrPolicyDetailsState extends State<hrPolicyDetails>
|
|||||||
],
|
],
|
||||||
(
|
(
|
||||||
label: 'Import',
|
label: 'Import',
|
||||||
icon: Icons.upload_file_rounded,
|
icon: Icons.file_download_outlined,
|
||||||
color: const Color(0xFFE26728),
|
color: const Color(0xFFE26728),
|
||||||
onTap: _openImportFlow,
|
onTap: _openImportFlow,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
label: 'Export',
|
label: 'Export',
|
||||||
icon: Icons.download_rounded,
|
icon: Icons.file_upload_outlined,
|
||||||
color: const Color(0xFFE26728),
|
color: const Color(0xFFE26728),
|
||||||
onTap: localTokenType == 'pre'
|
onTap: localTokenType == 'pre'
|
||||||
? null
|
? null
|
||||||
|
|||||||
1027
lib/presentation/pendingDependentApproval.dart
Normal file
1027
lib/presentation/pendingDependentApproval.dart
Normal file
File diff suppressed because it is too large
Load Diff
@ -750,6 +750,120 @@ class ApiService {
|
|||||||
return _makeGetRequest(url, headers);
|
return _makeGetRequest(url, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pending approval dependents list
|
||||||
|
/// (`GET getPendingApprovalDependents`) — post API only.
|
||||||
|
Future<Map<String, dynamic>> getPendingApprovalDependents({
|
||||||
|
String? clientId,
|
||||||
|
String? branchId,
|
||||||
|
String? search,
|
||||||
|
String? token,
|
||||||
|
}) async {
|
||||||
|
final authToken = token ?? _token;
|
||||||
|
if (authToken == null || authToken.isEmpty) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
final query = <String, String>{};
|
||||||
|
if (clientId != null && clientId.toString().trim().isNotEmpty) {
|
||||||
|
query['client_id'] = clientId.toString();
|
||||||
|
}
|
||||||
|
if (branchId != null && branchId.toString().trim().isNotEmpty) {
|
||||||
|
query['client_branch_id'] = branchId.toString();
|
||||||
|
query['branch_id'] = branchId.toString();
|
||||||
|
}
|
||||||
|
if (search != null && search.trim().isNotEmpty) {
|
||||||
|
query['search'] = search.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse(
|
||||||
|
'${Environment.apiUrlPost}getPendingApprovalDependents',
|
||||||
|
).replace(
|
||||||
|
queryParameters: query.isEmpty ? null : query,
|
||||||
|
);
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer ${token ?? _token ?? ''}',
|
||||||
|
'APP-SIGNATURE':
|
||||||
|
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await http.get(url, headers: headers);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return _parseJsonBody(response);
|
||||||
|
}
|
||||||
|
// API returns 404 when there are no pending dependents.
|
||||||
|
if (response.statusCode == 404) {
|
||||||
|
final body = _parseJsonBody(response);
|
||||||
|
return {
|
||||||
|
'status': 'success',
|
||||||
|
'code': 404,
|
||||||
|
'message': body['message'] ?? 'No pending approval dependents found',
|
||||||
|
'data': <dynamic>[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _handleResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Approve or reject a pending dependent
|
||||||
|
/// (`POST processDependentAdd`).
|
||||||
|
Future<Map<String, dynamic>> processDependentAdd({
|
||||||
|
required bool isPost,
|
||||||
|
required dynamic employeeId,
|
||||||
|
required dynamic clientPolicyId,
|
||||||
|
required String status,
|
||||||
|
dynamic hrId,
|
||||||
|
String? rejectReason,
|
||||||
|
String? token,
|
||||||
|
}) async {
|
||||||
|
final authToken = token ?? _token;
|
||||||
|
if (authToken == null || authToken.isEmpty) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
final baseUrl = isPost ? Environment.apiUrlPost : Environment.apiUrl;
|
||||||
|
final url = Uri.parse('${baseUrl}processDependentAdd');
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer ${token ?? _token ?? ''}',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'APP-SIGNATURE':
|
||||||
|
'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
||||||
|
};
|
||||||
|
final body = <String, dynamic>{
|
||||||
|
'employee_id': employeeId,
|
||||||
|
'client_policy_id': clientPolicyId,
|
||||||
|
'status': status,
|
||||||
|
};
|
||||||
|
if (hrId != null && hrId.toString().trim().isNotEmpty) {
|
||||||
|
body['hr_id'] = hrId is num ? hrId : int.tryParse(hrId.toString()) ?? hrId;
|
||||||
|
}
|
||||||
|
if (status == 'rejected' &&
|
||||||
|
rejectReason != null &&
|
||||||
|
rejectReason.trim().isNotEmpty) {
|
||||||
|
body['reject_reason'] = rejectReason.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await http.post(
|
||||||
|
url,
|
||||||
|
headers: headers,
|
||||||
|
body: jsonEncode(body),
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return _parseJsonBody(response);
|
||||||
|
}
|
||||||
|
// Surface API validation messages (400/404) without session redirect.
|
||||||
|
if (response.statusCode == 400 || response.statusCode == 404) {
|
||||||
|
final parsed = _parseJsonBody(response);
|
||||||
|
return {
|
||||||
|
'status': parsed['status'] ?? 'error',
|
||||||
|
'code': response.statusCode,
|
||||||
|
'message': parsed['message'] ??
|
||||||
|
parsed['data']?.toString() ??
|
||||||
|
'Request failed',
|
||||||
|
'data': parsed['data'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _handleResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
/// Excel export for employee list
|
/// Excel export for employee list
|
||||||
/// (`downloadEmployeeListExcel?client_id=&policy_id=&branch_id=`).
|
/// (`downloadEmployeeListExcel?client_id=&policy_id=&branch_id=`).
|
||||||
Future<http.Response> downloadEmployeeListExcel({
|
Future<http.Response> downloadEmployeeListExcel({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user