approvals screen done
This commit is contained in:
parent
b8bd8952ed
commit
7ce3e95b17
@ -54,6 +54,8 @@ class Environment {
|
||||
return "$base - Dashboard";
|
||||
case 'policies':
|
||||
return "$base - Policies";
|
||||
case 'pendingDependentApproval':
|
||||
return "$base - Approvals";
|
||||
case 'CdPoliciesList':
|
||||
return "$base - CD Details";
|
||||
case 'ClaimsPolicies':
|
||||
|
||||
@ -89,6 +89,12 @@ class _NhanceSideBarState extends State<NhanceSideBar> {
|
||||
'label': 'Policies',
|
||||
'icon': 'policies',
|
||||
});
|
||||
items.add({
|
||||
'route': 'pendingDependentApproval',
|
||||
'label': 'Approvals',
|
||||
'icon': 'pending_approve',
|
||||
'useMaterialIcon': true,
|
||||
});
|
||||
}
|
||||
|
||||
// CD
|
||||
@ -363,18 +369,25 @@ class _NhanceSideBarState extends State<NhanceSideBar> {
|
||||
final showClaimsSubMenu = isClaims && _hasMultipleClaimsSubMenus;
|
||||
final claimsDirectRoute =
|
||||
isClaims ? (_singleClaimsRoute ?? 'ClaimsPolicies') : null;
|
||||
final useMaterialIcon = item['useMaterialIcon'] == true;
|
||||
|
||||
return _SideItem(
|
||||
key: itemKey,
|
||||
icon: SvgPicture.string(
|
||||
SvgService.getSvg(item['icon']),
|
||||
width: 35,
|
||||
height: 35,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
Colors.white,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
icon: useMaterialIcon
|
||||
? const Icon(
|
||||
Icons.how_to_reg_outlined,
|
||||
color: Colors.white,
|
||||
size: 30,
|
||||
)
|
||||
: SvgPicture.string(
|
||||
SvgService.getSvg(item['icon']),
|
||||
width: 35,
|
||||
height: 35,
|
||||
colorFilter: const ColorFilter.mode(
|
||||
Colors.white,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
label: item['label'],
|
||||
isActive: isClaims ? isClaimsActive : activeRoute == item['route'],
|
||||
onTap: showClaimsSubMenu
|
||||
@ -730,10 +743,14 @@ class _SideItem extends StatelessWidget {
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
fontSize: 10,
|
||||
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/claims.dart';
|
||||
import 'package:nhancepolicy/presentation/nonEBClaimsList.dart';
|
||||
import 'package:nhancepolicy/presentation/pendingDependentApproval.dart';
|
||||
import 'package:nhancepolicy/presentation/policies.dart';
|
||||
import 'package:nhancepolicy/service/session/session_service.dart';
|
||||
import 'package:nhancepolicy/service/token_storage_service.dart';
|
||||
@ -187,6 +188,7 @@ const Set<String> _authProtectedRoutes = {
|
||||
'hrHome',
|
||||
'hrDashboard',
|
||||
'policies',
|
||||
'pendingDependentApproval',
|
||||
'claimsOverviewDashboard',
|
||||
'ClaimsPolicies',
|
||||
'nonEBClaimsList',
|
||||
@ -378,6 +380,9 @@ final Map<String, WidgetBuilder> appRoutes = {
|
||||
'policies': (context) => AuthWrapper(
|
||||
builder: (_) => const policies(),
|
||||
),
|
||||
'pendingDependentApproval': (context) => AuthWrapper(
|
||||
builder: (_) => const PendingDependentApproval(),
|
||||
),
|
||||
'CdPoliciesList': (context) => AuthWrapper(
|
||||
builder: (_) => CdPoliciesList(),
|
||||
),
|
||||
|
||||
@ -1947,13 +1947,13 @@ class _HrPolicyDetailsState extends State<hrPolicyDetails>
|
||||
],
|
||||
(
|
||||
label: 'Import',
|
||||
icon: Icons.upload_file_rounded,
|
||||
icon: Icons.file_download_outlined,
|
||||
color: const Color(0xFFE26728),
|
||||
onTap: _openImportFlow,
|
||||
),
|
||||
(
|
||||
label: 'Export',
|
||||
icon: Icons.download_rounded,
|
||||
icon: Icons.file_upload_outlined,
|
||||
color: const Color(0xFFE26728),
|
||||
onTap: localTokenType == 'pre'
|
||||
? 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);
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// (`downloadEmployeeListExcel?client_id=&policy_id=&branch_id=`).
|
||||
Future<http.Response> downloadEmployeeListExcel({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user