00917397380066 project@truinfosys.com

Screen 5:

(Add members.dart)

Screen description:

Code:

import ‘dart:io’;

import ‘package:cloud_firestore/cloud_firestore.dart’;

import ‘package:firebase_auth/firebase_auth.dart’;

import ‘package:flutter/material.dart’;

import ‘package:intl/intl.dart’;

import ‘package:path/path.dart’ as path;

import ‘package:tis_root01/rec.dart’;

import ‘package:tis_root01/common/CommonFooter.dart’;

import ‘package:tis_root01/dash.dart’;

import ‘package:tis_root01/rec.dart’;

import ‘package:tis_root01/view_member.dart’;

import ‘package:firebase_core/firebase_core.dart’;

import ‘package:firebase_database/firebase_database.dart’;

import ‘package:file_picker/file_picker.dart’;

import ‘package:dropdown_button2/dropdown_button2.dart’;

import ‘package:firebase_storage/firebase_storage.dart’ as firebase_storage;

import ‘../common/CommonHeader.dart’;

class Add extends StatefulWidget {

  final User? user; // Add this line

  const Add({Key? key, this.user}) : super(key: key);

  @override

  _AddState createState() => _AddState();

}

class _AddState extends State<Add> {

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final DatabaseReference _database = FirebaseDatabase.instance.reference();

  String? otpCode;

  User? user;

  TextEditingController phoneController = TextEditingController();

  FirebaseFirestore _firestore = FirebaseFirestore.instance;

  String verificationId = ”;

  TextEditingController otpController = TextEditingController();

  String selectedValue_mem = ”;

  String? selectedValue_state;

  String? selectedValue_district;

  String? selectedValue_gen;

  final TextEditingController textEditingController_1 = TextEditingController();

  final TextEditingController textEditingController_2 = TextEditingController();

  FirebaseAuth auth = FirebaseAuth.instance;

  bool otpVisibility = false;

  String verificationID = “”;

  String _textField1 = ”;

  String _textField2 = ”;

  String _textField3 = ”;

  String _textField4 = ”;

  String _textField5 = ”;

  String _textField6 = ”;

  File? _selectedFile;

  String _selectedFilePath = ”; // Add this line

  DateTime _selectedDate = DateTime.now();

  // ignore: prefer_final_fields

  List<String> _states = [‘TamilNadu’, ‘Others’];

  List<String> _District = [

    ‘Ariyalur’,

    ‘Chengalpattu’,

    ‘Chennai’,

    ‘Coimbatore’,

    ‘Cuddalore’,

    ‘Dharmapuri’,

    ‘Dindigul’,

    ‘Erode’,

    ‘Kallakurichi’,

    ‘Kanchipuram’,

    ‘Kanyakumari’,

    ‘Karur’,

    ‘Krishnagiri’,

    ‘Madurai’,

    ‘Nagapattinam’,

    ‘Namakkal’,

    ‘Nilgiris’,

    ‘Perambalur’,

    ‘Pudukkottai’,

    ‘Ramanathapuram’,

    ‘Ranipet’,

    ‘Salem’,

    ‘Sivaganga’,

    ‘Tenkasi’,

    ‘Thanjavur’,

    ‘Theni’,

    ‘Thoothukudi’,

    ‘Tiruchirappalli’,

    ‘Tirunelveli’,

    ‘Tirupathur’,

    ‘Tiruppur’,

    ‘Tiruvallur’,

    ‘Tiruvannamalai’,

    ‘Tiruvarur’,

    ‘Vellore’,

    ‘Viluppuram’,

    ‘ Virudhunagar’

  ];

  List<String> _gender = [‘Male’, ‘Female’, ‘Transgender’];

  List<String> _member = [

    ‘Ordinary(no fees)’,

    ‘Life(Rs.110)’,

    ‘Hereditary(Rs.560)’,

    ‘Olikkum Yadavar Murasu(annual/Rs.120)’,

        ‘Olikkum Yadavar Murasu(5 years/Rs.600)’

  ];

  //List<String> _dropdownOptions2 = [‘Choice A’, ‘Choice B’, ‘Choice C’];

  //List<String> _dropdownOptions3 = [‘Item X’, ‘Item Y’, ‘Item Z’];

// Inside your _pickFile() method

  Future<void> _pickFile() async {

    FilePickerResult? result = await FilePicker.platform.pickFiles();

    if (result != null) {

      String? filePath = result.files.single?.path;

      String? fileName = filePath != null ? path.basename(filePath) : null;

      if (fileName != null) {

        setState(() {

          _selectedFile = File(filePath!);

          _selectedFilePath = fileName; // Store the selected file name

        });

      }

    }

  }

  Future<String?> _uploadFile(File file) async {

    try {

      final fileName = path.basename(file.path); // Get the file name

      final storageRef = firebase_storage.FirebaseStorage.instance

          .ref()

          .child(‘$_textField1/$fileName’);

      final uploadTask = storageRef.putFile(file);

      // Wait for the upload to complete and get the download URL

      final snapshot = await uploadTask.whenComplete(() {});

      final downloadURL = await snapshot.ref.getDownloadURL();

      return downloadURL;

    } catch (e) {

      print(“File upload error: $e”);

      return null;

    }

  }

  Future<void> _submitForm() async {

    if (_formKey.currentState!.validate()) {

      _formKey.currentState!.save();

      try {

        final downloadURL = await _uploadFile(_selectedFile!);

        // Get the user’s phone number from the controller

        final userPhoneNumber = “+91” + phoneController.text;

        double amount = 0.0;

        String formattedDate = DateFormat(‘HH:mm’).format(_selectedDate);

        // Reference to the Firestore document based on phone number

        //final userDocRef =FirebaseFirestore.instance.doc(“users/$userPhoneNumber”);

        // Save data to Firebase

        FirebaseFirestore.instance.collection(‘YP_Community’).add({

          ‘Member’: selectedValue_mem,

          ‘Name’: _textField1,

          ‘Age’: _textField2,

          ‘Date’: formattedDate,

          ‘Gender’: selectedValue_gen,

          ‘Educational Qualification’: _textField3,

          ‘occupation’: _textField4,

          ‘Phone_no’: phoneController.text,

          ‘Address’: _textField5,

          ‘Email ID’: _textField6,

          ‘State’: selectedValue_state,

          ‘City’: selectedValue_district,

          ‘fleAttachmentURL’: downloadURL,

        });

        if (_selectedFile != null) {

          await _uploadFile(_selectedFile!); // Use the selected File object

        }

        ScaffoldMessenger.of(context).showSnackBar(

          SnackBar(content: Text(‘Data saved ‘)),

        );

        if (selectedValue_mem == ‘Ordinary(no fees)’) {

          amount = 0.0; // Set the amount for Member A

        } else if (selectedValue_mem == ‘Life(Rs.110)’) {

          amount = 110.0; // Set the amount for Member B

        } else if (selectedValue_mem == ‘Hereditary(Rs.560)’) {

          // Note the correct case here

          amount = 560.0; // Set the amount for Member C

        } else if (selectedValue_mem ==

            ‘Olikkum Yadavar Murasu(annual/Rs.120)’) {

          amount = 120.0; // Set a default amount for other cases

        } else {

          amount = 600.0;

        }

        final receiptData = ReceiptData(

            address: _textField5,

            amount: amount,

            date:formattedDate,

            membershipType: selectedValue_mem,

            name: _textField1,

            phoneNo:phoneController.text, // You can set the initial amount paid here

            );

        Navigator.push(

          context,

          MaterialPageRoute(

            builder: (context) => ReceiptScreen(data: receiptData),

          ),

        );

        //Navigator.push(context, MaterialPageRoute(builder: (context) => ReceiptScreen()));

      } catch (e) {

        // Handle exceptions

        if (e is FirebaseException) {

          print(“Firebase Exception: ${e.message}”);

          // Handle the exception according to your needs, such as showing an error message to the user.

        } else {

          // Handle other types of exceptions if necessary.

          print(“Unknown Exception: $e”);

        }

      }

    }

  }

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: PreferredSize(

        preferredSize: const Size.fromHeight(80.0),

        child: Container(

          decoration: const BoxDecoration(

            gradient: LinearGradient(

              colors: <Color>[Colors.blue, Color.fromRGBO(233, 30, 99, 1)],

            ),

          ),

          child: const CommonHeader(),

        ),

      ),

      body: SingleChildScrollView(

        child: Padding(

          padding: const EdgeInsets.all(16.0),

          child: Form(

            key: _formKey,

            child: Column(

              children: [

                const SizedBox(height: 30),

                DropdownButtonFormField2<String>(

                  isExpanded: true,

                  decoration: InputDecoration(

                    // Add Horizontal padding using menuItemStyleData.padding so it matches

                    // the menu padding when button’s width is not specified.

                    contentPadding: const EdgeInsets.symmetric(vertical: 16),

                    border: OutlineInputBorder(

                      borderRadius: BorderRadius.circular(15),

                    ),

                    // Add more decoration..

                  ),

                  hint: const Text(

                    ‘Membership Fee’,

                    style: TextStyle(fontSize: 14),

                  ),

                  items: _member

                      .map((item) => DropdownMenuItem<String>(

                            value: item,

                            child: Text(

                              item,

                              style: const TextStyle(

                                fontSize: 14,

                              ),

                            ),

                          ))

                      .toList(),

                  validator: (value) {

                    if (value == null) {

                      return ‘Please select Member.’;

                    }

                    return null;

                  },

                  onChanged: (value) {

                    //Do something when selected item is changed.

                  },

                  onSaved: (value) {

                    selectedValue_mem = value.toString();

                  },

                  buttonStyleData: const ButtonStyleData(

                    padding: EdgeInsets.only(right: 8),

                  ),

                  iconStyleData: const IconStyleData(

                    icon: Icon(

                      Icons.arrow_drop_down,

                      color: Colors.black45,

                    ),

                    iconSize: 24,

                  ),

                  dropdownStyleData: DropdownStyleData(

                    decoration: BoxDecoration(

                      borderRadius: BorderRadius.circular(15),

                    ),

                  ),

                  menuItemStyleData: const MenuItemStyleData(

                    padding: EdgeInsets.symmetric(horizontal: 16),

                  ),

                ),

                TextFormField(

                  decoration: InputDecoration(labelText: ‘Name’),

                  onSaved: (value) => _textField1 = value!,

                ),

                TextFormField(

                  decoration: InputDecoration(labelText: ‘Age’),

                  onSaved: (value) => _textField2 = value!,

                ),

                TextFormField(

                  decoration: InputDecoration(labelText: ‘Date of Birth’),

                  readOnly: true,

                  onTap: () async {

                    final selectedDate = await showDatePicker(

                      context: context,

                      initialDate: _selectedDate,

                      firstDate: DateTime(1900),

                      lastDate: DateTime.now(),

                    );

                    if (selectedDate != null && selectedDate != _selectedDate) {

                      setState(() {

                        _selectedDate = selectedDate;

                      });

                    }

                  },

                  controller: TextEditingController(

                    text: “${_selectedDate.toLocal()}”.split(‘ ‘)[0],

                  ),

                ),

                const SizedBox(height: 30),

                DropdownButtonFormField2<String>(

                  isExpanded: true,

                  decoration: InputDecoration(

                    // Add Horizontal padding using menuItemStyleData.padding so it matches

                    // the menu padding when button’s width is not specified.

                    contentPadding: const EdgeInsets.symmetric(vertical: 16),

                    border: OutlineInputBorder(

                      borderRadius: BorderRadius.circular(15),

                    ),

                    // Add more decoration..

                  ),

                  hint: const Text(

                    ‘Select Gender’,

                    style: TextStyle(fontSize: 14),

                  ),

                  items: _gender

                      .map((item) => DropdownMenuItem<String>(

                            value: item,

                            child: Text(

                              item,

                              style: const TextStyle(

                                fontSize: 14,

                              ),

                            ),

                          ))

                      .toList(),

                  validator: (value) {

                    if (value == null) {

                      return ‘Please select Gender.’;

                    }

                    return null;

                  },

                  onChanged: (value) {

                    //Do something when selected item is changed.

                  },

                  onSaved: (value) {

                    selectedValue_gen = value.toString();

                  },

                  buttonStyleData: const ButtonStyleData(

                    padding: EdgeInsets.only(right: 8),

                  ),

                  iconStyleData: const IconStyleData(

                    icon: Icon(

                      Icons.arrow_drop_down,

                      color: Colors.black45,

                    ),

                    iconSize: 24,

                  ),

                  dropdownStyleData: DropdownStyleData(

                    decoration: BoxDecoration(

                      borderRadius: BorderRadius.circular(15),

                    ),

                  ),

                  menuItemStyleData: const MenuItemStyleData(

                    padding: EdgeInsets.symmetric(horizontal: 16),

                  ),

                ),

                TextFormField(

                  decoration:

                      InputDecoration(labelText: ‘Educational Qualification’),

                  onSaved: (value) => _textField3 = value!,

                ),

                TextFormField(

                  decoration: InputDecoration(labelText: ‘Occupation’),

                  onSaved: (value) => _textField4 = value!,

                ),

                TextFormField(

                  controller: phoneController,

                  decoration: InputDecoration(

                    labelText: ‘Phone Number’,

                    prefix: Padding(

                      padding: EdgeInsets.all(4),

                      child: Text(‘+91’),

                    ),

                  ),

                  maxLength: 10,

                  keyboardType: TextInputType.phone,

                ),

                Visibility(

                  child: TextField(

                    controller: otpController,

                    decoration: InputDecoration(

                      hintText: ‘OTP’,

                      prefix: Padding(

                        padding: EdgeInsets.all(4),

                        child: Text(”),

                      ),

                    ),

                    maxLength: 6,

                    keyboardType: TextInputType.number,

                  ),

                  visible: otpVisibility,

                ),

                SizedBox(

                  height: 5,

                  width: 10,

                ),

                Visibility(

                  // Set visible property based on otpVisibility

                  //visible: otpVisibility,

                  child: MaterialButton(

                    color: Colors.indigo[900],

                    minWidth: 20,

                    onPressed: () {

                      if (otpVisibility) {

                        verifyOTP();

                      } else {

                        loginWithPhone();

                      }

                    },

                    child: Text(

                      otpVisibility ? “Verify” : “OTP”,

                      style: TextStyle(

                        color: Colors.white,

                        fontSize: 20,

                      ),

                    ),

                  ),

                ),

                Container(

                  child: TextFormField(

                    decoration: InputDecoration(labelText: ‘Address ‘),

                    onSaved: (value) => _textField5 = value!,

                  ),

                ),

                TextFormField(

                  decoration: InputDecoration(labelText: ‘Email’),

                  onSaved: (value) => _textField6 = value!,

                ),

                DropdownButtonHideUnderline(

                  child: DropdownButton2<String>(

                    isExpanded: true,

                    hint: Text(

                      ‘Select State’,

                      style: TextStyle(

                        fontSize: 14,

                        color: Theme.of(context).hintColor,

                      ),

                    ),

                    items: _states

                        .map((item) => DropdownMenuItem(

                              value: item,

                              child: Text(

                                item,

                                style: const TextStyle(

                                  fontSize: 14,

                                ),

                              ),

                            ))

                        .toList(),

                    value: selectedValue_state,

                    onChanged: (value) {

                      setState(() {

                        selectedValue_state = value;

                      });

                    },

                    buttonStyleData: const ButtonStyleData(

                      padding: EdgeInsets.symmetric(),

                      height: 40,

                      width: 350,

                    ),

                    dropdownStyleData: const DropdownStyleData(

                      maxHeight: 200,

                    ),

                    menuItemStyleData: const MenuItemStyleData(

                      height: 40,

                    ),

                    dropdownSearchData: DropdownSearchData(

                      searchController: textEditingController_1,

                      searchInnerWidgetHeight: 50,

                      searchInnerWidget: Container(

                        height: 50,

                        padding: const EdgeInsets.only(

                          top: 8,

                          bottom: 4,

                          right: 8,

                          left: 8,

                        ),

                        child: TextFormField(

                          expands: true,

                          maxLines: null,

                          controller: textEditingController_1,

                          decoration: InputDecoration(

                            isDense: true,

                            contentPadding: const EdgeInsets.symmetric(

                              horizontal: 10,

                              vertical: 8,

                            ),

                            hintText: ‘Search for State’,

                            hintStyle: const TextStyle(fontSize: 12),

                            border: OutlineInputBorder(

                              borderRadius: BorderRadius.circular(6),

                            ),

                          ),

                        ),

                      ),

                      searchMatchFn: (item, searchValue) {

                        return item.value.toString().contains(searchValue);

                      },

                    ),

                    //This to clear the search value when you close the menu

                    onMenuStateChange: (isOpen) {

                      if (!isOpen) {

                        textEditingController_1.clear();

                      }

                    },

                  ),

                ),

                //district

                DropdownButtonHideUnderline(

                  child: DropdownButton2<String>(

                    alignment: Alignment.centerLeft,

                    isExpanded: true,

                    hint: Text(

                      ‘Select City’,

                      style: TextStyle(

                        fontSize: 14,

                        color: Theme.of(context).hintColor,

                      ),

                    ),

                    items: _District.map((item) => DropdownMenuItem(

                          value: item,

                          child: Text(

                            item,

                            style: const TextStyle(

                              fontSize: 14,

                            ),

                          ),

                        )).toList(),

                    value: selectedValue_district,

                    onChanged: (value) {

                      setState(() {

                        selectedValue_district = value;

                      });

                    },

                    buttonStyleData: const ButtonStyleData(

                      padding: EdgeInsets.symmetric(),

                      height: 40,

                      width: 350,

                    ),

                    dropdownStyleData: const DropdownStyleData(

                      maxHeight: 200,

                    ),

                    menuItemStyleData: const MenuItemStyleData(

                      height: 40,

                    ),

                    dropdownSearchData: DropdownSearchData(

                      searchController: textEditingController_2,

                      searchInnerWidgetHeight: 50,

                      searchInnerWidget: Container(

                        height: 50,

                        padding: const EdgeInsets.only(

                          top: 8,

                          bottom: 4,

                          right: 8,

                          left: 8,

                        ),

                        child: TextFormField(

                          expands: true,

                          maxLines: null,

                          controller: textEditingController_2,

                          decoration: InputDecoration(

                            isDense: true,

                            contentPadding: const EdgeInsets.symmetric(

                              horizontal: 10,

                              vertical: 8,

                            ),

                            hintText: ‘Search for City’,

                            hintStyle: const TextStyle(fontSize: 12),

                            border: OutlineInputBorder(

                              borderRadius: BorderRadius.circular(6),

                            ),

                          ),

                        ),

                      ),

                      searchMatchFn: (item, searchValue) {

                        return item.value.toString().contains(searchValue);

                      },

                    ),

                    //This to clear the search value when you close the menu

                    onMenuStateChange: (isOpen) {

                      if (!isOpen) {

                        textEditingController_2.clear();

                      }

                    },

                  ),

                ),

                TextButton(

                  onPressed: _pickFile,

                  child: Text(‘Attach ID proof’),

                ),

                Text(‘Selected File: $_selectedFile’),

                ElevatedButton(

                  onPressed: _submitForm,

                  child: Text(‘ADD MEMBER’),

                ),

              ],

            ),

          ),

        ),

      ),

    );

  }

  void loginWithPhone() async {

    auth.verifyPhoneNumber(

      phoneNumber: “+91” + phoneController.text,

      verificationCompleted: (PhoneAuthCredential credential) async {

        await auth.signInWithCredential(credential).then((value) {

          print(“You are logged in successfully”);

        });

      },

      verificationFailed: (FirebaseAuthException e) {

        print(e.message);

      },

      codeSent: (String verificationId, int? resendToken) {

        otpVisibility = true;

        verificationID = verificationId;

        setState(() {

          //otpVisibility = false;

        });

      },

      codeAutoRetrievalTimeout: (String verificationId) {},

    );

  }

  void verifyOTP() async {

    PhoneAuthCredential credential = PhoneAuthProvider.credential(

        verificationId: verificationID, smsCode: otpController.text);

    await auth.signInWithCredential(credential).then(

      (value) {

        setState(() {

          user = FirebaseAuth.instance.currentUser;

          otpVisibility = false;

          visible:

          false;

        });

      },

    ).whenComplete(() {});

  }

}

Code Description :

# `Add` Class

The `Add` class represents a screen in a Flutter app where users can add new members to a community. It includes various input fields for member details, such as name, age, gender, and more. Additionally, it allows users to upload an ID proof document.

# Constructor

“`dart

const Add({Key? key, this.user}) : super(key: key);

“`

– The `Add` class constructor takes an optional `user` parameter, which represents the authenticated user. This parameter is used to identify the current user in the app.

# State Management

“`dart

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

final DatabaseReference _database = FirebaseDatabase.instance.reference();

String? otpCode;

User? user;

// … (other variable declarations)

“`

– `_formKey` is a global key used to manage the state of the form.

– `_database` is a reference to Firebase Realtime Database for storing data (this can be used later in the code).

– `otpCode` stores the OTP code used for phone number verification.

– `user` stores information about the authenticated user.

– Several `TextEditingController` instances are used to manage text input fields.

– Various lists, such as `_states`, `_District`, `_gender`, and `_member`, store options for dropdown selection.

# File Handling

“`dart

File? _selectedFile;

String _selectedFilePath = ”;

“`

– `_selectedFile` is used to store the selected ID proof file.

– `_selectedFilePath` holds the name of the selected file.

# Date Picker

“`dart

DateTime _selectedDate = DateTime.now();

“`

– `_selectedDate` is used to store the selected date of birth.

# Build Method

“`dart

@override

Widget build(BuildContext context) {

  // … (Widget tree)

}

“`

– The `build` method constructs the UI for the `Add` screen.

#Form

“`dart

Form(

  key: _formKey,

  child: Column(

    children: [

      // … (other form fields)

    ],

  ),

)

“`

– A `Form` widget wraps the input fields, enabling form validation and submission.

#Dropdown Selection Widgets

“`dart

DropdownButtonFormField2<String>(

  // … (dropdown configuration)

)

“`

– Dropdown selection widgets for membership type, gender, state, and district are implemented using `DropdownButtonFormField2`. They allow users to select options from predefined lists.

#Text Input Fields

“`dart

TextFormField(

  decoration: InputDecoration(labelText: ‘Name’),

  onSaved: (value) => _textField1 = value!,

)

“`

– `TextFormField` widgets are used for entering various details like name, age, educational qualification, and more. The `onSaved` callback saves the input value to respective variables.

#Date Picker

“`dart

TextFormField(

  // … (other properties)

  readOnly: true,

  onTap: () async {

    // … (date picker logic)

  },

  controller: TextEditingController(

    text: “${_selectedDate.toLocal()}”.split(‘ ‘)[0],

  ),

)

“`

– A `TextFormField` with a read-only text field is used to display the selected date of birth. When tapped, it opens a date picker dialog.

#File Upload Button

“`dart

TextButton(

  onPressed: _pickFile,

  child: Text(‘Attach ID proof’),

)

“`

– A `TextButton` labeled “Attach ID proof” allows users to pick and upload an ID proof document.

#Submit Button

“`dart

ElevatedButton(

  onPressed: _submitForm,

  child: Text(‘ADD MEMBER’),

)

“`

– An `ElevatedButton` labeled “ADD MEMBER” triggers the `_submitForm` method to validate and submit the form data.

#### Phone Number Verification

“`dart

void loginWithPhone() async {

  // … (phone number verification logic)

}

void verifyOTP() async {

  // … (OTP verification logic)

}

“`

– The `loginWithPhone` method initiates phone number verification using Firebase Authentication.

– The `verifyOTP` method is used to verify the OTP entered by the user.

#Firebase Data Storage

“`dart

Future<void> _uploadFile(File file) async {

  // … (file upload logic)

}

Future<void> _submitForm() async {

  // … (form submission logic)

}

“`

– `_uploadFile` uploads the selected ID proof file to Firebase Storage and returns a download URL.

– `_submitForm` is responsible for validating and submitting the form data to Firebase Firestore. It also includes logic to calculate membership fees and navigate to a receipt screen.

This Flutter screen allows users to add new community members, providing various details and attaching ID proof documents. It integrates Firebase for user authentication, Firestore for data storage, and Firebase Storage for file uploads, making it a comprehensive member registration feature in an app.

Audit: