In my list from the Firebase database, I want the user to be able to sort the list with date range. Thus choosing dates and displaying only the data based on the chosen date range.
My data contains the following fields:
1) "Date" : DateFormat("dd-MMM-yyyy").format(DateTime.now),
2) "Timestamp": Timestamp.now(),
In my code, I have the DateTimeRange already. How do I implement the function where the UI shows only the data within that range after the user selects the date range?
DateTimeRange? dateRange;
Future pickDateRange() async {
final initialDateRange = DateTimeRange(
start: DateTime.now(),
end: DateTime.now(),
);
final newDateRange = await showDateRangePicker(
context: context,
firstDate: DateTime(DateTime.now().year - 20),
lastDate: DateTime(DateTime.now().year + 20),
initialDateRange: dateRange ?? initialDateRange,
);
if (newDateRange == null) {
return;
} else {
setState(() => dateRange = newDateRange);
}
}
TextButton(
onTap: () => pickDateRange()
)
StreamBuilder(
stream: FirebaseFirestore.instance
.collectionGroup(widget.dailyTransactionsCollection)
.orderBy("Timestamp", descending: true)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text(
widget.errorString,
style: const TextStyle(color: Colors.white),
);
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
final data = snapshot.data!.docs[index];
final date = data["Date"];
final amount = data["Amount"];
final timestamp = data["Timestamp"];
if (dateRange == null) {
return ListTile(
title: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 50),
child: SizedBox(
width: screenWidth * 0.1,
child: Text(
date,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 100),
child: SizedBox(
width: screenWidth * 0.2,
child: Text("$amount"),
),
)
],
),
);
} else {
/* I want the function to return the same ListTile as the
one above, but only this time, the data should be within
the date range selected
*/
}
},
);
}
return Center(
child: Text(widget.noDataYetString),
);
},
),
2
Answers
Firestore queries can only contain inequality conditions (things like
>
,>=
,<>
, etc) on a single field. From the documentation on query limitations:So in your current data model, you can select one specific date (with a
==
condition onDate
) and then select a time range (with>=
and<=
conditions onTimestamp
). But you can’t select a start and end time across multiple dates with your current data model.To allow that, you’ll have to change your data model and store the exact timestamp in a single field (of type
Timestamp
). Once you have that, you can put>=
and<=
conditions on that single field, and implement the use-case.