0

I have a datatable in Flutter which display data from a Firebase database. It includes two columns namely 'Registration Date' and 'Expiry Date' which I was to sort when the user taps on the respective columns. Moreover, I have used DateFormat('dd-MM-yyyy') to format the dates, so those are stored as strings in my database.

This is one such entry in my database and this is how the columns look in the DataTable.

import 'dart:math';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:sub_mgmt/page/addnewpage.dart';
import 'package:sub_mgmt/page/data/users.dart';
import 'package:sub_mgmt/page/model/user.dart';

import 'editpage.dart';

class MemberList extends StatefulWidget {
  const MemberList({Key? key}) : super(key: key);

  @override
  State<MemberList> createState() => MemberListState();
}

class MemberListState extends State<MemberList> {
  static int counter = 1;

  // Reading data from firebase
  CollectionReference _referenceMembers =
      FirebaseFirestore.instance.collection('users');
  late Stream<QuerySnapshot> _streamMembers;
  List<int> selectedIndex = [];
  List<String> selectedDocID = [];

  final searchController = TextEditingController();


  @override
  void initState() {
    super.initState();
    _streamMembers = _referenceMembers.snapshots();
  }

  int? sortColumnIndex;
  bool isAscending = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder<QuerySnapshot>(
          stream: _streamMembers,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasError) {
              return Center(child: Text(snapshot.error.toString()));
            }

            if (snapshot.connectionState == ConnectionState.active) {
              QuerySnapshot querySnapshot = snapshot.data;
              List<QueryDocumentSnapshot> listQueryDocumentSnapshot =
                  querySnapshot.docs;
              counter = 0;
              return ScrollableWidget(
                child: Column(
                  children: [
                    DataTable(
                      sortAscending: isAscending,
                      sortColumnIndex: sortColumnIndex,
                      columns: [
                        DataColumn(
                          label: Text(
                            'Sr',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Name',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Phone',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Plan',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Fee Paid',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                        DataColumn(
                          label: Text(
                            'Reg. Date',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                          onSort: onSort,
                        ),
                        DataColumn(
                          label: Text(
                            'Expiry Date',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                          onSort: onSort,
                        ),
                        DataColumn(
                          label: Text(
                            '',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                      ],
                      rows: listQueryDocumentSnapshot
                          .map((element) => DataRow(
                                selected: selectedDocID.contains(element.id),
                                onSelectChanged: (isSelected) => setState(() {
                                  final isAdding =
                                      isSelected != null && isSelected;

                                  if (isAdding) {
                                    selectedDocID.add(element.id);
                                  } else {
                                    selectedDocID.remove(element.id);
                                  }
                                }),
                                cells: <DataCell>[
                                  DataCell(Text((++counter).toString())),
                                  DataCell(Text(element['Name'])),
                                  DataCell(Text(element['Phone'].toString())),
                                  DataCell(Text(element['Plan'].toString())),
                                  DataCell(
                                      Text(element['Fee Paid'].toString())),
                                  DataCell(Text(element['Registration Date'])),
                                  DataCell(Text(element['Expiry Date'])),
                                  DataCell(IconButton(
                                    splashRadius: 22,
                                    color: Colors.black38,
                                    icon: Icon(Icons.edit),
                                    onPressed: () {
                                      Navigator.push(
                                        context,
                                        MaterialPageRoute(
                                          builder: (context) => EditPage(
                                              element.id,
                                              element['Name'],
                                              element['Phone'],
                                              element['Plan'],
                                              element['Fee Paid'],
                                              element['Registration Date']),
                                        ),
                                      );
                                    },
                                  ))
                                ],
                              ))
                          .toList(),
                      columnSpacing: 32,
                    ),
                    SizedBox(height: 80),
                  ],
                ),
              );
            }

            return Center(child: CircularProgressIndicator());
          }),
      floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
      floatingActionButton: Padding(
        padding: const EdgeInsets.all(18.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              child: FloatingActionButton(
                onPressed: () {
                  if (selectedDocID.isNotEmpty) {
                    showDialog(
                        context: context,
                        builder: (BuildContext context) {
                          return AlertDialog(
                            title: Text("Delete"),
                            content: Text("Delete Data?"),
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(15)),
                            actions: [
                              TextButton(
                                  onPressed: () {
                                    Navigator.of(context).pop();
                                  },
                                  child: Text("No")),
                              TextButton(
                                  onPressed: () {
                                    for (var i in selectedDocID) {
                                      final docUser = FirebaseFirestore.instance
                                          .collection('users')
                                          .doc(i);
                                      docUser.delete();
                                    }
                                    Navigator.of(context).pop();
                                  },
                                  child: Text("Yes"))
                            ],
                          );
                        });
                  }
                },
                tooltip: 'Delete',
                elevation: 4.0,
                child: Icon(Icons.delete),
              ),
            ),
            FloatingActionButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => AddNewPage()));
              },
              tooltip: 'Add',
              elevation: 4.0,
              child: Icon(Icons.add),
            )
          ],
        ),
      ),
    );
  }

  void onSort(int columnIndex, bool ascending) async {

    setState(() {
      this.sortColumnIndex = columnIndex;
      this.isAscending = ascending;
    });
  }
}

class ScrollableWidget extends StatelessWidget {
  final Widget child;
  const ScrollableWidget({
    Key? key,
    required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      physics: BouncingScrollPhysics(),
      scrollDirection: Axis.horizontal,
      child: SingleChildScrollView(
        physics: BouncingScrollPhysics(),
        scrollDirection: Axis.vertical,
        child: child,
      ),
    );
  }
}

I understand that I need to use the onSort property of DataColumn, but I'm facing difficulty in implementing it. Any help would be appreciated.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

0

I have used DateFormat('dd-MM-yyyy') to format the dates, so those are stored as strings in my database.

Strings are sorted in Firestore (and most databases) in lexicographical order, and in the data format you've chosen that is different from the chronological order of the dates they represent.

To fix this problem at its root, either store actual Timestamp or Date values, or (if you persist in storing it as a string) use a date format that is suitable for ordering, such as ISO-8601: "yyyy-MM-dd".

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807