here is the list which i get from server `
[
{
"Name": "101 Working hours",
"Balance": "8.00",
"Date": "2022-10-19",
"ShiftName": "AU128"
},
{
"Name": "102 Bonus pay",
"Balance": "3:48",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "110 Split Shift",
"Balance": "1:00",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-20",
"ShiftName": ""
},
{
"Name": "101 Working hours",
"Balance": "8.00",
"Date": "2022-10-21",
"ShiftName": "AU128"
},
{
"Name": "102 Bonus pay",
"Balance": "3:48",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "110 Split Shift",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
},
]
`
here you can see date is repeating and all i want to avoid date repetition on FE. you can see app Screenshot to get an idea which i get and which i want to achieve.
the data i get.
the data i want to be achieved
I tried to avoid date repetition and insert data on same list if date is same but all the time i get repetition date and data as you can see in image.
my code:
Expanded(
child: Consumer<EmployeeWageAccountsProvider>(
builder: (context, data, child) {
if (!data.isLoading) {
int length = data.getEmployeeAccountsData!.length;
if (data.getEmployeeAccountsData!.isNotEmpty) {
wageAccountsData = data.getEmployeeAccountsData!;
return ListView.builder(
itemCount: length,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, i) {
return WageAccountsCard(
date: Helper.formatStringDate(
wageAccountsData[i].date!),
balance: wageAccountsData[i].balance,
name: wageAccountsData[i].name,
shiftName: wageAccountsData[i].shiftName,
);
},
);
}
return noDataFound(context, 50);
}
return const WageAccountsShimmer();
}),
)
wageacount card
class WageAccountsCard extends StatelessWidget {
final String? date;
final String? balance;
final String? name;
final String? shiftName;
const WageAccountsCard(
{Key? key, this.date, this.name, this.balance,
this.shiftName})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.all(8),
decoration: CustomBoxDecoration.cardDecoration(context,
shadow: true),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
shiftName!,
style: wageTextStyle,
),
Text(
date.toString(),
style: wageTextStyle,
),
],
),
SizedBox(
height: Styles.height(context) * 0.01,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context).wage_type,
style: cTextStyle,
),
Text(
S.of(context).balance,
style: cTextStyle,
),
],
),
const Divider(
color: Colors.black,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
name!,
style: cTextStyle,
),
Text(
balance.toString(),
style: cTextStyle,
),
],
),
SizedBox(
height: Styles.height(context) * 0.01,
),
],
),
);
}
}
model class
class EmployeeWageAccountsModel {
String? name;
String? balance;
String? date;
String? shiftName;
EmployeeWageAccountsModel({this.name, this.balance, this.date,
this.shiftName});
EmployeeWageAccountsModel.fromJson(Map<String, dynamic> json) {
name = json['Name'];
balance = json['Balance'];
date = json['Date'];
shiftName = json['ShiftName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Name'] = name;
data['Balance'] = balance;
data['Date'] = date;
data['ShiftName'] = shiftName;
return data;
}
}
parsing data from API
List<EmployeeWageAccountsModel> employeeWageAccountsList =
List<EmployeeWageAccountsModel>.from(
employeeWageAccountsResponse.map((model) =>
EmployeeWageAccountsModel.fromJson(model)));
CodePudding user response:
You could build a Map<String, List<Map<String, String>>>
using forEach
where key would be unique dates and values would be the list of objects.
void main() {
const data = [
{
"Name": "101 Working hours",
"Balance": "8.00",
"Date": "2022-10-19",
"ShiftName": "AU128"
},
{
"Name": "102 Bonus pay",
"Balance": "3:48",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "110 Split Shift",
"Balance": "1:00",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-19",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-20",
"ShiftName": ""
},
{
"Name": "101 Working hours",
"Balance": "8.00",
"Date": "2022-10-21",
"ShiftName": "AU128"
},
{
"Name": "102 Bonus pay",
"Balance": "3:48",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "110 Split Shift",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
},
];
final Map<String, List<Map<String, String>>> dates = {};
data.forEach((e) {
if (dates.containsKey(e['Date'])) {
dates[e['Date']]?.add(e);
} else {
dates[e['Date']!] = [e];
}
});
dates.forEach((e, k) {
print("$e\n${k.join("\n")}");
print('\n');
});
}
CodePudding user response:
One way to achive this is to use equatable package so you can compare objects
class Person extends Equatable {
const Person(this.name,this.date);
final String name;
final DateTime date;
@override
List<Object> get props => [name,date];
}
now you can compare two objects of type Person and with a simple function you can remove the repetition . example:
List<Person> yourList = [];
// before you add new object check if its already available
int getEqual(Person onePerson)=>yourList.indexWhere((element)=> element == onePerson);
if (getEqual(onePerson) != -1){
// object was not found in the list
yourList.add(onePerson);
}
// then sort your list by date using sort method
yourList.sort((a,b) => a.date.compareTo(b.date));
CodePudding user response:
You can use collection package and group your data with date :
var grouped = groupBy(xdata, (Map value) => value['Date']);
then you can make list base on grouped
. Note that xdata
is your list that you get from server.
grouped
is map and contain this:
{
2022-10-19: [
{Name: 101 Working hours, Balance: 8.00, Date: 2022-10-19, ShiftName: AU128},
{Name: 102 Bonus pay, Balance: 3:48, Date: 2022-10-19, ShiftName: },
{Name: 110 Split Shift, Balance: 1:00, Date: 2022-10-19, ShiftName: },
{Name: 111 Wage reduction, Balance: 1:00, Date: 2022-10-19, ShiftName: }
],
2022-10-20: [
{Name: 111 Wage reduction, Balance: 1:00, Date: 2022-10-20, ShiftName: }
],
2022-10-21: [
{Name: 101 Working hours, Balance: 8.00, Date: 2022-10-21, ShiftName: AU128},
{Name: 102 Bonus pay, Balance: 3:48, Date: 2022-10-21, ShiftName: },
{Name: 110 Split Shift, Balance: 1:00, Date: 2022-10-21, ShiftName: },
{Name: 111 Wage reduction, Balance: 1:00, Date: 2022-10-21, ShiftName: }
]
}
also change your model class to this:
class EmployeeWageAccountsModel {
String? date;
String? shiftName;
List<Wage>? wages;
EmployeeWageAccountsModel({this.wages, this.date, this.shiftName});
EmployeeWageAccountsModel.fromJson(Map<String, dynamic> json) {
wages = (json.values.first as List).map((e) => Wage.fromJson(e)).toList();
date = json.keys.first;
shiftName = json.values.first[0]['ShiftName'];
}
...
}
class Wage {
String? name;
String? balance;
Wage({this.name, this.balance});
Wage.fromJson(Map<String, dynamic> json) {
name = json['Name'];
balance = json['Balance'];
}
}
and parse it like this:
var grouped =
groupBy(employeeWageAccountsResponse, (Map value) => value['Date']);
List<EmployeeWageAccountsModel> employeeWageAccountsList =
List<EmployeeWageAccountsModel>.from(grouped.entries
.map((e) => EmployeeWageAccountsModel.fromJson({e.key: e.value})));
then change your list item to this:
class WageAccountsCard extends StatelessWidget {
final String? date;
final String? shiftName;
final List<Wage>? wages;
const WageAccountsCard(
{Key? key,
this.date,
this.shiftName,
this.wages})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.all(8),
decoration: CustomBoxDecoration.cardDecoration(context, shadow: true),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
shiftName!,
style: wageTextStyle,
),
Text(
date.toString(),
style: wageTextStyle,
),
],
),
SizedBox(
height: Styles.height(context) * 0.01,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context).wage_type,
style: cTextStyle,
),
Text(
S.of(context).balance,
style: cTextStyle,
),
],
),
const Divider(
color: Colors.black,
),
ListView.builder(
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
wages![index].name!,
style: cTextStyle,
),
Text(
wages![index].balance.toString(),
style: cTextStyle,
),
],
);
},
itemCount: wages!.length,
shrinkWrap: true,
),
SizedBox(
height: Styles.height(context) * 0.01,
),
],
),
);
}
}