You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudsolutions-atoms/lib/modules/site_request_module/providers/site_request_provider.dart

467 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/modules/site_request_module/models/dropdown_models.dart';
import 'package:test_sa/modules/site_request_module/models/request_type_model.dart';
import 'package:test_sa/modules/site_request_module/models/site_request_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'dart:convert';
import 'package:http/http.dart';
class SiteRequestProvider extends ChangeNotifier {
bool _loading = false;
bool get loading => _loading;
set loading(bool value) {
_loading = value;
notifyListeners();
}
String? _errorMessage;
String? get errorMessage => _errorMessage;
int? stateCode;
// Get current user from UserProvider
String getCurrentUserEmployeeId(UserProvider userProvider) {
return userProvider.user?.employeeId ?? '';
}
String getCurrentUserFullName(UserProvider userProvider) {
return userProvider.user?.username ?? '';
}
String getCurrentUserEmail(UserProvider userProvider) {
return userProvider.user?.email ?? '';
}
String getCurrentUserMobile(UserProvider userProvider) {
return userProvider.user?.phoneNumber ?? '';
}
String getCurrentUserExtension(UserProvider userProvider) {
return 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<RequestTypeModel> _requestTypes = [];
List<RequestTypeModel> get requestTypes => _requestTypes;
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);
List listJson = responseData['data'] ?? responseData;
_requestTypes = listJson
.map((item) => Lookup.fromJson(item))
.map((lookup) => RequestTypeModel(
id: lookup.id?.toString() ?? lookup.value?.toString() ?? '',
name: lookup.name ?? '',
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';
}
_loading = false;
notifyListeners();
return response.statusCode;
}
List<SiteRequestSiteModel> _allSites = [];
List<SiteRequestSiteModel> get allSites => _allSites;
Future<int> fetchSites() async {
if (_loading) return -2;
_loading = true;
_errorMessage = null;
notifyListeners();
late Response response;
try {
response = await ApiManager.instance.get(
URLs.signUpGetSiteList,
enableToastMessage: false,
);
} catch (error) {
_loading = false;
stateCode = -1;
_errorMessage = 'Failed to fetch sites';
notifyListeners();
return -1;
}
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;
notifyListeners();
return -1;
}
} else {
_errorMessage = 'Failed to fetch sites';
}
_loading = false;
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;
_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;
}
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;
}
} else {
_errorMessage = 'Failed to fetch departments';
}
_loading = false;
notifyListeners();
return response.statusCode;
}
// 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
final siteIdsArray = request.siteIds.asMap().entries.map((entry) {
return {
"id": 0,
"siteId": int.tryParse(request.siteIds[entry.key]) ?? 0,
"siteName": request.siteNames[entry.key],
"oldSiteId": 0,
"oldSitName": ""
};
}).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 = {
"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) {
try {
var responseData = json.decode(response.body);
// Add request to history with server response
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';
loading = false;
notifyListeners();
return true; // Still return true as request was submitted
}
} else {
try {
var errorData = json.decode(response.body);
_errorMessage = errorData['message'] ?? 'Failed to submit request';
} catch (e) {
_errorMessage = 'Failed to submit request';
}
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
if (loadMore) {
_isLoadingMore = true;
} else {
loading = true;
_currentPage = 1;
_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) {
final data = json.decode(response.body);
if (data['isSuccess'] == true) {
List<SiteRequestModel> siteRequests = (data['data'] as List?)
?.map((item) => SiteRequestModel.fromJson(item))
.toList() ?? [];
if (loadMore) {
_requestHistory.addAll(siteRequests);
} else {
_requestHistory.clear();
_requestHistory.addAll(siteRequests);
}
// Update pagination state
_currentPage = page;
_hasMoreData = siteRequests.length >= size;
} else {
_errorMessage = data['message'] ?? 'Failed to fetch site requests';
}
} else {
_errorMessage = 'Failed to fetch site requests';
}
} catch (e) {
_errorMessage = 'Error: ${e.toString()}';
} finally {
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();
}
}