333 lines
11 KiB
Dart
333 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:taxglide/consts/app_asstes.dart';
|
|
import 'package:taxglide/consts/app_colors.dart';
|
|
import 'package:taxglide/consts/comman_button.dart';
|
|
import 'package:taxglide/consts/comman_container_auth.dart';
|
|
import 'package:taxglide/consts/comman_textformfileds.dart';
|
|
import 'package:taxglide/consts/validation_popup.dart';
|
|
import 'package:taxglide/controller/api_contoller.dart';
|
|
import 'package:taxglide/router/consts_routers.dart';
|
|
import 'package:taxglide/consts/app_style.dart';
|
|
|
|
class SignupScreen extends ConsumerStatefulWidget {
|
|
const SignupScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<SignupScreen> createState() => _SignupScreenState();
|
|
}
|
|
|
|
class _SignupScreenState extends ConsumerState<SignupScreen> {
|
|
final ValidationPopup _validationPopup = ValidationPopup();
|
|
|
|
final TextEditingController _nameController = TextEditingController();
|
|
final TextEditingController _mobileController = TextEditingController();
|
|
final TextEditingController _emailController = TextEditingController();
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// Get arguments from navigation if available
|
|
final args = Get.arguments;
|
|
if (args != null && args is Map<String, dynamic>) {
|
|
_nameController.text = args['name'] ?? '';
|
|
_emailController.text = args['email'] ?? '';
|
|
_mobileController.text = args['mobile'] ?? '';
|
|
}
|
|
}
|
|
|
|
// Error state tracking
|
|
bool _nameError = false;
|
|
bool _mobileError = false;
|
|
bool _emailError = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Listen to signup state
|
|
final signupState = ref.watch(signupProvider);
|
|
|
|
// Handle API response
|
|
ref.listen<AsyncValue<Map<String, dynamic>>>(signupProvider, (
|
|
previous,
|
|
next,
|
|
) {
|
|
next.when(
|
|
data: (response) {
|
|
if (response.isNotEmpty) {
|
|
if (response['success'] == true) {
|
|
_validationPopup.showSuccessMessage(
|
|
context,
|
|
"Sign up successful! OTP sent to your mobile.",
|
|
);
|
|
|
|
// Navigate to RegisterOtpScreen with all data
|
|
Future.delayed(const Duration(milliseconds: 500), () {
|
|
Get.toNamed(
|
|
ConstRouters.registerOtp,
|
|
arguments: {
|
|
'name': _nameController.text,
|
|
'email': _emailController.text,
|
|
'mobile': _mobileController.text,
|
|
},
|
|
);
|
|
});
|
|
} else {
|
|
_validationPopup.showErrorMessage(
|
|
context,
|
|
response['error'] ?? 'Signup failed',
|
|
);
|
|
}
|
|
}
|
|
},
|
|
error: (error, stackTrace) {
|
|
_validationPopup.showErrorMessage(
|
|
context,
|
|
'An error occurred: ${error.toString()}',
|
|
);
|
|
},
|
|
loading: () {},
|
|
);
|
|
});
|
|
|
|
return PopScope(
|
|
canPop: false,
|
|
onPopInvokedWithResult: (didPop, result) {
|
|
if (didPop) return;
|
|
Get.offAllNamed(ConstRouters.login);
|
|
},
|
|
child: Scaffold(
|
|
body: Stack(
|
|
children: [
|
|
// 🌈 Background gradient
|
|
Container(
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [
|
|
Color(0xFFFFF8F0),
|
|
Color(0xFFEBC894),
|
|
Color(0xFFE8DAF2),
|
|
Color(0xFFB49EF4),
|
|
],
|
|
stops: [0.0, 0.3, 0.6, 1.0],
|
|
),
|
|
),
|
|
),
|
|
|
|
// 📜 Scrollable content
|
|
SingleChildScrollView(
|
|
child: SizedBox(
|
|
height: MediaQuery.of(context).size.height,
|
|
child: Center(
|
|
child: CommonContainerAuth(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Image.asset(
|
|
AppAssets.taxgildelogoauth,
|
|
width: 141,
|
|
height: 100,
|
|
fit: BoxFit.contain,
|
|
),
|
|
const SizedBox(height: 20),
|
|
|
|
// 🟣 Title
|
|
Text(
|
|
"Sign Up",
|
|
textAlign: TextAlign.center,
|
|
style: AppTextStyles.semiBold.copyWith(
|
|
fontSize: 32,
|
|
height: 1.3,
|
|
letterSpacing: 0.01 * 32,
|
|
color: AppColors.authheading,
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 25),
|
|
|
|
// 👤 Name Field
|
|
Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
"Name*",
|
|
style: AppTextStyles.semiBold.copyWith(
|
|
fontSize: 14,
|
|
color: AppColors.authheading,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
CommanTextFormField(
|
|
hintText: 'Enter Company Name',
|
|
controller: _nameController,
|
|
hasError: _nameError,
|
|
onChanged: (value) {
|
|
if (_nameError && value.isNotEmpty) {
|
|
setState(() {
|
|
_nameError = false;
|
|
});
|
|
}
|
|
},
|
|
),
|
|
|
|
const SizedBox(height: 10),
|
|
|
|
// 📱 Mobile Number Field
|
|
Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
"Contact Number *",
|
|
style: AppTextStyles.semiBold.copyWith(
|
|
fontSize: 14,
|
|
color: AppColors.authheading,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
CommanTextFormField(
|
|
hintText: 'Enter Contact Number',
|
|
controller: _mobileController,
|
|
hasError: _mobileError,
|
|
keyboardType: TextInputType.phone,
|
|
onChanged: (value) {
|
|
if (_mobileError && value.isNotEmpty) {
|
|
setState(() {
|
|
_mobileError = false;
|
|
});
|
|
}
|
|
},
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
// 📧 Email Field
|
|
Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
"Email *",
|
|
style: AppTextStyles.semiBold.copyWith(
|
|
fontSize: 14,
|
|
color: AppColors.authheading,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
|
|
CommanTextFormField(
|
|
hintText: 'Enter Email ID',
|
|
controller: _emailController,
|
|
hasError: _emailError,
|
|
keyboardType: TextInputType.emailAddress,
|
|
onChanged: (value) {
|
|
if (_emailError && value.isNotEmpty) {
|
|
setState(() {
|
|
_emailError = false;
|
|
});
|
|
}
|
|
},
|
|
),
|
|
const SizedBox(height: 30),
|
|
|
|
// ✅ Submit Button
|
|
signupState.isLoading
|
|
? const CircularProgressIndicator()
|
|
: CommanButton(
|
|
text: "Submit",
|
|
onPressed: () {
|
|
_handleSignup();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _handleSignup() {
|
|
// Reset all errors first
|
|
setState(() {
|
|
_nameError = false;
|
|
_mobileError = false;
|
|
_emailError = false;
|
|
});
|
|
|
|
bool hasError = false;
|
|
|
|
// Validate name
|
|
if (_nameController.text.isEmpty) {
|
|
setState(() {
|
|
_nameError = true;
|
|
});
|
|
hasError = true;
|
|
}
|
|
|
|
// Validate mobile
|
|
if (_mobileController.text.isEmpty) {
|
|
setState(() {
|
|
_mobileError = true;
|
|
});
|
|
hasError = true;
|
|
} else if (!_validationPopup.validateMobileNumber(
|
|
context,
|
|
_mobileController.text,
|
|
)) {
|
|
setState(() {
|
|
_mobileError = true;
|
|
});
|
|
hasError = true;
|
|
}
|
|
|
|
// Validate email - NOW WITH FORMAT CHECK
|
|
if (_emailController.text.isEmpty) {
|
|
setState(() {
|
|
_emailError = true;
|
|
});
|
|
hasError = true;
|
|
} else if (!_validationPopup.validateEmail(
|
|
context,
|
|
_emailController.text,
|
|
)) {
|
|
setState(() {
|
|
_emailError = true;
|
|
});
|
|
hasError = true;
|
|
}
|
|
|
|
// Show error message if any field has error
|
|
if (hasError) {
|
|
_validationPopup.showErrorMessage(
|
|
context,
|
|
"Please fill all required fields correctly",
|
|
);
|
|
return;
|
|
}
|
|
|
|
// All validations passed - call API
|
|
ref
|
|
.read(signupProvider.notifier)
|
|
.signup(
|
|
_nameController.text,
|
|
_mobileController.text,
|
|
_emailController.text,
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_nameController.dispose();
|
|
_mobileController.dispose();
|
|
_emailController.dispose();
|
|
super.dispose();
|
|
}
|
|
}
|