Finished Archive screen
This commit is contained in:
parent
5f190cb99a
commit
e05f5bc093
6 changed files with 182 additions and 30 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'screens/archive_screen.dart';
|
||||||
import 'screens/event_screen.dart';
|
import 'screens/event_screen.dart';
|
||||||
import 'screens/events_screen.dart';
|
import 'screens/events_screen.dart';
|
||||||
import 'screens/home_screen.dart';
|
import 'screens/home_screen.dart';
|
||||||
|
|
@ -91,6 +92,12 @@ class App extends StatelessWidget {
|
||||||
return NewEventScreen();
|
return NewEventScreen();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else if (routeTokens.first == 'archive') {
|
||||||
|
return MaterialPageRoute(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return ArchiveScreen();
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Default route.
|
// Default route.
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
|
|
|
||||||
|
|
@ -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<List<TaskModel>>();
|
||||||
|
|
||||||
|
// Stream getters.
|
||||||
|
/// An observable of the current logged in user.
|
||||||
|
Observable<FirebaseUser> get userStream => _auth.userStream;
|
||||||
|
|
||||||
|
/// An observable of the done tasks linked to the current user.
|
||||||
|
Observable<List<TaskModel>> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,11 +197,15 @@ class FirestoreProvider {
|
||||||
///
|
///
|
||||||
/// The [event] parameter is used to query tasks that are part of a certain
|
/// The [event] parameter is used to query tasks that are part of a certain
|
||||||
/// event.
|
/// event.
|
||||||
Observable<List<TaskModel>> getUserTasks(String username, {String event}) {
|
Observable<List<TaskModel>> getUserTasks(
|
||||||
|
String username, {
|
||||||
|
String event,
|
||||||
|
bool done = false,
|
||||||
|
}) {
|
||||||
Query query = _firestore
|
Query query = _firestore
|
||||||
.collection('tasks')
|
.collection('tasks')
|
||||||
.where('ownerUsername', isEqualTo: username)
|
.where('ownerUsername', isEqualTo: username)
|
||||||
.where('done', isEqualTo: false);
|
.where('done', isEqualTo: done);
|
||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
query = query.where('event', isEqualTo: event);
|
query = query.where('event', isEqualTo: event);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart' hide AppBar;
|
||||||
|
|
||||||
import '../blocs/archive_bloc.dart';
|
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 {
|
class ArchiveScreen extends StatefulWidget {
|
||||||
_ArchiveScreenstate createState() => _ArchiveScreenstate();
|
_ArchiveScreenstate createState() => _ArchiveScreenstate();
|
||||||
|
|
@ -9,7 +14,65 @@ class ArchiveScreen extends StatefulWidget {
|
||||||
class _ArchiveScreenstate extends State<ArchiveScreen> {
|
class _ArchiveScreenstate extends State<ArchiveScreen> {
|
||||||
final bloc = ArchiveBloc();
|
final bloc = ArchiveBloc();
|
||||||
|
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
bloc.fetchTasks();
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold();
|
return StreamBuilder(
|
||||||
|
stream: bloc.userStream,
|
||||||
|
builder: (context, AsyncSnapshot<FirebaseUser> 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<List<TaskModel>> tasksSnap) {
|
||||||
|
if (!tasksSnap.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: LoadingIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildList(tasksSnap.data);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildList(List<TaskModel> 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(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,12 @@ class PopulatedDrawer extends StatelessWidget {
|
||||||
action: () => Navigator.of(context)
|
action: () => Navigator.of(context)
|
||||||
.pushNamedAndRemoveUntil('home/', (_) => false),
|
.pushNamedAndRemoveUntil('home/', (_) => false),
|
||||||
),
|
),
|
||||||
|
buildDrawerTile(
|
||||||
|
text: 'Archive',
|
||||||
|
isSelected: selectedScreen == Screen.archive,
|
||||||
|
action: () => Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil('archive/', (_) => false),
|
||||||
|
),
|
||||||
buildDrawerTile(
|
buildDrawerTile(
|
||||||
text: 'Events',
|
text: 'Events',
|
||||||
isSelected: selectedScreen == Screen.events,
|
isSelected: selectedScreen == Screen.events,
|
||||||
|
|
@ -124,4 +130,5 @@ class PopulatedDrawer extends StatelessWidget {
|
||||||
enum Screen {
|
enum Screen {
|
||||||
home,
|
home,
|
||||||
events,
|
events,
|
||||||
|
archive,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ class TaskListTile extends StatelessWidget with Tile {
|
||||||
/// Function to be called when the "event" button is pressed.
|
/// Function to be called when the "event" button is pressed.
|
||||||
final VoidCallback onEventPressed;
|
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.
|
/// Whether or not the event button should be hidden.
|
||||||
final bool hideEventButton;
|
final bool hideEventButton;
|
||||||
|
|
||||||
|
|
@ -35,6 +38,7 @@ class TaskListTile extends StatelessWidget with Tile {
|
||||||
TaskListTile({
|
TaskListTile({
|
||||||
@required this.task,
|
@required this.task,
|
||||||
this.onDone,
|
this.onDone,
|
||||||
|
this.onUndo,
|
||||||
this.onEditPressed,
|
this.onEditPressed,
|
||||||
this.onEventPressed,
|
this.onEventPressed,
|
||||||
this.hideEventButton = false,
|
this.hideEventButton = false,
|
||||||
|
|
@ -93,34 +97,49 @@ class TaskListTile extends StatelessWidget with Tile {
|
||||||
|
|
||||||
/// Builds the section that contains the 3 buttons for the tile.
|
/// Builds the section that contains the 3 buttons for the tile.
|
||||||
Widget buildButtonSection() {
|
Widget buildButtonSection() {
|
||||||
final bottomRowChildren = <Widget>[];
|
final columnChildren = <Widget>[];
|
||||||
|
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 = <Widget>[];
|
||||||
|
|
||||||
bottomRowChildren.add(
|
bottomRowChildren.add(
|
||||||
ActionButton(
|
|
||||||
onPressed: onEditPressed,
|
|
||||||
text: 'Edit',
|
|
||||||
leadingIconData: Icons.edit,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hideEventButton) {
|
|
||||||
bottomRowChildren.addAll([
|
|
||||||
SizedBox(
|
|
||||||
width: 4,
|
|
||||||
),
|
|
||||||
ActionButton(
|
ActionButton(
|
||||||
onPressed: onEventPressed,
|
onPressed: onEditPressed,
|
||||||
text: 'Event',
|
text: 'Edit',
|
||||||
leadingIconData: FontAwesomeIcons.calendar,
|
leadingIconData: Icons.edit,
|
||||||
),
|
),
|
||||||
]);
|
);
|
||||||
}
|
|
||||||
return Expanded(
|
if (!hideEventButton) {
|
||||||
flex: 5,
|
bottomRowChildren.addAll([
|
||||||
child: Column(
|
SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
width: 4,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
),
|
||||||
children: <Widget>[
|
ActionButton(
|
||||||
|
onPressed: onEventPressed,
|
||||||
|
text: 'Event',
|
||||||
|
leadingIconData: FontAwesomeIcons.calendar,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
columnChildren.addAll(
|
||||||
|
[
|
||||||
ActionButton(
|
ActionButton(
|
||||||
onPressed: onDone,
|
onPressed: onDone,
|
||||||
text: 'Done',
|
text: 'Done',
|
||||||
|
|
@ -135,6 +154,16 @@ class TaskListTile extends StatelessWidget with Tile {
|
||||||
children: bottomRowChildren,
|
children: bottomRowChildren,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
flex: 5,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
task.done ? MainAxisAlignment.start : MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: columnChildren,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue