Skip to content

Commit

Permalink
feat: pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
SethCohen committed Mar 21, 2023
1 parent ce48987 commit 8c68b71
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 208 deletions.
2 changes: 2 additions & 0 deletions src/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:asl/pages/manage_page.dart';
import 'package:asl/providers/data_provider.dart';
import 'package:asl/themes/comfy.dart';
import 'package:asl/widgets/lesson.dart';
import 'package:asl/widgets/review.dart';
Expand Down Expand Up @@ -30,6 +31,7 @@ class MyApp extends StatelessWidget {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => GoogleSignInProvider()),
ChangeNotifierProvider(create: (_) => DataProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
Expand Down
28 changes: 16 additions & 12 deletions src/lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import 'package:asl/pages/dictionary_page.dart';
import 'package:asl/pages/lessons_page.dart';
import 'package:asl/pages/manage_page.dart';
import 'package:asl/pages/review_page.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:asl/providers/data_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
Expand All @@ -15,9 +15,11 @@ class HomePage extends StatefulWidget {
}

class _HomePageState extends State<HomePage> {
CollectionReference lessons =
FirebaseFirestore.instance.collection('lessons');
final user = FirebaseAuth.instance.currentUser!;
@override
void initState() {
super.initState();
context.read<DataProvider>().loadData();
}

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -55,13 +57,15 @@ class _HomePageState extends State<HomePage> {
),
],
),
body: const TabBarView(children: <Widget>[
LessonsPage(),
ReviewPage(),
DictionaryPage(),
CreatorPage(),
ManagePage(),
]),
body: const TabBarView(
children: <Widget>[
LessonsPage(),
ReviewPage(),
DictionaryPage(),
CreatorPage(),
ManagePage(),
],
),
),
),
),
Expand Down
184 changes: 50 additions & 134 deletions src/lib/pages/lessons_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:asl/providers/data_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class LessonsPage extends StatefulWidget {
const LessonsPage({super.key});
Expand All @@ -10,149 +10,65 @@ class LessonsPage extends StatefulWidget {
}

class _LessonsPageState extends State<LessonsPage> {
final user = FirebaseAuth.instance.currentUser!;
final ScrollController _scrollController = ScrollController();

@override
Widget build(BuildContext context) {
return Center(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection("lessons").snapshots(),
builder: (context, snapshot1) {
if (snapshot1.hasData) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("users")
.doc(user.uid)
.collection("progress")
.snapshots(),
builder: (context, snapshot2) {
if (snapshot2.hasData) {
final lessonsCollection = snapshot1.data!.docs;
final progressCollection = snapshot2.data!.docs;

return SizedBox(
width: MediaQuery.of(context).size.width * 0.33,
child: ListView.builder(
itemCount: lessonsCollection.length,
itemBuilder: (context, index) {
final lesson = lessonsCollection[index];
final lessonTitle = _convertIdToTitle(lesson.id);

final lessonProgress =
_getLessonProgress(progressCollection, lesson);

final iconColour =
_lessonColour(lessonProgress, lesson.id);

return Card(
child: ListTile(
title: Text(lessonTitle),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
lessonProgress[index]
['lessonCardsRemaining']
.toString(),
style: TextStyle(color: iconColour),
),
Icon(Icons.check_circle, color: iconColour),
],
),
onTap: () => Navigator.pushNamed(
context,
'/lesson',
arguments: {
'lessonId': lesson.id,
'isReview': false,
},
)),
);
},
),
);
} else if (snapshot2.hasError) {
return const Text('Something went wrong!');
} else {
return const CircularProgressIndicator();
}
},
);
} else if (snapshot1.hasError) {
return const Text('Something went wrong!');
} else {
return const CircularProgressIndicator();
}
}),
);
}

String _convertIdToTitle(String input) {
return input.replaceAll('lesson', 'Lesson ');
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.maxScrollExtent -
_scrollController.position.pixels <=
MediaQuery.of(context).size.height * 0.20) {
context.read<DataProvider>().loadMoreDecks();
}
});
}

List<Map<String, dynamic>> _getLessonProgress(
List<QueryDocumentSnapshot> progressCollection,
QueryDocumentSnapshot lesson,
) {
_initializeLessonProgress(progressCollection, lesson);

return progressCollection.map((lessonProgress) {
final data = lessonProgress.data() as Map<String, dynamic>;
return {
'id': lessonProgress.id,
'complete': data['complete'],
'inProgress': data['inProgress'],
'lessonCardsRemaining': data['lessonCardsRemaining'],
};
}).toList();
}
@override
Widget build(BuildContext context) {
final decks = context.watch<DataProvider>().decks;
final user = context.watch<DataProvider>().user;

void _initializeLessonProgress(
List<QueryDocumentSnapshot> progressCollection,
QueryDocumentSnapshot lesson,
) {
bool lessonDoesntExist = !progressCollection
.any((lessonProgress) => lessonProgress.id == lesson.id);
return ListView.builder(
controller: _scrollController,
itemCount: decks.length,
itemBuilder: (context, index) {
final userDeckProgress = user.deckProgress[decks[index].id] ??
{'isCompleted': false, 'isInProgress': false, 'cards': {}};
final iconColour = _lessonColour(userDeckProgress);

if (lessonDoesntExist) {
FirebaseFirestore.instance
.collection("lessons")
.doc(lesson.id)
.collection('cards')
.get()
.then(
(value) {
final lessonCardsRemaining = value.size;
FirebaseFirestore.instance
.collection("users")
.doc(user.uid)
.collection("progress")
.doc(lesson.id)
.set(
{
"complete": false,
"inProgress": false,
"lessonCardsRemaining": lessonCardsRemaining
},
SetOptions(merge: true),
);
},
);
}
return Card(
child: ListTile(
title: Text(decks[index].name),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
userDeckProgress['cards'].length.toString(),
style: TextStyle(color: iconColour),
),
Icon(Icons.check_circle, color: iconColour),
],
),
onTap: () => Navigator.pushNamed(
context,
'/lesson',
arguments: {
'deckName': decks[index].name,
'isReview': false,
},
)),
);
},
);
}

Color _lessonColour(
List<Map<String, dynamic>> currentLessonProgress,
String lessonId,
Map<String, dynamic> currentLessonProgress,
) {
return currentLessonProgress
.where((element) => element['id'] == lessonId)
.first['complete']
return currentLessonProgress['isCompleted']
? Colors.green
: currentLessonProgress
.where((element) => element['id'] == lessonId)
.first['inProgress']
: currentLessonProgress['isInProgress']
? Colors.orange
: Colors.black38;
}
Expand Down
Loading

0 comments on commit 8c68b71

Please sign in to comment.