improvements

export_module_ui_ux_enhancement_signup
WaseemAbbasi22 3 weeks ago
parent 69c09f7bd0
commit cdc6953605

@ -61,6 +61,7 @@ class URLs {
static get signUpGetCompaniesByAssetGroup => "$_baseUrl/Company/GetCompaniesByAssetGroup";
static get signUpGetSiteList => "$_baseUrl/Customer/GetSiteList";
static get signUpGetDepartmentAutoComplete => "$_baseUrl/Department/GetDepartmentAutoCompleteByAssetGroup";
static get signUpGetDepartmentsBySitesAndAssetGroup => "$_baseUrl/Department/GetDepartmentsBySitesAndAssetGroup";
// Site Request APIs
static get getSiteRequestTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=4016"; // get site request types
@ -586,7 +587,8 @@ class URLs {
static get getDemoRequests => "$_baseUrl/DemoRequest/GetDemoRequests"; // get demo request history
// Application Demo Request APIs
static get getApplicationDemoRoles => "$_baseUrl/Account/GetRolesByAssetGroupId?assetGroupId=6"; // get roles for application demo request
// static get getApplicationDemoRoles => "$_baseUrl/Account/GetRolesByAssetGroupId?assetGroupId=6"; // get roles for application demo request
static get getApplicationDemoRoles => "$_baseUrl/RoleDemo/GetDemoRolesAutoComplete"; // get roles for application demo request
static get submitApplicationDemoRequest => "$_baseUrl/DemoUser/CreateDemoUser"; // post submit application demo request// get application demo request history
static get sendDemoUserOtp => "$_baseUrl/DemoUser/EmailVerification"; // post send OTP to user
static get verifyDemoUserOtp => "$_baseUrl/DemoUser/VerifyOtp"; // post verify OTP

@ -1,11 +1,11 @@
import 'dart:developer';
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/modules/applicationDemo/models/application_demo_request_model.dart';
import 'package:test_sa/modules/applicationDemo/models/role_model.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
/// Provider for managing application demo request operations
class ApplicationDemoRequestProvider extends ChangeNotifier {
bool _loading = false;
bool _roleLoading = false;
@ -13,7 +13,6 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
String? _errorMessage;
String? _successMessage;
// Getters
bool get loading => _loading;
bool get roleLoading => _roleLoading;
@ -24,7 +23,6 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
List<ApplicationDemoRoleModel> get roles => _roles;
// Setter
set loading(bool value) {
_loading = value;
notifyListeners();
@ -35,29 +33,30 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
notifyListeners();
}
/// Get headers without authentication token for public APIs
Map<String, String> get _unauthenticatedHeaders => {
'Content-Type': 'application/json',
'X-Timezone-Offset': DateTime.now().timeZoneOffset.toString().split(".").first,
};
/// Fetches available roles from the server (without authentication)
Future<int> fetchRoles() async {
Future<int> fetchRoles({String? searchText}) async {
if (roleLoading) return -2;
roleLoading = true;
_errorMessage = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse(URLs.getApplicationDemoRoles),
headers: _unauthenticatedHeaders,
);
final response = await ApiManager.instance.post(URLs.getApplicationDemoRoles, headers: _unauthenticatedHeaders, body: {'searchText': searchText ?? ''});
if (response.statusCode >= 200 && response.statusCode < 300) {
final List<dynamic> responseData = jsonDecode(response.body);
_roles = responseData.map((json) => ApplicationDemoRoleModel.fromJson(json)).toList();
final Map<String, dynamic> responseData = jsonDecode(response.body);
List<dynamic> rolesList = [];
if (responseData.containsKey('data')) {
rolesList = responseData['data'] is List ? responseData['data'] : [];
} else if (responseData.containsKey('roles')) {
rolesList = responseData['roles'] is List ? responseData['roles'] : [];
}
_roles = rolesList.map((json) => ApplicationDemoRoleModel.fromJson(json)).toList();
roleLoading = false;
notifyListeners();
@ -87,10 +86,10 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
try {
final requestBody = request.toJson();
final response = await http.post(
Uri.parse(URLs.submitApplicationDemoRequest),
final response = await ApiManager.instance.post(
URLs.submitApplicationDemoRequest,
headers: _unauthenticatedHeaders,
body: json.encode(requestBody),
body: requestBody,
);
if (response.statusCode >= 200 && response.statusCode < 300) {
@ -134,10 +133,10 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
'typeSend': typeSend,
};
final response = await http.post(
Uri.parse(URLs.sendDemoUserOtp),
final response = await ApiManager.instance.post(
URLs.sendDemoUserOtp,
headers: _unauthenticatedHeaders,
body: json.encode(requestBody),
body: requestBody,
);
if (response.statusCode >= 200 && response.statusCode < 300) {
@ -185,10 +184,10 @@ class ApplicationDemoRequestProvider extends ChangeNotifier {
requestBody['phoneNumber'] = phoneNumber;
}
final response = await http.post(
Uri.parse(URLs.verifyDemoUserOtp),
final response = await ApiManager.instance.post(
URLs.verifyDemoUserOtp,
headers: _unauthenticatedHeaders,
body: json.encode(requestBody),
body: requestBody,
);
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -18,7 +18,7 @@ class DepartmentModel extends Base {
factory DepartmentModel.fromJson(Map<String, dynamic> json) {
return DepartmentModel(
id: json['id'],
departmentName: json['departmentName'],
departmentName: json['departmentName']??json['name'],
departmentCode: json['departmentCode'],
ntCode: json['ntCode'],
operationalHours: json['operationalHours'],

@ -6,9 +6,9 @@ class SignUpRequestModel {
final String? emailAddress;
final String? mobileNumber;
final String? extensionNumber;
final int? siteId;
final List<int>? siteIds;
final String? erpSite;
final int? departmentId;
final List<int>? departmentIds;
final String? erpDepartment;
final String? role;
final bool isFromERP;
@ -21,9 +21,9 @@ class SignUpRequestModel {
this.emailAddress,
this.mobileNumber,
this.extensionNumber,
this.siteId,
this.siteIds,
this.erpSite,
this.departmentId,
this.departmentIds,
this.erpDepartment,
this.role,
required this.isFromERP,
@ -32,19 +32,15 @@ class SignUpRequestModel {
Map<String, dynamic> toJson() {
return {
'assetGroupId': assetGroupId ?? 0,
'companyId': companyId ?? 0,
'employeeId': employeeId ?? '',
'fullName': fullName ?? '',
'emailAddress': emailAddress ?? '',
'mobileNumber': mobileNumber ?? '',
'extensionNumber': extensionNumber ?? '',
if(siteId!=null)
'siteId': siteId,
// 'siteId': siteId ?? 0,
'siteIds': siteIds,
'erpSite': erpSite ?? '',
if(departmentId!=null)
'departmentId': departmentId,
'departmentIds': departmentIds,
'erpDepartment': erpDepartment ?? '',
'role': role ?? '',
'isFromERP': isFromERP,

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/modules/signup/models/department_model.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
@ -28,8 +29,9 @@ class SignupDepartmentProvider extends LoadingListNotifier<DepartmentModel> {
'X-Timezone-Offset': DateTime.now().timeZoneOffset.toString().split(".").first,
};
final response = await http.get(
Uri.parse('${URLs.signUpGetDepartmentAutoComplete}?assetGroupId=$id'),
final response = await ApiManager.instance.get(
'${URLs.signUpGetDepartmentAutoComplete}?assetGroupId=$id',
// Uri.parse('${URLs.signUpGetDepartmentAutoComplete}?assetGroupId=$id'),
headers: headers,
);
@ -71,4 +73,68 @@ class SignupDepartmentProvider extends LoadingListNotifier<DepartmentModel> {
return -1;
}
}
/// Fetches departments based on selected sites and asset group
Future<int> getDepartmentsBySites({
required List<int> siteIds,
required int assetGroupId,
}) async {
log('Fetching departments for sites: $siteIds and asset group: $assetGroupId');
if (loading) return -2;
if (siteIds.isEmpty) {
log('Department fetch: Site IDs are empty, clearing items');
items = [];
notifyListeners();
return -1;
}
loading = true;
notifyListeners();
try {
final headers = {
'Content-Type': 'application/json',
'X-Timezone-Offset': DateTime.now().timeZoneOffset.toString().split(".").first,
};
final body = {
'siteIds': siteIds,
'assetGroupId': assetGroupId,
};
final response = await ApiManager.instance.post(
URLs.signUpGetDepartmentsBySitesAndAssetGroup,
headers: headers,
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = json.decode(response.body);
if (data is Map && data['data'] != null && data['data'] is List) {
items = (data['data'] as List).map((item) => DepartmentModel.fromJson(item)).toList();
} else if (data is List) {
items = data.map((item) => DepartmentModel.fromJson(item)).toList();
} else {
items = [];
}
} else {
items = [];
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
log('Department by sites API error: $error');
loading = false;
stateCode = -1;
items = [];
notifyListeners();
return -1;
}
}
}

@ -27,6 +27,7 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/multiple_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/swipe_module/dialoge/single_btn_dialog.dart';
import 'package:test_sa/views/widgets/dialogs/dialog.dart';
@ -62,8 +63,8 @@ class _SignUpScreenState extends State<SignUpScreen> {
// Selected values
AssetGroup? _selectedAssetGroup;
Company? _selectedCompany;
SiteModel? _selectedSite;
DepartmentModel? _selectedDepartment;
List<SiteModel> _selectedSite=[];
List<DepartmentModel> _selectedDepartment=[];
EmployeeERPModel? _employeeERPData; // Store the ERP employee data
bool _isHMGGroup = false;
bool _employeeFetched = false;
@ -352,43 +353,92 @@ class _SignUpScreenState extends State<SignUpScreen> {
}
Widget _buildSiteDropdown() {
return SingleItemDropDownMenu<SiteModel, SignupSiteProvider>(
return MultipleItemDropDownMenu<SiteModel, SignupSiteProvider>(
context: context,
title: "Site",
initialValue: _selectedSite,
showAsFullScreenDialog: true,
requestById: _selectedAssetGroup?.id,
onSelect: (value) {
// staticData: provider.roles,
// loading: provider.roleLoading,
showAsFullScreenDialog: true,
onSelect: (selectedSites) {
setState(() {
_selectedSite = value;
_selectedSite = selectedSites ?? [];
// Clear departments when sites change
_selectedDepartment = [];
// _rolesValidationError = null; // Clear error when roles are selected
});
// No need to fetch departments when site changes - they are independent
},
validator: (value) {
if (value == null) return "Site is required";
return null;
// Fetch departments based on selected sites
if (_selectedSite.isNotEmpty && _selectedAssetGroup?.id != null) {
final siteIds = _selectedSite.map((site) => site.id ?? 0).where((id) => id != 0).toList();
if (siteIds.isNotEmpty) {
_departmentProvider.getDepartmentsBySites(
siteIds: siteIds,
assetGroupId: _selectedAssetGroup!.id!,
);
}
} else {
// If no sites selected, clear departments
_departmentProvider.items = [];
_departmentProvider.notifyListeners();
}
},
);
// return SingleItemDropDownMenu<SiteModel, SignupSiteProvider>(
// context: context,
// title: "Site",
// initialValue: _selectedSite,
// showAsFullScreenDialog: true,
// requestById: _selectedAssetGroup?.id,
// onSelect: (value) {
// setState(() {
// _selectedSite = value;
// });
// // No need to fetch departments when site changes - they are independent
// },
// validator: (value) {
// if (value == null) return "Site is required";
// return null;
// },
// );
}
Widget _buildDepartmentDropdown() {
return SingleItemDropDownMenu<DepartmentModel, SignupDepartmentProvider>(
return MultipleItemDropDownMenu<DepartmentModel, SignupDepartmentProvider>(
context: context,
title: "Department",
initialValue: _selectedDepartment,
showAsFullScreenDialog: true,
// showAsBottomSheet: true,
requestById: _selectedAssetGroup?.id,
onSelect: (value) {
// staticData: provider.roles,
// loading: provider.roleLoading,
showAsFullScreenDialog: true,
onSelect: (selectedDepartments) {
setState(() {
_selectedDepartment = value;
_selectedDepartment = selectedDepartments ?? [];
// _rolesValidationError = null; // Clear error when roles are selected
});
},
validator: (value) {
if (value == null) return "Department is required";
return null;
},
);
// return SingleItemDropDownMenu<DepartmentModel, SignupDepartmentProvider>(
// context: context,
// title: "Department",
// initialValue: _selectedDepartment,
// showAsFullScreenDialog: true,
// // showAsBottomSheet: true,
// requestById: _selectedAssetGroup?.id,
// onSelect: (value) {
// setState(() {
// _selectedDepartment = value;
// });
// },
// validator: (value) {
// if (value == null) return "Department is required";
// return null;
// },
// );
}
Widget _buildRoleField() {
@ -482,8 +532,8 @@ class _SignUpScreenState extends State<SignUpScreen> {
_mobileController.clear();
_extensionController.clear();
_roleController.clear();
_selectedSite = null;
_selectedDepartment = null;
_selectedSite = [];
_selectedDepartment = [];
_employeeFetched = false;
_employeeERPData = null;
}
@ -520,13 +570,13 @@ class _SignUpScreenState extends State<SignUpScreen> {
}
// Site is mandatory for HMG
if (_selectedSite == null) {
if (_selectedSite.isEmpty) {
Fluttertoast.showToast(msg: "Site is required");
return;
}
//
// // Department is mandatory for HMG
if (_selectedDepartment == null) {
if (_selectedDepartment.isEmpty) {
Fluttertoast.showToast(msg: "Department is required");
return;
}
@ -560,13 +610,13 @@ class _SignUpScreenState extends State<SignUpScreen> {
}
// Site is mandatory for Non-HMG
if (_selectedSite == null) {
if (_selectedSite.isEmpty) {
Fluttertoast.showToast(msg: "Site is required");
return;
}
// Department is mandatory for Non-HMG
if (_selectedDepartment == null) {
if (_selectedDepartment.isEmpty) {
Fluttertoast.showToast(msg: "Department is required");
return;
}
@ -620,9 +670,11 @@ class _SignUpScreenState extends State<SignUpScreen> {
mobileNumber: _mobileController.text,
extensionNumber: _extensionController.text.isEmpty ? null : _extensionController.text,
// For HMG: send both selected IDs and ERP data
siteId: _selectedSite?.id,
// siteId: _selectedSite?.id,
siteIds: _selectedSite.map((site) => site.id??0).toList(),
// erpSite: _isHMGGroup ? _employeeERPData?.branchCode : null,
departmentId: _selectedDepartment?.id,
departmentIds: _selectedDepartment.map((department) => department.id??0).toList(),
// departmentIds: _selectedDepartment?.id,
// erpDepartment: _isHMGGroup ? _employeeERPData?.branchName : null,
role: _roleController.text,
isFromERP: _isHMGGroup,

Loading…
Cancel
Save