I want my Transaction screen to be categorized in months and i build the transaction screen using list view separated .
Here is my Transaction Screen code and i used the intl date package to get the date
class ScreenTransaction extends StatelessWidget {
const ScreenTransaction({super.key});
@override
Widget build(BuildContext context) {
TransactionDB.interface.refreshTransaction();
CategoryDB.instance.refreshUI();
return ValueListenableBuilder(
valueListenable: TransactionDB.interface.transactionListNotifier,
builder: (BuildContext ctx, List<TransactionModel> newList, _) {
return ListView.separated(
padding: EdgeInsets.all(10),
itemBuilder: (ctx, index) {
final _list = newList[index];
return Slidable(
key: Key(_list.id!),
startActionPane: ActionPane(
motion: DrawerMotion(),
children: [
SlidableAction(
onPressed: (ctx) {
TransactionDB.interface.deleteTransaction(_list.id!);
},
icon: Icons.delete,
backgroundColor: Colors.red,
label: 'Delete',
),
],
),
child: Card(
child: ListTile(
leading: CircleAvatar(
backgroundColor: _list.type == CategoryType.income
? Colors.green
: Colors.red,
child: Text(
parsedDate(_list.date),
textAlign: TextAlign.center,
),
radius: 30,
),
title: Text('Rs ${_list.amount}'),
subtitle: Text(_list.categoryModel.name),
),
),
);
},
separatorBuilder: (ctx, index) {
return SizedBox(height: 10);
},
itemCount: newList.length,
);
},
);
}
String parsedDate(DateTime date) {
final _date = DateFormat.MMMd().format(date);
final _splittedDate = _date.split(' ');
return '${_splittedDate.last}n ${_splittedDate.first}';
}
}
This is how my transaction screen looks like now
I want a header like march 2024 and february 2024 and the the list items to be under that header.
2
Answers
You can group your transactions based on dates – assuming the transactions are already sorted by date – using one list.
First, create a function that takes a list of Transactions and return a list of Objects. The function iterates over the list of transactions and adds the transactions in order based on their date as follows:
In your build, call the above function on your transactions list, and then build each item according to its type as follows:
You customize how the date will appear as you wish, but I guess this should achieve what you are looking for.
Good luck!
Here’s a step by step guide on how I would do it.
1. Extract all the dates from your transaction list
newList
to a new listdatesList
I am using the
parsedDateHeaders
function to exclude theday
from the date and create the header’s format.2. Now that we have the list of dates by month, remove all the repeated/duplicated dates.
3. In your
ListView
widget, use thedatesList
(headers) as the itemCount.4. Now we can use a
Column
widget to add headers and the transactions underneath it. But instead of adding anotherbuilder
for the transactions, usemapping
instead.5. Before mapping the transactions, use a function to compare the transaction’s months with the header’s month, then add them to a new list
_filteredList
You can also get the index of each transaction like this:
6. Now add the condition that if
_filteredList
is empty (not the correct month), return SizedBox.shrink(), otherwise, return the transactions widget.See full demo here: https://dartpad.dev/?id=38334d9b986e39fa64cbdccb99636871