Flutter: how to order list by dateTime - flutter

I have a list like this:
var orderedEvents = [
{
"realTime": "2021-07-28 12:00:02.000" // Flutter dateTime but saved as String
},
{
"realTime": "2021-07-28 12:00:00.000"
},
{
"realTime": "2021-07-28 12:00:01.000"
}
];
And I do:
orderedEvents.sort((a, b) {
final realTimeA = DateTime.parse(a["realTime"]);
final realTimeB = DateTime.parse(b["realTime"]);
return realTimeA.isBefore(realTimeB) ? -1 : 1;
});
But it's not ordered properly obtaining 0, 2 and 1.

First make sure to convert from Strings to DateTimes.
Afterward, simply use the following:
orderedEvents.sort((a,b) {
final realTimeA = DateTime.parse(a["realTime"]);
final realTimeB = DateTime.parse(b["realTime"]);
return realTimeA.compareTo(realTimeB);
});

Related

RiverPod Maintaining selected item of list

I am new to riverpod and trying to figure out a state management issue.
I have one list, and two independent states which need access to the list. The states also need to select an element of the list and know what its index is. The list can totally change (add or remove elements) and the states need to determine if their selected element is still in the list and update the index accordingly (to 0 if it is not found)
Here is an example with Riverpod in pure dart:
import 'package:riverpod/riverpod.dart';
void main(List<String> arguments) {
final container = ProviderContainer();
List<String> names = ["Jack", "Adam", "Sally"];
container.read(nameListProvider.notifier).setNames(names);
//selectedName1 = "Adam"
//selectedIndex1 = 1
//selectedName2 = "Sally"
//selectedIndex2 = 2
names.remove('Adam');
container.read(nameListProvider.notifier).setNames(names);
// print(selectedName1) = "Jack" // set to 0 because selection was removed
// print(selectedIndex1) = 0
// print(selectedName2) = "Sally"
// print(selectedIndex2) = 1 // decrement to match Sally's new list index
}
final nameListProvider =
StateNotifierProvider<NameListNotifier, List<String>>((ref) {
return NameListNotifier();
});
class NameListNotifier extends StateNotifier<List<String>> {
NameListNotifier() : super([]);
setNames(List<String> names) {
state = names;
}
}
But I need the selected Name and Index to be Providers
Update: Here is my more elegant solution:
import 'package:riverpod/riverpod.dart';
void main(List<String> arguments) {
final container = ProviderContainer();
List<String> names = ["Jack", "Adam", "Sally"];
print(container.read(nameListProvider));
container.read(nameListProvider.notifier).setNames(names);
var first = container.read(selectionProvider(1).notifier);
first.setName(1);
print(container.read(selectionProvider(1)).name);
var second = container.read(selectionProvider(2).notifier);
second.setName(2);
print(container.read(selectionProvider(2)).name);
names.remove('Adam');
List<String> newNames = List.from(names);
container.read(nameListProvider.notifier).setNames(newNames);
print(container.read(selectionProvider(1)).name);
print(container.read(selectionProvider(1)).index);
print(container.read(selectionProvider(2)).name);
print(container.read(selectionProvider(2)).index);
print(container.read(nameListProvider));
}
final selectionProvider =
StateNotifierProvider.family<SelectionNotifier, Selection, int>(
(ref, page) {
return SelectionNotifier(ref.read);
});
class SelectionNotifier extends StateNotifier<Selection> {
Reader _read;
SelectionNotifier(this._read) : super(Selection());
update() {
final String? selectedName = state.name;
final List<String> names = _read(nameListProvider);
if (names == []) {
state = Selection();
return null;
}
if (selectedName == null) {
state = Selection(name: names[0], index: 0);
return;
}
int i = names.indexOf(selectedName);
if (i == -1) {
state = Selection(name: names[0], index: 0);
return;
}
state = Selection(name: selectedName, index: i);
return;
}
setName(int index) {
final List<String> names = _read(nameListProvider);
state = Selection(name: names[index], index: index);
}
}
final nameListProvider =
StateNotifierProvider<NameListNotifier, List<String>>((ref) {
return NameListNotifier(ref.read);
});
class NameListNotifier extends StateNotifier<List<String>> {
Reader _read;
NameListNotifier(this._read) : super([]);
setNames(List<String> names) {
state = names;
_read(selectionProvider(0).notifier).update();
_read(selectionProvider(1).notifier).update();
}
}
class Selection {
final String? name;
final int? index;
Selection({this.name, this.index});
}

Flutter search from model provider

After a few days it didn't work, I combined the data on the model initially
example: Samsung has a lot of data and I have combined it into an array, I want to ask how to make a search based on the brand name of the model?
#override
Widget build(BuildContext context) {
remoteModelId.clear();
isLoading = true;
final products = Provider.of<List<Brands>>(context);
return Scaffold(
...
body: products != null
? ListView.separated(
itemCount: products.length,
itemBuilder: (context, index) {
var lol = [];
var idModel = [];
var sublist = [].join();
var countList =[];
//var allList =[];
//var subLol = lol.indexOf(lol);
for(var ok in products){
lol.add(ok.brandName);
idModel.add(ok.ids);
countList.add(lol);
if(lol.contains(lol)){
sublist.compareTo(lol[index]);
break;
}
}
distinctIds = lol.toSet().toList();
hasilakhir = Set.of(distinctIds).toList();
newDataList = List.from(distinctIds);
templist.add(hasilakhir);
final myMap = Map();
lol.forEach((element) {
if(!myMap.containsKey(element)){
myMap[element] = 1;
return false;
}else{
myMap[element] += 1;
return false;
}
});
//newDataList = newDataList.map((brand)=>brand.toLowerCase()).toList();
return ListTile(
title: Text(hasilakhir[index]),
Thanks
I am not sure what you need, but here is some example code:
// Get products with a specific brandName
print(
'Number of Samsung=${products.where((p) => p.brandName == 'Samsung').length}');
// Count products by brandName - like your code
final map = Map();
products.forEach((product) {
if (!map.containsKey(product.brandName)) {
map[product.brandName] = 1;
} else {
map[product.brandName] += 1;
}
});
print('map=$map');
// Group products by brandName, with the count and list of ids
final map2 = Map();
products.forEach((product) {
if (!map2.containsKey(product.brandName)) {
map2[product.brandName] = {
'count': 1,
'ids': [product.ids]
};
} else {
var current = map2[product.brandName];
current['count']++;
current['ids'].add(product.ids);
}
});
print('map2=$map2');
The output with my test data is:
Number of Samsung=3
map={Samsung: 3, Apple: 3}
map2={Samsung: {count: 3, ids: [S1, S2, S3]}, Apple: {count: 3, ids: [iPhone1, iPhone2, iPhone3]}}
I do not know if it is helpful, but I have annotated some of your code below:
// Get list of distinct brandNames
var distinctIds = lol.toSet().toList();
// Get list of distinct brandNames - same as distinctIds
var hasilakhir = Set.of(distinctIds).toList();
// Copy list distinctIds
var newDataList = List.from(distinctIds);
List templist = [];
// Make a list with one element which is the list of brandNames
templist.add(hasilakhir);

Unable to add key and bool value into nested list

Example Code (Not working):
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true; // able to add the key and bool value
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
return item;
}).toList();
print(result);
}
return error 'bool' is not a subtype of type 'String'
Expected Result
[
{
sku: SKU0001,
no_desc: true,
uids: [
{
uid: U001,
is_scanned: true // must be boolean
}
]
}
]
It work when i try in String value.
uid['is_scanned'] = 'true';
How can I add bool value into the nested list?
If I am writing in javascript way,
it should be able to add the key into nested array ( list ).
But why in dart lang, it prompt me error?
Can someone expert in dart lang willing to explain to me?
Your issue can be fixed by creating a new Map instance in the inner .map method with the Map.from constructor.
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
should be changed to:
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
I believe this issue is due to dart implicitly declaring the inner uids maps as Map<String, String> so creating a new instance changes this and allows you to assign any value to the keys of the Map.
Full working sample:
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true;
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
return item;
}).toList();
print(result);
}

Dart : Convert From Iterable<ActivityModel> To ActivityModel

I have model Like This :
Model
class ActivityModel {
String idActivity;
String titleActivity;
String dateTimeActivity;
int isDoneActivity;
int codeIconActivity;
String informationActivity;
String createdDateActivity;
ActivityModel({
this.idActivity,
this.titleActivity,
this.dateTimeActivity,
this.isDoneActivity,
this.codeIconActivity,
this.informationActivity,
this.createdDateActivity,
});
ActivityModel.fromSqflite(Map<String, dynamic> map)
: idActivity = map['id_activity'],
titleActivity = map['title_activity'],
dateTimeActivity = map['datetime_activity'],
isDoneActivity = map['is_done_activity'],
codeIconActivity = map['code_icon_activity'],
informationActivity = map['information_activity'],
createdDateActivity = map['created_date'];
Map<String, dynamic> toMapForSqflite() {
return {
'id_activity': this.idActivity,
'title_activity': this.titleActivity,
'datetime_activity': this.dateTimeActivity,
'is_done_activity': this.isDoneActivity,
'code_icon_activity': this.codeIconActivity,
'information_activity': this.informationActivity,
'created_date': this.createdDateActivity,
};
}
I want get data where dateTimeActivity is before than date now, then i update isDoneActivity = 1 with this code :
Source code
final passedDateItem = _selectedActivityItem.where((element) {
DateTime convertStringToDateTime =
DateTime.parse(element.dateTimeActivity);
return convertStringToDateTime.isBefore(DateTime.now());
});
if (passedDateItem != null) {
print('Not Null');
} else {
print('Nulledd');
return null;
}
The problem is , passedDateItem return Iterable[ActivityModel] , it's possible to convert it to ActivityModel? So i can easly update like this ?
if (passedDateItem != null) {
passedDateItem.isDoneActivity = 1; <<<
// return passedDateItem.map((e) => e.isDoneActivity = 1);
// final testtt= passedDateItem.
print('Not Null');
} else {
print('Nulledd');
return null;
}
Iterate through passedDateItem
for (var activityModel in passedDateItem) {
//..conditions
activityModel.isDoneActivity = 1;
}
If you are only interested in the first/last element of passedDateItem
use
passedDateItem.first.isDoneActivity == 1
or
passedDateItem.last.isDoneActivity == 1
make sure passedDateItem is not empty in that case.

Sort out dates for flutter check box/ Date scheduler

I have a service which returns a list of dates, which the user can opt for a future payment.
In the UI, there are three drop down boxes, one each for year, month and date.
Now when the user selects a particular year, then the months shown in the next drop down should only contain months corresponding to that particular selected year and similarly when the month is selected only the corresponding dates to that particular selected month should be shown.
The service response is something like below :
[
{
"availableDate":"03/13/2020"
},
{
"availableDate":"04/14/2020"
},
{
"availableDate":"01/15/2020"
},
{
"availableDate":"01/16/2020"
},
{
"availableDate":"02/17/2020"
},
{
"availableDate":"02/18/2020"
},
{
"availableDate":"02/22/2021"
}
]
I was able to split out the dates,months and years and when I tried to change values using onChange, didn't get the desired result. Could some one please help me with the logic or maybe give me a link to get started?
I have found out a solution.
First initialize the variables :
List _serviceData = [];
List _yearList = [];
List _monthList = [];
List _dateList = [];
List<SchedulerYear> _yearData = new List<SchedulerYear>();
List<SchedulerMonth> _monthData = new List<SchedulerMonth>();
List<SchedulerDate> _dateData = new List<SchedulerDate>();
var yearData = [];
var monthData = [];
var _loadData, _year, _month, _date;
Models used :
class SchedulerYear {
String year;
String month;
String date;
SchedulerYear({this.year,this.month,this.date});
#override
String toString() {
return '$year $month $date';
}
}
class SchedulerMonth {
String month;
String date;
SchedulerMonth({this.month,this.date});
#override
String toString() {
return '$month $date';
}
}
class SchedulerDate {
String date;
SchedulerDate({this.date});
#override
String toString() {
return '$date';
}
}
And finally the functions :
List<DropdownMenuItem<String>> getMenuItems(List options) {
List<DropdownMenuItem<String>> items = List();
for (String n in options) {
items.add(DropdownMenuItem(value: n, child: Text(n)));
}
return items;
}
_getYears() async {
_serviceData = await serviceHandler.fadfj; // the service response as a List
_yearData = [];
_yearList = [];
_yearItems = [];
for (int i = 0; i < _serviceData.length; i++) {
_loadData = _serviceData[i].toString();
_month = _loadData.split('/')[0];
_date = _loadData.split('/')[1];
_year = _loadData.split('/')[2];
_yearData.add(SchedulerYear(year: _year, month: _month, date: _date));
_yearList.add(_year);
}
_yearList = _yearList.toSet().toList();
_yearItems = getMenuItems(_yearList);
_selectedYear = _yearItems[0].value;
yearData = _yearData;
}
_getMonths(selectedYear) {
_dateItems = [];
_dateItems = getMenuItems(_initialDate);
_selectedDate = _dateItems[0].value;
_yearData = yearData;
_monthData = [];
_monthList = [];
_monthItems = [];
for (int i = 0; i < _yearData.length; i++) {
if (_yearData[i].year == selectedYear) {
_monthData.add(SchedulerMonth(month: _yearData[i].month, date: _yearData[i].date));
_monthList.add(_yearData[i].month);
}
}
monthData = _monthData;
_monthList = _monthList.toSet().toList();
_monthItems = getMenuItems(_monthList);
_selectedMonth = _monthItems[0].value;
}
_getDates(selectedMonth) {
_monthData = monthData;
_dateData = [];
_dateList = [];
_dateItems = [];
for (int i = 0; i < _monthData.length; i++) {
if (_monthData[i].month == selectedMonth) {
_dateData.add(SchedulerDate(date: _monthData[i].date));
_dateList.add(_monthData[i].date);
}
}
_dateList = _dateList.toSet().toList();
_dateItems = getMenuItems(_dateList);
_selectedDate = _dateItems[0].value;
}
_getYears() is called inside init() and the _getMonths(selectedYear) is called onChange of years dropdown button and _getDates(selectedMonth) on the months dropdown button