Debug School

rakesh kumar
rakesh kumar

Posted on • Edited on

Explain the use of Mixins in flutter

Why we use mixins
Application of mixins
Coding example of mixins
Reuse App bar action

Why we use mixins

Mixins in Flutter (and Dart) are a way to reuse a class’s code in multiple class hierarchies. Mixins allow you to add functionality to classes without needing inheritance, making it easier to maintain and reuse code. They are used to encapsulate and share behavior between classes.

Key Points about Mixins

Code Reusability: Mixins allow you to reuse methods and properties in multiple classes.
Avoid Multiple Inheritance: Dart does not support multiple inheritance, but mixins offer a way to achieve similar behavior.
Flexibility: You can mix in multiple mixins into a single class, providing a flexible way to combine functionality.

In other words mixins are normal classes from which we can borrow methods(or variables) from without extending the class. In dart we can do this by

For Java developers, it is a completely new concept to learn as Java does not supports multiple inheritance or mixins. Java tries to make up for this by using Interfaces, but that is not as useful or flexible as mixins.

class B {  //B is not allowed to extend any other class other than object
  method(){
     ....
  }
}

class A with B {
  ....
     ......
}
void main() {
  A a = A();
  a.method();  //we got the method without inheriting B
}
Enter fullscreen mode Exit fullscreen mode

Defining a Mixin

In Dart, a mixin is created using the mixin keyword.

Example: LoggerMixin
Let's define a mixin for logging purposes.

import 'package:logger/logger.dart';

// Define the LoggerMixin
mixin LoggerMixin {
  final Logger _logger = Logger();

  void logInfo(String message) {
    _logger.i(message);
  }

  void logError(String message) {
    _logger.e(message);
  }
}
Enter fullscreen mode Exit fullscreen mode

Using the LoggerMixin
To use the mixin, you simply include it in the class definition using the with keyword.

class MyClass with LoggerMixin {
  final String name;

  MyClass(this.name);

  void doSomething() {
    logInfo('$name is doing something.');
    try {
      // Simulate an error
      int result = 1 ~/ 0;
    } catch (e) {
      logError('Error occurred: $e');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Complete Example in a Flutter App
Let's put everything together and create a simple Flutter app that uses the LoggerMixin.

Step 1: Add Dependencies
Add the logger package to your pubspec.yaml file.

dependencies:
  flutter:
    sdk: flutter
  logger: ^1.0.0
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the LoggerMixin
Create a file logger_mixin.dart and define the LoggerMixin.

// logger_mixin.dart
import 'package:logger/logger.dart';

mixin LoggerMixin {
  final Logger _logger = Logger();

  void logInfo(String message) {
    _logger.i(message);
  }

  void logError(String message) {
    _logger.e(message);
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a Class Using the LoggerMixin
Create a file my_class.dart and define the MyClass which uses the LoggerMixin.

// my_class.dart
import 'logger_mixin.dart';

class MyClass with LoggerMixin {
  final String name;

  MyClass(this.name);

  void doSomething() {
    logInfo('$name is doing something.');
    try {
      // Simulate an error
      int result = 1 ~/ 0;
    } catch (e) {
      logError('Error occurred: $e');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Integrate MyClass in Flutter App
Update your main.dart to use MyClass and display the log output.

import 'package:flutter/material.dart';
import 'my_class.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final MyClass myInstance = MyClass('TestInstance');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mixin Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            myInstance.doSomething();
          },
          child: Text('Do Something'),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Explanation

LoggerMixin: This mixin provides logging functionality through logInfo and logError methods.
MyClass: This class uses the LoggerMixin to gain logging capabilities. It logs messages when performing actions and handling errors.
Flutter App: The main Flutter app integrates MyClass and demonstrates how to use the logging functionality. When you press the "Do Something" button, the doSomething method is called, and log messages are printed to the console.
Running the Example
When you run the Flutter app and press the "Do Something" button, you should see log messages in the console, demonstrating the logging functionality added to MyClass via the LoggerMixin.

This example showcases how mixins in Flutter can be used to encapsulate and reuse functionality across different classes, promoting clean and maintainable code.

Application of mixins

LoggerMixin
A mixin to provide logging capabilities.

import 'package:logger/logger.dart';

mixin LoggerMixin {
  final Logger _logger = Logger();

  void logInfo(String message) {
    _logger.i(message);
  }

  void logError(String message) {
    _logger.e(message);
  }
}

class MyClass with LoggerMixin {
  void doSomething() {
    logInfo('Doing something');
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. ValidationMixin A mixin to provide form validation methods.
mixin ValidationMixin {
  bool isValidEmail(String email) {
    return email.contains('@');
  }

  bool isValidPassword(String password) {
    return password.length > 6;
  }
}

class LoginForm with ValidationMixin {
  final String email;
  final String password;

  LoginForm(this.email, this.password);

  bool validate() {
    return isValidEmail(email) && isValidPassword(password);
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. DisposalMixin A mixin to provide a method to dispose resources.
mixin DisposalMixin {
  final List<void Function()> _disposeCallbacks = [];

  void addDisposeCallback(void Function() callback) {
    _disposeCallbacks.add(callback);
  }

  void dispose() {
    for (var callback in _disposeCallbacks) {
      callback();
    }
  }
}

class MyResource with DisposalMixin {
  void initialize() {
    // Initialize resources
    addDisposeCallback(() {
      // Dispose resource
      print('Resource disposed');
    });
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. StateHelperMixin A mixin to provide common state management methods for stateful widgets.
import 'package:flutter/material.dart';

mixin StateHelperMixin<T extends StatefulWidget> on State<T> {
  void showSnackbar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
  }
}

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> with StateHelperMixin<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('State Helper Mixin Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            showSnackbar('Hello, World!');
          },
          child: Text('Show Snackbar'),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. ConnectivityMixin A mixin to check network connectivity.
import 'package:connectivity_plus/connectivity_plus.dart';

mixin ConnectivityMixin {
  final Connectivity _connectivity = Connectivity();

  Future<bool> isConnected() async {
    var connectivityResult = await _connectivity.checkConnectivity();
    return connectivityResult != ConnectivityResult.none;
  }
}

class MyService with ConnectivityMixin {
  Future<void> fetchData() async {
    if (await isConnected()) {
      // Fetch data
      print('Fetching data...');
    } else {
      print('No internet connection');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. NavigationMixin A mixin to provide navigation methods.
import 'package:flutter/material.dart';

mixin NavigationMixin<T extends StatefulWidget> on State<T> {
  void navigateTo(Widget page) {
    Navigator.of(context).push(MaterialPageRoute(builder: (context) => page));
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with NavigationMixin<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Navigation Mixin Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            navigateTo(SecondPage());
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Text('This is the second page'),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. ErrorHandlingMixin A mixin to provide error handling methods.
mixin ErrorHandlingMixin {
  void handleError(dynamic error) {
    print('An error occurred: $error');
  }
}

class MyErrorProneClass with ErrorHandlingMixin {
  void riskyOperation() {
    try {
      // Simulate an error
      throw Exception('Something went wrong');
    } catch (error) {
      handleError(error);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

LifecycleMixin
A mixin to provide lifecycle methods, especially useful for handling logic when widgets are initialized and disposed.

import 'package:flutter/widgets.dart';

mixin LifecycleMixin<T extends StatefulWidget> on State<T> {
  @override
  void initState() {
    super.initState();
    onInit();
  }

  @override
  void dispose() {
    onDispose();
    super.dispose();
  }

  void onInit() {
    // Override this method in the class using this mixin
  }

  void onDispose() {
    // Override this method in the class using this mixin
  }
}

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> with LifecycleMixin<MyStatefulWidget> {
  @override
  void onInit() {
    super.onInit();
    print('Widget Initialized');
  }

  @override
  void onDispose() {
    super.onDispose();
    print('Widget Disposed');
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. CacheMixin A mixin to provide caching capabilities for data.
mixin CacheMixin<T> {
  final Map<String, T> _cache = {};

  void cacheData(String key, T value) {
    _cache[key] = value;
  }

  T? getCachedData(String key) {
    return _cache[key];
  }

  void clearCache() {
    _cache.clear();
  }
}

class DataService with CacheMixin<String> {
  void fetchData() {
    // Fetch and cache data
    cacheData('key1', 'value1');
  }

  String? retrieveData() {
    return getCachedData('key1');
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. AnimationMixin A mixin to provide common animation utilities.
import 'package:flutter/animation.dart';

mixin AnimationMixin<T extends StatefulWidget> on State<T>, SingleTickerProviderStateMixin<T> {
  late AnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..forward();
  }

  @override
  void dispose() {
    animationController.dispose();
    super.dispose();
  }
}

class AnimatedWidgetExample extends StatefulWidget {
  @override
  _AnimatedWidgetExampleState createState() => _AnimatedWidgetExampleState();
}

class _AnimatedWidgetExampleState extends State<AnimatedWidgetExample> with AnimationMixin<AnimatedWidgetExample> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FadeTransition(
          opacity: animationController,
          child: Text('Hello, World!'),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. LocalizationMixin A mixin to provide localization capabilities.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

mixin LocalizationMixin {
  String getTranslatedText(BuildContext context, String key) {
    // Implement your localization logic here
    // For example, using a localization package
    return key;
  }
}

class LocalizedWidget extends StatelessWidget with LocalizationMixin {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(getTranslatedText(context, 'title')),
      ),
      body: Center(
        child: Text(getTranslatedText(context, 'hello_world')),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. ThemeMixin A mixin to provide theme management.
import 'package:flutter/material.dart';

mixin ThemeMixin<T extends StatefulWidget> on State<T> {
  ThemeData get currentTheme => Theme.of(context);

  bool get isDarkMode => currentTheme.brightness == Brightness.dark;
}

class ThemedWidget extends StatefulWidget {
  @override
  _ThemedWidgetState createState() => _ThemedWidgetState();
}

class _ThemedWidgetState extends State<ThemedWidget> with ThemeMixin<ThemedWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Themed Widget'),
      ),
      body: Center(
        child: Text(
          isDarkMode ? 'Dark Mode' : 'Light Mode',
          style: TextStyle(color: isDarkMode ? Colors.white : Colors.black),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. StateManagementMixin A mixin to provide state management utilities.
mixin StateManagementMixin<T extends StatefulWidget> on State<T> {
  bool _isLoading = false;

  bool get isLoading => _isLoading;

  void setLoading(bool loading) {
    setState(() {
      _isLoading = loading;
    });
  }
}

class StateManagedWidget extends StatefulWidget {
  @override
  _StateManagedWidgetState createState() => _StateManagedWidgetState();
}

class _StateManagedWidgetState extends State<StateManagedWidget> with StateManagementMixin<StateManagedWidget> {
  void loadData() async {
    setLoading(true);
    await Future.delayed(Duration(seconds: 2));
    setLoading(false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('State Management Mixin'),
      ),
      body: Center(
        child: isLoading
            ? CircularProgressIndicator()
            : ElevatedButton(
                onPressed: loadData,
                child: Text('Load Data'),
              ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. PermissionMixin A mixin to handle permission requests.
import 'package:permission_handler/permission_handler.dart';

mixin PermissionMixin {
  Future<bool> requestPermission(Permission permission) async {
    final status = await permission.request();
    return status == PermissionStatus.granted;
  }

  Future<bool> checkPermission(Permission permission) async {
    final status = await permission.status;
    return status == PermissionStatus.granted;
  }
}

class PermissionWidget extends StatelessWidget with PermissionMixin {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Permission Mixin Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            if (await requestPermission(Permission.camera)) {
              print('Camera permission granted');
            } else {
              print('Camera permission denied');
            }
          },
          child: Text('Request Camera Permission'),
        ),
      ),
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

Coding example of mixins

save the data using flutter secure storage dependency

  final secureStorage = FlutterSecureStorage();
     await secureStorage.write(key: 'orgRoleId', value: orgRoleId.toString()); // Save orgRoleId
Enter fullscreen mode Exit fullscreen mode

Image description

Get data using flutter secure storage

  final orgSlug = widget.orgSlug;
     final secureStorage = FlutterSecureStorage();
  final orgRoleId = await secureStorage.read(key: 'orgRoleId');  
     setState(() {
      _userRole = determineUserRole(orgRoleId); // Use the mixin to determine the role
    });
Enter fullscreen mode Exit fullscreen mode

Image description

apply logic in mixins dart file

Image description

 if (_userRole != 'User') 
              ElevatedButton(
                onPressed: () {                 
                  _showSendMailDialog(context);
                },
                child: Text('Add Email'),
              ),
Enter fullscreen mode Exit fullscreen mode
SizedBox(height: 8),// Row for action icons
                                      Row(
                                        mainAxisAlignment: MainAxisAlignment.end,
                                        children: [

                                           if (_userRole != 'User') 
                                          IconButton(
                                            icon: Icon(Icons.edit, color: Colors.blue),
                                            onPressed: () {
                                              _showEditEmailDialog(emailItem); // Implement your edit logic
                                            },
                                            tooltip: 'Edit Email',
                                          ),
                                           if (_userRole != 'Manager' && _userRole != 'User') 
                                          IconButton(
                                            icon: Icon(Icons.delete, color: Colors.red),
                                            onPressed: () {
                                              _showDeleteEmailDialog(context, emailItem);

                                            },
                                            tooltip: 'Delete Email',
                                          ),
                                        ],
                                      ),
Enter fullscreen mode Exit fullscreen mode

Full code Implementation

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:provider/provider.dart';
import 'package:wizbrand/Screen/Influencer/createemail.dart';
import 'package:wizbrand/model/email.dart';
import 'package:wizbrand/view_modal/organization_view_model.dart';
import 'package:wizbrand/Screen/layout/rolemixins.dart';
import 'package:wizbrand/Screen/layout/drawer.dart';


class EmailScreen extends StatefulWidget {
  final String orgSlug;

  EmailScreen({required this.orgSlug});

  @override
  _EmailScreenState createState() => _EmailScreenState();
}

class _EmailScreenState extends State<EmailScreen> with DrawerMixin, RoleMixin {
  String _userRole = '';
  String? _email;
  TextEditingController _searchController = TextEditingController();
List<EmailModel> _filteredEmails = []; // List to hold filtered emails
  final TextEditingController _emailController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _fetchData();
  }

  Future<void> _fetchData() async {
    final organizationViewModel = Provider.of<OrganizationViewModel>(context, listen: false);
    final credentials = await _getCredentials();
    final email = credentials['email'];
    final orgSlug = widget.orgSlug;
    final secureStorage = FlutterSecureStorage();
    final orgRoleId = await secureStorage.read(key: 'orgRoleId');
    final orgUserId = await secureStorage.read(key: 'orgUserId');
    final orgUserorgId = await secureStorage.read(key: 'orgUserorgId');

    setState(() {
        print(orgRoleId);
      _userRole = determineUserRole(orgRoleId); // Determine the user role
         print("emailscreen role id coming");
       print(_userRole);
    });

    if (email != null && orgSlug.isNotEmpty) {
      await organizationViewModel.getEmailassets(email, orgSlug, orgRoleId.toString(), orgUserId.toString(), orgUserorgId.toString()); // Fetch email assets
   _filteredEmails = organizationViewModel.my_emails; // Initialize with full data
    }
  }

void _filterEmails(String query) {
    final organizationViewModel = Provider.of<OrganizationViewModel>(context, listen: false);
    final allEmails = organizationViewModel.my_emails;

    setState(() {
        _filteredEmails = allEmails.where((emailItem) {
            final emailLower = emailItem.email?.toLowerCase() ?? '';
            final phoneLower = emailItem.phoneNumber?.toLowerCase() ?? '';
            final queryLower = query.toLowerCase();

            return emailLower.contains(queryLower) || phoneLower.contains(queryLower);
        }).toList();
    });
}
  Future<Map<String, String?>> _getCredentials() async {
    final secureStorage = FlutterSecureStorage();
    String? email = await secureStorage.read(key: 'email');
    String? password = await secureStorage.read(key: 'password');
    return {'email': email, 'password': password};
  }

  Future<void> _saveEmail() async {
    final secureStorage = FlutterSecureStorage();
    await secureStorage.write(key: 'email', value: _emailController.text);
    setState(() {
      _email = _emailController.text; // Update displayed email
    });
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Email saved successfully')),
    );
  }

  @override
  Widget build(BuildContext context) {
    final organizationViewModel = Provider.of<OrganizationViewModel>(context);

    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: true,
        backgroundColor: Colors.blue,
        centerTitle: true,
        title: Text(
          'Email - $_userRole', // Display role dynamically in the AppBar
          style: TextStyle(color: Colors.white),
        ),
      ),
      drawer: buildDrawer(context, orgSlug: widget.orgSlug),
      body: buildBaseScreen(
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(height: 20),
              // Mail button at the top
              if (_userRole != 'User') 
              ElevatedButton(
                onPressed: () {                 
                  _showSendMailDialog(context);
                },
                child: Text('Add Email'),
              ),
                    SizedBox(height: 20),
                                Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: TextField(
                          controller: _searchController,
                          decoration: InputDecoration(
                              labelText: 'Search by Email or Phone Number',
                              border: OutlineInputBorder(),
                              prefixIcon: Icon(Icons.search),
                          ),
                          onChanged: (value) {
                              _filterEmails(value); // Call filter method on text change
                          },
                      ),
                    ),
                                // ListView for displaying fetched emails
              Expanded(
                child: organizationViewModel.isLoading
                    ? Center(child: CircularProgressIndicator())
                    : _filteredEmails.isEmpty
                        ? Center(child: Text('No emails found for this organization.'))
                        : ListView.builder(
                            itemCount: _filteredEmails.length,
                              itemBuilder: (context, index) {
                                  final emailItem = _filteredEmails[index];
                              return Card(
                                margin: const EdgeInsets.symmetric(vertical: 8.0),
                                shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(10),
                                  side: BorderSide(color: Colors.grey[300]!),
                                ),
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Column(
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      SizedBox(height: 8),
                                       RichText(
                                      text: TextSpan(
                                        children: [
                                          TextSpan(
                                            text: 'Email: ', // The static part
                                            style: TextStyle(
                                              fontSize: 16,color: Colors.black,
                                              fontWeight: FontWeight.bold, // Bold style for 'Email:'
                                            ),
                                          ),
                                          TextSpan(
                                            text: '${emailItem.email ?? 'No Email Address'}', // The dynamic part
                                            style: TextStyle(
                                              fontSize: 14,color: Colors.black, // Regular size for the email
                                              fontWeight: FontWeight.normal, // Regular font weight for the email
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                      SizedBox(height: 8),

                                          RichText(
                                      text: TextSpan(
                                        children: [
                                          TextSpan(
                                            text: 'Mobile: ', // The static part
                                            style: TextStyle(
                                              fontSize: 16,color: Colors.black,
                                              fontWeight: FontWeight.bold, // Bold style for 'Email:'
                                            ),
                                          ),
                                          TextSpan(
                                            text: '${emailItem.phoneNumber ?? 'No Mobile'}', // The dynamic part
                                            style: TextStyle(
                                              fontSize: 14,color: Colors.black, // Regular size for the email
                                              fontWeight: FontWeight.normal, // Regular font weight for the email
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                      SizedBox(height: 8),

                                          RichText(
                                      text: TextSpan(
                                        children: [
                                          TextSpan(
                                            text: 'Password Hint: ', // The static part
                                            style: TextStyle(
                                              fontSize: 16,color: Colors.black,
                                              fontWeight: FontWeight.bold, // Bold style for 'Email:'
                                            ),
                                          ),
                                          TextSpan(
                                            text: '${emailItem.passwordHint ?? 'No Password Hint'}', // The dynamic part
                                            style: TextStyle(
                                              fontSize: 14,color: Colors.black, // Regular size for the email
                                              fontWeight: FontWeight.normal, // Regular font weight for the email
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                    SizedBox(height: 8),
                                      RichText(
                                      text: TextSpan(
                                        children: [
                                          TextSpan(
                                            text: 'Account Recovery: ', // The static part
                                            style: TextStyle(
                                              fontSize: 16,color: Colors.black,
                                              fontWeight: FontWeight.bold, // Bold style for 'Email:'
                                            ),
                                          ),
                                          TextSpan(
                                            text: '${emailItem.accountRecoveryDetails ?? 'No Account Recovery'}', // The dynamic part
                                            style: TextStyle(
                                              fontSize: 14,color: Colors.black, // Regular size for the email
                                              fontWeight: FontWeight.normal, // Regular font weight for the email
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                      SizedBox(height: 8),// Row for action icons
                                      Row(
                                        mainAxisAlignment: MainAxisAlignment.end,
                                        children: [

                                           if (_userRole != 'User') 
                                          IconButton(
                                            icon: Icon(Icons.edit, color: Colors.blue),
                                            onPressed: () {
                                              _showEditEmailDialog(emailItem); // Implement your edit logic
                                            },
                                            tooltip: 'Edit Email',
                                          ),
                                           if (_userRole != 'Manager' && _userRole != 'User') 
                                          IconButton(
                                            icon: Icon(Icons.delete, color: Colors.red),
                                            onPressed: () {
                                              _showDeleteEmailDialog(context, emailItem);

                                            },
                                            tooltip: 'Delete Email',
                                          ),
                                        ],
                                      ),
                                    ],
                                  ),
                                ),
                              );
                            },
                          ),
              ),
            ],
          ),
        ),
      ),
    );
  }


void _showSendMailDialog(BuildContext context) async {
  // Fetch the parameters from secure storage
  final secureStorage = FlutterSecureStorage();
  final orgRoleId = await secureStorage.read(key: 'orgRoleId');
  final orgUserId = await secureStorage.read(key: 'orgUserId');
  final orgUserorgId = await secureStorage.read(key: 'orgUserorgId');
  await showDialog(
    context: context,
    builder: (BuildContext context) {
      return CreateEmailDialog(
        orgSlug: widget.orgSlug, // Pass the existing parameter
        orgRoleId: orgRoleId!,   // Pass the new parameter
        orgUserId: orgUserId!,   // Pass the new parameter
        orgUserorgId: orgUserorgId!, // Pass the new parameter
      );
    },
  );
}

void _showEditEmailDialog(emailItem) async{
   final secureStorage = FlutterSecureStorage();
  final orgRoleId = await secureStorage.read(key: 'orgRoleId');
  final orgUserId = await secureStorage.read(key: 'orgUserId');
  final orgUserorgId = await secureStorage.read(key: 'orgUserorgId');
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return CreateEmailDialog(   
        orgSlug: widget.orgSlug, // Pass the existing parameter
        orgRoleId: orgRoleId!,   // Pass the new parameter
        orgUserId: orgUserId!,   // Pass the new parameter
        orgUserorgId: orgUserorgId!, 
        email: emailItem.email, // Existing email
        phoneNumber: emailItem.phoneNumber, // Existing phone number
        password: emailItem.password, // Existing password
        passwordHint: emailItem.passwordHint, // Existing password hint
        accountRecoveryDetails: emailItem.accountRecoveryDetails, // Existing recovery details
        id: emailItem.id, // Pass the ID of the email

      );
    },
  );
}


   void _showDeleteEmailDialog(BuildContext context, emailItem) async {
  // Show confirmation dialog
  final confirmed = await showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text('Delete Email'),
        content: Text('Are you sure you want to delete this Email?'),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(false); // Cancel action
            },
            child: Text('Cancel'),
          ),
          ElevatedButton(
            onPressed: () {
              Navigator.of(context).pop(true); // Confirm action
            },
            style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
            child: Text('Delete'),
          ),
        ],
      );
    },
  );

  // If confirmed, call the API to delete the project
  if (confirmed == true) {
    final organizationViewModel = Provider.of<OrganizationViewModel>(context, listen: false);

    try {
      // Make API call to delete the project
      await organizationViewModel.deleteEmail(
        emailItem.id, // Pass the project ID for deletion
        widget.orgSlug, // Pass the organization slug if necessary
      );    

      _fetchData(); // Refresh the project list
    } catch (error) {
      print("Error while deleting project: $error");
    }
  }
}

  Widget buildBaseScreen({required Widget body}) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
      ),
      child: body,
    );
  }

  // Helper method to determine user role

}
Enter fullscreen mode Exit fullscreen mode

Reuse App bar action

mixin dart file

import 'package:flutter/material.dart';
import 'package:wizbrand/Screen/Auth/loginscreen.dart';
import 'package:wizbrand/Screen/Influencer/createorg.dart';
import 'package:wizbrand/Screen/Influencer/dashboard.dart';
import 'package:wizbrand/Screen/Influencer/organizationScreen.dart';
import 'package:wizbrand/Screen/layout/basescreen.dart';

mixin NavigationMixin<T extends StatefulWidget> on State<T> {
  Widget buildBaseScreen({required Widget body, required int currentIndex, required String title}) {
    return BaseScreen(
      currentIndex: currentIndex,
      title: title,
      body: body,
    );
  }

  List<Widget> buildAppBarActions(BuildContext context) {
    return [
      IconButton(
        icon: Icon(Icons.home, color: Colors.white),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => HomeScreen()), // Replace HomeScreen with your actual screen
          );
        },
      ),
      IconButton(
        icon: Icon(Icons.business, color: Colors.white),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => OrganizationScreen()), // Replace OrganizationScreen with your actual screen
          );
        },
      ),
    ];
  }
}
Enter fullscreen mode Exit fullscreen mode

Apply reusability in dart file
Include NavigationMixin

class _ProjectScreenState extends State<ProjectScreen> with DrawerMixin, RoleMixin, NavigationMixin {
Enter fullscreen mode Exit fullscreen mode

Include buildAppBarActions

appBar: AppBar(
  automaticallyImplyLeading: true,
  backgroundColor: Colors.blue,
  centerTitle: true,
  title: Text(
    'Projects - $_userRole', // Display role dynamically in the AppBar
    style: TextStyle(color: Colors.white),
  ),
 actions: buildAppBarActions(context),
),
Enter fullscreen mode Exit fullscreen mode

Add parameter currentIndex,title in buildBaseScreen

buildBaseScreen(
            body: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Your existing body content...
                ],
              ),
            ),
            currentIndex: 0, // Set an appropriate index
            title: 'Projects', // Set the title as needed
          ),
Enter fullscreen mode Exit fullscreen mode

Update Widget buildBaseScreen Your Method:

Widget buildBaseScreen({required Widget body, required int currentIndex, required String title}) {
  return Container(
    decoration: BoxDecoration(
      color: Colors.white,
    ),
    child: Column(
      children: [
        // Optionally, add a title if needed
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Text(
            title,
            style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          ),
        ),
        Expanded(child: body),
      ],
    ),
  );
}
Enter fullscreen mode Exit fullscreen mode

reference1
reference2

Top comments (0)