From 14e845b18a7e614c8d616085cad8607ea7472325 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 <50428976+WaseemAbbasi22@users.noreply.github.com> Date: Thu, 4 Jun 2026 10:51:47 +0300 Subject: [PATCH] signup inprogress --- lib/controllers/api_routes/urls.dart | 4 + lib/main.dart | 10 + lib/modules/signup/models/company_model.dart | 35 ++ .../signup/models/employee_erp_model.dart | 39 ++ lib/modules/signup/models/group_model.dart | 35 ++ .../signup/models/signup_request_model.dart | 41 ++ .../signup/providers/company_provider.dart | 33 ++ .../signup/providers/group_provider.dart | 32 ++ .../signup/providers/signup_provider.dart | 100 ++++ lib/modules/signup/screens/signup_screen.dart | 479 ++++++++++++++++++ lib/new_views/pages/login_page.dart | 11 + 11 files changed, 819 insertions(+) create mode 100644 lib/modules/signup/models/company_model.dart create mode 100644 lib/modules/signup/models/employee_erp_model.dart create mode 100644 lib/modules/signup/models/group_model.dart create mode 100644 lib/modules/signup/models/signup_request_model.dart create mode 100644 lib/modules/signup/providers/company_provider.dart create mode 100644 lib/modules/signup/providers/group_provider.dart create mode 100644 lib/modules/signup/providers/signup_provider.dart create mode 100644 lib/modules/signup/screens/signup_screen.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index b0dc87c8..6c3dceb0 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -52,6 +52,10 @@ class URLs { static get updateNewPassword => "$_baseUrl/Account/UpdatenewPassword"; // validate OTP. static get getUserRota => "$_baseUrl/Account/GetUserRota"; // validate OTP. + // SignUp APIs + static get signUpGetEmployeeFromERP => "$_baseUrl/SignUpRequest/GetEmployeeFromERP"; + static get signUpSubmit => "$_baseUrl/SignUpRequest/Submit"; + // static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // mobile login static get register => "$_baseUrl/handle/create/user"; // post static get updateProfile => "$_baseUrl/update/user/profile"; // post diff --git a/lib/main.dart b/lib/main.dart index c10bc2c1..c2c68505 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -55,6 +55,10 @@ import 'package:test_sa/modules/medical_gas_inspection/create_medical_gas_reques import 'package:test_sa/modules/medical_gas_inspection/providers/item_type_provider.dart'; import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_inspection_provider.dart'; import 'package:test_sa/modules/medical_gas_inspection/providers/order_type_provider.dart'; +import 'package:test_sa/modules/signup/providers/company_provider.dart'; +import 'package:test_sa/modules/signup/providers/group_provider.dart'; +import 'package:test_sa/modules/signup/providers/signup_provider.dart'; +import 'package:test_sa/modules/signup/screens/signup_screen.dart'; import 'package:test_sa/modules/tm_module/gas_refill/create_gas_refill_request.dart'; import 'package:test_sa/modules/tm_module/gas_refill/update_gas_refill_request.dart'; import 'package:test_sa/modules/traf_module/create_traf_request_page.dart'; @@ -337,6 +341,11 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => MedicalDepartmentProvider(), lazy: true), ChangeNotifierProvider(create: (_) => FlowMedicalDepartmentProvider(), lazy: true), + // SIGNUP MODULE PROVIDERS (3) + ChangeNotifierProvider(create: (_) => CompanyProvider(), lazy: true), + ChangeNotifierProvider(create: (_) => GroupProvider(), lazy: true), + ChangeNotifierProvider(create: (_) => SignUpProvider(), lazy: true), + // EMPLOYEE/USER PROVIDERS (2) ChangeNotifierProvider(create: (_) => NurseProvider(), lazy: true), ChangeNotifierProvider(create: (_) => UserSearchProvider(), lazy: true), @@ -412,6 +421,7 @@ class MyApp extends StatelessWidget { CreateSystemInternalAuditForm.id: (_) => const CreateSystemInternalAuditForm(), UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(), UpdateSystemInternalAuditPage.id: (_) => UpdateSystemInternalAuditPage(), + SignUpScreen.routeName: (_) => const SignUpScreen(), CreateLoanRequestPage.id: (_) => CreateLoanRequestPage(), CreateMedicalGasRequestPage.id: (_) => CreateMedicalGasRequestPage(), CreateDemoRequestPage.id: (_) => CreateDemoRequestPage(), diff --git a/lib/modules/signup/models/company_model.dart b/lib/modules/signup/models/company_model.dart new file mode 100644 index 00000000..a2f0529b --- /dev/null +++ b/lib/modules/signup/models/company_model.dart @@ -0,0 +1,35 @@ +import 'package:test_sa/models/base.dart'; + +class Company extends Base { + final String? code; + final String? displayName; + + Company({ + this.code, + this.displayName, + }) : super(identifier: code, name: displayName); + + factory Company.fromJson(Map json) { + return Company( + code: json['code'], + displayName: json['displayName'], + ); + } + + Map toJson() { + return { + 'code': code, + 'displayName': displayName, + }; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Company && + runtimeType == other.runtimeType && + code == other.code; + + @override + int get hashCode => code.hashCode; +} diff --git a/lib/modules/signup/models/employee_erp_model.dart b/lib/modules/signup/models/employee_erp_model.dart new file mode 100644 index 00000000..e95b7e5a --- /dev/null +++ b/lib/modules/signup/models/employee_erp_model.dart @@ -0,0 +1,39 @@ +class EmployeeERPModel { + final String? employeeId; + final String? fullName; + final String? email; + final String? mobileNumber; + final bool? existsInAtoms; + final String? message; + + EmployeeERPModel({ + this.employeeId, + this.fullName, + this.email, + this.mobileNumber, + this.existsInAtoms, + this.message, + }); + + factory EmployeeERPModel.fromJson(Map json) { + return EmployeeERPModel( + employeeId: json['employeeId']?.toString(), + fullName: json['fullName'], + email: json['email'], + mobileNumber: json['mobileNumber'], + existsInAtoms: json['existsInAtoms'], + message: json['message'], + ); + } + + Map toJson() { + return { + 'employeeId': employeeId, + 'fullName': fullName, + 'email': email, + 'mobileNumber': mobileNumber, + 'existsInAtoms': existsInAtoms, + 'message': message, + }; + } +} diff --git a/lib/modules/signup/models/group_model.dart b/lib/modules/signup/models/group_model.dart new file mode 100644 index 00000000..47883310 --- /dev/null +++ b/lib/modules/signup/models/group_model.dart @@ -0,0 +1,35 @@ +import 'package:test_sa/models/base.dart'; + +class Group extends Base { + final String? code; + final String? displayName; + + Group({ + this.code, + this.displayName, + }) : super(identifier: code, name: displayName); + + factory Group.fromJson(Map json) { + return Group( + code: json['code'], + displayName: json['displayName'], + ); + } + + Map toJson() { + return { + 'code': code, + 'displayName': displayName, + }; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Group && + runtimeType == other.runtimeType && + code == other.code; + + @override + int get hashCode => code.hashCode; +} diff --git a/lib/modules/signup/models/signup_request_model.dart b/lib/modules/signup/models/signup_request_model.dart new file mode 100644 index 00000000..b6713129 --- /dev/null +++ b/lib/modules/signup/models/signup_request_model.dart @@ -0,0 +1,41 @@ +class SignUpRequestModel { + final String? companyCode; + final String? groupCode; + final String? employeeId; + final String? fullName; + final String? email; + final String? mobileNumber; + final String? extensionNumber; + final int? siteId; + final int? departmentId; + final String? role; + + SignUpRequestModel({ + this.companyCode, + this.groupCode, + this.employeeId, + this.fullName, + this.email, + this.mobileNumber, + this.extensionNumber, + this.siteId, + this.departmentId, + this.role, + }); + + Map toJson() { + return { + 'companyCode': companyCode, + 'groupCode': groupCode, + 'employeeId': employeeId, + 'fullName': fullName, + 'email': email, + 'mobileNumber': mobileNumber, + 'extensionNumber': extensionNumber, + 'siteId': siteId, + 'departmentId': departmentId, + 'role': role, + }; + } +} + diff --git a/lib/modules/signup/providers/company_provider.dart b/lib/modules/signup/providers/company_provider.dart new file mode 100644 index 00000000..5d36b478 --- /dev/null +++ b/lib/modules/signup/providers/company_provider.dart @@ -0,0 +1,33 @@ +import 'package:test_sa/modules/signup/models/company_model.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +class CompanyProvider extends LoadingListNotifier { + @override + Future getData({int? id}) async { + if (loading) return -2; + loading = true; + notifyListeners(); + + try { + // TODO: Replace with actual API call when available + await Future.delayed(const Duration(milliseconds: 500)); + + items = [ + Company(code: 'FM', displayName: 'Flow Medical (FM)'), + Company(code: 'FMS', displayName: 'Facility Management and Safety (FMS)'), + Company(code: 'Ajaji', displayName: 'Ajaji'), + ]; + + stateCode = 200; + loading = false; + notifyListeners(); + return 200; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} + diff --git a/lib/modules/signup/providers/group_provider.dart b/lib/modules/signup/providers/group_provider.dart new file mode 100644 index 00000000..d87305e4 --- /dev/null +++ b/lib/modules/signup/providers/group_provider.dart @@ -0,0 +1,32 @@ +import 'package:test_sa/modules/signup/models/group_model.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +class GroupProvider extends LoadingListNotifier { + @override + Future getData({int? id}) async { + if (loading) return -2; + loading = true; + notifyListeners(); + + try { + // TODO: Replace with actual API call when available + await Future.delayed(const Duration(milliseconds: 500)); + + items = [ + Group(code: 'HMG', displayName: 'HMG'), + Group(code: 'Non-HMG', displayName: 'Non-HMG'), + ]; + + stateCode = 200; + loading = false; + notifyListeners(); + return 200; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} + diff --git a/lib/modules/signup/providers/signup_provider.dart b/lib/modules/signup/providers/signup_provider.dart new file mode 100644 index 00000000..5cf0caf2 --- /dev/null +++ b/lib/modules/signup/providers/signup_provider.dart @@ -0,0 +1,100 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.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/signup/models/employee_erp_model.dart'; +import 'package:test_sa/modules/signup/models/signup_request_model.dart'; + +class SignUpProvider extends ChangeNotifier { + bool _loading = false; + bool get loading => _loading; + + set loading(bool value) { + _loading = value; + notifyListeners(); + } + + EmployeeERPModel? _employeeData; + EmployeeERPModel? get employeeData => _employeeData; + + String? _errorMessage; + String? get errorMessage => _errorMessage; + + /// Fetch employee details from ERP + Future getEmployeeFromERP(String employeeId) async { + if (loading) return null; + + loading = true; + _errorMessage = null; + _employeeData = null; + notifyListeners(); + + try { + final url = '${URLs.signUpGetEmployeeFromERP}?employeeId=$employeeId'; + Response response = await ApiManager.instance.get(url, enableToastMessage: false); + + if (response.statusCode >= 200 && response.statusCode < 300) { + final data = json.decode(response.body); + _employeeData = EmployeeERPModel.fromJson(data['data']); + + loading = false; + notifyListeners(); + return _employeeData; + } else { + final data = json.decode(response.body); + _errorMessage = data['message'] ?? 'Failed to fetch employee details'; + loading = false; + notifyListeners(); + return null; + } + } catch (error) { + _errorMessage = 'Failed to fetch employee details'; + loading = false; + notifyListeners(); + return null; + } + } + + /// Submit signup request + Future submitSignUpRequest(SignUpRequestModel request) async { + if (loading) return false; + + loading = true; + _errorMessage = null; + notifyListeners(); + + try { + Response response = await ApiManager.instance.post( + URLs.signUpSubmit, + body: request.toJson(), + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + loading = false; + notifyListeners(); + return true; + } else { + final data = json.decode(response.body); + _errorMessage = data['message'] ?? 'Failed to submit signup request'; + loading = false; + notifyListeners(); + return false; + } + } catch (error) { + _errorMessage = 'Failed to submit signup request'; + loading = false; + notifyListeners(); + return false; + } + } + + void reset() { + _loading = false; + _employeeData = null; + _errorMessage = null; + notifyListeners(); + } +} + diff --git a/lib/modules/signup/screens/signup_screen.dart b/lib/modules/signup/screens/signup_screen.dart new file mode 100644 index 00000000..28636928 --- /dev/null +++ b/lib/modules/signup/screens/signup_screen.dart @@ -0,0 +1,479 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/site.dart'; +import 'package:test_sa/modules/signup/models/company_model.dart'; +import 'package:test_sa/modules/signup/models/group_model.dart'; +import 'package:test_sa/modules/signup/models/signup_request_model.dart'; +import 'package:test_sa/modules/signup/providers/company_provider.dart'; +import 'package:test_sa/modules/signup/providers/group_provider.dart'; +import 'package:test_sa/modules/signup/providers/signup_provider.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +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/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/department_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; + +class SignUpScreen extends StatefulWidget { + static const String routeName = "/signup_screen"; + + const SignUpScreen({Key? key}) : super(key: key); + + @override + State createState() => _SignUpScreenState(); +} + +class _SignUpScreenState extends State { + final GlobalKey _formKey = GlobalKey(); + + late CompanyProvider _companyProvider; + late GroupProvider _groupProvider; + late SignUpProvider _signUpProvider; + late DepartmentProvider _departmentProvider; + + // Form field controllers + final TextEditingController _employeeIdController = TextEditingController(); + final TextEditingController _fullNameController = TextEditingController(); + final TextEditingController _emailController = TextEditingController(); + final TextEditingController _mobileController = TextEditingController(); + final TextEditingController _extensionController = TextEditingController(); + final TextEditingController _roleController = TextEditingController(); + + // Selected values + Company? _selectedCompany; + Group? _selectedGroup; + Site? _selectedSite; + Lookup? _selectedDepartment; + + bool _isHMGGroup = false; + bool _employeeFetched = false; + bool _isSubmitting = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _companyProvider.getData(); + _groupProvider.getData(); + }); + } + + @override + void dispose() { + _employeeIdController.dispose(); + _fullNameController.dispose(); + _emailController.dispose(); + _mobileController.dispose(); + _extensionController.dispose(); + _roleController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _companyProvider = Provider.of(context); + _groupProvider = Provider.of(context); + _signUpProvider = Provider.of(context); + _departmentProvider = Provider.of(context); + + return Scaffold( + backgroundColor: AppColor.scaffoldBackground(context), + appBar: const DefaultAppBar(title: "Sign Up"), + body: Form( + key: _formKey, + child: SingleChildScrollView( + padding: EdgeInsets.all(16.toScreenWidth), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildCompanyDropdown(), + 16.height, + _buildGroupDropdown(), + 16.height, + if (_selectedGroup != null) ..._buildDynamicFields(), + 24.height, + _buildSubmitButton(), + ], + ), + ), + ), + ); + } + + Widget _buildCompanyDropdown() { + return SingleItemDropDownMenu( + context: context, + title: "Company", + initialValue: _selectedCompany, + showAsFullScreenDialog: false, + showAsBottomSheet: true, + onSelect: (value) { + setState(() { + _selectedCompany = value; + }); + }, + validator: (value) { + if (value == null) return "Company is required"; + return null; + }, + ); + } + + Widget _buildGroupDropdown() { + return SingleItemDropDownMenu( + context: context, + title: "Group", + initialValue: _selectedGroup, + showAsFullScreenDialog: false, + showAsBottomSheet: true, + onSelect: (value) { + setState(() { + _selectedGroup = value; + _isHMGGroup = value?.code == 'HMG'; + _employeeFetched = false; + _clearForm(); + }); + }, + validator: (value) { + if (value == null) return "Group is required"; + return null; + }, + ); + } + + List _buildDynamicFields() { + if (_isHMGGroup) { + return [ + _buildEmployeeIdField(), + 16.height, + if (_employeeFetched) ...[ + _buildReadOnlyField("Full Name", _fullNameController), + 16.height, + _buildReadOnlyField("Email Address", _emailController), + 16.height, + _buildReadOnlyField("Mobile Number", _mobileController), + 16.height, + _buildExtensionField(), + 16.height, + _buildSiteDropdown(), + 16.height, + _buildDepartmentDropdown(), + 16.height, + _buildRoleField(), + ], + ]; + } else { + return [ + _buildReadOnlyEmployeeIdField(), + 16.height, + _buildFullNameField(), + 16.height, + _buildEmailField(), + 16.height, + _buildMobileField(), + 16.height, + _buildExtensionField(), + 16.height, + _buildSiteDropdown(), + 16.height, + _buildDepartmentDropdown(), + 16.height, + _buildRoleField(), + ]; + } + } + + Widget _buildEmployeeIdField() { + return AppTextFormField( + controller: _employeeIdController, + labelText: "Employee ID", + hintText: "Enter Employee ID", + textInputType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) return "Employee ID is required"; + if (!Validator.isNumeric(value)) return "Employee ID must be numeric"; + return null; + }, + onChange: (value) { + if (value.isNotEmpty && Validator.isNumeric(value)) { + _fetchEmployeeDetails(value); + } + }, + ); + } + + Widget _buildReadOnlyEmployeeIdField() { + return AppTextFormField( + initialValue: "Will be generated after admin approval", + labelText: "Employee ID", + enable: false, + backgroundColor: AppColor.disableFieldBackground(context), + ); + } + + Widget _buildReadOnlyField(String label, TextEditingController controller) { + return AppTextFormField( + controller: controller, + labelText: label, + enable: false, + backgroundColor: AppColor.disableFieldBackground(context), + ); + } + + Widget _buildFullNameField() { + return AppTextFormField( + controller: _fullNameController, + labelText: "Full Name", + hintText: "Enter Full Name", + validator: (value) { + if (value == null || value.isEmpty) return "Full Name is required"; + return null; + }, + ); + } + + Widget _buildEmailField() { + return AppTextFormField( + controller: _emailController, + labelText: "Email Address", + hintText: "Enter Email Address", + textInputType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) return "Email is required"; + if (!Validator.isEmail(value)) return "Invalid email format"; + return null; + }, + ); + } + + Widget _buildMobileField() { + return AppTextFormField( + controller: _mobileController, + labelText: "Mobile Number", + hintText: "Enter Mobile Number", + textInputType: TextInputType.phone, + validator: (value) { + if (value == null || value.isEmpty) return "Mobile Number is required"; + if (!Validator.isPhoneNumber(value)) return "Invalid mobile number"; + return null; + }, + ); + } + + Widget _buildExtensionField() { + return AppTextFormField( + controller: _extensionController, + labelText: "Extension Number", + hintText: "Enter Extension Number (Optional)", + textInputType: TextInputType.number, + validator: (value) { + if (value != null && value.isNotEmpty && !Validator.isNumeric(value)) { + return "Extension must be numeric"; + } + return null; + }, + ); + } + + Widget _buildSiteDropdown() { + return SingleItemDropDownMenu( + context: context, + title: "Site", + initialValue: _selectedSite, + showAsFullScreenDialog: false, + showAsBottomSheet: true, + onSelect: (value) { + setState(() { + _selectedSite = value; + _selectedDepartment = null; + }); + if (value != null) { + _departmentProvider.getData(id: value.id?.toInt()); + } + }, + validator: (value) { + if (value == null) return "Site is required"; + return null; + }, + ); + } + + Widget _buildDepartmentDropdown() { + return SingleItemDropDownMenu( + context: context, + title: "Department", + initialValue: _selectedDepartment, + showAsFullScreenDialog: false, + showAsBottomSheet: true, + onSelect: (value) { + setState(() { + _selectedDepartment = value; + }); + }, + validator: (value) { + if (value == null) return "Department is required"; + return null; + }, + ); + } + + Widget _buildRoleField() { + return AppTextFormField( + controller: _roleController, + labelText: "Role", + hintText: "Enter Role", + validator: (value) { + if (value == null || value.isEmpty) return "Role is required"; + return null; + }, + ); + } + + Widget _buildSubmitButton() { + return AppFilledButton( + label: "Submit", + maxWidth: true, + loading: _isSubmitting, + disableButton: _isSubmitting, + onPressed: _submitForm, + ); + } + + Future _fetchEmployeeDetails(String employeeId) async { + final employee = await _signUpProvider.getEmployeeFromERP(employeeId); + + if (employee != null) { + if (employee.existsInAtoms == true) { + if (mounted) { + _showAlreadyExistsDialog(); + } + _clearForm(); + _employeeIdController.clear(); + return; + } + + setState(() { + _employeeFetched = true; + _fullNameController.text = employee.fullName ?? ''; + _emailController.text = employee.email ?? ''; + _mobileController.text = employee.mobileNumber ?? ''; + }); + } else { + setState(() { + _employeeFetched = false; + }); + Fluttertoast.showToast( + msg: _signUpProvider.errorMessage ?? "Failed to fetch employee details", + ); + } + } + + void _showAlreadyExistsDialog() { + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: AppColor.background(context), + title: "Account Exists".bodyText(context), + content: "Already you have an account on Atoms".bodyText(context), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: "OK".bodyText(context).custom(color: AppColor.primary10), + ), + ], + ), + ); + } + + void _clearForm() { + _fullNameController.clear(); + _emailController.clear(); + _mobileController.clear(); + _extensionController.clear(); + _roleController.clear(); + _selectedSite = null; + _selectedDepartment = null; + } + + Future _submitForm() async { + if (!_formKey.currentState!.validate()) return; + + if (_isHMGGroup && !_employeeFetched) { + Fluttertoast.showToast(msg: "Please enter a valid Employee ID"); + return; + } + + setState(() { + _isSubmitting = true; + }); + + if (mounted) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => const AppLazyLoading(), + ); + } + + final request = SignUpRequestModel( + companyCode: _selectedCompany?.code, + groupCode: _selectedGroup?.code, + employeeId: _isHMGGroup ? _employeeIdController.text : null, + fullName: _fullNameController.text, + email: _emailController.text, + mobileNumber: _mobileController.text, + extensionNumber: _extensionController.text.isEmpty ? null : _extensionController.text, + siteId: _selectedSite?.id?.toInt(), + departmentId: _selectedDepartment?.id, + role: _roleController.text, + ); + + final success = await _signUpProvider.submitSignUpRequest(request); + + if (mounted) { + Navigator.pop(context); // Close loading dialog + } + + setState(() { + _isSubmitting = false; + }); + + if (success) { + if (mounted) { + _showSuccessDialog(); + } + } else { + Fluttertoast.showToast( + msg: _signUpProvider.errorMessage ?? "Failed to submit signup request", + ); + } + } + + void _showSuccessDialog() { + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: AppColor.background(context), + title: "Success".bodyText(context), + content: "Your signup request has been submitted successfully. It will be reviewed by the Human Resources Admin." + .bodyText(context), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); // Close dialog + Navigator.pop(context); // Go back to login + }, + child: "OK".bodyText(context).custom(color: AppColor.primary10), + ), + ], + ), + ); + } +} diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 1c6a83bd..7e3f88c2 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -15,6 +15,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/new_models/general_response_model.dart'; import 'package:test_sa/modules/cx_module/chat/chat_page.dart'; import 'package:test_sa/modules/cx_module/survey/survey_page.dart'; +import 'package:test_sa/modules/signup/screens/signup_screen.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/forget_password_module/forget_passwod_verify_otp.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; @@ -227,6 +228,16 @@ class _LoginPageState extends State { ), 16.height, AppFilledButton(label: context.translation.signIn, buttonColor: AppColor.primary10, maxWidth: true, onPressed: _login), + 16.height, + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + "Don't have an account? ".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50), + "Sign Up".bodyText(context).custom(color: AppColor.primary10, fontWeight: FontWeight.w600).onPress(() { + Navigator.pushNamed(context, SignUpScreen.routeName); + }), + ], + ), ], ), ),