|
|
|
|
@ -9,80 +9,75 @@ import 'package:test_sa/models/lookup.dart';
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'package:http/http.dart';
|
|
|
|
|
|
|
|
|
|
/// Provider for managing site request operations including:
|
|
|
|
|
/// - Fetching request types
|
|
|
|
|
/// - Managing user's current sites
|
|
|
|
|
/// - Submitting site requests
|
|
|
|
|
/// - Fetching and paginating request history
|
|
|
|
|
class SiteRequestProvider extends ChangeNotifier {
|
|
|
|
|
// Constants
|
|
|
|
|
static const int _defaultPageSize = 10;
|
|
|
|
|
static const String _errorFetchFailed = 'Failed to fetch data';
|
|
|
|
|
static const String _errorSubmitFailed = 'Failed to submit request';
|
|
|
|
|
|
|
|
|
|
// Loading states
|
|
|
|
|
bool _loading = false;
|
|
|
|
|
bool get loading => _loading;
|
|
|
|
|
bool _isLoadingMore = false;
|
|
|
|
|
|
|
|
|
|
set loading(bool value) {
|
|
|
|
|
_loading = value;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
// Data
|
|
|
|
|
List<RequestTypeModel> _requestTypes = [];
|
|
|
|
|
List<SiteRequestSiteModel> _userCurrentSites = [];
|
|
|
|
|
List<SiteRequestModel> _requestHistory = [];
|
|
|
|
|
|
|
|
|
|
String? _errorMessage;
|
|
|
|
|
String? get errorMessage => _errorMessage;
|
|
|
|
|
// Pagination
|
|
|
|
|
int _currentPage = 1;
|
|
|
|
|
int _pageSize = _defaultPageSize;
|
|
|
|
|
bool _hasMoreData = true;
|
|
|
|
|
|
|
|
|
|
// Error handling
|
|
|
|
|
String? _errorMessage;
|
|
|
|
|
int? stateCode;
|
|
|
|
|
|
|
|
|
|
// Get current user from UserProvider
|
|
|
|
|
String getCurrentUserEmployeeId(UserProvider userProvider) {
|
|
|
|
|
return userProvider.user?.userID ?? '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String getCurrentUserFullName(UserProvider userProvider) {
|
|
|
|
|
return userProvider.user?.username ?? '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String getCurrentUserEmail(UserProvider userProvider) {
|
|
|
|
|
return userProvider.user?.email ?? '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String getCurrentUserMobile(UserProvider userProvider) {
|
|
|
|
|
return userProvider.user?.phoneNumber ?? '';
|
|
|
|
|
}
|
|
|
|
|
// Getters
|
|
|
|
|
bool get loading => _loading;
|
|
|
|
|
bool get isLoadingMore => _isLoadingMore;
|
|
|
|
|
String? get errorMessage => _errorMessage;
|
|
|
|
|
int get currentPage => _currentPage;
|
|
|
|
|
bool get hasMoreData => _hasMoreData;
|
|
|
|
|
List<RequestTypeModel> get requestTypes => _requestTypes;
|
|
|
|
|
List<SiteRequestSiteModel> get userCurrentSites => _userCurrentSites;
|
|
|
|
|
List<SiteRequestModel> get requestHistory => _requestHistory;
|
|
|
|
|
|
|
|
|
|
String getCurrentUserExtension(UserProvider userProvider) {
|
|
|
|
|
return userProvider.user?.extensionNo ?? '';
|
|
|
|
|
}
|
|
|
|
|
// User helper methods
|
|
|
|
|
String getCurrentUserEmployeeId(UserProvider userProvider) => userProvider.user?.userID ?? '';
|
|
|
|
|
String getCurrentUserFullName(UserProvider userProvider) => userProvider.user?.username ?? '';
|
|
|
|
|
String getCurrentUserEmail(UserProvider userProvider) => userProvider.user?.email ?? '';
|
|
|
|
|
String getCurrentUserMobile(UserProvider userProvider) => userProvider.user?.phoneNumber ?? '';
|
|
|
|
|
String getCurrentUserExtension(UserProvider userProvider) => userProvider.user?.extensionNo ?? '';
|
|
|
|
|
|
|
|
|
|
String getCurrentUserRole(UserProvider userProvider) {
|
|
|
|
|
// Get the first role if available
|
|
|
|
|
if (userProvider.user?.userRoles != null && userProvider.user!.userRoles!.isNotEmpty) {
|
|
|
|
|
return userProvider.user!.userRoles!.first.name ?? '';
|
|
|
|
|
}
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<String> getCurrentUserAssignedSites(UserProvider userProvider) {
|
|
|
|
|
return [];
|
|
|
|
|
List<String> getCurrentUserAssignedSites(UserProvider userProvider) => [];
|
|
|
|
|
bool hasAssignedSites(List<String> assignedSites) => assignedSites.isNotEmpty;
|
|
|
|
|
|
|
|
|
|
// Setter
|
|
|
|
|
set loading(bool value) {
|
|
|
|
|
_loading = value;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<RequestTypeModel> _requestTypes = [];
|
|
|
|
|
List<RequestTypeModel> get requestTypes => _requestTypes;
|
|
|
|
|
/// Fetches available request types from the server
|
|
|
|
|
Future<int> fetchRequestTypes() async {
|
|
|
|
|
if (_loading) return -2;
|
|
|
|
|
|
|
|
|
|
_loading = true;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
|
|
late Response response;
|
|
|
|
|
try {
|
|
|
|
|
response = await ApiManager.instance.get(
|
|
|
|
|
URLs.getSiteRequestTypes,
|
|
|
|
|
enableToastMessage: false,
|
|
|
|
|
);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_loading = false;
|
|
|
|
|
stateCode = -1;
|
|
|
|
|
_errorMessage = 'Failed to fetch request types';
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stateCode = response.statusCode;
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
try {
|
|
|
|
|
var responseData = json.decode(response.body);
|
|
|
|
|
return _performApiCall(
|
|
|
|
|
apiCall: () => ApiManager.instance.get(URLs.getSiteRequestTypes, enableToastMessage: false),
|
|
|
|
|
onSuccess: (responseData) {
|
|
|
|
|
List listJson = responseData['data'] ?? responseData;
|
|
|
|
|
_requestTypes = listJson
|
|
|
|
|
.map((item) => Lookup.fromJson(item))
|
|
|
|
|
@ -92,250 +87,225 @@ class SiteRequestProvider extends ChangeNotifier {
|
|
|
|
|
value: lookup.value,
|
|
|
|
|
))
|
|
|
|
|
.toList();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Failed to parse request types: $e';
|
|
|
|
|
_loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
_errorMessage = 'Failed to fetch request types';
|
|
|
|
|
},
|
|
|
|
|
errorMessage: 'Failed to fetch request types',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return response.statusCode;
|
|
|
|
|
}
|
|
|
|
|
List<SiteRequestSiteModel> _allSites = [];
|
|
|
|
|
List<SiteRequestSiteModel> get allSites => _allSites;
|
|
|
|
|
Future<int> fetchSites() async {
|
|
|
|
|
/// Fetches user's current sites for Change/Remove Site operations
|
|
|
|
|
Future<int> fetchUserCurrentSites(String userId) async {
|
|
|
|
|
if (_loading) return -2;
|
|
|
|
|
|
|
|
|
|
_loading = true;
|
|
|
|
|
return _performApiCall(
|
|
|
|
|
apiCall: () => ApiManager.instance.post(URLs.getUserSites(userId), showToast: false, body: {}),
|
|
|
|
|
onSuccess: (responseData) {
|
|
|
|
|
List listJson = responseData['data'] ?? [];
|
|
|
|
|
_userCurrentSites = listJson
|
|
|
|
|
.map((item) => SiteRequestSiteModel(
|
|
|
|
|
id: item['siteId']?.toString() ?? '',
|
|
|
|
|
name: item['siteName'] ?? '',
|
|
|
|
|
))
|
|
|
|
|
.toList();
|
|
|
|
|
},
|
|
|
|
|
errorMessage: 'Failed to fetch user sites',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Submits a site request to the server
|
|
|
|
|
Future<bool> submitSiteRequest(SiteRequestModel request, UserProvider userProvider) async {
|
|
|
|
|
loading = true;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
|
|
late Response response;
|
|
|
|
|
try {
|
|
|
|
|
response = await ApiManager.instance.get(
|
|
|
|
|
URLs.signUpGetSiteList,
|
|
|
|
|
enableToastMessage: false,
|
|
|
|
|
);
|
|
|
|
|
final isChangeSiteRequest = _requestTypes.any((type) =>
|
|
|
|
|
type.identifier == request.requestType && (type.name?.toLowerCase().contains('change') ?? false));
|
|
|
|
|
|
|
|
|
|
final requestBody = _buildRequestBody(request, userProvider, isChangeSiteRequest);
|
|
|
|
|
|
|
|
|
|
final response = await ApiManager.instance.post(URLs.submitSiteRequest, body: requestBody);
|
|
|
|
|
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
_handleSubmitSuccess(response, request);
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
_handleSubmitError(response);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_loading = false;
|
|
|
|
|
stateCode = -1;
|
|
|
|
|
_errorMessage = 'Failed to fetch sites';
|
|
|
|
|
_errorMessage = '$_errorSubmitFailed: $error';
|
|
|
|
|
loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stateCode = response.statusCode;
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
try {
|
|
|
|
|
var responseData = json.decode(response.body);
|
|
|
|
|
List listJson = responseData is List ? responseData : responseData['data'] ?? [];
|
|
|
|
|
_allSites = listJson
|
|
|
|
|
.map((item) => SiteRequestSiteModel(
|
|
|
|
|
id: item['id']?.toString() ?? '',
|
|
|
|
|
name: item['name']?.toString() ?? '',
|
|
|
|
|
))
|
|
|
|
|
.toList();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Failed to parse sites';
|
|
|
|
|
_loading = false;
|
|
|
|
|
/// Fetches paginated site requests
|
|
|
|
|
Future<void> fetchSiteRequests({
|
|
|
|
|
int? pageSize,
|
|
|
|
|
int? pageNumber,
|
|
|
|
|
bool loadMore = false,
|
|
|
|
|
required UserProvider userProvider,
|
|
|
|
|
}) async {
|
|
|
|
|
final size = pageSize ?? _pageSize;
|
|
|
|
|
final page = pageNumber ?? (loadMore ? _currentPage + 1 : 1);
|
|
|
|
|
|
|
|
|
|
if (size <= 0 || page < 1) {
|
|
|
|
|
_errorMessage = 'Invalid pagination parameters';
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_setLoadingState(loadMore);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
final response = await ApiManager.instance.post(
|
|
|
|
|
URLs.getSiteRequests,
|
|
|
|
|
body: {
|
|
|
|
|
"pageSize": size,
|
|
|
|
|
"pageNumber": page,
|
|
|
|
|
"userId": getCurrentUserEmployeeId(userProvider),
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
|
_handleFetchSuccess(response, page, size, loadMore);
|
|
|
|
|
} else {
|
|
|
|
|
_errorMessage = 'Failed to fetch sites';
|
|
|
|
|
_errorMessage = _errorFetchFailed;
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Error: ${e.toString()}';
|
|
|
|
|
} finally {
|
|
|
|
|
_resetLoadingState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Loads more site requests (pagination)
|
|
|
|
|
Future<void> loadMoreSiteRequests({required UserProvider userProvider}) async {
|
|
|
|
|
if (!_hasMoreData || _isLoadingMore) return;
|
|
|
|
|
await fetchSiteRequests(loadMore: true, userProvider: userProvider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Refreshes site requests (resets to first page)
|
|
|
|
|
Future<void> refreshSiteRequests({required UserProvider userProvider}) async {
|
|
|
|
|
await fetchSiteRequests(pageNumber: 1, pageSize: _pageSize, userProvider: userProvider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Resets provider state
|
|
|
|
|
void reset() {
|
|
|
|
|
_loading = false;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
_requestHistory.clear();
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return response.statusCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mock departments as Base models
|
|
|
|
|
List<SiteRequestDepartmentModel> _allDepartments = [];
|
|
|
|
|
List<SiteRequestDepartmentModel> get allDepartments => _allDepartments;
|
|
|
|
|
|
|
|
|
|
// Fetch departments from API (Step 3)
|
|
|
|
|
Future<int> fetchDepartments() async {
|
|
|
|
|
if (_loading) return -2;
|
|
|
|
|
// Private helper methods
|
|
|
|
|
|
|
|
|
|
/// Generic API call handler to reduce duplication
|
|
|
|
|
Future<int> _performApiCall({
|
|
|
|
|
required Future<Response> Function() apiCall,
|
|
|
|
|
required void Function(dynamic) onSuccess,
|
|
|
|
|
required String errorMessage,
|
|
|
|
|
}) async {
|
|
|
|
|
_loading = true;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
|
|
late Response response;
|
|
|
|
|
try {
|
|
|
|
|
response = await ApiManager.instance.get(
|
|
|
|
|
URLs.signUpGetDepartmentAutoComplete,
|
|
|
|
|
enableToastMessage: false,
|
|
|
|
|
);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_loading = false;
|
|
|
|
|
stateCode = -1;
|
|
|
|
|
_errorMessage = 'Failed to fetch departments';
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final response = await apiCall();
|
|
|
|
|
stateCode = response.statusCode;
|
|
|
|
|
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
try {
|
|
|
|
|
var responseData = json.decode(response.body);
|
|
|
|
|
List listJson = responseData is List ? responseData : responseData['data'] ?? [];
|
|
|
|
|
_allDepartments = listJson
|
|
|
|
|
.map((item) => SiteRequestDepartmentModel(
|
|
|
|
|
id: item['id']?.toString() ?? '',
|
|
|
|
|
name: item['name']?.toString() ?? '',
|
|
|
|
|
))
|
|
|
|
|
.toList();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Failed to parse departments';
|
|
|
|
|
_loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
final responseData = json.decode(response.body);
|
|
|
|
|
onSuccess(responseData);
|
|
|
|
|
} else {
|
|
|
|
|
_errorMessage = 'Failed to fetch departments';
|
|
|
|
|
_errorMessage = errorMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return response.statusCode;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_loading = false;
|
|
|
|
|
stateCode = -1;
|
|
|
|
|
_errorMessage = errorMessage;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// History of submitted requests
|
|
|
|
|
final List<SiteRequestModel> _requestHistory = [];
|
|
|
|
|
List<SiteRequestModel> get requestHistory => _requestHistory;
|
|
|
|
|
|
|
|
|
|
// Pagination state
|
|
|
|
|
int _currentPage = 1;
|
|
|
|
|
int _pageSize = 10;
|
|
|
|
|
bool _hasMoreData = true;
|
|
|
|
|
bool _isLoadingMore = false;
|
|
|
|
|
|
|
|
|
|
int get currentPage => _currentPage;
|
|
|
|
|
bool get hasMoreData => _hasMoreData;
|
|
|
|
|
bool get isLoadingMore => _isLoadingMore;
|
|
|
|
|
|
|
|
|
|
// Get available sites based on request type
|
|
|
|
|
List<SiteRequestSiteModel> getAvailableSites(String requestType, List<String> assignedSites) {
|
|
|
|
|
if (requestType == 'Remove Site') {
|
|
|
|
|
// Only return currently assigned sites
|
|
|
|
|
return _allSites.where((site) {
|
|
|
|
|
return assignedSites.contains(site.name ?? '');
|
|
|
|
|
}).toList();
|
|
|
|
|
}
|
|
|
|
|
// For Add Site and Change Site, return all sites
|
|
|
|
|
return _allSites;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if user has assigned sites for removal
|
|
|
|
|
bool hasAssignedSites(List<String> assignedSites) {
|
|
|
|
|
return assignedSites.isNotEmpty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Submit site request (local only, no API)
|
|
|
|
|
Future<bool> submitSiteRequest(SiteRequestModel request, UserProvider userProvider) async {
|
|
|
|
|
loading = true;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
|
|
|
|
|
late Response response;
|
|
|
|
|
try {
|
|
|
|
|
// Prepare site IDs array with correct structure
|
|
|
|
|
Map<String, dynamic> _buildRequestBody(
|
|
|
|
|
SiteRequestModel request,
|
|
|
|
|
UserProvider userProvider,
|
|
|
|
|
bool isChangeSiteRequest,
|
|
|
|
|
) {
|
|
|
|
|
final siteIdsArray = request.siteIds.asMap().entries.map((entry) {
|
|
|
|
|
final index = entry.key;
|
|
|
|
|
return {
|
|
|
|
|
"id": 0,
|
|
|
|
|
"siteId": int.tryParse(request.siteIds[entry.key]) ?? 0,
|
|
|
|
|
"siteName": request.siteNames[entry.key],
|
|
|
|
|
"oldSiteId": 0,
|
|
|
|
|
"oldSitName": ""
|
|
|
|
|
"siteId": int.tryParse(request.siteIds[index]) ?? 0,
|
|
|
|
|
"siteName": request.siteNames[index],
|
|
|
|
|
"oldSiteId": (isChangeSiteRequest &&
|
|
|
|
|
request.oldSiteIds != null &&
|
|
|
|
|
index < request.oldSiteIds!.length)
|
|
|
|
|
? int.tryParse(request.oldSiteIds![index]) ?? 0
|
|
|
|
|
: 0,
|
|
|
|
|
"oldSitName": (isChangeSiteRequest &&
|
|
|
|
|
request.oldSiteNames != null &&
|
|
|
|
|
index < request.oldSiteNames!.length)
|
|
|
|
|
? request.oldSiteNames![index]
|
|
|
|
|
: ""
|
|
|
|
|
};
|
|
|
|
|
}).toList();
|
|
|
|
|
|
|
|
|
|
// Prepare department IDs array with correct structure
|
|
|
|
|
final departmentIdsArray = (request.departmentIds != null && request.departmentIds!.isNotEmpty)
|
|
|
|
|
? request.departmentIds!.asMap().entries.map((entry) {
|
|
|
|
|
return {
|
|
|
|
|
"id": 0,
|
|
|
|
|
"departmentId": int.tryParse(request.departmentIds![entry.key]) ?? 0,
|
|
|
|
|
"departmentName": request.departmentNames![entry.key],
|
|
|
|
|
"oldDepartmentId": 0,
|
|
|
|
|
"oldDepartmentName": ""
|
|
|
|
|
};
|
|
|
|
|
}).toList()
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
// Prepare the request body matching the API specification
|
|
|
|
|
final requestBody = {
|
|
|
|
|
return {
|
|
|
|
|
"id": 0,
|
|
|
|
|
"userId": getCurrentUserEmployeeId(userProvider),
|
|
|
|
|
"requestTypeId": int.tryParse(request.requestType) ?? 0,
|
|
|
|
|
"siteIds": siteIdsArray,
|
|
|
|
|
"departmentIds": departmentIdsArray,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
response = await ApiManager.instance.post(
|
|
|
|
|
URLs.submitSiteRequest,
|
|
|
|
|
body: requestBody,
|
|
|
|
|
);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_errorMessage = 'Failed to submit request: $error';
|
|
|
|
|
loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stateCode = response.statusCode;
|
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
|
|
|
void _handleSubmitSuccess(Response response, SiteRequestModel request) {
|
|
|
|
|
try {
|
|
|
|
|
var responseData = json.decode(response.body);
|
|
|
|
|
// Add request to history with server response
|
|
|
|
|
final responseData = json.decode(response.body);
|
|
|
|
|
final requestWithId = request.copyWith(
|
|
|
|
|
id: responseData['id']?.toString() ?? 'REQ_${DateTime.now().millisecondsSinceEpoch}',
|
|
|
|
|
status: responseData['status']?.toString() ?? 'Pending',
|
|
|
|
|
requestDate: DateTime.now(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
_requestHistory.insert(0, requestWithId);
|
|
|
|
|
loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Request submitted but failed to parse response';
|
|
|
|
|
} finally {
|
|
|
|
|
loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return true; // Still return true as request was submitted
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _handleSubmitError(Response response) {
|
|
|
|
|
try {
|
|
|
|
|
var errorData = json.decode(response.body);
|
|
|
|
|
_errorMessage = errorData['message'] ?? 'Failed to submit request';
|
|
|
|
|
final errorData = json.decode(response.body);
|
|
|
|
|
_errorMessage = errorData['message'] ?? _errorSubmitFailed;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Failed to submit request';
|
|
|
|
|
_errorMessage = _errorSubmitFailed;
|
|
|
|
|
}
|
|
|
|
|
loading = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fetch paginated site requests
|
|
|
|
|
Future<void> fetchSiteRequests({int? pageSize, int? pageNumber, bool loadMore = false}) async {
|
|
|
|
|
final size = pageSize ?? _pageSize;
|
|
|
|
|
final page = pageNumber ?? (loadMore ? _currentPage + 1 : 1);
|
|
|
|
|
|
|
|
|
|
if (size <= 0 || page < 1) {
|
|
|
|
|
_errorMessage = 'Invalid pagination parameters';
|
|
|
|
|
notifyListeners();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set loading state
|
|
|
|
|
void _setLoadingState(bool loadMore) {
|
|
|
|
|
if (loadMore) {
|
|
|
|
|
_isLoadingMore = true;
|
|
|
|
|
} else {
|
|
|
|
|
@ -344,24 +314,15 @@ class SiteRequestProvider extends ChangeNotifier {
|
|
|
|
|
_hasMoreData = true;
|
|
|
|
|
_requestHistory.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
final response = await ApiManager.instance.post(
|
|
|
|
|
URLs.getSiteRequests,
|
|
|
|
|
body: {
|
|
|
|
|
"pageSize": size,
|
|
|
|
|
"pageNumber": page,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
|
void _handleFetchSuccess(Response response, int page, int size, bool loadMore) {
|
|
|
|
|
final data = json.decode(response.body);
|
|
|
|
|
|
|
|
|
|
if (data['isSuccess'] == true) {
|
|
|
|
|
List<SiteRequestModel> siteRequests = (data['data'] as List?)
|
|
|
|
|
final siteRequests = (data['data'] as List?)
|
|
|
|
|
?.map((item) => SiteRequestModel.fromJson(item))
|
|
|
|
|
.toList() ?? [];
|
|
|
|
|
|
|
|
|
|
@ -372,95 +333,16 @@ class SiteRequestProvider extends ChangeNotifier {
|
|
|
|
|
_requestHistory.addAll(siteRequests);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update pagination state
|
|
|
|
|
_currentPage = page;
|
|
|
|
|
_hasMoreData = siteRequests.length >= size;
|
|
|
|
|
} else {
|
|
|
|
|
_errorMessage = data['message'] ?? 'Failed to fetch site requests';
|
|
|
|
|
_errorMessage = data['message'] ?? _errorFetchFailed;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
_errorMessage = 'Failed to fetch site requests';
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
_errorMessage = 'Error: ${e.toString()}';
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
|
|
void _resetLoadingState() {
|
|
|
|
|
loading = false;
|
|
|
|
|
_isLoadingMore = false;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load more site requests (for pagination)
|
|
|
|
|
Future<void> loadMoreSiteRequests() async {
|
|
|
|
|
if (!_hasMoreData || _isLoadingMore) return;
|
|
|
|
|
await fetchSiteRequests(loadMore: true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Refresh site requests (reset to first page)
|
|
|
|
|
Future<void> refreshSiteRequests() async {
|
|
|
|
|
await fetchSiteRequests(pageNumber: 1, pageSize: _pageSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset provider state
|
|
|
|
|
void reset() {
|
|
|
|
|
_loading = false;
|
|
|
|
|
_errorMessage = null;
|
|
|
|
|
_requestHistory.clear();
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add mock history data for testing
|
|
|
|
|
void addMockHistoryData(UserProvider userProvider) {
|
|
|
|
|
final mockRequests = [
|
|
|
|
|
SiteRequestModel(
|
|
|
|
|
id: 'REQ_001',
|
|
|
|
|
requestType: 'Add Site',
|
|
|
|
|
employeeId: getCurrentUserEmployeeId(userProvider),
|
|
|
|
|
fullName: getCurrentUserFullName(userProvider),
|
|
|
|
|
emailAddress: getCurrentUserEmail(userProvider),
|
|
|
|
|
mobileNumber: getCurrentUserMobile(userProvider),
|
|
|
|
|
extensionNumber: getCurrentUserExtension(userProvider),
|
|
|
|
|
siteIds: ['site_3', 'site_4'],
|
|
|
|
|
siteNames: ['Site C', 'Site D'],
|
|
|
|
|
departmentIds: ['dept_2'],
|
|
|
|
|
departmentNames: ['IT'],
|
|
|
|
|
role: getCurrentUserRole(userProvider),
|
|
|
|
|
status: 'Approved',
|
|
|
|
|
requestDate: DateTime.now().subtract(const Duration(days: 5)),
|
|
|
|
|
),
|
|
|
|
|
SiteRequestModel(
|
|
|
|
|
id: 'REQ_002',
|
|
|
|
|
requestType: 'Change Site',
|
|
|
|
|
employeeId: getCurrentUserEmployeeId(userProvider),
|
|
|
|
|
fullName: getCurrentUserFullName(userProvider),
|
|
|
|
|
emailAddress: getCurrentUserEmail(userProvider),
|
|
|
|
|
mobileNumber: getCurrentUserMobile(userProvider),
|
|
|
|
|
extensionNumber: getCurrentUserExtension(userProvider),
|
|
|
|
|
siteIds: ['site_1'],
|
|
|
|
|
siteNames: ['Site A'],
|
|
|
|
|
departmentIds: ['dept_1', 'dept_3'],
|
|
|
|
|
departmentNames: ['HR', 'Finance'],
|
|
|
|
|
role: getCurrentUserRole(userProvider),
|
|
|
|
|
status: 'Pending',
|
|
|
|
|
requestDate: DateTime.now().subtract(const Duration(days: 2)),
|
|
|
|
|
),
|
|
|
|
|
SiteRequestModel(
|
|
|
|
|
id: 'REQ_003',
|
|
|
|
|
requestType: 'Remove Site',
|
|
|
|
|
employeeId: getCurrentUserEmployeeId(userProvider),
|
|
|
|
|
fullName: getCurrentUserFullName(userProvider),
|
|
|
|
|
emailAddress: getCurrentUserEmail(userProvider),
|
|
|
|
|
mobileNumber: getCurrentUserMobile(userProvider),
|
|
|
|
|
extensionNumber: getCurrentUserExtension(userProvider),
|
|
|
|
|
siteIds: ['site_2'],
|
|
|
|
|
siteNames: ['Site B'],
|
|
|
|
|
role: getCurrentUserRole(userProvider),
|
|
|
|
|
status: 'Rejected',
|
|
|
|
|
requestDate: DateTime.now().subtract(const Duration(days: 10)),
|
|
|
|
|
),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
_requestHistory.addAll(mockRequests);
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|