// ignore_for_file: prefer_const_constructors, library_private_types_in_public_api
import 'package:auth_buttons/auth_buttons.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_application_1/Project/LoginPage/login_project.dart';
import 'package:flutter_application_1/Project/utils/colors.dart';
import 'package:string_validator/string_validator.dart';
bool _obscureText = true;
bool isLoading = false;
String? _selectedSchool;
class SignupProject extends StatefulWidget {
const SignupProject({Key? key}) : super(key: key);
@override
_SignupProjectState createState() => _SignupProjectState();
}
class _SignupProjectState extends State<SignupProject> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late String _email, _password;
late String _firstName, _lastName, _phone, _studentID, _school;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(36),
child: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: Colors.black,
onPressed: () {
// Clear the selected school
setState(() {
_selectedSchool = null;
_firstName = '';
_lastName = '';
_email = '';
_school = '';
_password = '';
_phone = '';
_studentID = '';
});
// Navigate back to the previous screen
Navigator.of(context).pop();
},
),
title: Column(
children: const [
Center(
child: Text(
'Create Account',
style: TextStyle(
color: kBackgroundColor,
fontSize: 18,
fontWeight: FontWeight.w700),
),
),
],
),
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.more_vert),
)
],
),
),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: ListView(
scrollDirection: Axis.vertical,
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Create Account',
style: TextStyle(
color: kBackgroundColor,
fontSize: 35,
fontWeight: FontWeight.w500),
),
RichText(
text: TextSpan(
text:
'Enter your name email and password \nfor sign up. ',
style: TextStyle(
height: 1.3,
color: Color(0xff868686),
fontSize: 13,
fontWeight: FontWeight.w400,
),
children: const <TextSpan>[
TextSpan(
text: 'Already have an account? ',
style: TextStyle(
color: kGreenColor,
fontWeight: FontWeight.w400,
),
),
],
),
),
SizedBox(height: 15),
TextFormField(
// First name
keyboardType: TextInputType.name,
textCapitalization: TextCapitalization.words,
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your first name';
} else if (!isAlpha(value)) {
return 'Only Letters Please';
}
return null;
},
onSaved: (value) => _firstName = value!.trim(),
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'First Name',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
SizedBox(height: 10),
TextFormField(
// Last name
keyboardType: TextInputType.name,
textCapitalization: TextCapitalization.words,
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your last name';
} else if (!isAlpha(value)) {
return 'Only Letters Please';
}
return null;
},
onSaved: (input) => _lastName = input!.trim(),
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'Last Name',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
SizedBox(height: 10),
TextFormField(
// student ID
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(10)
],
validator: (value) {
if (value!.isEmpty) {
return 'Please enter your Student ID';
} else if (isAlpha(value)) {
return 'Only Numbers Please';
} else if (value.length < 10) {
return 'Please enter a VALID Student ID';
}
return null;
},
onSaved: (input) => _studentID = input!,
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'Student ID',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
SizedBox(height: 10),
DropdownButtonFormField<String>(
value: _selectedSchool,
onChanged: (String? newValue) {
setState(() {
_selectedSchool = newValue;
});
},
items: const [
DropdownMenuItem(
value: 'School of Liberal Arts',
child: Text('School of Liberal Arts'),
),
DropdownMenuItem(
value: 'School of Science',
child: Text('School of Science'),
),
DropdownMenuItem(
value: 'School of Management',
child: Text('School of Management'),
),
DropdownMenuItem(
value: 'School of Information Technology',
child: Text('School of Information Technology'),
),
DropdownMenuItem(
value: 'School of Agro-Industry',
child: Text('School of Agro-Industry'),
),
DropdownMenuItem(
value: 'School of Law',
child: Text('School of Law'),
),
DropdownMenuItem(
value: 'School of Cosmetic Science',
child: Text('School of Cosmetic Science'),
),
DropdownMenuItem(
value: 'School of Health Sciences',
child: Text('School of Health Sciences'),
),
DropdownMenuItem(
value: 'School of Nursing',
child: Text('School of Nursing'),
),
DropdownMenuItem(
value: 'School of Anti-Aging Medicine',
child: Text('School of Anti-Aging Medicine'),
),
DropdownMenuItem(
value: 'School of Medicine',
child: Text('School of Medicine'),
),
DropdownMenuItem(
value: 'School of Dentistry',
child: Text('School of Dentistry'),
),
DropdownMenuItem(
value: 'dental clinic School of Dentistry',
child: Text('dental clinic School of Dentistry'),
),
DropdownMenuItem(
value: 'School of Social Innovation',
child: Text('School of Social Innovation'),
),
DropdownMenuItem(
value: 'School of Chinese Sciences',
child: Text('School of Chinese Sciences'),
),
DropdownMenuItem(
value: 'School of Integrative Medicine',
child: Text('School of Integrative Medicine'),
),
],
onSaved: (input) => _school = input!,
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'School of',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Select your school';
}
return null;
},
),
SizedBox(height: 10),
TextFormField(
// Phone number
keyboardType: TextInputType.phone,
textInputAction: TextInputAction.next,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(9)
],
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your phone number';
} else if (isAlpha(value)) {
return 'Only Numbers Please';
} else if (value.length < 9) {
return 'Please enter a VALID phone number';
}
return null;
},
onSaved: (input) => _phone = input!,
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'Phone Number',
prefixText: '(+66) ',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
SizedBox(height: 10),
TextFormField(
// Email
keyboardType: TextInputType.emailAddress,
textCapitalization: TextCapitalization.words,
textInputAction: TextInputAction.next,
validator: (value) {
if (value!.isEmpty) {
return 'Please enter an email address';
} else if (!RegExp(r"^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$")
.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
},
onSaved: (input) => _email = input!.trim(),
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'Email Address',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
),
SizedBox(height: 10),
TextFormField(
textInputAction: TextInputAction.done,
validator: (input) {
if (input!.length < 8) {
return 'Your password needs to be at least 8 characters';
} else if (input.isEmpty) {
return 'Please enter your password';
}
},
onSaved: (input) => _password = input!.trim(),
decoration: InputDecoration(
isDense: true,
filled: true,
fillColor: Color.fromARGB(246, 246, 246, 246),
contentPadding: EdgeInsets.fromLTRB(14, 18, 14, 10),
labelText: 'Password',
labelStyle: TextStyle(fontSize: 14),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(
color: Color.fromARGB(232, 232, 232, 232),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
suffixIcon: IconButton(
icon: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
),
obscureText: _obscureText,
),
SizedBox(height: 15),
Center(
child: ElevatedButton(
onPressed: signUp,
style: ElevatedButton.styleFrom(
backgroundColor: kGreenColor,
foregroundColor: kWhiteColor,
padding: EdgeInsets.all(13),
minimumSize: Size(350, 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
'REGISTER',
),
),
),
SizedBox(height: 15),
Text(
' By Signing up you agree to our Terms Conditions & Privacy Policy.',
style: TextStyle(
height: 1.3,
color: Color(0xff868686),
fontSize: 13,
fontWeight: FontWeight.w400,
),
textAlign: TextAlign.center,
),
],
),
],
),
),
),
);
}
Future<void> signUp() async {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
try {
UserCredential userCredential =
await _auth.createUserWithEmailAndPassword(
email: _email,
password: _password,
);
// Create a Firestore document for the new user
FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user!.uid)
.set({
'firstName': _firstName,
'lastName': _lastName,
'phone': '+66$_phone',
'studentID': _studentID,
'school': _school,
'email': _email,
'image_url':
'https://firebasestorage.googleapis.com/v0/b/project-tongz-1.appspot.com/o/admin_images%2Fd4c961732ba6ec52c0bbde63c9cb9e5dd6593826ee788080599f68920224e27d.jpg?alt=media&token=c6c0f02a-56d5-47b7-8933-3fa946f4f033',
'uid': userCredential.user!.uid,
'role': 'user',
});
// Clear form fields
_formKey.currentState!.reset();
_firstName = '';
_lastName = '';
_email = '';
_school = '';
_password = '';
_phone = '';
_studentID = '';
// Clear selected school
setState(() {
_selectedSchool = null;
});
// Add user's first and last name to their account
await userCredential.user?.updateDisplayName(
'$_firstName $_lastName $_phone $_studentID $_school');
// Send email verification
await sendEmailVerification(context);
// ignore: use_build_context_synchronously
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const LoginProject()),
);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
debugPrint('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
debugPrint('The account already exists for that email.');
}
} catch (e) {
// ignore: avoid_print
print(e);
}
}
}
//EMAIL VERIFICATION
Future<void> sendEmailVerification(BuildContext context) async {
try {
_auth.currentUser!.sendEmailVerification();
showSnackBar(context, 'Email verification sent!');
} on FirebaseAuthException catch (e) {
showSnackBar(context, e.message!); // Display error message
}
}
}
void showSnackBar(BuildContext context, String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(text),
),
);
}