added the site and department dropdown

export_module_ui_ux_enhancement_signup
WaseemAbbasi22 3 weeks ago
parent d9eb1ae835
commit 7fc19d9058

@ -60,6 +60,12 @@ class URLs {
static get signUpGetSiteList => "$_baseUrl/Customer/GetSiteList"; static get signUpGetSiteList => "$_baseUrl/Customer/GetSiteList";
static get signUpGetDepartmentAutoComplete => "$_baseUrl/Department/GetDepartmentAutoCompleteByAssetGroup"; static get signUpGetDepartmentAutoComplete => "$_baseUrl/Department/GetDepartmentAutoCompleteByAssetGroup";
// Site Request APIs
static get getSiteRequestTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=4016"; // get site request types
static get submitSiteRequest => "$_baseUrl/SiteRequest/CreateSiteRequest"; // post submit site request
static get getSiteRequestHistory => "$_baseUrl/SiteRequest/GetSiteRequestHistory"; // get site request history
static get getDepartmentsBySites => "$_baseUrl/Customer/GetDepartmentsBySites"; // post get departments by sites
// static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // mobile login // static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // mobile login
static get register => "$_baseUrl/handle/create/user"; // post static get register => "$_baseUrl/handle/create/user"; // post
static get updateProfile => "$_baseUrl/update/user/profile"; // post static get updateProfile => "$_baseUrl/update/user/profile"; // post

@ -82,6 +82,7 @@ import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
import 'package:test_sa/new_views/swipe_module/swipe_view.dart'; import 'package:test_sa/new_views/swipe_module/swipe_view.dart';
import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart';
import 'package:test_sa/providers/department_provider.dart'; import 'package:test_sa/providers/department_provider.dart';
import 'package:test_sa/providers/department_by_sites_provider.dart';
import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart';
import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart';
import 'package:test_sa/providers/gas_request_providers/gas_status_provider.dart'; import 'package:test_sa/providers/gas_request_providers/gas_status_provider.dart';
@ -341,6 +342,7 @@ class MyApp extends StatelessWidget {
// DEPARTMENT/LOCATION PROVIDERS (5) // DEPARTMENT/LOCATION PROVIDERS (5)
ChangeNotifierProvider(create: (_) => DepartmentProvider(), lazy: true), ChangeNotifierProvider(create: (_) => DepartmentProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => DepartmentBySitesProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => SiteProvider(), lazy: true), ChangeNotifierProvider(create: (_) => SiteProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => MappedSiteProvider(), lazy: true), ChangeNotifierProvider(create: (_) => MappedSiteProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => MedicalDepartmentProvider(), lazy: true), ChangeNotifierProvider(create: (_) => MedicalDepartmentProvider(), lazy: true),

@ -1,9 +1,11 @@
import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/base.dart';
class RequestTypeModel extends Base { class RequestTypeModel extends Base {
final int? value;
RequestTypeModel({ RequestTypeModel({
required String id, required String id,
required String name, required String name,
this.value,
}) : super(identifier: id, name: name); }) : super(identifier: id, name: name);
} }

@ -1,8 +1,13 @@
import 'package:flutter/material.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/dropdown_models.dart';
import 'package:test_sa/modules/site_request_module/models/mock_user_model.dart';
import 'package:test_sa/modules/site_request_module/models/request_type_model.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/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 { class SiteRequestProvider extends ChangeNotifier {
bool _loading = false; bool _loading = false;
@ -16,67 +21,212 @@ class SiteRequestProvider extends ChangeNotifier {
String? _errorMessage; String? _errorMessage;
String? get errorMessage => _errorMessage; String? get errorMessage => _errorMessage;
// Mock user data int? stateCode;
late MockUserModel _currentUser;
MockUserModel get currentUser => _currentUser;
// Request types as Base models // Get current user from UserProvider
final List<RequestTypeModel> _requestTypes = [ String getCurrentUserEmployeeId(UserProvider userProvider) {
RequestTypeModel(id: 'add_site', name: 'Add Site'), return userProvider.user?.employeeId ?? '';
RequestTypeModel(id: 'change_site', name: 'Change Site'), }
RequestTypeModel(id: 'remove_site', name: 'Remove Site'),
]; 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) {
// You can modify this based on how assigned sites are stored in your User model
// For now, returning empty list as it's not clear from the User model
// You may need to fetch this from another source or API
return [];
}
// Request types from API
List<RequestTypeModel> _requestTypes = [];
List<RequestTypeModel> get requestTypes => _requestTypes; List<RequestTypeModel> get requestTypes => _requestTypes;
// Mock sites as Base models // Fetch request types from API (Step 1)
final List<SiteRequestSiteModel> _allSites = [ Future<int> fetchRequestTypes() async {
SiteRequestSiteModel(id: 'site_1', name: 'Site A'), if (_loading) return -2;
SiteRequestSiteModel(id: 'site_2', name: 'Site B'),
SiteRequestSiteModel(id: 'site_3', name: 'Site C'), _loading = true;
SiteRequestSiteModel(id: 'site_4', name: 'Site D'), _errorMessage = null;
SiteRequestSiteModel(id: 'site_5', name: 'Site E'), 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;
}
// Mock sites as Base models
List<SiteRequestSiteModel> _allSites = [];
List<SiteRequestSiteModel> get allSites => _allSites; List<SiteRequestSiteModel> get allSites => _allSites;
// Mock departments as Base models // Fetch sites from API (Step 2)
final List<SiteRequestDepartmentModel> _allDepartments = [ Future<int> fetchSites() async {
SiteRequestDepartmentModel(id: 'dept_1', name: 'HR'), if (_loading) return -2;
SiteRequestDepartmentModel(id: 'dept_2', name: 'IT'),
SiteRequestDepartmentModel(id: 'dept_3', name: 'Finance'),
SiteRequestDepartmentModel(id: 'dept_4', name: 'Operations'),
SiteRequestDepartmentModel(id: 'dept_5', name: 'Administration'),
];
List<SiteRequestDepartmentModel> get allDepartments => _allDepartments; _loading = true;
_errorMessage = null;
notifyListeners();
// History of submitted requests late Response response;
final List<SiteRequestModel> _requestHistory = []; try {
List<SiteRequestModel> get requestHistory => _requestHistory; response = await ApiManager.instance.get(
URLs.signUpGetSiteList,
enableToastMessage: false,
);
} catch (error) {
_loading = false;
stateCode = -1;
_errorMessage = 'Failed to fetch sites';
notifyListeners();
return -1;
}
SiteRequestProvider() { stateCode = response.statusCode;
_initializeMockUser(); 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;
} }
void _initializeMockUser() { // Mock departments as Base models
_currentUser = MockUserModel( List<SiteRequestDepartmentModel> _allDepartments = [];
employeeId: 'EMP001', List<SiteRequestDepartmentModel> get allDepartments => _allDepartments;
fullName: 'John Smith',
emailAddress: 'john.smith@test.com', // Fetch departments from API (Step 3)
mobileNumber: '+966500000000', Future<int> fetchDepartments() async {
extensionNumber: '1234', if (_loading) return -2;
role: 'Engineer',
assignedSites: ['Site A', 'Site B'], _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;
// Get available sites based on request type // Get available sites based on request type
List<SiteRequestSiteModel> getAvailableSites(String requestType) { List<SiteRequestSiteModel> getAvailableSites(String requestType, List<String> assignedSites) {
if (requestType == 'Remove Site') { if (requestType == 'Remove Site') {
// Only return currently assigned sites // Only return currently assigned sites
return _allSites.where((site) { return _allSites.where((site) {
return _currentUser.assignedSites.contains(site.name ?? ''); return assignedSites.contains(site.name ?? '');
}).toList(); }).toList();
} }
// For Add Site and Change Site, return all sites // For Add Site and Change Site, return all sites
@ -84,47 +234,140 @@ class SiteRequestProvider extends ChangeNotifier {
} }
// Check if user has assigned sites for removal // Check if user has assigned sites for removal
bool hasAssignedSites() { bool hasAssignedSites(List<String> assignedSites) {
return _currentUser.assignedSites.isNotEmpty; return assignedSites.isNotEmpty;
} }
// Submit site request (local only, no API) // Submit site request (local only, no API)
Future<bool> submitSiteRequest(SiteRequestModel request) async { Future<bool> submitSiteRequest(SiteRequestModel request, UserProvider userProvider) async {
loading = true; loading = true;
_errorMessage = null; _errorMessage = null;
notifyListeners(); notifyListeners();
// Simulate network delay late Response response;
await Future.delayed(const Duration(seconds: 1));
try { try {
// Add request to history with a generated ID // Prepare site IDs array with correct structure
final requestWithId = request.copyWith( final siteIdsArray = request.siteIds.asMap().entries.map((entry) {
id: 'REQ_${DateTime.now().millisecondsSinceEpoch}', return {
status: 'Pending', "id": 0,
requestDate: DateTime.now(), "siteId": int.tryParse(request.siteIds[entry.key]) ?? 0,
); "siteName": request.siteNames[entry.key],
"oldSiteId": 0,
"oldSitName": ""
};
}).toList();
_requestHistory.insert(0, requestWithId); // 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; loading = false;
notifyListeners(); notifyListeners();
return true; return false;
} catch (error) { }
_errorMessage = 'Failed to submit request';
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; loading = false;
notifyListeners(); notifyListeners();
return false; return false;
} }
} }
// Get request by ID // Fetch request history from API (Step 5)
SiteRequestModel? getRequestById(String id) { Future<int> fetchRequestHistory() async {
if (_loading) return -2;
_loading = true;
_errorMessage = null;
notifyListeners();
late Response response;
try { try {
return _requestHistory.firstWhere((request) => request.id == id); response = await ApiManager.instance.get(
} catch (e) { URLs.getSiteRequestHistory,
return null; enableToastMessage: false,
);
} catch (error) {
_loading = false;
stateCode = -1;
_errorMessage = 'Failed to fetch request history';
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'] ?? [];
_requestHistory.clear();
_requestHistory.addAll(
listJson.map((item) => SiteRequestModel.fromJson(item)).toList()
);
} catch (e) {
_errorMessage = 'Failed to parse request history';
_loading = false;
notifyListeners();
return -1;
}
} else {
_errorMessage = 'Failed to fetch request history';
}
_loading = false;
notifyListeners();
return response.statusCode;
} }
// Reset provider state // Reset provider state
@ -132,56 +375,55 @@ class SiteRequestProvider extends ChangeNotifier {
_loading = false; _loading = false;
_errorMessage = null; _errorMessage = null;
_requestHistory.clear(); _requestHistory.clear();
_initializeMockUser();
notifyListeners(); notifyListeners();
} }
// Add mock history data for testing // Add mock history data for testing
void addMockHistoryData() { void addMockHistoryData(UserProvider userProvider) {
final mockRequests = [ final mockRequests = [
SiteRequestModel( SiteRequestModel(
id: 'REQ_001', id: 'REQ_001',
requestType: 'Add Site', requestType: 'Add Site',
employeeId: _currentUser.employeeId, employeeId: getCurrentUserEmployeeId(userProvider),
fullName: _currentUser.fullName, fullName: getCurrentUserFullName(userProvider),
emailAddress: _currentUser.emailAddress, emailAddress: getCurrentUserEmail(userProvider),
mobileNumber: _currentUser.mobileNumber, mobileNumber: getCurrentUserMobile(userProvider),
extensionNumber: _currentUser.extensionNumber, extensionNumber: getCurrentUserExtension(userProvider),
siteIds: ['site_3', 'site_4'], siteIds: ['site_3', 'site_4'],
siteNames: ['Site C', 'Site D'], siteNames: ['Site C', 'Site D'],
departmentIds: ['dept_2'], departmentIds: ['dept_2'],
departmentNames: ['IT'], departmentNames: ['IT'],
role: _currentUser.role, role: getCurrentUserRole(userProvider),
status: 'Approved', status: 'Approved',
requestDate: DateTime.now().subtract(const Duration(days: 5)), requestDate: DateTime.now().subtract(const Duration(days: 5)),
), ),
SiteRequestModel( SiteRequestModel(
id: 'REQ_002', id: 'REQ_002',
requestType: 'Change Site', requestType: 'Change Site',
employeeId: _currentUser.employeeId, employeeId: getCurrentUserEmployeeId(userProvider),
fullName: _currentUser.fullName, fullName: getCurrentUserFullName(userProvider),
emailAddress: _currentUser.emailAddress, emailAddress: getCurrentUserEmail(userProvider),
mobileNumber: _currentUser.mobileNumber, mobileNumber: getCurrentUserMobile(userProvider),
extensionNumber: _currentUser.extensionNumber, extensionNumber: getCurrentUserExtension(userProvider),
siteIds: ['site_1'], siteIds: ['site_1'],
siteNames: ['Site A'], siteNames: ['Site A'],
departmentIds: ['dept_1', 'dept_3'], departmentIds: ['dept_1', 'dept_3'],
departmentNames: ['HR', 'Finance'], departmentNames: ['HR', 'Finance'],
role: _currentUser.role, role: getCurrentUserRole(userProvider),
status: 'Pending', status: 'Pending',
requestDate: DateTime.now().subtract(const Duration(days: 2)), requestDate: DateTime.now().subtract(const Duration(days: 2)),
), ),
SiteRequestModel( SiteRequestModel(
id: 'REQ_003', id: 'REQ_003',
requestType: 'Remove Site', requestType: 'Remove Site',
employeeId: _currentUser.employeeId, employeeId: getCurrentUserEmployeeId(userProvider),
fullName: _currentUser.fullName, fullName: getCurrentUserFullName(userProvider),
emailAddress: _currentUser.emailAddress, emailAddress: getCurrentUserEmail(userProvider),
mobileNumber: _currentUser.mobileNumber, mobileNumber: getCurrentUserMobile(userProvider),
extensionNumber: _currentUser.extensionNumber, extensionNumber: getCurrentUserExtension(userProvider),
siteIds: ['site_2'], siteIds: ['site_2'],
siteNames: ['Site B'], siteNames: ['Site B'],
role: _currentUser.role, role: getCurrentUserRole(userProvider),
status: 'Rejected', status: 'Rejected',
requestDate: DateTime.now().subtract(const Duration(days: 10)), requestDate: DateTime.now().subtract(const Duration(days: 10)),
), ),

@ -1,9 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/modules/site_request_module/models/dropdown_models.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/models/new_models/department.dart';
import 'package:test_sa/providers/gas_request_providers/site_provider.dart';
import 'package:test_sa/providers/department_by_sites_provider.dart';
import 'package:test_sa/modules/site_request_module/models/request_type_model.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/modules/site_request_module/models/site_request_model.dart';
import 'package:test_sa/modules/site_request_module/providers/site_request_provider.dart'; import 'package:test_sa/modules/site_request_module/providers/site_request_provider.dart';
@ -16,6 +21,8 @@ import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/new_views/common_widgets/multiple_item_drop_down_menu.dart'; import 'package:test_sa/new_views/common_widgets/multiple_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
class SiteRequestFormScreen extends StatefulWidget { class SiteRequestFormScreen extends StatefulWidget {
static const String routeName = "/site_request_form"; static const String routeName = "/site_request_form";
@ -30,16 +37,52 @@ class _SiteRequestFormScreenState extends State<SiteRequestFormScreen> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late SiteRequestProvider _provider; late SiteRequestProvider _provider;
late UserProvider _userProvider;
RequestTypeModel? _selectedRequestType; RequestTypeModel? _selectedRequestType;
List<SiteRequestSiteModel> _selectedSites = []; List<Site> _selectedSites = [];
List<SiteRequestDepartmentModel> _selectedDepartments = []; List<Department> _selectedDepartments = [];
bool _isSubmitting = false; bool _isSubmitting = false;
bool _isLoadingData = true;
@override
void initState() {
super.initState();
_loadInitialData();
}
Future<void> _loadInitialData() async {
// Load data after first frame to access context
WidgetsBinding.instance.addPostFrameCallback((_) async {
_provider = Provider.of<SiteRequestProvider>(context, listen: false);
// Fetch only request types (sites and departments are loaded by their providers)
await _provider.fetchRequestTypes();
if (mounted) {
setState(() {
_isLoadingData = false;
});
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_provider = Provider.of<SiteRequestProvider>(context); _provider = Provider.of<SiteRequestProvider>(context);
_userProvider = Provider.of<UserProvider>(context);
// Show loading indicator while fetching initial data
if (_isLoadingData) {
return Scaffold(
backgroundColor: AppColor.scaffoldBackground(context),
appBar: const DefaultAppBar(title: "Site Request"),
body: const Center(
child: AppLazyLoading(),
),
);
}
return Scaffold( return Scaffold(
backgroundColor: AppColor.scaffoldBackground(context), backgroundColor: AppColor.scaffoldBackground(context),
@ -54,22 +97,14 @@ class _SiteRequestFormScreenState extends State<SiteRequestFormScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildRequestTypeDropdown(), _buildUserInfoCard(),
16.height, 16.height,
_buildReadOnlyField("Full Name", _provider.currentUser.fullName), _buildRequestTypeDropdown(),
16.height,
_buildReadOnlyField("Email Address", _provider.currentUser.emailAddress),
16.height,
_buildReadOnlyField("Mobile Number", _provider.currentUser.mobileNumber),
16.height,
_buildReadOnlyField("Extension Number", _provider.currentUser.extensionNumber),
16.height, 16.height,
if (_selectedRequestType != null) ...[ if (_selectedRequestType != null) ...[
_buildSiteMultiSelect(), _buildSiteMultiSelect(),
16.height, 16.height,
_buildDepartmentMultiSelect(), _buildDepartmentMultiSelect(),
16.height,
_buildReadOnlyField("Role", _provider.currentUser.role),
], ],
], ],
), ),
@ -83,7 +118,7 @@ class _SiteRequestFormScreenState extends State<SiteRequestFormScreen> {
color: AppColor.background(context), color: AppColor.background(context),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Colors.black.withValues(alpha: 0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, -2), offset: const Offset(0, -2),
), ),
@ -120,86 +155,103 @@ class _SiteRequestFormScreenState extends State<SiteRequestFormScreen> {
); );
} }
Widget _buildReadOnlyField(String label, String value) { Widget _buildUserInfoCard() {
return AppTextFormField( return Column(
initialValue: value, crossAxisAlignment: CrossAxisAlignment.start,
labelText: label, children: [
enable: false, InfoHeader16Widget("Requester Information"),
backgroundColor: AppColor.disableFieldBackground(context), 8.height,
); InfoTextWidget(label: "Full Name",value: _provider.getCurrentUserFullName(_userProvider),showEmptyValue: true,),
InfoTextWidget(label: "Email Address",value: _provider.getCurrentUserEmail(_userProvider),showEmptyValue: true,),
InfoTextWidget(label: "Mobile Number",value: _provider.getCurrentUserMobile(_userProvider),showEmptyValue: true,),
InfoTextWidget(label: "Extension Number", value: _provider.getCurrentUserExtension(_userProvider),showEmptyValue: true,),
InfoTextWidget(label: "Role",value: _provider.getCurrentUserRole(_userProvider),showEmptyValue: true,),
],
).toShadowContainer(context);
} }
Widget _buildSiteMultiSelect() { Widget _buildInfoRow(String label, String value, {bool isLast = false}) {
final availableSites = _provider.getAvailableSites(_selectedRequestType!.name!); return Padding(
padding: EdgeInsets.only(bottom: isLast ? 0 : 12.toScreenHeight),
// Check if user has assigned sites for Remove Site request child: Row(
if (_selectedRequestType!.name == 'Remove Site' && !_provider.hasAssignedSites()) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( SizedBox(
padding: EdgeInsets.all(16.toScreenWidth), width: 130.toScreenWidth,
decoration: BoxDecoration( child: Text(
color: AppColor.disableFieldBackground(context), "$label:",
borderRadius: BorderRadius.circular(16), style: TextStyle(
border: Border.all( fontSize: 14,
color: AppColor.border2Color(context), color: AppColor.labelTextStyleColor(context),
width: 1, fontWeight: FontWeight.w500,
), ),
), ),
child: Column( ),
crossAxisAlignment: CrossAxisAlignment.start, Expanded(
children: [ child: Text(
"Site *".bodyText(context).custom( value.isEmpty ? "-" : value,
color: AppColor.floatingTextStyleColor(context), style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 14,
fontSize: 12, color: AppColor.textStyleColor(context),
), ),
4.height,
"No assigned sites available for removal".bodyText(context).custom(
color: AppColor.labelTextStyleColor(context),
),
],
), ),
), ),
], ],
); ),
} );
}
return MultipleItemDropDownMenu<SiteRequestSiteModel, NullableLoadingProvider>( Widget _buildSiteMultiSelect() {
return MultipleItemDropDownMenu<Site, SiteProvider>(
context: context, context: context,
title: "Site", title: context.translation.bySite,
initialValue: _selectedSites, initialValue: _selectedSites,
staticData: availableSites, showAsBottomSheet: true,
showAsFullScreenDialog: true, backgroundColor: context.isDark ? AppColor.neutral60 : Colors.white,
showAsBottomSheet: false, showShadow: true,
height: 56.toScreenHeight,
showCancel: true,
onSelect: (value) { onSelect: (value) {
setState(() { if (value != null) {
_selectedSites = value ?? []; setState(() {
}); _selectedSites = value;
_selectedDepartments.clear(); // Clear departments when sites change
// Update department provider with new site IDs
final departmentProvider = Provider.of<DepartmentBySitesProvider>(context, listen: false);
final siteIds = value.map((site) => int.tryParse(site.identifier ?? '0') ?? 0).toList();
departmentProvider.setSiteIds(siteIds);
departmentProvider.getData();
});
}
}, },
); );
} }
Widget _buildDepartmentMultiSelect() { Widget _buildDepartmentMultiSelect() {
return MultipleItemDropDownMenu<SiteRequestDepartmentModel, NullableLoadingProvider>( return MultipleItemDropDownMenu<Department, DepartmentBySitesProvider>(
context: context, context: context,
title: "Department (Optional)", title: "Departments",
initialValue: _selectedDepartments, initialValue: _selectedDepartments,
staticData: _provider.allDepartments, showAsBottomSheet: true,
showAsFullScreenDialog: true, backgroundColor: context.isDark ? AppColor.neutral60 : Colors.white,
showAsBottomSheet: false, showShadow: true,
height: 56.toScreenHeight,
showCancel: true,
onSelect: (value) { onSelect: (value) {
setState(() { if (value != null) {
_selectedDepartments = value ?? []; setState(() {
}); _selectedDepartments = value;
});
}
}, },
); );
} }
Widget _buildSubmitButton() { Widget _buildSubmitButton() {
// Disable button if Remove Site is selected and no assigned sites // Disable button if Remove Site is selected and no assigned sites
final isDisabled = _selectedRequestType?.name == 'Remove Site' && !_provider.hasAssignedSites(); final assignedSites = _provider.getCurrentUserAssignedSites(_userProvider);
final isDisabled = _selectedRequestType?.name == 'Remove Site' && !_provider.hasAssignedSites(assignedSites);
return AppFilledButton( return AppFilledButton(
label: "Submit", label: "Submit",
@ -239,22 +291,22 @@ class _SiteRequestFormScreenState extends State<SiteRequestFormScreen> {
} }
final request = SiteRequestModel( final request = SiteRequestModel(
requestType: _selectedRequestType!.name ?? '', requestType: _selectedRequestType!.value?.toString() ?? '', // Use value instead of id
employeeId: _provider.currentUser.employeeId, employeeId: _provider.getCurrentUserEmployeeId(_userProvider),
fullName: _provider.currentUser.fullName, fullName: _provider.getCurrentUserFullName(_userProvider),
emailAddress: _provider.currentUser.emailAddress, emailAddress: _provider.getCurrentUserEmail(_userProvider),
mobileNumber: _provider.currentUser.mobileNumber, mobileNumber: _provider.getCurrentUserMobile(_userProvider),
extensionNumber: _provider.currentUser.extensionNumber, extensionNumber: _provider.getCurrentUserExtension(_userProvider),
siteIds: _selectedSites.map((s) => s.identifier ?? '').toList(), siteIds: _selectedSites.map((s) => s.identifier ?? '').toList(),
siteNames: _selectedSites.map((s) => s.name ?? '').toList(), siteNames: _selectedSites.map((s) => s.name ?? '').toList(),
departmentIds: _selectedDepartments.isNotEmpty ? _selectedDepartments.map((d) => d.identifier ?? '').toList() : null, departmentIds: _selectedDepartments.isNotEmpty ? _selectedDepartments.map((d) => d.identifier ?? '').toList() : null,
departmentNames: _selectedDepartments.isNotEmpty ? _selectedDepartments.map((d) => d.name ?? '').toList() : null, departmentNames: _selectedDepartments.isNotEmpty ? _selectedDepartments.map((d) => d.name ?? '').toList() : null,
role: _provider.currentUser.role, role: _provider.getCurrentUserRole(_userProvider),
status: 'Pending', status: 'Pending',
requestDate: DateTime.now(), requestDate: DateTime.now(),
); );
final success = await _provider.submitSiteRequest(request); final success = await _provider.submitSiteRequest(request, _userProvider);
if (mounted) { if (mounted) {
Navigator.pop(context); // Close loading dialog Navigator.pop(context); // Close loading dialog

@ -1,10 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/site_request_module/models/site_request_model.dart'; import 'package:test_sa/modules/site_request_module/models/site_request_model.dart';
import 'package:test_sa/modules/site_request_module/providers/site_request_provider.dart'; import 'package:test_sa/modules/site_request_module/providers/site_request_provider.dart';
import 'package:test_sa/modules/site_request_module/screens/site_request_form_screen.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
@ -19,14 +22,27 @@ class SiteRequestHistoryScreen extends StatefulWidget {
class _SiteRequestHistoryScreenState extends State<SiteRequestHistoryScreen> { class _SiteRequestHistoryScreenState extends State<SiteRequestHistoryScreen> {
late SiteRequestProvider _provider; late SiteRequestProvider _provider;
late UserProvider _userProvider;
bool _isLoadingData = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Add mock history data for demonstration purposes _loadHistoryData();
WidgetsBinding.instance.addPostFrameCallback((_) { }
if (_provider.requestHistory.isEmpty) {
_provider.addMockHistoryData(); Future<void> _loadHistoryData() async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
_provider = Provider.of<SiteRequestProvider>(context, listen: false);
_userProvider = Provider.of<UserProvider>(context, listen: false);
// Fetch request history from API
await _provider.fetchRequestHistory();
if (mounted) {
setState(() {
_isLoadingData = false;
});
} }
}); });
} }
@ -34,20 +50,53 @@ class _SiteRequestHistoryScreenState extends State<SiteRequestHistoryScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_provider = Provider.of<SiteRequestProvider>(context); _provider = Provider.of<SiteRequestProvider>(context);
_userProvider = Provider.of<UserProvider>(context);
return Scaffold( return Scaffold(
backgroundColor: AppColor.scaffoldBackground(context), backgroundColor: AppColor.scaffoldBackground(context),
appBar: const DefaultAppBar(title: "Site Request History"), appBar: DefaultAppBar(
body: _provider.requestHistory.isEmpty title: "Site Request History",
? _buildEmptyState() actions: [
: ListView.builder( Container(
padding: EdgeInsets.all(16.toScreenWidth), padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
itemCount: _provider.requestHistory.length, margin: const EdgeInsets.only(right: 8),
itemBuilder: (context, index) { decoration: BoxDecoration(
final request = _provider.requestHistory[index]; color: AppColor.background(context),
return _buildRequestCard(request); border: Border.all(color: AppColor.border2Color(context)),
}, borderRadius: BorderRadius.circular(16),
), ),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add, size: 20, color: AppColor.textStyleColor(context)),
Text(
"New Request",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColor.textStyleColor(context),
),
),
4.width,
],
),
).onPress(() {
Navigator.pushNamed(context, SiteRequestFormScreen.routeName);
}),
],
),
body: _isLoadingData
? const Center(child: CircularProgressIndicator())
: _provider.requestHistory.isEmpty
? _buildEmptyState()
: ListView.builder(
padding: EdgeInsets.all(16.toScreenWidth),
itemCount: _provider.requestHistory.length,
itemBuilder: (context, index) {
final request = _provider.requestHistory[index];
return _buildRequestCard(request);
},
),
); );
} }
@ -59,7 +108,7 @@ class _SiteRequestHistoryScreenState extends State<SiteRequestHistoryScreen> {
Icon( Icon(
Icons.inbox_outlined, Icons.inbox_outlined,
size: 80, size: 80,
color: AppColor.icon2Color(context).withOpacity(0.5), color: AppColor.icon2Color(context).withValues(alpha: 0.5),
), ),
16.height, 16.height,
"No site requests found".heading5(context).custom( "No site requests found".heading5(context).custom(
@ -75,125 +124,254 @@ class _SiteRequestHistoryScreenState extends State<SiteRequestHistoryScreen> {
} }
Widget _buildRequestCard(SiteRequestModel request) { Widget _buildRequestCard(SiteRequestModel request) {
return Card( return Container(
margin: EdgeInsets.only(bottom: 16.toScreenHeight), margin: EdgeInsets.only(bottom: 16.toScreenHeight),
elevation: 2, decoration: BoxDecoration(
shape: RoundedRectangleBorder( color: AppColor.background(context),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
), ),
color: AppColor.background(context),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.toScreenWidth), padding: EdgeInsets.all(16.toScreenWidth),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Status and Date Row
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: request.requestType.heading6(context).custom( child: Wrap(
color: AppColor.labelTextStyleColor(context), spacing: 8,
fontWeight: FontWeight.bold, runSpacing: 8,
children: [
_buildStatusLabel(request.status),
_buildRequestTypeLabel(request.requestType),
],
), ),
), ),
_buildStatusBadge(request.status), Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
DateFormat('dd MMM yyyy').format(request.requestDate),
style: TextStyle(
fontSize: 12,
color: AppColor.labelTextStyleColor(context),
),
),
Text(
DateFormat('hh:mm a').format(request.requestDate),
style: TextStyle(
fontSize: 10,
color: AppColor.lightTextColor(context),
),
),
],
),
], ],
), ),
16.height,
// Request ID
if (request.id != null) ...[
_buildInfoRow("Request ID", request.id!),
12.height,
],
Divider(color: AppColor.border2Color(context)),
12.height,
// Requester Information Section
"Requester Information".heading6(context).custom(
color: AppColor.textStyleColor(context),
fontWeight: FontWeight.w600,
),
12.height, 12.height,
_buildInfoRow("Request ID", request.id ?? "N/A"),
8.height,
_buildInfoRow("Employee ID", request.employeeId),
8.height,
_buildInfoRow("Full Name", request.fullName), _buildInfoRow("Full Name", request.fullName),
8.height, _buildInfoRow("Employee ID", request.employeeId),
_buildInfoRow("Email", request.emailAddress), _buildInfoRow("Email", request.emailAddress),
8.height,
_buildInfoRow("Mobile", request.mobileNumber), _buildInfoRow("Mobile", request.mobileNumber),
8.height,
if (request.extensionNumber != null && request.extensionNumber!.isNotEmpty) if (request.extensionNumber != null && request.extensionNumber!.isNotEmpty)
_buildInfoRow("Extension", request.extensionNumber!), _buildInfoRow("Extension", request.extensionNumber!),
8.height,
_buildInfoRow("Role", request.role), _buildInfoRow("Role", request.role),
8.height,
_buildInfoRow( 16.height,
"Site(s)", Divider(color: AppColor.border2Color(context)),
request.siteNames.join(", "), 12.height,
// Site Information Section
"Site Information".heading6(context).custom(
color: AppColor.textStyleColor(context),
fontWeight: FontWeight.w600,
),
12.height,
_buildInfoRow("Request Type", request.requestType),
12.height,
// Sites List
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Sites:",
style: TextStyle(
fontSize: 14,
color: AppColor.labelTextStyleColor(context),
fontWeight: FontWeight.w500,
),
),
8.width,
Expanded(
child: Wrap(
spacing: 6,
runSpacing: 6,
children: request.siteNames.map((site) => _buildChip(site)).toList(),
),
),
],
), ),
// Departments List (if available)
if (request.departmentNames != null && request.departmentNames!.isNotEmpty) ...[ if (request.departmentNames != null && request.departmentNames!.isNotEmpty) ...[
8.height, 12.height,
_buildInfoRow( Row(
"Department(s)", crossAxisAlignment: CrossAxisAlignment.start,
request.departmentNames!.join(", "), children: [
Text(
"Departments:",
style: TextStyle(
fontSize: 14,
color: AppColor.labelTextStyleColor(context),
fontWeight: FontWeight.w500,
),
),
8.width,
Expanded(
child: Wrap(
spacing: 6,
runSpacing: 6,
children: request.departmentNames!.map((dept) => _buildChip(dept)).toList(),
),
),
],
), ),
], ],
8.height,
_buildInfoRow(
"Request Date",
DateFormat('dd MMM yyyy, hh:mm a').format(request.requestDate),
),
], ],
), ),
), ),
); );
} }
Widget _buildInfoRow(String label, String value) { Widget _buildStatusLabel(String status) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 120.toScreenWidth,
child: "$label:".bodyText(context).custom(
color: AppColor.lightTextColor(context),
fontSize: 13,
),
),
Expanded(
child: value.bodyText(context).custom(
color: AppColor.labelTextStyleColor(context),
fontSize: 13,
fontWeight: FontWeight.w500,
),
),
],
);
}
Widget _buildStatusBadge(String status) {
Color backgroundColor; Color backgroundColor;
Color textColor; Color textColor;
switch (status.toLowerCase()) { switch (status.toLowerCase()) {
case 'approved': case 'approved':
backgroundColor = Colors.green.withOpacity(0.1); backgroundColor = AppColor.greenStatusColor;
textColor = Colors.green; textColor = AppColor.greenStatusTextColor;
break; break;
case 'rejected': case 'rejected':
backgroundColor = Colors.red.withOpacity(0.1); backgroundColor = AppColor.redStatusColor;
textColor = Colors.red; textColor = AppColor.redStatusTextColor;
break; break;
case 'pending': case 'pending':
default: default:
backgroundColor = Colors.orange.withOpacity(0.1); backgroundColor = AppColor.yellowStatusColor;
textColor = Colors.orange; textColor = AppColor.yellowStatusTextColor;
break; break;
} }
return Container( return Container(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 6.toScreenHeight),
horizontal: 12.toScreenWidth,
vertical: 6.toScreenHeight,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor, color: backgroundColor,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(4),
), ),
child: status.bodyText(context).custom( child: Text(
color: textColor, status,
fontSize: 12, style: TextStyle(
fontWeight: FontWeight.w600, fontSize: 12,
fontWeight: FontWeight.w600,
color: textColor,
),
),
);
}
Widget _buildRequestTypeLabel(String requestType) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 6.toScreenHeight),
decoration: BoxDecoration(
color: AppColor.primary10.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(4),
border: Border.all(color: AppColor.primary10.withValues(alpha: 0.3)),
),
child: Text(
requestType,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: AppColor.primary10,
),
),
);
}
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: EdgeInsets.only(bottom: 8.toScreenHeight),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 120.toScreenWidth,
child: Text(
"$label:",
style: TextStyle(
fontSize: 14,
color: AppColor.labelTextStyleColor(context),
fontWeight: FontWeight.w500,
),
),
),
Expanded(
child: Text(
value,
style: TextStyle(
fontSize: 14,
color: AppColor.textStyleColor(context),
),
),
),
],
), ),
); );
} }
}
Widget _buildChip(String label) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 10.toScreenWidth, vertical: 4.toScreenHeight),
decoration: BoxDecoration(
color: AppColor.primary10.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColor.primary10.withValues(alpha: 0.2)),
),
child: Text(
label,
style: TextStyle(
fontSize: 12,
color: AppColor.primary10,
fontWeight: FontWeight.w500,
),
),
);
}
}

@ -4,7 +4,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/site_request_module/screens/site_request_form_screen.dart'; import 'package:test_sa/modules/site_request_module/screens/site_request_history_screen.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/login_page.dart';
import 'package:test_sa/new_views/swipe_module/swipe_history_view.dart'; import 'package:test_sa/new_views/swipe_module/swipe_history_view.dart';
@ -71,8 +71,8 @@ class AppDrawer extends StatelessWidget {
// drawerItem("rate_us", context.translation.rateUs, context), // drawerItem("rate_us", context.translation.rateUs, context),
// 18.height, // 18.height,
drawerItem("setting", context.translation.settings, context).onPress(() => Navigator.of(context).pushNamed(SettingsPage.id)), drawerItem("setting", context.translation.settings, context).onPress(() => Navigator.of(context).pushNamed(SettingsPage.id)),
drawerItem("setting", "Site Request", context).onPress(() => Navigator.of(context).pushNamed(SiteRequestFormScreen.routeName)),
18.height, 18.height,
drawerItem("setting", "Site Request", context).onPress(() => Navigator.of(context).pushNamed(SiteRequestHistoryScreen.routeName)),
18.height, 18.height,
if (userProvider.user != null && userProvider.user?.employeeIsHMG == false) if (userProvider.user != null && userProvider.user?.employeeIsHMG == false)
drawerItem("swipe", "Swipe History", context).onPress(() => Navigator.of(context).pushNamed(SwipeHistoryView.routeName)), drawerItem("swipe", "Swipe History", context).onPress(() => Navigator.of(context).pushNamed(SwipeHistoryView.routeName)),

@ -0,0 +1,49 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/models/new_models/department.dart';
import '../controllers/api_routes/api_manager.dart';
import '../controllers/api_routes/urls.dart';
import 'loading_list_notifier.dart';
class DepartmentBySitesProvider extends LoadingListNotifier<Department> {
List<int> siteIds = [];
void setSiteIds(List<int> ids) {
siteIds = ids;
}
@override
Future getData({int? id}) async {
if (loading ?? false) return -2;
if (siteIds.isEmpty) {
items = [];
notifyListeners();
return 200;
}
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.post(
URLs.getDepartmentsBySites,
body: {"siteIds": siteIds},
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
var responseData = json.decode(response.body);
List departmentListJson = responseData is List ? responseData : responseData['data'] ?? [];
items = departmentListJson.map((item) => Department.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}
Loading…
Cancel
Save