From e05f5bc09384c507bbf27f22359685ba6b9c7e5c Mon Sep 17 00:00:00 2001 From: AYM1607 Date: Sun, 28 Apr 2019 18:37:37 -0500 Subject: [PATCH] Finished Archive screen --- lib/src/App.dart | 7 ++ lib/src/blocs/archive_bloc.dart | 44 ++++++++++++- lib/src/resources/firestore_provider.dart | 8 ++- lib/src/screens/archive_screen.dart | 67 ++++++++++++++++++- lib/src/widgets/populated_drawer.dart | 7 ++ lib/src/widgets/task_list_tile.dart | 79 ++++++++++++++++------- 6 files changed, 182 insertions(+), 30 deletions(-) diff --git a/lib/src/App.dart b/lib/src/App.dart index 16e21c9..aada9e5 100644 --- a/lib/src/App.dart +++ b/lib/src/App.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'screens/archive_screen.dart'; import 'screens/event_screen.dart'; import 'screens/events_screen.dart'; import 'screens/home_screen.dart'; @@ -91,6 +92,12 @@ class App extends StatelessWidget { return NewEventScreen(); }, ); + } else if (routeTokens.first == 'archive') { + return MaterialPageRoute( + builder: (BuildContext context) { + return ArchiveScreen(); + }, + ); } // Default route. return MaterialPageRoute( diff --git a/lib/src/blocs/archive_bloc.dart b/lib/src/blocs/archive_bloc.dart index 19be05b..ffe4651 100644 --- a/lib/src/blocs/archive_bloc.dart +++ b/lib/src/blocs/archive_bloc.dart @@ -1 +1,43 @@ -class ArchiveBloc {} +import 'dart:async'; + +import 'package:rxdart/rxdart.dart'; + +import '../utils.dart' show kTaskListPriorityTransforemer; +import '../models/task_model.dart'; +import '../resources/firestore_provider.dart'; +import '../resources/google_sign_in_provider.dart'; +import '../services/auth_service.dart'; + +export '../services/auth_service.dart' show FirebaseUser; + +class ArchiveBloc { + /// An instance of the auth service. + AuthService _auth = authService; + + /// An instance of the firestore provider. + FirestoreProvider _firestore = firestoreProvider; + + final _tasks = BehaviorSubject>(); + + // Stream getters. + /// An observable of the current logged in user. + Observable get userStream => _auth.userStream; + + /// An observable of the done tasks linked to the current user. + Observable> get tasks => + _tasks.stream.transform(kTaskListPriorityTransforemer); + + void fetchTasks() async { + final userModel = await _auth.getCurrentUserModel(); + _firestore.getUserTasks(userModel.username, done: true).pipe(_tasks); + } + + void undoTask(TaskModel task) { + _firestore.updateTask(task.id, done: false); + } + + dispose() async { + await _tasks.drain(); + _tasks.close(); + } +} diff --git a/lib/src/resources/firestore_provider.dart b/lib/src/resources/firestore_provider.dart index d894eea..7d803e2 100644 --- a/lib/src/resources/firestore_provider.dart +++ b/lib/src/resources/firestore_provider.dart @@ -197,11 +197,15 @@ class FirestoreProvider { /// /// The [event] parameter is used to query tasks that are part of a certain /// event. - Observable> getUserTasks(String username, {String event}) { + Observable> getUserTasks( + String username, { + String event, + bool done = false, + }) { Query query = _firestore .collection('tasks') .where('ownerUsername', isEqualTo: username) - .where('done', isEqualTo: false); + .where('done', isEqualTo: done); if (event != null) { query = query.where('event', isEqualTo: event); diff --git a/lib/src/screens/archive_screen.dart b/lib/src/screens/archive_screen.dart index a978f15..5edbd58 100644 --- a/lib/src/screens/archive_screen.dart +++ b/lib/src/screens/archive_screen.dart @@ -1,6 +1,11 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide AppBar; import '../blocs/archive_bloc.dart'; +import '../models/task_model.dart'; +import '../widgets/app_bar.dart'; +import '../widgets/loading_indicator.dart'; +import '../widgets/populated_drawer.dart'; +import '../widgets/task_list_tile.dart'; class ArchiveScreen extends StatefulWidget { _ArchiveScreenstate createState() => _ArchiveScreenstate(); @@ -9,7 +14,65 @@ class ArchiveScreen extends StatefulWidget { class _ArchiveScreenstate extends State { final bloc = ArchiveBloc(); + initState() { + super.initState(); + bloc.fetchTasks(); + } + Widget build(BuildContext context) { - return Scaffold(); + return StreamBuilder( + stream: bloc.userStream, + builder: (context, AsyncSnapshot userSnap) { + String userAvatarUrl, userDisplayName = '', userEmail = ''; + + if (userSnap.hasData) { + userAvatarUrl = userSnap.data.photoUrl; + userDisplayName = userSnap.data.displayName; + userEmail = userSnap.data.email; + } + + return Scaffold( + drawer: PopulatedDrawer( + userAvatarUrl: userAvatarUrl, + userDisplayName: userDisplayName, + userEmail: userEmail, + selectedScreen: Screen.archive, + ), + appBar: AppBar( + title: 'Archive', + hasDrawer: true, + ), + body: StreamBuilder( + stream: bloc.tasks, + builder: (context, AsyncSnapshot> tasksSnap) { + if (!tasksSnap.hasData) { + return Center( + child: LoadingIndicator(), + ); + } + + return buildList(tasksSnap.data); + }, + ), + ); + }, + ); + } + + Widget buildList(List tasks) { + return ListView( + padding: EdgeInsets.only(top: 15), + children: tasks + .map( + (task) => Padding( + padding: EdgeInsets.only(bottom: 15), + child: TaskListTile( + task: task, + onUndo: () => bloc.undoTask(task), + ), + ), + ) + .toList(), + ); } } diff --git a/lib/src/widgets/populated_drawer.dart b/lib/src/widgets/populated_drawer.dart index 4b344aa..857031d 100644 --- a/lib/src/widgets/populated_drawer.dart +++ b/lib/src/widgets/populated_drawer.dart @@ -54,6 +54,12 @@ class PopulatedDrawer extends StatelessWidget { action: () => Navigator.of(context) .pushNamedAndRemoveUntil('home/', (_) => false), ), + buildDrawerTile( + text: 'Archive', + isSelected: selectedScreen == Screen.archive, + action: () => Navigator.of(context) + .pushNamedAndRemoveUntil('archive/', (_) => false), + ), buildDrawerTile( text: 'Events', isSelected: selectedScreen == Screen.events, @@ -124,4 +130,5 @@ class PopulatedDrawer extends StatelessWidget { enum Screen { home, events, + archive, } diff --git a/lib/src/widgets/task_list_tile.dart b/lib/src/widgets/task_list_tile.dart index 406fb40..ed3df00 100644 --- a/lib/src/widgets/task_list_tile.dart +++ b/lib/src/widgets/task_list_tile.dart @@ -20,6 +20,9 @@ class TaskListTile extends StatelessWidget with Tile { /// Function to be called when the "event" button is pressed. final VoidCallback onEventPressed; + /// Function to be called when the "undo" button is pressed. + final VoidCallback onUndo; + /// Whether or not the event button should be hidden. final bool hideEventButton; @@ -35,6 +38,7 @@ class TaskListTile extends StatelessWidget with Tile { TaskListTile({ @required this.task, this.onDone, + this.onUndo, this.onEditPressed, this.onEventPressed, this.hideEventButton = false, @@ -93,34 +97,49 @@ class TaskListTile extends StatelessWidget with Tile { /// Builds the section that contains the 3 buttons for the tile. Widget buildButtonSection() { - final bottomRowChildren = []; + final columnChildren = []; + if (task.done) { + columnChildren.addAll( + [ + SizedBox( + height: 25, + ), + ActionButton( + onPressed: onUndo, + text: 'Undo', + trailingIconData: FontAwesomeIcons.timesCircle, + color: Colors.white, + textColor: Colors.black, + radius: 14, + width: 72, + ), + ], + ); + } else { + final bottomRowChildren = []; - bottomRowChildren.add( - ActionButton( - onPressed: onEditPressed, - text: 'Edit', - leadingIconData: Icons.edit, - ), - ); - - if (!hideEventButton) { - bottomRowChildren.addAll([ - SizedBox( - width: 4, - ), + bottomRowChildren.add( ActionButton( - onPressed: onEventPressed, - text: 'Event', - leadingIconData: FontAwesomeIcons.calendar, + onPressed: onEditPressed, + text: 'Edit', + leadingIconData: Icons.edit, ), - ]); - } - return Expanded( - flex: 5, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ + ); + + if (!hideEventButton) { + bottomRowChildren.addAll([ + SizedBox( + width: 4, + ), + ActionButton( + onPressed: onEventPressed, + text: 'Event', + leadingIconData: FontAwesomeIcons.calendar, + ), + ]); + } + columnChildren.addAll( + [ ActionButton( onPressed: onDone, text: 'Done', @@ -135,6 +154,16 @@ class TaskListTile extends StatelessWidget with Tile { children: bottomRowChildren, ), ], + ); + } + + return Expanded( + flex: 5, + child: Column( + mainAxisAlignment: + task.done ? MainAxisAlignment.start : MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.end, + children: columnChildren, ), ); }