When a user signs up for my app, they enter their preferences and the items are sorted by a property in their profile called "recommended" which comes from the api: "[Breakfast, Dinner, Desserts, Dine In]"
I have a tab bar where the user can tab through main preferences ie: [All options, food type, beverages] and when the user gets to each preference they get a subset that allows them to sort further that comes from Tabcategories. These are the working examples and the one that doesn't work:
Data comes in via my future:
var productsInHeadings =
_getProductsInHeadings(filteredProducts)
.where((e) => e.products.length != 0)
.toList();
Then gets filtered into buckets within the tabs.
enum FilterTabs { Breakfast,Rec, Lunch, Dinner, Dessert, All }
typedef void FilterTabCallback(FilterTabs tab);
List<ProductsInHeading> _getProductsInHeadings(List<Product> items) {
switch (selectedTab) {
case FilterTabs.Breakfast:
final Map<String, List<Product>> allBreakfast =
Map.fromEntries(TabCategories.breakfast.map((e) => MapEntry(e, [])));
Map<String, List<Product>> headingItems =
items.fold(allBreakfast, (breakfast, element) {
if (!breakfast.containsKey(element.food)) { //food would be classified breakfast, lunch, or dinner
return breakfast;
}
return breakfast
..update(element.food, (value) => value..add(element));
});
productList = headingItems;
print("headingItems: $headingItems");
return headingItems.entries
.map((e) => ProductsInHeading(e.key, e.value..sort()))
.toList()
..sort()
..where((e) => e.products.length != 0);
break;
}}
For each tab in the bucket, then displayed in a separate class
itemBuilder: (context, index) {
currentProducts = snapshot.data;
return HeaderAndListing(
productsInHeading: _currentCat != -1
? productsInHeadings[_currentCat]
: productsInHeadings[index],
showHeading: selectedTab != FilterTabs.All,
restaurant: restaurant,
starCount: starCount,
rating: rating,
filterNum: _currentCat,
currentIndex: _tabDetails[selectedTab.index]);
},
),
Center(child: _subSort(productsInHeadings)),
]);
This one does not:
case FilterTabs.Rec:
final Map<String, List<Product>> allRecommended =
Map.fromEntries(recCategories.map((e) => MapEntry(e, [])));
Map<String, List> headingItems =
items.fold(allRecommended, (rec, element) {
if (!rec.containsKey(userProfile.recommended)) {
return rec;
}
return rec..update(userProfile.recommended, (value) => value..add(element));
});
productList = headingItems;
print("headingItems: $headingItems");
return headingItems.entries
.map((e) => ProductsInHeading(e.key, e.value..sort()))
.toList()
..sort()
..where((e) => e.products.length != 0);
break;
Why does the first sort work but, the second one does not?
Related
I'm new as a Flutter programmer and I'm having difficulty working with a list that has pagination, if I remove the pagination the list doesn't load. Need help. The state manager I'm using is Getx.
This is my DTO class.
class PaginationFilter {
int? page;
int? pagesize;
#override
String toString() {
return 'PaginationFilterAlbum{page: $page, pagesize: $pagesize}';
}
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is PaginationFilter &&
runtimeType == other.runtimeType &&
page == other.page &&
pagesize == other.pagesize;
#override
int get hashCode => page.hashCode ^ pagesize.hashCode;
}
Here is where I consume the API.
Future<List<Post>> getAlbum(PaginationFilter filter, {
bool isFavoritedPage = false,
bool isNewEdition = false,
}) async {
dio.options.headers['Cookie'] = 'ASP.NET_SessionId=${user.sessionID}';
final response = await dio.get(
isFavoritedPage ? AppConstants.apiFavoritedsPost : AppConstants.apiPosts,
queryParameters: {
'sessionId': user.sessionID,
'CodUserProfile': '${user.codUser!}',
'CodUserLogged': '${user.codUser!}',
'Page': '${filter.page}', /*Aqui fica a pagina*/
'pagesize': '${filter.pagesize}', /*Aqui a quantidade de registros em cada pagina*/
'myPostOnly': isFavoritedPage ? 'true' : 'false',
},
);
final body = response.data['ListPosts'] as List;
return body.map((post) => Post.fromJson(post)).toList();
}
Here is my controller class
final _posts = <Post>[].obs;
var response = null;
final _paginationFilterAlbum = PaginationFilter().obs;
int? get pagesize => _paginationFilterAlbum.value.pagesize;
int? get _page => _paginationFilterAlbum.value.page;
final _lastPageAlgum = false.obs;
bool get lastPageAlgum => _lastPageAlgum.value;
#override
void onInit(){
ever(_paginationFilterAlbum, (_) => getAlbum());
_changePaginationFilterAlgum(1, 10);
super.onInit();
}
void _changePaginationFilterAlgum(int page, int pagesize){
_paginationFilterAlbum.update((val) {
val?.page = page;
val?.pagesize = pagesize;
});
}
void changeTotalPerPage(int limitValue){
_posts.clear();
_lastPageAlgum.value = false;
_changePaginationFilterAlgum(1, limitValue);
}
void nextPage() => _changePaginationFilterAlgum(_page! + 1, pagesize!);
Future<List<Post>> getAlbum([bool isFavoritedPage = false]) async {
response =
await repository.getAlbum(_paginationFilterAlbum.value,isFavoritedPage: isFavoritedPage);
if(response.isEmpty){
_lastPageAlgum. value = true;
}
_posts.addAll(response);
return response;
}
here is my my list
Expanded(
child: FutureBuilder<List<Post>>(
future: controller.getAlbum(),
builder: (context, snapshot) {
final List<Post> posts = snapshot.data ?? [];
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CupertinoActivityIndicator());
}
return ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: posts.length,
itemBuilder: (context, index) {
return PostWidget(post: posts[index]);
},
);
},
),
),
Could you please help me how do I load the entire list using pagination?
I tried to send list of int in params on http get method, my laravel backend cant recieve list of int from params and give error code 500;
getFilterContent() {
Map<String, dynamic> data = {'key': '1'};
if (saleFilter!) {
data.putIfAbsent('sale', () => '1');
}
if (isNewFilter!) {
data.putIfAbsent('is_new', () => '1');
}
if (pharmaciesFilter
.where((element) => element.isSelected == true)
.toList()
.length >
0) {
data.putIfAbsent(
'pharmacies',
() => List.generate(
pharmaciesFilter
.where((element) => element.isSelected == true)
.toList()
.length,
(index) {
var list = pharmaciesFilter
.where((element) => element.isSelected == true)
.toList();
return list[index].id.toString();
},
));
}
if (selFilterPrice
.where((element) => element.selected == true)
.toList()
.length >
0) {
var list =
selFilterPrice.where((element) => element.selected == true).toList();
data.putIfAbsent(
'prices',
() => List.generate(
selFilterPrice
.where((element) => element.selected == true)
.toList()
.length,
(index) {
// data['prices'].add(list[index].id.toString());
return list[index].id.toString();
},
));
}
return data;
}
final uri =
Uri.http(url, '/api/v1/categories/$id/medicines', getFilterContent());
print(uri);
//It print' http:..../categories/11/medicines?key=1&sale=1&prices=1&prices=2&prices=3'
I am having trouble with a method that is checking if the item is stored in the firestore database.
void add(BuildContext context, CartItem item) {
_items.add(item);
AuthService authService = Provider.of<AuthService>(context, listen: false);
Map<String, dynamic> cartMap = Map();
_items.forEach((CartItem item) {
cartMap['title'] = (item.product as Product).title;
cartMap['name'] = (item.product as Product).name;
});
_instance = FirebaseFirestore.instance;
_instance!
.collection('cart')
.doc(authService.getCurrentUser()) //need to get logged in account's id
.update({
'cartProduct': FieldValue.arrayUnion([cartMap])
}).then((value) {
print(_items.length);
notifyListeners();
});}
The add Method adds the item to the firestore in a way like the example image.
However, after I delete the data using the remove method,
void remove(BuildContext context, CartItem item) {
_items.remove(item);
AuthService authService = Provider.of<AuthService>(context, listen: false);
Map<String, dynamic> cartMap = Map();
// _items.forEach((CartItem item) {
cartMap['title'] = (item.product as Product).title;
cartMap['name'] = (item.product as Product).name;
// });
_instance = FirebaseFirestore.instance;
_instance!.collection('cart').doc(authService.getCurrentUser()).update({
'cartProduct': FieldValue.arrayRemove([cartMap]),
}).then((value) {
print(_items.length);
notifyListeners();
}); }
I check if the data is added to the cartProduct using isProductAddedToCart method and the result is still true. Also, when I print the _items.length, it doesn't decrease after I use the remove method.
bool isProductAddedToCart(Product? pro) {
return _items.length >= 0 ? _items.any(
(CartItem item) => item.product!.title == pro!.title) : false;
}
This is the code where I want to use the isProductAddedToCart method.
Consumer<CartService>(
builder: (context, cart, child) {
Widget renderedButton;
if (cart.isProductAddedToCart(widget.product) == false) {
renderedButton = DefaultButton(
text: "Participate",
press: () {
print(cart.isProductAddedToCart(widget.product));
cartService.add(context, CartItem(product: widget.product));
print(cart.isProductAddedToCart(widget.product));
},
);
} else {
renderedButton = DefaultButton(
text: "Delete",
press: () {
print(cart.isProductAddedToCart(widget.product));
cartService.remove(
context, CartItem(product: widget.product));
print(cart.isProductAddedToCart(widget.product));
},
);
}
return renderedButton;
I'm listening to 2 collections on firebase using RxDart. The data is being pulled, but the merge with RxDart does not go into my code. So that part passes. What could be the problem??
User and Conversation collections are listening. I can reach this data and ı can write on the console. But Rx Code passes.
#override
Stream<List<Chat?>> getAllConversation(String userId) async* {
Stream<List<Conversation?>> conversationStream = _firestore
.collection(_conversationCollectionName)
.where(
Conversation.memebersKey,
arrayContains: userId,
)
.orderBy(
Conversation.sentAtKey,
)
.snapshots()
.map(
(event) => event.docs
.map((e) => _getConversationFromDocumentSnapshot(e, e.id))
.toList(),
);
Stream<List<User?>> userStream =
_firestore.collection(_usersCollectionName).snapshots().map(
(event) => event.docs
.map((e) => _getUserFromDocumentSnapshot(
e,
))
.toList(),
);
yield* Rx.combineLatest2(
conversationStream,
userStream,
(List<Conversation?> conversations, List<User?> users) {
print('Rx içinde giriyor');
return conversations.map((conversation) {
if (conversation != null) {
var otherUser = conversation.memebers[0] == userId
? conversation.memebers[1]
: conversation.memebers[0];
bool isOwnMessage =
conversation.lastUserId == userId ? true : false;
User? user = users.firstWhere((user) {
return user!.userId == otherUser;
});
return Chat(
id: conversation.conversationId,
user: user,
message: conversation.lastMessages,
unReadMessageCount: isOwnMessage ? 0 : conversation.unRead,
isOwnMessage: isOwnMessage,
sentAt: conversation.sentAt,
senderId: userId,
);
}
}).toList();
},
);
}
I have been struggling for hours now to retrieve data from firestore as a list so I can show them in a search bar suggestion.
This below function will retrieve data from firestore and return some selected fields as a list.
Future<List> getNewsOnSearchBar() async {
final String _collection = 'news';
final Firestore _fireStore = Firestore.instance;
var newsList = [];
print("1");
Future<QuerySnapshot> getData() async {
print("2");
return await _fireStore.collection(_collection).getDocuments();
}
QuerySnapshot val = await getData();
if (val.documents.length > 0) {
print("3");
for (int i = 0; i < val.documents.length; i++) {
newsList.add(val.documents[i].data["headline"]);
}
} else {
print("Not Found");
}
print("4");
return newsList;
}
And below is my Search bar widget. It has an attribute searchList which is of type List<dynamic>. It accept values such as:
var list = ["a", "b", "c"];
searchList: list
So I want to call that above function getNewsOnSearchBar() and set the list to the attribute searchList. I tried below and it doesn't work.
Widget _showSearchBar(BuildContext context) {
return FutureBuilder(
future: getNewsOnSearchBar(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return _progressIndicator();
} else {
return GFSearchBar(
searchList: [], //how can I assign the list return from `getNewsOnSearchBar()` here?
searchQueryBuilder: (query, list) {
return list
.where((item) =>
item.toLowerCase().contains(query.toLowerCase()))
.toList();
},
overlaySearchListItemBuilder: (item) {
return Container(
padding: const EdgeInsets.all(3),
child: Text(
item,
style: const TextStyle(fontSize: 18),
),
);
},
onItemSelected: (item) {},
);
}
});
}
Could you help me, Please?
Since your function getNewsOnSearchBar() is returning a list, you can use snapshot.data.
so your function becomes something like this
return GFSearchBar(
searchList: snapshot.data,
searchQueryBuilder: (query, list) {
return list
.where((item) =>
item.toLowerCase().contains(query.toLowerCase()))
.toList();
},
You can do it in two ways.
1-you can retrieve the documents for firebase and then you can use the Map function to create a list.
2-You can create a Firebase Functions to retrieve the information as you expect.