Merge pull request 'feature/pagination' (#42) from feature/pagination into main
Reviewed-on: #42
This commit is contained in:
commit
452faf05d8
@ -42,17 +42,53 @@ class ListItemOrganizers extends StatefulWidget {
|
||||
|
||||
// homepage state
|
||||
class _MyHomePageState extends State<ListItemOrganizers> {
|
||||
int _fetchCount = 0;
|
||||
bool _isLoading = false;
|
||||
late ScrollController _scrollController;
|
||||
|
||||
final AuthService _authService = AuthService();
|
||||
|
||||
void _incrementFetchCount() {
|
||||
setState(() {
|
||||
_fetchCount++;
|
||||
});
|
||||
}
|
||||
|
||||
void _scrollListener() {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
_incrementFetchCount();
|
||||
_fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _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<List<Events>> getPosts(organizer) async {
|
||||
static Future<List<Events>> getPosts(organizer, {count = 0}) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var accessToken = prefs.getString("access_token") ?? "";
|
||||
final List<Events> body = [];
|
||||
if (accessToken.isNotEmpty) {
|
||||
var url = Uri.parse("${globals.api}/events?organizers=${organizer}");
|
||||
DateTime currentDatetime = DateTime.now();
|
||||
num limit = 20 * (count + 1);
|
||||
var url = Uri.parse(
|
||||
"${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}"
|
||||
@ -67,6 +103,14 @@ class _MyHomePageState extends State<ListItemOrganizers> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_authService.checkTokenStatus(context);
|
||||
_scrollController = ScrollController();
|
||||
_scrollController.addListener(_scrollListener);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
// build function
|
||||
@ -109,7 +153,10 @@ class _MyHomePageState extends State<ListItemOrganizers> {
|
||||
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!);
|
||||
|
@ -44,15 +44,53 @@ class ListItemTags extends StatefulWidget {
|
||||
class _MyHomePageState extends State<ListItemTags> {
|
||||
// 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 _scrollListener() {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
_incrementFetchCount();
|
||||
|
||||
_fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _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<List<Events>> getPosts(tags) async {
|
||||
static Future<List<Events>> getPosts(tags, {count = 0}) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var accessToken = prefs.getString("access_token") ?? "";
|
||||
final List<Events> body = [];
|
||||
if (accessToken.isNotEmpty) {
|
||||
var url = Uri.parse("${globals.api}/events?tags=${tags}");
|
||||
DateTime currentDatetime = DateTime.now();
|
||||
num limit = 20 * (count + 1);
|
||||
|
||||
var url = Uri.parse(
|
||||
"${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}"
|
||||
@ -67,6 +105,15 @@ class _MyHomePageState extends State<ListItemTags> {
|
||||
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 +155,10 @@ class _MyHomePageState extends State<ListItemTags> {
|
||||
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!);
|
||||
|
@ -48,6 +48,9 @@ class ListItemMenu extends StatefulWidget {
|
||||
class _MyHomePageState extends State<ListItemMenu> {
|
||||
BannerAd? _bannerAd;
|
||||
final AuthService _authService = AuthService();
|
||||
late ScrollController _scrollController;
|
||||
int _fetchCount = 0;
|
||||
bool _isLoading = false;
|
||||
|
||||
Future<List<Events>> postsFuture = getPosts();
|
||||
List<Events> filteredPosts = [];
|
||||
@ -144,6 +147,37 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
return "${year}-${month}-${day}";
|
||||
}
|
||||
|
||||
void _incrementFetchCount() {
|
||||
setState(() {
|
||||
_fetchCount++;
|
||||
});
|
||||
_fetchData();
|
||||
}
|
||||
|
||||
void _scrollListener() {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
_incrementFetchCount();
|
||||
}
|
||||
|
||||
// Scroll to top
|
||||
}
|
||||
|
||||
Future<void> _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 +187,19 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
_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<void> _getCurrentLocation() async {
|
||||
PermissionStatus status = await Permission.location.status;
|
||||
@ -346,8 +389,10 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
} else {
|
||||
queryParameters = dateParameter;
|
||||
}
|
||||
int limit = 20 * (_fetchCount + 1);
|
||||
|
||||
return Uri.parse("${globals.api}/$endpoint?$queryParameters");
|
||||
return Uri.parse(
|
||||
"${globals.api}/$endpoint?$queryParameters&limit=${limit}");
|
||||
}
|
||||
|
||||
Future<void> searchSuggestionsByItem(String input) async {
|
||||
@ -358,7 +403,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
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) {
|
||||
@ -422,16 +467,17 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> body = json.decode(utf8.decode(response.bodyBytes));
|
||||
print("results fetch : ${body}");
|
||||
print("fetch count : ${_fetchCount}");
|
||||
// Update state after getting the response
|
||||
if (body.isEmpty) {
|
||||
_fetchCount--;
|
||||
}
|
||||
setState(() {
|
||||
if (body.isNotEmpty) {
|
||||
// If we have results, map them to Events
|
||||
filteredPosts = body
|
||||
.map((e) => Events.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
} else {
|
||||
// If no results, clear filteredPosts
|
||||
filteredPosts.clear();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@ -570,6 +616,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
controller: inputItem,
|
||||
labelText: 'Search by item',
|
||||
onChanged: (value) {
|
||||
_fetchCount = 0;
|
||||
if (value.isNotEmpty) {
|
||||
setState(() {
|
||||
itemName = value;
|
||||
@ -587,6 +634,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
}
|
||||
},
|
||||
onClear: () {
|
||||
_fetchCount = 0;
|
||||
setState(() {
|
||||
inputItem.clear();
|
||||
itemName = '';
|
||||
@ -598,6 +646,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
},
|
||||
suggestions: suggestionsItem,
|
||||
onSuggestionTap: (suggestion) async {
|
||||
_fetchCount = 0;
|
||||
setState(() {
|
||||
itemName = suggestion['name'];
|
||||
inputItem.text = itemName;
|
||||
@ -613,6 +662,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
controller: inputTags,
|
||||
labelText: 'Search by tags',
|
||||
onChanged: (value) {
|
||||
_fetchCount = 0;
|
||||
if (value.isNotEmpty) {
|
||||
setState(() {
|
||||
itemTags = value;
|
||||
@ -630,6 +680,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
}
|
||||
},
|
||||
onClear: () {
|
||||
_fetchCount = 0;
|
||||
setState(() {
|
||||
inputTags.clear();
|
||||
});
|
||||
@ -637,6 +688,8 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
},
|
||||
suggestions: suggestionsTags,
|
||||
onSuggestionTap: (suggestion) async {
|
||||
_fetchCount = 0;
|
||||
|
||||
setState(() {
|
||||
itemTags = suggestion['name'];
|
||||
inputTags.text = itemTags;
|
||||
@ -660,6 +713,8 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
controller: inputGeo,
|
||||
labelText: 'Search by geographical zone',
|
||||
onChanged: (value) async {
|
||||
_fetchCount = 0;
|
||||
|
||||
if (value.isNotEmpty) {
|
||||
setState(() {
|
||||
geographicalZone = value;
|
||||
@ -681,6 +736,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
}
|
||||
},
|
||||
onClear: () async {
|
||||
_fetchCount = 0;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.remove("city_lat");
|
||||
prefs.remove("city_long");
|
||||
@ -696,6 +752,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
},
|
||||
suggestions: suggestionsGeo,
|
||||
onSuggestionTap: (suggestion) async {
|
||||
_fetchCount = 0;
|
||||
final latitude = suggestion['geometry']['coordinates'][1];
|
||||
final longitude = suggestion['geometry']['coordinates'][0];
|
||||
setState(() {
|
||||
@ -770,12 +827,22 @@ class _MyHomePageState extends State<ListItemMenu> {
|
||||
}
|
||||
|
||||
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}'),
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user