import 'package:flutter/material.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:provider/provider.dart'; import 'package:dropdown_search/dropdown_search.dart'; import 'package:environment_monitoring_app/services/api_service.dart'; import 'package:environment_monitoring_app/auth_provider.dart'; class RegisterScreen extends StatefulWidget { const RegisterScreen({super.key}); @override State createState() => _RegisterScreenState(); } class _RegisterScreenState extends State { final _formKey = GlobalKey(); final ApiService _apiService = ApiService(); bool _isLoading = false; String _errorMessage = ''; // Controllers for text fields final TextEditingController _usernameController = TextEditingController(); final TextEditingController _firstNameController = TextEditingController(); final TextEditingController _lastNameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _confirmPasswordController = TextEditingController(); final TextEditingController _phoneController = TextEditingController(); // State for dropdown selections int? _selectedDepartmentId; int? _selectedCompanyId; int? _selectedPositionId; @override void dispose() { _usernameController.dispose(); _firstNameController.dispose(); _lastNameController.dispose(); _emailController.dispose(); _passwordController.dispose(); _confirmPasswordController.dispose(); _phoneController.dispose(); super.dispose(); } Future _register() async { if (!_formKey.currentState!.validate()) { return; } setState(() { _isLoading = true; _errorMessage = ''; }); final connectivityResult = await Connectivity().checkConnectivity(); if (connectivityResult == ConnectivityResult.none) { if (!mounted) return; setState(() { _isLoading = false; _errorMessage = 'An internet connection is required to register.'; }); _showSnackBar(_errorMessage, isError: true); return; } final result = await _apiService.register( username: _usernameController.text.trim(), firstName: _firstNameController.text.trim(), lastName: _lastNameController.text.trim(), email: _emailController.text.trim(), password: _passwordController.text.trim(), phoneNumber: _phoneController.text.trim(), departmentId: _selectedDepartmentId, companyId: _selectedCompanyId, positionId: _selectedPositionId, ); if (!mounted) return; if (result['success'] == true) { _showSnackBar('Registration successful! Please log in.', isError: false); Navigator.of(context).pop(); } else { setState(() { _isLoading = false; _errorMessage = result['message'] ?? 'An unknown registration error occurred.'; }); _showSnackBar(_errorMessage, isError: true); } } void _showSnackBar(String message, {bool isError = false}) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: isError ? Theme.of(context).colorScheme.error : Colors.green, ), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Register')), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), // Use a Consumer to rebuild the form when the provider's data changes child: Consumer( builder: (context, auth, child) { // Access the cached data from the listening AuthProvider final departments = auth.departments ?? []; final companies = auth.companies ?? []; final positions = auth.positions ?? []; return Form( key: _formKey, child: Column( children: [ TextFormField( controller: _usernameController, decoration: const InputDecoration(labelText: 'Username *'), validator: (value) => value!.isEmpty ? 'Username is required' : null, ), const SizedBox(height: 16), TextFormField( controller: _firstNameController, decoration: const InputDecoration(labelText: 'First Name'), ), const SizedBox(height: 16), TextFormField( controller: _lastNameController, decoration: const InputDecoration(labelText: 'Last Name'), ), const SizedBox(height: 16), TextFormField( controller: _emailController, decoration: const InputDecoration(labelText: 'Email *'), keyboardType: TextInputType.emailAddress, validator: (value) { if (value == null || value.isEmpty) return 'Email is required'; if (!RegExp(r'\S+@\S+\.\S+').hasMatch(value)) return 'Please enter a valid email'; return null; }, ), const SizedBox(height: 16), TextFormField( controller: _passwordController, decoration: const InputDecoration(labelText: 'Password *'), obscureText: true, validator: (value) => (value?.length ?? 0) < 6 ? 'Password must be at least 6 characters' : null, ), const SizedBox(height: 16), TextFormField( controller: _confirmPasswordController, decoration: const InputDecoration(labelText: 'Confirm Password *'), obscureText: true, validator: (value) { if (value != _passwordController.text) return 'Passwords do not match'; return null; }, ), const SizedBox(height: 16), TextFormField( controller: _phoneController, decoration: const InputDecoration(labelText: 'Phone Number'), keyboardType: TextInputType.phone, ), const SizedBox(height: 16), DropdownSearch>( items: departments, itemAsString: (item) => item['department_name'], onChanged: (value) => setState(() => _selectedDepartmentId = value?['department_id']), popupProps: const PopupProps.menu(showSearchBox: true), dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Department")), ), const SizedBox(height: 16), DropdownSearch>( items: companies, itemAsString: (item) => item['company_name'], onChanged: (value) => setState(() => _selectedCompanyId = value?['company_id']), popupProps: const PopupProps.menu(showSearchBox: true), dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Company")), ), const SizedBox(height: 16), DropdownSearch>( items: positions, itemAsString: (item) => item['position_name'], onChanged: (value) => setState(() => _selectedPositionId = value?['position_id']), popupProps: const PopupProps.menu(showSearchBox: true), dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Position")), ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator() : ElevatedButton( onPressed: _register, style: ElevatedButton.styleFrom( minimumSize: const Size(double.infinity, 50), ), child: const Text('Register'), ), if (_errorMessage.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 12), child: Text( _errorMessage, style: TextStyle(color: Theme.of(context).colorScheme.error), textAlign: TextAlign.center, ), ), ], ), ); }, ), ), ); } }