From 4f7c8f60d0fd3d2218b1e8d276973e39935f01c6 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 19 Mar 2025 23:40:38 +0100 Subject: [PATCH 01/10] add increment and decrement to pagination --- covas_mobile/lib/pages/ListItemMenu.dart | 67 +++++++++++++++++++++++- covas_mobile/pubspec.lock | 4 +- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 5ffa41d..0f02b1b 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -48,6 +48,9 @@ class ListItemMenu extends StatefulWidget { class _MyHomePageState extends State { BannerAd? _bannerAd; final AuthService _authService = AuthService(); + late ScrollController _scrollController; + int _fetchCount = 0; + bool _isLoading = false; Future> postsFuture = getPosts(); List filteredPosts = []; @@ -144,6 +147,46 @@ class _MyHomePageState extends State { return "${year}-${month}-${day}"; } + void _incrementFetchCount() { + setState(() { + _fetchCount++; + }); + } + + void _decrementFetchCount() { + setState(() { + if (_fetchCount > 0 && filteredPosts.isNotEmpty) { + _fetchCount--; + } + }); + } + + void _scrollListener() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + _incrementFetchCount(); + } else if (_scrollController.position.pixels == + _scrollController.position.minScrollExtent) { + _decrementFetchCount(); + } + _fetchData(); + } + + Future _fetchData() async { + print("Counter : ${_fetchCount}"); + if (_isLoading) return; + setState(() { + _isLoading = true; + }); + + await Future.delayed(Duration(seconds: 2)); + fetchPostsByLocation(); + + setState(() { + _isLoading = false; + }); + } + @override void initState() { super.initState(); @@ -153,10 +196,19 @@ class _MyHomePageState extends State { _bannerAd = ad; }); }); + _scrollController = ScrollController(); + _scrollController.addListener(_scrollListener); + // Initialize data fetch when the page loads _getCurrentLocation(); } + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + // Get the device's current location Future _getCurrentLocation() async { PermissionStatus status = await Permission.location.status; @@ -347,7 +399,8 @@ class _MyHomePageState extends State { queryParameters = dateParameter; } - return Uri.parse("${globals.api}/$endpoint?$queryParameters"); + return Uri.parse( + "${globals.api}/$endpoint?$queryParameters&skip=${_fetchCount}"); } Future searchSuggestionsByItem(String input) async { @@ -770,12 +823,22 @@ class _MyHomePageState extends State { } return ListView.separated( - itemCount: displayedPosts.length, + controller: _scrollController, + itemCount: displayedPosts.isNotEmpty + ? displayedPosts.length + + (_isLoading ? 1 : 0) // Add 1 only if loading + : 0, itemBuilder: (context, index) { + if (index >= displayedPosts.length) { + return _isLoading + ? Center(child: CircularProgressIndicator()) + : SizedBox.shrink(); + } final post = displayedPosts[index]; final startDate = DateTime.parse(post.startDate!); final date = DateFormat.yMd().format(startDate); final time = DateFormat.Hm().format(startDate); + return ListTile( title: Text('${post.name!}'), subtitle: Text('${post.place!}\n${date} ${time}'), diff --git a/covas_mobile/pubspec.lock b/covas_mobile/pubspec.lock index f8e2f6c..770d04a 100644 --- a/covas_mobile/pubspec.lock +++ b/covas_mobile/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: args - sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" asn1lib: dependency: transitive description: From 52580c656886b2bd9e4e6ab806de60ea3ed09124 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 24 Mar 2025 22:10:49 +0100 Subject: [PATCH 02/10] fetchCount to 0 --- covas_mobile/lib/pages/ListItemMenu.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 0f02b1b..a9b362f 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -623,6 +623,7 @@ class _MyHomePageState extends State { controller: inputItem, labelText: 'Search by item', onChanged: (value) { + _fetchCount = 0; if (value.isNotEmpty) { setState(() { itemName = value; @@ -640,6 +641,7 @@ class _MyHomePageState extends State { } }, onClear: () { + _fetchCount = 0; setState(() { inputItem.clear(); itemName = ''; @@ -651,6 +653,8 @@ class _MyHomePageState extends State { }, suggestions: suggestionsItem, onSuggestionTap: (suggestion) async { + _fetchCount = 0; + setState(() { itemName = suggestion['name']; inputItem.text = itemName; @@ -666,6 +670,8 @@ class _MyHomePageState extends State { controller: inputTags, labelText: 'Search by tags', onChanged: (value) { + _fetchCount = 0; + if (value.isNotEmpty) { setState(() { itemTags = value; @@ -683,6 +689,7 @@ class _MyHomePageState extends State { } }, onClear: () { + _fetchCount = 0; setState(() { inputTags.clear(); }); @@ -690,6 +697,8 @@ class _MyHomePageState extends State { }, suggestions: suggestionsTags, onSuggestionTap: (suggestion) async { + _fetchCount = 0; + setState(() { itemTags = suggestion['name']; inputTags.text = itemTags; @@ -713,6 +722,8 @@ class _MyHomePageState extends State { controller: inputGeo, labelText: 'Search by geographical zone', onChanged: (value) async { + _fetchCount = 0; + if (value.isNotEmpty) { setState(() { geographicalZone = value; @@ -734,6 +745,8 @@ class _MyHomePageState extends State { } }, onClear: () async { + _fetchCount = 0; + final prefs = await SharedPreferences.getInstance(); prefs.remove("city_lat"); prefs.remove("city_long"); @@ -749,6 +762,8 @@ class _MyHomePageState extends State { }, suggestions: suggestionsGeo, onSuggestionTap: (suggestion) async { + _fetchCount = 0; + final latitude = suggestion['geometry']['coordinates'][1]; final longitude = suggestion['geometry']['coordinates'][0]; setState(() { From 510e366216f13416577e736ac216dbad8fc07700 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 24 Mar 2025 22:47:49 +0100 Subject: [PATCH 03/10] add pagination --- .../lib/pages/ListItemByOrganizers.dart | 62 ++++++++++++++++++- covas_mobile/lib/pages/ListItemByTags.dart | 62 ++++++++++++++++++- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemByOrganizers.dart b/covas_mobile/lib/pages/ListItemByOrganizers.dart index 3a89580..23f0c26 100644 --- a/covas_mobile/lib/pages/ListItemByOrganizers.dart +++ b/covas_mobile/lib/pages/ListItemByOrganizers.dart @@ -42,17 +42,62 @@ class ListItemOrganizers extends StatefulWidget { // homepage state class _MyHomePageState extends State { + int _fetchCount = 0; + bool _isLoading = false; + late ScrollController _scrollController; + final AuthService _authService = AuthService(); + void _incrementFetchCount() { + setState(() { + _fetchCount++; + }); + } + + void _decrementFetchCount() { + setState(() { + if (_fetchCount > 0) { + _fetchCount--; + } + }); + } + + void _scrollListener() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + _incrementFetchCount(); + } else if (_scrollController.position.pixels == + _scrollController.position.minScrollExtent) { + _decrementFetchCount(); + } + _fetchData(); + } + + Future _fetchData() async { + print("Counter : ${_fetchCount}"); + if (_isLoading) return; + setState(() { + _isLoading = true; + }); + + await Future.delayed(Duration(seconds: 2)); + getPosts(widget.organizer, count: _fetchCount); + + setState(() { + _isLoading = false; + }); + } + // variable to call and store future list of posts // function to fetch data from api and return future list of posts - static Future> getPosts(organizer) async { + static Future> getPosts(organizer, {count = 0}) async { SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; final List body = []; if (accessToken.isNotEmpty) { - var url = Uri.parse("${globals.api}/events?organizers=${organizer}"); + var url = Uri.parse( + "${globals.api}/events?organizers=${organizer}&skip=${count}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}" @@ -67,6 +112,14 @@ class _MyHomePageState extends State { void initState() { super.initState(); _authService.checkTokenStatus(context); + _scrollController = ScrollController(); + _scrollController.addListener(_scrollListener); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); } // build function @@ -109,7 +162,10 @@ class _MyHomePageState extends State { foregroundColor: Colors.white, ), body: ListView.separated( - itemCount: posts.length, + controller: _scrollController, + itemCount: posts.isNotEmpty + ? posts.length + (_isLoading ? 1 : 0) // Add 1 only if loading + : 0, itemBuilder: (context, index) { final post = posts[index]; final startDate = DateTime.parse(post.startDate!); diff --git a/covas_mobile/lib/pages/ListItemByTags.dart b/covas_mobile/lib/pages/ListItemByTags.dart index 3866cc9..5844cbe 100644 --- a/covas_mobile/lib/pages/ListItemByTags.dart +++ b/covas_mobile/lib/pages/ListItemByTags.dart @@ -44,15 +44,59 @@ class ListItemTags extends StatefulWidget { class _MyHomePageState extends State { // variable to call and store future list of posts + int _fetchCount = 0; + bool _isLoading = false; + late ScrollController _scrollController; + final AuthService _authService = AuthService(); + void _incrementFetchCount() { + setState(() { + _fetchCount++; + }); + } + + void _decrementFetchCount() { + setState(() { + if (_fetchCount > 0) { + _fetchCount--; + } + }); + } + + void _scrollListener() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + _incrementFetchCount(); + } else if (_scrollController.position.pixels == + _scrollController.position.minScrollExtent) { + _decrementFetchCount(); + } + _fetchData(); + } + + Future _fetchData() async { + print("Counter : ${_fetchCount}"); + if (_isLoading) return; + setState(() { + _isLoading = true; + }); + + await Future.delayed(Duration(seconds: 2)); + getPosts(widget.tags, count: _fetchCount); + + setState(() { + _isLoading = false; + }); + } + // function to fetch data from api and return future list of posts - static Future> getPosts(tags) async { + static Future> getPosts(tags, {count = 0}) async { SharedPreferences prefs = await SharedPreferences.getInstance(); var accessToken = prefs.getString("access_token") ?? ""; final List body = []; if (accessToken.isNotEmpty) { - var url = Uri.parse("${globals.api}/events?tags=${tags}"); + var url = Uri.parse("${globals.api}/events?tags=${tags}&skip=${count}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}" @@ -67,6 +111,15 @@ class _MyHomePageState extends State { void initState() { super.initState(); _authService.checkTokenStatus(context); + _authService.checkTokenStatus(context); + _scrollController = ScrollController(); + _scrollController.addListener(_scrollListener); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); } // build function @@ -108,7 +161,10 @@ class _MyHomePageState extends State { foregroundColor: Colors.white, ), body: ListView.separated( - itemCount: posts.length, + controller: _scrollController, + itemCount: posts.isNotEmpty + ? posts.length + (_isLoading ? 1 : 0) // Add 1 only if loading + : 0, itemBuilder: (context, index) { final post = posts[index]; final startDate = DateTime.parse(post.startDate!); From 1bcc8372c66140bc3c272e470c2886b0834f0f0d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 23 May 2025 00:01:48 +0200 Subject: [PATCH 04/10] pagination work for main page --- covas_mobile/lib/pages/ListItemMenu.dart | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index a9b362f..9db6a1e 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -153,21 +153,10 @@ class _MyHomePageState extends State { }); } - void _decrementFetchCount() { - setState(() { - if (_fetchCount > 0 && filteredPosts.isNotEmpty) { - _fetchCount--; - } - }); - } - void _scrollListener() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _incrementFetchCount(); - } else if (_scrollController.position.pixels == - _scrollController.position.minScrollExtent) { - _decrementFetchCount(); } _fetchData(); } @@ -475,13 +464,19 @@ class _MyHomePageState extends State { if (response.statusCode == 200) { final List body = json.decode(utf8.decode(response.bodyBytes)); print("results fetch : ${body}"); + print("fetch count : ${_fetchCount}"); // Update state after getting the response setState(() { - if (body.isNotEmpty) { + if ((body.isNotEmpty) || (_fetchCount > 0)) { + if (body.isEmpty) { + _fetchCount = 0; + } // If we have results, map them to Events - filteredPosts = body - .map((e) => Events.fromJson(e as Map)) - .toList(); + filteredPosts.addAll( + body + .map((e) => Events.fromJson(e as Map)) + .toList(), + ); } else { // If no results, clear filteredPosts filteredPosts.clear(); From 7468c5f24cd734480dea110f4308a590c84fb66f Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 23 May 2025 23:47:17 +0200 Subject: [PATCH 05/10] change fetchCOunt --- covas_mobile/lib/pages/ListItemMenu.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 9db6a1e..b6cd544 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -469,7 +469,7 @@ class _MyHomePageState extends State { setState(() { if ((body.isNotEmpty) || (_fetchCount > 0)) { if (body.isEmpty) { - _fetchCount = 0; + _fetchCount--; } // If we have results, map them to Events filteredPosts.addAll( From 6c1c650fa14141e871d86444f36d6b234544054c Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 25 May 2025 23:39:37 +0200 Subject: [PATCH 06/10] add last data --- covas_mobile/lib/pages/ListItemMenu.dart | 25 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index b6cd544..9d726c7 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -50,6 +50,7 @@ class _MyHomePageState extends State { final AuthService _authService = AuthService(); late ScrollController _scrollController; int _fetchCount = 0; + bool _last = false; bool _isLoading = false; Future> postsFuture = getPosts(); @@ -470,13 +471,16 @@ class _MyHomePageState extends State { if ((body.isNotEmpty) || (_fetchCount > 0)) { if (body.isEmpty) { _fetchCount--; + _last = true; } // If we have results, map them to Events - filteredPosts.addAll( - body - .map((e) => Events.fromJson(e as Map)) - .toList(), - ); + if (!_last) { + filteredPosts.addAll( + body + .map((e) => Events.fromJson(e as Map)) + .toList(), + ); + } } else { // If no results, clear filteredPosts filteredPosts.clear(); @@ -619,6 +623,7 @@ class _MyHomePageState extends State { labelText: 'Search by item', onChanged: (value) { _fetchCount = 0; + _last = false; if (value.isNotEmpty) { setState(() { itemName = value; @@ -637,6 +642,7 @@ class _MyHomePageState extends State { }, onClear: () { _fetchCount = 0; + _last = false; setState(() { inputItem.clear(); itemName = ''; @@ -649,7 +655,7 @@ class _MyHomePageState extends State { suggestions: suggestionsItem, onSuggestionTap: (suggestion) async { _fetchCount = 0; - + _last = false; setState(() { itemName = suggestion['name']; inputItem.text = itemName; @@ -666,7 +672,7 @@ class _MyHomePageState extends State { labelText: 'Search by tags', onChanged: (value) { _fetchCount = 0; - + _last = false; if (value.isNotEmpty) { setState(() { itemTags = value; @@ -693,6 +699,7 @@ class _MyHomePageState extends State { suggestions: suggestionsTags, onSuggestionTap: (suggestion) async { _fetchCount = 0; + _last = false; setState(() { itemTags = suggestion['name']; @@ -718,6 +725,7 @@ class _MyHomePageState extends State { labelText: 'Search by geographical zone', onChanged: (value) async { _fetchCount = 0; + _last = false; if (value.isNotEmpty) { setState(() { @@ -741,7 +749,7 @@ class _MyHomePageState extends State { }, onClear: () async { _fetchCount = 0; - + _last = false; final prefs = await SharedPreferences.getInstance(); prefs.remove("city_lat"); prefs.remove("city_long"); @@ -758,6 +766,7 @@ class _MyHomePageState extends State { suggestions: suggestionsGeo, onSuggestionTap: (suggestion) async { _fetchCount = 0; + _last = false; final latitude = suggestion['geometry']['coordinates'][1]; final longitude = suggestion['geometry']['coordinates'][0]; From ec7a2860747c49efb50f4045f1bbc30ff76adaaa Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 27 May 2025 23:36:19 +0200 Subject: [PATCH 07/10] pagination wip --- covas_mobile/lib/pages/ListItemMenu.dart | 53 +++++++++++------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index 9d726c7..ce5e366 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -50,8 +50,8 @@ class _MyHomePageState extends State { final AuthService _authService = AuthService(); late ScrollController _scrollController; int _fetchCount = 0; - bool _last = false; bool _isLoading = false; + bool _lastData = false; Future> postsFuture = getPosts(); List filteredPosts = []; @@ -149,9 +149,12 @@ class _MyHomePageState extends State { } void _incrementFetchCount() { - setState(() { - _fetchCount++; - }); + if (!_lastData) { + setState(() { + _fetchCount++; + }); + _fetchData(); + } } void _scrollListener() { @@ -159,7 +162,8 @@ class _MyHomePageState extends State { _scrollController.position.maxScrollExtent) { _incrementFetchCount(); } - _fetchData(); + + // Scroll to top } Future _fetchData() async { @@ -467,23 +471,15 @@ class _MyHomePageState extends State { print("results fetch : ${body}"); print("fetch count : ${_fetchCount}"); // Update state after getting the response + if (body.isEmpty) { + _lastData = true; + } setState(() { - if ((body.isNotEmpty) || (_fetchCount > 0)) { - if (body.isEmpty) { - _fetchCount--; - _last = true; - } + if (body.isNotEmpty) { // If we have results, map them to Events - if (!_last) { - filteredPosts.addAll( - body - .map((e) => Events.fromJson(e as Map)) - .toList(), - ); - } - } else { - // If no results, clear filteredPosts - filteredPosts.clear(); + filteredPosts.addAll(body + .map((e) => Events.fromJson(e as Map)) + .toList()); } }); } else { @@ -623,7 +619,7 @@ class _MyHomePageState extends State { labelText: 'Search by item', onChanged: (value) { _fetchCount = 0; - _last = false; + _lastData = false; if (value.isNotEmpty) { setState(() { itemName = value; @@ -642,7 +638,7 @@ class _MyHomePageState extends State { }, onClear: () { _fetchCount = 0; - _last = false; + _lastData = false; setState(() { inputItem.clear(); itemName = ''; @@ -655,7 +651,7 @@ class _MyHomePageState extends State { suggestions: suggestionsItem, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _last = false; + _lastData = false; setState(() { itemName = suggestion['name']; inputItem.text = itemName; @@ -672,7 +668,7 @@ class _MyHomePageState extends State { labelText: 'Search by tags', onChanged: (value) { _fetchCount = 0; - _last = false; + _lastData = false; if (value.isNotEmpty) { setState(() { itemTags = value; @@ -691,6 +687,7 @@ class _MyHomePageState extends State { }, onClear: () { _fetchCount = 0; + _lastData = false; setState(() { inputTags.clear(); }); @@ -699,7 +696,7 @@ class _MyHomePageState extends State { suggestions: suggestionsTags, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _last = false; + _lastData = false; setState(() { itemTags = suggestion['name']; @@ -725,7 +722,7 @@ class _MyHomePageState extends State { labelText: 'Search by geographical zone', onChanged: (value) async { _fetchCount = 0; - _last = false; + _lastData = false; if (value.isNotEmpty) { setState(() { @@ -749,7 +746,7 @@ class _MyHomePageState extends State { }, onClear: () async { _fetchCount = 0; - _last = false; + _lastData = false; final prefs = await SharedPreferences.getInstance(); prefs.remove("city_lat"); prefs.remove("city_long"); @@ -766,7 +763,7 @@ class _MyHomePageState extends State { suggestions: suggestionsGeo, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _last = false; + _lastData = false; final latitude = suggestion['geometry']['coordinates'][1]; final longitude = suggestion['geometry']['coordinates'][0]; From 600bf8d2f4bda68a43cb6a9a2a0c3906443c6516 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 30 May 2025 23:39:50 +0200 Subject: [PATCH 08/10] add pagination with limit --- covas_mobile/lib/pages/ListItemMenu.dart | 32 ++++++++---------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemMenu.dart b/covas_mobile/lib/pages/ListItemMenu.dart index ce5e366..4614044 100644 --- a/covas_mobile/lib/pages/ListItemMenu.dart +++ b/covas_mobile/lib/pages/ListItemMenu.dart @@ -51,7 +51,6 @@ class _MyHomePageState extends State { late ScrollController _scrollController; int _fetchCount = 0; bool _isLoading = false; - bool _lastData = false; Future> postsFuture = getPosts(); List filteredPosts = []; @@ -149,12 +148,10 @@ class _MyHomePageState extends State { } void _incrementFetchCount() { - if (!_lastData) { - setState(() { - _fetchCount++; - }); - _fetchData(); - } + setState(() { + _fetchCount++; + }); + _fetchData(); } void _scrollListener() { @@ -392,9 +389,10 @@ class _MyHomePageState extends State { } else { queryParameters = dateParameter; } + int limit = 20 * (_fetchCount + 1); return Uri.parse( - "${globals.api}/$endpoint?$queryParameters&skip=${_fetchCount}"); + "${globals.api}/$endpoint?$queryParameters&limit=${limit}"); } Future searchSuggestionsByItem(String input) async { @@ -405,7 +403,7 @@ class _MyHomePageState extends State { var url = await getUrlForEvents(); final response = await http.get(url, headers: { "Content-Type": "application/json", - HttpHeaders.cookieHeader: "access_token=$accessToken" + HttpHeaders.cookieHeader: "acce0ss_token=$accessToken" }); if (response.statusCode == 200) { @@ -472,14 +470,14 @@ class _MyHomePageState extends State { print("fetch count : ${_fetchCount}"); // Update state after getting the response if (body.isEmpty) { - _lastData = true; + _fetchCount--; } setState(() { if (body.isNotEmpty) { // If we have results, map them to Events - filteredPosts.addAll(body + filteredPosts = body .map((e) => Events.fromJson(e as Map)) - .toList()); + .toList(); } }); } else { @@ -619,7 +617,6 @@ class _MyHomePageState extends State { labelText: 'Search by item', onChanged: (value) { _fetchCount = 0; - _lastData = false; if (value.isNotEmpty) { setState(() { itemName = value; @@ -638,7 +635,6 @@ class _MyHomePageState extends State { }, onClear: () { _fetchCount = 0; - _lastData = false; setState(() { inputItem.clear(); itemName = ''; @@ -651,7 +647,6 @@ class _MyHomePageState extends State { suggestions: suggestionsItem, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _lastData = false; setState(() { itemName = suggestion['name']; inputItem.text = itemName; @@ -668,7 +663,6 @@ class _MyHomePageState extends State { labelText: 'Search by tags', onChanged: (value) { _fetchCount = 0; - _lastData = false; if (value.isNotEmpty) { setState(() { itemTags = value; @@ -687,7 +681,6 @@ class _MyHomePageState extends State { }, onClear: () { _fetchCount = 0; - _lastData = false; setState(() { inputTags.clear(); }); @@ -696,7 +689,6 @@ class _MyHomePageState extends State { suggestions: suggestionsTags, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _lastData = false; setState(() { itemTags = suggestion['name']; @@ -722,7 +714,6 @@ class _MyHomePageState extends State { labelText: 'Search by geographical zone', onChanged: (value) async { _fetchCount = 0; - _lastData = false; if (value.isNotEmpty) { setState(() { @@ -746,7 +737,6 @@ class _MyHomePageState extends State { }, onClear: () async { _fetchCount = 0; - _lastData = false; final prefs = await SharedPreferences.getInstance(); prefs.remove("city_lat"); prefs.remove("city_long"); @@ -763,8 +753,6 @@ class _MyHomePageState extends State { suggestions: suggestionsGeo, onSuggestionTap: (suggestion) async { _fetchCount = 0; - _lastData = false; - final latitude = suggestion['geometry']['coordinates'][1]; final longitude = suggestion['geometry']['coordinates'][0]; setState(() { From afae3293c4bd15d8d20b8c30a405bb74aacf6341 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 2 Jun 2025 22:22:33 +0200 Subject: [PATCH 09/10] add current date --- covas_mobile/lib/pages/ListItemByOrganizers.dart | 3 ++- covas_mobile/lib/pages/ListItemByTags.dart | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemByOrganizers.dart b/covas_mobile/lib/pages/ListItemByOrganizers.dart index 23f0c26..b642120 100644 --- a/covas_mobile/lib/pages/ListItemByOrganizers.dart +++ b/covas_mobile/lib/pages/ListItemByOrganizers.dart @@ -96,8 +96,9 @@ class _MyHomePageState extends State { var accessToken = prefs.getString("access_token") ?? ""; final List body = []; if (accessToken.isNotEmpty) { + DateTime currentDatetime = DateTime.now(); var url = Uri.parse( - "${globals.api}/events?organizers=${organizer}&skip=${count}"); + "${globals.api}/events?organizers=${organizer}&skip=${count}¤t_datetime=${currentDatetime.toString()}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}" diff --git a/covas_mobile/lib/pages/ListItemByTags.dart b/covas_mobile/lib/pages/ListItemByTags.dart index 5844cbe..dda75a4 100644 --- a/covas_mobile/lib/pages/ListItemByTags.dart +++ b/covas_mobile/lib/pages/ListItemByTags.dart @@ -96,7 +96,9 @@ class _MyHomePageState extends State { var accessToken = prefs.getString("access_token") ?? ""; final List body = []; if (accessToken.isNotEmpty) { - var url = Uri.parse("${globals.api}/events?tags=${tags}&skip=${count}"); + DateTime currentDatetime = DateTime.now(); + var url = Uri.parse( + "${globals.api}/events?tags=${tags}&skip=${count}¤t_datetime=${currentDatetime.toString()}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}" From 3a64f1ae3628b37215ca64caceff1051d0dad6c9 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 2 Jun 2025 23:03:49 +0200 Subject: [PATCH 10/10] add pagination for other pages --- .../lib/pages/ListItemByOrganizers.dart | 16 +++------------- covas_mobile/lib/pages/ListItemByTags.dart | 18 +++++------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/covas_mobile/lib/pages/ListItemByOrganizers.dart b/covas_mobile/lib/pages/ListItemByOrganizers.dart index b642120..86ade76 100644 --- a/covas_mobile/lib/pages/ListItemByOrganizers.dart +++ b/covas_mobile/lib/pages/ListItemByOrganizers.dart @@ -54,23 +54,12 @@ class _MyHomePageState extends State { }); } - void _decrementFetchCount() { - setState(() { - if (_fetchCount > 0) { - _fetchCount--; - } - }); - } - void _scrollListener() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _incrementFetchCount(); - } else if (_scrollController.position.pixels == - _scrollController.position.minScrollExtent) { - _decrementFetchCount(); + _fetchData(); } - _fetchData(); } Future _fetchData() async { @@ -97,8 +86,9 @@ class _MyHomePageState extends State { final List body = []; if (accessToken.isNotEmpty) { DateTime currentDatetime = DateTime.now(); + num limit = 20 * (count + 1); var url = Uri.parse( - "${globals.api}/events?organizers=${organizer}&skip=${count}¤t_datetime=${currentDatetime.toString()}"); + "${globals.api}/events?organizers=${organizer}&limit=${limit}¤t_datetime=${currentDatetime.toString()}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}" diff --git a/covas_mobile/lib/pages/ListItemByTags.dart b/covas_mobile/lib/pages/ListItemByTags.dart index dda75a4..475b4ed 100644 --- a/covas_mobile/lib/pages/ListItemByTags.dart +++ b/covas_mobile/lib/pages/ListItemByTags.dart @@ -56,23 +56,13 @@ class _MyHomePageState extends State { }); } - void _decrementFetchCount() { - setState(() { - if (_fetchCount > 0) { - _fetchCount--; - } - }); - } - void _scrollListener() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _incrementFetchCount(); - } else if (_scrollController.position.pixels == - _scrollController.position.minScrollExtent) { - _decrementFetchCount(); + + _fetchData(); } - _fetchData(); } Future _fetchData() async { @@ -97,8 +87,10 @@ class _MyHomePageState extends State { final List body = []; if (accessToken.isNotEmpty) { DateTime currentDatetime = DateTime.now(); + num limit = 20 * (count + 1); + var url = Uri.parse( - "${globals.api}/events?tags=${tags}&skip=${count}¤t_datetime=${currentDatetime.toString()}"); + "${globals.api}/events?tags=${tags}&limit=${limit}¤t_datetime=${currentDatetime.toString()}"); final response = await http.get(url, headers: { "Content-Type": "application/json", HttpHeaders.cookieHeader: "access_token=${accessToken}"