Asset-Borrowing-App / lib / Project / LoginPage / register.dart
register.dart
Raw
// 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),
    ),
  );
}